1 /*
2  * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 
27 
28 /*
29  * FUNCTION
30  *      mlib_ImageLookUp - table lookup
31  *
32  * SYNOPSIS
33  *      mlib_status mlib_ImageLookUp(mlib_image       *dst,
34  *                                   const mlib_image *src,
35  *                                   void             **table)
36  *
37  * ARGUMENT
38  *      dst      Pointer to destination image.
39  *      src      Pointer to source image.
40  *      table    Lookup table.
41  *
42  * DESCRIPTION
43  *      The mlib_ImageLookUp function performs general table lookup on an
44  *      image. The destination image is obtained by passing a source image
45  *      through a lookup table.
46  *
47  *      The source image may be 1-, 2-, 3-, or 4-channeled of data types
48  *      MLIB_BIT, MLIB_BYTE, MLIB_SHORT, or MLIB_INT. The lookup table may be
49  *      1-, 2-, 3-, or 4-channeled of data types MLIB_BYTE, MLIB_SHORT, MLIB_INT,
50  *      MLIB_FLOAT, or MLIB_DOUBLE. The destination image must have the same
51  *      number of channels as either source image or the lookup table,
52  *      whichever is greater, and the same data type as the lookup table.
53  *
54  *      It is the user's responsibility to make sure that the lookup table
55  *      supplied is suitable for the source image. Specifically, the table
56  *      entries cover the entire range of source data. Otherwise, the result
57  *      of this function is undefined.
58  *
59  *      The pixel values of the destination image are defined as the following:
60  *
61  *      If the source image is single-channeled and the destination image is
62  *      multi-channeled, then the lookup table has the same number of channels
63  *      as the destination image:
64  *
65  *          dst[x][y][c] = table[c][src[x][y][0]]
66  *
67  *      If the source image is multi-channeled and the destination image is
68  *      multi-channeled, with the same number of channels as the source image,
69  *      then the lookup table will have the same number of channels as
70  *      the source image:
71  *
72  *          dst[x][y][c] = table[c][src[x][y][c]]
73  */
74 
75 #include "mlib_image.h"
76 #include "mlib_ImageCheck.h"
77 #include "mlib_ImageLookUp.h"
78 #include "mlib_v_ImageLookUpFunc.h"
79 
80 /***************************************************************/
81 #define CALL_SIFUNC(STYPE, DTYPE, TYPE)                            \
82   switch (nchan) {                                                 \
83     case 2:                                                        \
84       mlib_v_ImageLookUpSI_##STYPE##_##DTYPE##_2(sa, slb, da, dlb, \
85           xsize, ysize, (const TYPE **) table);                    \
86       break;                                                       \
87     case 3:                                                        \
88       mlib_v_ImageLookUpSI_##STYPE##_##DTYPE##_3(sa, slb, da, dlb, \
89           xsize, ysize, (const TYPE **) table);                    \
90       break;                                                       \
91     case 4:                                                        \
92       mlib_v_ImageLookUpSI_##STYPE##_##DTYPE##_4(sa, slb, da, dlb, \
93           xsize, ysize, (const TYPE **) table);                    \
94       break;                                                       \
95     default:                                                       \
96       return MLIB_FAILURE;                                         \
97   }                                                                \
98   return MLIB_SUCCESS
99 
100 /***************************************************************/
101 #define CALL_FUNC(STYPE, DTYPE, TYPE)                            \
102   switch (nchan) {                                               \
103     case 1:                                                      \
104       mlib_v_ImageLookUp_##STYPE##_##DTYPE##_1(sa, slb, da, dlb, \
105           xsize, ysize, (const TYPE **) table);                  \
106       break;                                                     \
107     case 2:                                                      \
108       mlib_v_ImageLookUp_##STYPE##_##DTYPE##_2(sa, slb, da, dlb, \
109           xsize, ysize, (const TYPE **) table);                  \
110       break;                                                     \
111     case 3:                                                      \
112       mlib_v_ImageLookUp_##STYPE##_##DTYPE##_3(sa, slb, da, dlb, \
113           xsize, ysize, (const TYPE **) table);                  \
114       break;                                                     \
115     case 4:                                                      \
116       mlib_v_ImageLookUp_##STYPE##_##DTYPE##_4(sa, slb, da, dlb, \
117           xsize, ysize, (const TYPE **) table);                  \
118       break;                                                     \
119     default:                                                     \
120       return MLIB_FAILURE;                                       \
121   }                                                              \
122   return MLIB_SUCCESS
123 
124 /***************************************************************/
mlib_ImageLookUp(mlib_image * dst,const mlib_image * src,const void ** table)125 mlib_status mlib_ImageLookUp(mlib_image       *dst,
126                              const mlib_image *src,
127                              const void       **table)
128 {
129   mlib_s32 slb, dlb, xsize, ysize, nchan, ichan, bitoff_src;
130   mlib_type stype, dtype;
131   void *sa, *da;
132 
133   MLIB_IMAGE_CHECK(src);
134   MLIB_IMAGE_CHECK(dst);
135   MLIB_IMAGE_SIZE_EQUAL(src, dst);
136   MLIB_IMAGE_CHAN_SRC1_OR_EQ(src, dst);
137 
138   stype = mlib_ImageGetType(src);
139   dtype = mlib_ImageGetType(dst);
140   ichan = mlib_ImageGetChannels(src);
141   nchan = mlib_ImageGetChannels(dst);
142   xsize = mlib_ImageGetWidth(src);
143   ysize = mlib_ImageGetHeight(src);
144   slb = mlib_ImageGetStride(src);
145   dlb = mlib_ImageGetStride(dst);
146   sa = mlib_ImageGetData(src);
147   da = mlib_ImageGetData(dst);
148 
149   if (ichan == nchan) {
150     if (dtype == MLIB_BYTE) {
151       if (stype == MLIB_BYTE) {
152         CALL_FUNC(U8, U8, mlib_u8);
153       }
154       else if (stype == MLIB_SHORT) {
155         CALL_FUNC(S16, U8, mlib_u8);
156       }
157       else if (stype == MLIB_USHORT) {
158         CALL_FUNC(U16, U8, mlib_u8);
159       }
160       else if (stype == MLIB_INT) {
161         CALL_FUNC(S32, U8, mlib_u8);
162       }
163       else if (stype == MLIB_BIT) {
164         if (nchan != 1)
165           return MLIB_FAILURE;
166 
167         bitoff_src = mlib_ImageGetBitOffset(src); /* bits to first byte */
168         return mlib_ImageLookUp_Bit_U8_1(sa, slb, da, dlb, xsize, ysize, nchan,
169                                          bitoff_src, (const mlib_u8 **) table);
170       }
171     }
172     else if (dtype == MLIB_SHORT) {
173       if (stype == MLIB_BYTE) {
174         CALL_FUNC(U8, S16, mlib_s16);
175       }
176       else if (stype == MLIB_SHORT) {
177         CALL_FUNC(S16, S16, mlib_s16);
178       }
179       else if (stype == MLIB_USHORT) {
180         CALL_FUNC(U16, S16, mlib_s16);
181       }
182       else if (stype == MLIB_INT) {
183         CALL_FUNC(S32, S16, mlib_s16);
184       }
185     }
186     else if (dtype == MLIB_USHORT) {
187       if (stype == MLIB_BYTE) {
188         CALL_FUNC(U8, U16, mlib_u16);
189       }
190       else if (stype == MLIB_SHORT) {
191         CALL_FUNC(S16, U16, mlib_u16);
192       }
193       else if (stype == MLIB_USHORT) {
194         CALL_FUNC(U16, U16, mlib_u16);
195       }
196       else if (stype == MLIB_INT) {
197         CALL_FUNC(S32, U16, mlib_u16);
198       }
199     }
200     else if (dtype == MLIB_INT) {
201       if (stype == MLIB_BYTE) {
202         CALL_FUNC(U8, S32, mlib_s32);
203       }
204       else if (stype == MLIB_SHORT) {
205         CALL_FUNC(S16, S32, mlib_s32);
206       }
207       else if (stype == MLIB_USHORT) {
208         CALL_FUNC(U16, S32, mlib_s32);
209       }
210       else if (stype == MLIB_INT) {
211         if ((nchan >= 1) && (nchan <= 4)) {
212           mlib_v_ImageLookUp_S32_S32(sa, slb, da, dlb, xsize, ysize, (const mlib_s32 **) table,
213                                      nchan);
214           return MLIB_SUCCESS;
215         }
216         else {
217           return MLIB_FAILURE;
218         }
219       }
220     }
221     else if (dtype == MLIB_FLOAT) {
222       if (stype == MLIB_BYTE) {
223         CALL_FUNC(U8, S32, mlib_s32);
224       }
225       else if (stype == MLIB_SHORT) {
226         CALL_FUNC(S16, S32, mlib_s32);
227       }
228       else if (stype == MLIB_USHORT) {
229         CALL_FUNC(U16, S32, mlib_s32);
230       }
231       else if (stype == MLIB_INT) {
232         if ((nchan >= 1) && (nchan <= 4)) {
233           mlib_v_ImageLookUp_S32_S32(sa, slb, da, dlb, xsize, ysize, (const mlib_s32 **) table,
234                                      nchan);
235           return MLIB_SUCCESS;
236         }
237         else {
238           return MLIB_FAILURE;
239         }
240       }
241     }
242     else if (dtype == MLIB_DOUBLE) {
243       if (stype == MLIB_BYTE) {
244         mlib_ImageLookUp_U8_D64(sa, slb, da, dlb / 8, xsize, ysize, nchan,
245                                 (const mlib_d64 **) table);
246         return MLIB_SUCCESS;
247       }
248       else if (stype == MLIB_SHORT) {
249         mlib_ImageLookUp_S16_D64(sa, slb / 2, da, dlb / 8, xsize, ysize, nchan,
250                                  (const mlib_d64 **) table);
251         return MLIB_SUCCESS;
252       }
253       else if (stype == MLIB_USHORT) {
254         mlib_ImageLookUp_U16_D64(sa, slb / 2, da, dlb / 8, xsize, ysize, nchan,
255                                  (const mlib_d64 **) table);
256         return MLIB_SUCCESS;
257       }
258       else if (stype == MLIB_INT) {
259         mlib_ImageLookUp_S32_D64(sa, slb / 4, da, dlb / 8, xsize, ysize, nchan,
260                                  (const mlib_d64 **) table);
261         return MLIB_SUCCESS;
262       }
263     }
264   }
265   else if (ichan == 1) {
266     if (dtype == MLIB_BYTE) {
267       if (stype == MLIB_BYTE) {
268         CALL_SIFUNC(U8, U8, mlib_u8);
269       }
270       else if (stype == MLIB_SHORT) {
271         CALL_SIFUNC(S16, U8, mlib_u8);
272       }
273       else if (stype == MLIB_USHORT) {
274         CALL_SIFUNC(U16, U8, mlib_u8);
275       }
276       else if (stype == MLIB_INT) {
277         CALL_SIFUNC(S32, U8, mlib_u8);
278       }
279       else if (stype == MLIB_BIT) {
280         bitoff_src = mlib_ImageGetBitOffset(src); /* bits to first byte */
281 
282         if (nchan == 2) {
283           return mlib_ImageLookUp_Bit_U8_2(sa, slb, da, dlb, xsize, ysize, nchan,
284                                            bitoff_src, (const mlib_u8 **) table);
285         }
286         else if (nchan == 3) {
287           return mlib_ImageLookUp_Bit_U8_3(sa, slb, da, dlb, xsize, ysize, nchan,
288                                            bitoff_src, (const mlib_u8 **) table);
289         }
290         else {                              /* (nchan == 4) */
291           return mlib_ImageLookUp_Bit_U8_4(sa, slb, da, dlb, xsize, ysize, nchan,
292                                            bitoff_src, (const mlib_u8 **) table);
293         }
294       }
295     }
296     else if (dtype == MLIB_SHORT) {
297       if (stype == MLIB_BYTE) {
298         CALL_SIFUNC(U8, S16, mlib_s16);
299       }
300       else if (stype == MLIB_SHORT) {
301         CALL_SIFUNC(S16, S16, mlib_s16);
302       }
303       else if (stype == MLIB_USHORT) {
304         CALL_SIFUNC(U16, S16, mlib_s16);
305       }
306       else if (stype == MLIB_INT) {
307         CALL_SIFUNC(S32, S16, mlib_s16);
308       }
309     }
310     else if (dtype == MLIB_USHORT) {
311       if (stype == MLIB_BYTE) {
312         CALL_SIFUNC(U8, U16, mlib_u16);
313       }
314       else if (stype == MLIB_SHORT) {
315         CALL_SIFUNC(S16, U16, mlib_u16);
316       }
317       else if (stype == MLIB_USHORT) {
318         CALL_SIFUNC(U16, U16, mlib_u16);
319       }
320       else if (stype == MLIB_INT) {
321         CALL_SIFUNC(S32, U16, mlib_u16);
322       }
323     }
324     else if (dtype == MLIB_INT) {
325 
326       if (stype == MLIB_BYTE) {
327         CALL_SIFUNC(U8, S32, mlib_s32);
328       }
329       else if (stype == MLIB_SHORT) {
330         CALL_SIFUNC(S16, S32, mlib_s32);
331       }
332       else if (stype == MLIB_USHORT) {
333         CALL_SIFUNC(U16, S32, mlib_s32);
334       }
335       else if (stype == MLIB_INT) {
336         if ((nchan >= 1) && (nchan <= 4)) {
337           mlib_v_ImageLookUpSI_S32_S32(sa, slb, da, dlb, xsize, ysize,
338                                        (const mlib_s32 **) table, nchan);
339           return MLIB_SUCCESS;
340         }
341         else {
342           return MLIB_FAILURE;
343         }
344       }
345     }
346     else if (dtype == MLIB_FLOAT) {
347 
348       if (stype == MLIB_BYTE) {
349         CALL_SIFUNC(U8, S32, mlib_s32);
350       }
351       else if (stype == MLIB_SHORT) {
352         CALL_SIFUNC(S16, S32, mlib_s32);
353       }
354       else if (stype == MLIB_USHORT) {
355         CALL_SIFUNC(U16, S32, mlib_s32);
356       }
357       else if (stype == MLIB_INT) {
358         if ((nchan >= 1) && (nchan <= 4)) {
359           mlib_v_ImageLookUpSI_S32_S32(sa, slb, da, dlb, xsize, ysize,
360                                        (const mlib_s32 **) table, nchan);
361           return MLIB_SUCCESS;
362         }
363         else {
364           return MLIB_FAILURE;
365         }
366       }
367     }
368     else if (dtype == MLIB_DOUBLE) {
369       if (stype == MLIB_BYTE) {
370         mlib_ImageLookUpSI_U8_D64(sa, slb, da, dlb / 8, xsize, ysize, nchan,
371                                   (const mlib_d64 **) table);
372         return MLIB_SUCCESS;
373       }
374       else if (stype == MLIB_SHORT) {
375         mlib_ImageLookUpSI_S16_D64(sa, slb / 2, da, dlb / 8, xsize, ysize, nchan,
376                                    (const mlib_d64 **) table);
377         return MLIB_SUCCESS;
378       }
379       else if (stype == MLIB_USHORT) {
380         mlib_ImageLookUpSI_U16_D64(sa, slb / 2, da, dlb / 8, xsize, ysize, nchan,
381                                    (const mlib_d64 **) table);
382         return MLIB_SUCCESS;
383       }
384       else if (stype == MLIB_INT) {
385         mlib_ImageLookUpSI_S32_D64(sa, slb / 4, da, dlb / 8, xsize, ysize, nchan,
386                                    (const mlib_d64 **) table);
387         return MLIB_SUCCESS;
388       }
389     }
390   }
391 
392   return MLIB_FAILURE;
393 }
394 
395 /***************************************************************/
396