Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / DtHelp / il / ilmap.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
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.
26         */
27
28 #include "ilint.h"
29 #include "ilpipelem.h"
30 #include "ilerrors.h"
31
32
33         /*  Private data for map pipe functions.
34         */
35 typedef struct {
36
37         /*  Data inited by ilMap() when pipe element added. */
38     ilClientImage   mapImage;               /* map (lookup table) image */
39     ilPtr           pTranslate;             /* ptr to map image pixels */
40
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;
48
49
50         /*  --------------------- ilMapInit -------------------------- */
51         /*  Init() function: copy values from given images to private for fast reference.
52         */
53 static ilError ilMapInit (
54     ilPtr              pPrivate,
55     ilImageInfo        *pSrcImage,
56     ilImageInfo        *pDstImage
57     )
58 {
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;
65     return IL_OK;
66 }
67
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.
71         */
72 static ilError ilMapByteExecute (
73     ilExecuteData          *pData,
74     long                    dstLine,
75     long                   *pNLines
76     )
77 {
78 ilMapPrivPtr                pPriv;
79 long                        srcRowBytes, dstRowBytes, nRowsM1, nLinesM1;
80 ilPtr                       pSrcLine, pDstLine;
81 register long               rowCount;
82 register ilPtr              pSrc, pDst, pTranslate;
83
84         /*  Get data from private, exit if no rows or lines to do.
85         */
86     pPriv = (ilMapPrivPtr)pData->pPrivate;
87     nRowsM1 = pPriv->width;
88     if (nRowsM1 <= 0)
89         return;
90     nRowsM1--;
91     nLinesM1 = *pNLines;
92     if (nLinesM1 <= 0)
93         return;
94     nLinesM1--;
95
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;
101
102         /*  Lookup each src byte in table (256-wide byte image) and copy to dst.
103         */
104     do {
105         pSrc = pSrcLine;
106         pSrcLine += srcRowBytes;
107         pDst = pDstLine;
108         pDstLine += dstRowBytes;
109         rowCount = nRowsM1;
110         do {
111             *pDst++ = (ilByte)pTranslate[*pSrc++];
112             } while (--rowCount >= 0);
113         } while (--nLinesM1 >= 0);
114
115     return IL_OK;
116 }
117
118         /*  --------------------- ilMap3ByteExecute -------------------------- */
119         /*  Execute() pipe element function for 3 byte/pixel, pixel order case.
120         */
121 static ilError ilMap3ByteExecute (
122     ilExecuteData          *pData,
123     long                    dstLine,
124     long                   *pNLines
125     )
126 {
127 ilMapPrivPtr                pPriv;
128 long                        srcRowBytes, dstRowBytes, nRowsM1, nLinesM1;
129 ilPtr                       pSrcLine, pDstLine;
130 register long               rowCount;
131 register ilPtr              pSrc, pDst, pTranslate;
132
133         /*  Get data from private, exit if no rows or lines to do.
134         */
135     pPriv = (ilMapPrivPtr)pData->pPrivate;
136     nRowsM1 = pPriv->width;
137     if (nRowsM1 <= 0)
138         return;
139     nRowsM1--;
140     nLinesM1 = *pNLines;
141     if (nLinesM1 <= 0)
142         return;
143     nLinesM1--;
144
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;
150
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.
153         */
154     do {
155         pSrc = pSrcLine;
156         pSrcLine += srcRowBytes;
157         pDst = pDstLine;
158         pDstLine += dstRowBytes;
159         rowCount = nRowsM1;
160         do {
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);
166
167     return IL_OK;
168 }
169
170
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.
177         */
178 static ilError ilMapDestroy (
179     ilPtr     pPrivate
180     )
181 {
182     ilMapPrivPtr pPriv = (ilMapPrivPtr)pPrivate;
183     ilDestroyObject ((ilObject)pPriv->mapImage);
184     return IL_OK;
185 }
186
187         /*  ------------------------ ilMap ---------------------------------- */
188         /*  Public function: see spec.
189             Use "mapImage" as a lookup table for each pixel in the pipe image.
190         */
191 ilBool ilMap (
192     ilPipe              pipe,
193     ilClientImage       mapImage
194     )
195 {
196 register ilMapPrivPtr   pPriv;
197 register ilContext      context;
198 ilPipeInfo              info;
199 ilImageDes              des;
200 ilImageFormat           format;
201 ilImageInfo            *pInfo;
202 long                    width, height;
203 int                     i;
204 ilError               (*executeProc) ();
205
206         /*  Validate that pipe and image are such, and that they have the same context.
207         */
208     context = pipe->context;
209     if (pipe->objectType != IL_PIPE) {
210         context->error = IL_ERROR_OBJECT_TYPE;
211         return FALSE;
212         }
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);
217
218         /*  Get pipe info; if pipe not in IL_PIPE_FORMING state: error.
219         */                          
220     if (ilGetPipeInfo (pipe, TRUE, &info, &des, &format) != IL_PIPE_FORMING) {
221         if (!pipe->context->error)
222             ilDeclarePipeInvalid (pipe, IL_ERROR_PIPE_STATE);
223         return FALSE;
224         }
225
226         /*  Query mapImage; must be uncompressed, 256x1, # samples = same as pipe image,
227             each 8 bits/sample, or error.
228         */
229     if (!ilQueryClientImage (mapImage, &pInfo, 0))
230         return FALSE;
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);
238
239         /*  Handle 1 and 3 byte (pixel format) cases; set "executeProc" accordingly.
240         */
241     if (des.nSamplesPerPixel == 1) {
242         if (format.nBitsPerSample[0] != 8)
243             if (!ilConvert (pipe, (ilImageDes *)NULL, IL_FORMAT_BYTE, 0, NULL))
244                 return FALSE;
245         executeProc = ilMapByteExecute;
246         }
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))
253                 return FALSE;
254         executeProc = ilMap3ByteExecute;
255         }
256     else return ilDeclarePipeInvalid (pipe, IL_ERROR_NOT_IMPLEMENTED);
257
258         /*  Add a filter to do the map, copy data to private.  Inc refCount for mapImage;
259             see notes for ilMapDestroy().
260         */
261     pPriv = (ilMapPrivPtr)ilAddPipeElement (pipe, IL_FILTER, sizeof (ilMapPrivRec), 
262                          0, (ilSrcElementData *)NULL, (ilDstElementData *)NULL, 
263                          ilMapInit, IL_NPF, ilMapDestroy, executeProc, NULL, 0);
264     if (!pPriv)
265         return FALSE;
266     pPriv->mapImage = mapImage;
267     ((ilObjectPtr)mapImage)->refCount++;
268     pPriv->pTranslate = pInfo->plane[0].pPixels;
269
270     context->error = IL_OK;
271     return TRUE;
272 }
273
274