2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: ilmap.c /main/5 1996/06/19 12:21:21 ageorge $ */
24 /* /ilc/ilmap.c : Contains ilMap(), which adds a pipe element to remap
25 the pipe image given a LUT image.
29 #include "ilpipelem.h"
33 /* Private data for map pipe functions.
37 /* Data inited by ilMap() when pipe element added. */
38 ilClientImage mapImage; /* map (lookup table) image */
39 ilPtr pTranslate; /* ptr to map image pixels */
41 /* Rest of the data is inited by the Init() function */
42 long width; /* width of src/dst images */
43 long srcRowBytes; /* bytes/row of src image */
44 ilPtr pSrcPixels; /* ptr to start of src pixels */
45 long dstRowBytes; /* bytes/row of dst image */
46 ilPtr pDstPixels; /* ptr to start of dst pixels */
47 } ilMapPrivRec, *ilMapPrivPtr;
50 /* --------------------- ilMapInit -------------------------- */
51 /* Init() function: copy values from given images to private for fast reference.
53 static ilError ilMapInit (
55 ilImageInfo *pSrcImage,
56 ilImageInfo *pDstImage
59 ilMapPrivPtr pPriv = (ilMapPrivPtr)pPrivate;
60 pPriv->width = pSrcImage->width;
61 pPriv->srcRowBytes = pSrcImage->plane[0].nBytesPerRow;
62 pPriv->pSrcPixels = pSrcImage->plane[0].pPixels;
63 pPriv->dstRowBytes = pDstImage->plane[0].nBytesPerRow;
64 pPriv->pDstPixels = pDstImage->plane[0].pPixels;
68 /* --------------------- ilMapByteExecute -------------------------- */
69 /* Execute() pipe element function for case where the source is an image
70 of bytes. Lookup each byte in the 256-wide translate image and pass to dst.
72 static ilError ilMapByteExecute (
79 long srcRowBytes, dstRowBytes, nRowsM1, nLinesM1;
80 ilPtr pSrcLine, pDstLine;
81 register long rowCount;
82 register ilPtr pSrc, pDst, pTranslate;
84 /* Get data from private, exit if no rows or lines to do.
86 pPriv = (ilMapPrivPtr)pData->pPrivate;
87 nRowsM1 = pPriv->width;
96 srcRowBytes = pPriv->srcRowBytes;
97 pSrcLine = pPriv->pSrcPixels + pData->srcLine * srcRowBytes;
98 dstRowBytes = pPriv->dstRowBytes;
99 pDstLine = pPriv->pDstPixels + dstLine * dstRowBytes;
100 pTranslate = pPriv->pTranslate;
102 /* Lookup each src byte in table (256-wide byte image) and copy to dst.
106 pSrcLine += srcRowBytes;
108 pDstLine += dstRowBytes;
111 *pDst++ = (ilByte)pTranslate[*pSrc++];
112 } while (--rowCount >= 0);
113 } while (--nLinesM1 >= 0);
118 /* --------------------- ilMap3ByteExecute -------------------------- */
119 /* Execute() pipe element function for 3 byte/pixel, pixel order case.
121 static ilError ilMap3ByteExecute (
122 ilExecuteData *pData,
128 long srcRowBytes, dstRowBytes, nRowsM1, nLinesM1;
129 ilPtr pSrcLine, pDstLine;
130 register long rowCount;
131 register ilPtr pSrc, pDst, pTranslate;
133 /* Get data from private, exit if no rows or lines to do.
135 pPriv = (ilMapPrivPtr)pData->pPrivate;
136 nRowsM1 = pPriv->width;
145 srcRowBytes = pPriv->srcRowBytes;
146 pSrcLine = pPriv->pSrcPixels + pData->srcLine * srcRowBytes;
147 dstRowBytes = pPriv->dstRowBytes;
148 pDstLine = pPriv->pDstPixels + dstLine * dstRowBytes;
149 pTranslate = pPriv->pTranslate;
151 /* For each pixel, lookup the samples independently. The src, dst and map images
152 are all 3 components in sample order - must multiply * 3 to index.
156 pSrcLine += srcRowBytes;
158 pDstLine += dstRowBytes;
161 *pDst++ = (pTranslate + 0)[*pSrc++ * 3];
162 *pDst++ = (pTranslate + 1)[*pSrc++ * 3];
163 *pDst++ = (pTranslate + 2)[*pSrc++ * 3];
164 } while (--rowCount >= 0);
165 } while (--nLinesM1 >= 0);
171 /* ------------------------ ilMapDestroy -------------------------------- */
172 /* Destroy() function for ilWriteMap(). Calls ilDestroyObject() with
173 element's pObject, which should point to the image. The image's refCount
174 is inc'd when pipe element added. ilDestroyObject() will dec it and free
175 the image if the refCount is 0. Using refCount this way prevents the user
176 from destroying a map image still attached to a pipe.
178 static ilError ilMapDestroy (
182 ilMapPrivPtr pPriv = (ilMapPrivPtr)pPrivate;
183 ilDestroyObject ((ilObject)pPriv->mapImage);
187 /* ------------------------ ilMap ---------------------------------- */
188 /* Public function: see spec.
189 Use "mapImage" as a lookup table for each pixel in the pipe image.
193 ilClientImage mapImage
196 register ilMapPrivPtr pPriv;
197 register ilContext context;
200 ilImageFormat format;
204 ilError (*executeProc) ();
206 /* Validate that pipe and image are such, and that they have the same context.
208 context = pipe->context;
209 if (pipe->objectType != IL_PIPE) {
210 context->error = IL_ERROR_OBJECT_TYPE;
213 if (mapImage->objectType != IL_CLIENT_IMAGE)
214 return ilDeclarePipeInvalid (pipe, IL_ERROR_OBJECT_TYPE);
215 if (mapImage->context != context)
216 return ilDeclarePipeInvalid (pipe, IL_ERROR_CONTEXT_MISMATCH);
218 /* Get pipe info; if pipe not in IL_PIPE_FORMING state: error.
220 if (ilGetPipeInfo (pipe, TRUE, &info, &des, &format) != IL_PIPE_FORMING) {
221 if (!pipe->context->error)
222 ilDeclarePipeInvalid (pipe, IL_ERROR_PIPE_STATE);
226 /* Query mapImage; must be uncompressed, 256x1, # samples = same as pipe image,
227 each 8 bits/sample, or error.
229 if (!ilQueryClientImage (mapImage, &pInfo, 0))
231 if ((pInfo->width != 256) || (pInfo->height != 1)
232 || (pInfo->pDes->compression != IL_UNCOMPRESSED)
233 || (pInfo->pDes->nSamplesPerPixel != des.nSamplesPerPixel))
234 return ilDeclarePipeInvalid (pipe, IL_ERROR_MAP_IMAGE);
235 for (i = 0; i < des.nSamplesPerPixel; i++)
236 if (pInfo->pFormat->nBitsPerSample[i] != 8)
237 return ilDeclarePipeInvalid (pipe, IL_ERROR_MAP_IMAGE);
239 /* Handle 1 and 3 byte (pixel format) cases; set "executeProc" accordingly.
241 if (des.nSamplesPerPixel == 1) {
242 if (format.nBitsPerSample[0] != 8)
243 if (!ilConvert (pipe, (ilImageDes *)NULL, IL_FORMAT_BYTE, 0, NULL))
245 executeProc = ilMapByteExecute;
247 else if (des.nSamplesPerPixel == 3) {
248 if ((format.nBitsPerSample[0] != 8)
249 || (format.nBitsPerSample[1] != 8)
250 || (format.nBitsPerSample[2] != 8)
251 || (format.sampleOrder != IL_SAMPLE_PIXELS))
252 if (!ilConvert (pipe, (ilImageDes *)NULL, IL_FORMAT_3BYTE_PIXEL, 0, NULL))
254 executeProc = ilMap3ByteExecute;
256 else return ilDeclarePipeInvalid (pipe, IL_ERROR_NOT_IMPLEMENTED);
258 /* Add a filter to do the map, copy data to private. Inc refCount for mapImage;
259 see notes for ilMapDestroy().
261 pPriv = (ilMapPrivPtr)ilAddPipeElement (pipe, IL_FILTER, sizeof (ilMapPrivRec),
262 0, (ilSrcElementData *)NULL, (ilDstElementData *)NULL,
263 ilMapInit, IL_NPF, ilMapDestroy, executeProc, NULL, 0);
266 pPriv->mapImage = mapImage;
267 ((ilObjectPtr)mapImage)->refCount++;
268 pPriv->pTranslate = pInfo->plane[0].pPixels;
270 context->error = IL_OK;