1 /*
2  * Copyright (c) 2003, 2011, 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  * FUNCTION
28  *      mlib_ImageColorTrue2Index - convert a true color image to an indexed
29  *                                  color image
30  *
31  * SYNOPSIS
32  *      mlib_status mlib_ImageColorTrue2Index(mlib_image       *dst,
33  *                                            const mlib_image *src,
34  *                                            const void       *colormap)
35  *
36  * ARGUMENTS
37  *      colormap  Internal data structure for inverse color mapping.
38  *      dst       Pointer to destination image.
39  *      src       Pointer to source image.
40  *
41  * DESCRIPTION
42  *      Convert a true color image to a pseudo color image with the method
43  *      of finding the nearest matched lut entry for each pixel.
44  *
45  *      The src can be an MLIB_BYTE or MLIB_SHORT image with 3 or 4 channels.
46  *      The dst must be a 1-channel MLIB_BYTE or MLIB_SHORT image.
47  *
48  *      The lut might have either 3 or 4 channels. The type of the lut can be
49  *      one of the following:
50  *              MLIB_BYTE in, MLIB_BYTE out (i.e., BYTE-to-BYTE)
51  *              MLIB_BYTE in, MLIB_SHORT out (i.e., BYTE-to-SHORT)
52  *              MLIB_SHORT in, MLIB_SHORT out (i.e., SHORT-to-SHORT)
53  *              MLIB_SHORT in, MLIB_BYTE out (i.e., SHORT-to-BYTE)
54  *
55  *      The src image and the lut must have same number of channels.
56  */
57 
58 #include "mlib_image.h"
59 #include "mlib_ImageColormap.h"
60 #include "mlib_ImageCheck.h"
61 
62 /***************************************************************/
63 
64 /*#define USE_VIS_CODE*/
65 
66 #ifdef USE_VIS_CODE
67 #include "vis_proto.h"
68 #define VIS_ALIGNADDR(X, Y)  vis_alignaddr((void *)(X), (Y))
69 #endif
70 
71 /***************************************************************/
72 
73 #define LUT_BYTE_COLORS_3CHANNELS  1000
74 #define LUT_BYTE_COLORS_4CHANNELS  3000
75 #define LUT_SHORT_COLORS_3CHANNELS 1000
76 #define LUT_SHORT_COLORS_4CHANNELS 1000
77 
78 /***************************************************************/
79 
80 #define MAIN_COLORTRUE2INDEX_LOOP( FROM_TYPE, TO_TYPE, NCHANNELS )       \
81   for( y = 0; y < height; y++ )                                          \
82   {                                                                      \
83     mlib_ImageColorTrue2IndexLine_##FROM_TYPE##_##TO_TYPE##_##NCHANNELS( \
84       sdata, ddata, width, colormap );                                   \
85                                                                          \
86     sdata += sstride;                                                    \
87     ddata += dstride;                                                    \
88   }
89 
90 /***************************************************************/
91 
92 #define COLOR_CUBE_U8_3_SEARCH( TABLE_POINTER_TYPE, SHIFT, STEP ) \
93 {                                                                 \
94   const mlib_u8 *c0, *c1, *c2;                                    \
95   TABLE_POINTER_TYPE *table = s->table;                           \
96   mlib_s32 bits = s->bits;                                        \
97   mlib_s32 nbits = 8 - bits;                                      \
98   mlib_s32 mask = ~( ( 1 << nbits ) - 1 );                        \
99   mlib_s32 j;                                                     \
100                                                                   \
101   c0 = src + SHIFT;                                               \
102   c1 = src + 1 + SHIFT;                                           \
103   c2 = src + 2 + SHIFT;                                           \
104                                                                   \
105   switch( bits )                                                  \
106   {                                                               \
107     case 1:                                                       \
108     case 2:                                                       \
109     {                                                             \
110       mlib_s32 bits0 = 8 - bits;                                  \
111       mlib_s32 bits1 = bits0 - bits;                              \
112       mlib_s32 bits2 = bits1 - bits;                              \
113                                                                   \
114       for( j = 0; j < length; j++ )                               \
115       {                                                           \
116         dst[ j ] = table[ ( ( *c0 & mask ) >> bits2 ) |           \
117           ( ( *c1 & mask ) >> bits1 ) |                           \
118           ( ( *c2 & mask ) >> bits0 ) ];                          \
119                                                                   \
120         c0 += STEP;                                               \
121         c1 += STEP;                                               \
122         c2 += STEP;                                               \
123       }                                                           \
124       break;                                                      \
125     }                                                             \
126     case 3:                                                       \
127     {                                                             \
128       for( j = 0; j < length; j++ )                               \
129       {                                                           \
130         dst[ j ] = table[ ( ( *c0 & mask ) << 1 ) |               \
131           ( ( *c1 & mask ) >> 2 ) |                               \
132           ( ( *c2 & mask ) >> 5 ) ];                              \
133                                                                   \
134         c0 += STEP;                                               \
135         c1 += STEP;                                               \
136         c2 += STEP;                                               \
137       }                                                           \
138       break;                                                      \
139     }                                                             \
140     case 4:                                                       \
141     {                                                             \
142       for( j = 0; j < length; j++ )                               \
143       {                                                           \
144         dst[ j ] = table[ ( ( *c0 & mask ) << 4 ) |               \
145           ( *c1 & mask ) |                                        \
146           ( ( *c2 & mask ) >> 4 ) ];                              \
147                                                                   \
148         c0 += STEP;                                               \
149         c1 += STEP;                                               \
150         c2 += STEP;                                               \
151       }                                                           \
152       break;                                                      \
153     }                                                             \
154     case 5:                                                       \
155     case 6:                                                       \
156     case 7:                                                       \
157     {                                                             \
158       mlib_s32 bits0 = 8 - bits;                                  \
159       mlib_s32 bits1 = bits * 2 - 8;                              \
160       mlib_s32 bits2 = bits1 + bits;                              \
161                                                                   \
162       for( j = 0; j < length; j++ )                               \
163       {                                                           \
164         dst[ j ] = table[ ( ( *c0 & mask ) << bits2 ) |           \
165           ( ( *c1 & mask ) << bits1 ) |                           \
166           ( ( *c2 & mask ) >> bits0 ) ];                          \
167                                                                   \
168         c0 += STEP;                                               \
169         c1 += STEP;                                               \
170         c2 += STEP;                                               \
171       }                                                           \
172       break;                                                      \
173     }                                                             \
174     case 8:                                                       \
175     {                                                             \
176       for( j = 0; j < length; j++ )                               \
177       {                                                           \
178         dst[ j ] = table[ ( ( *c0 & mask ) << 16 ) |              \
179           ( ( *c1 & mask ) << 8 ) |                               \
180           ( *c2 & mask ) ];                                       \
181                                                                   \
182         c0 += STEP;                                               \
183         c1 += STEP;                                               \
184         c2 += STEP;                                               \
185       }                                                           \
186       break;                                                      \
187     }                                                             \
188   }                                                               \
189 }
190 
191 /***************************************************************/
192 #define COLOR_CUBE_U8_4_SEARCH( TABLE_TYPE )                    \
193 {                                                               \
194   const mlib_u8 *c0, *c1, *c2, *c3;                             \
195   TABLE_TYPE *table = s->table;                                 \
196   mlib_s32 bits = s->bits;                                      \
197   mlib_s32 nbits = 8 - bits;                                    \
198   mlib_s32 mask = ~( ( 1 << nbits ) - 1 );                      \
199   mlib_s32 j;                                                   \
200                                                                 \
201   c0 = src;                                                     \
202   c1 = src + 1;                                                 \
203   c2 = src + 2;                                                 \
204   c3 = src + 3;                                                 \
205                                                                 \
206   switch( bits )                                                \
207   {                                                             \
208     case 1:                                                     \
209     {                                                           \
210       for( j = 0; j < length; j++ )                             \
211       {                                                         \
212         dst[ j ] = table[ ( ( *c0 & mask ) >> 4 ) |             \
213           ( ( *c1 & mask ) >> 5 ) |                             \
214           ( ( *c2 & mask ) >> 6 ) |                             \
215           ( ( *c3 & mask ) >> 7 ) ];                            \
216                                                                 \
217         c0 += 4;                                                \
218         c1 += 4;                                                \
219         c2 += 4;                                                \
220         c3 += 4;                                                \
221       }                                                         \
222       break;                                                    \
223     }                                                           \
224     case 2:                                                     \
225     {                                                           \
226       for( j = 0; j < length; j++ )                             \
227       {                                                         \
228         dst[ j ] = table[ ( *c0 & mask ) |                      \
229           ( ( *c1 & mask ) >> 2 ) |                             \
230           ( ( *c2 & mask ) >> 4 ) |                             \
231           ( ( *c3 & mask ) >> 6 ) ];                            \
232                                                                 \
233         c0 += 4;                                                \
234         c1 += 4;                                                \
235         c2 += 4;                                                \
236         c3 += 4;                                                \
237           }                                                     \
238       break;                                                    \
239     }                                                           \
240     case 3:                                                     \
241     {                                                           \
242       for( j = 0; j < length; j++ )                             \
243       {                                                         \
244         dst[ j ] = table[ ( ( *c0 & mask ) << 4 ) |             \
245           ( ( *c1 & mask ) << 1 ) |                             \
246           ( ( *c2 & mask ) >> 2 ) |                             \
247           ( ( *c3 & mask ) >> 5 ) ];                            \
248                                                                 \
249         c0 += 4;                                                \
250         c1 += 4;                                                \
251         c2 += 4;                                                \
252         c3 += 4;                                                \
253       }                                                         \
254       break;                                                    \
255     }                                                           \
256     case 4:                                                     \
257     {                                                           \
258       for( j = 0; j < length; j++ )                             \
259       {                                                         \
260         dst[ j ] = table[ ( ( *c0 & mask ) << 8 ) |             \
261           ( ( *c1 & mask ) << 4 ) |                             \
262           ( *c2 & mask ) |                                      \
263           ( ( *c3 & mask ) >> 4 ) ];                            \
264                                                                 \
265         c0 += 4;                                                \
266         c1 += 4;                                                \
267         c2 += 4;                                                \
268         c3 += 4;                                                \
269       }                                                         \
270       break;                                                    \
271     }                                                           \
272     case 5:                                                     \
273     case 6:                                                     \
274     {                                                           \
275       mlib_s32 bits3 = bits * 4 - 8;                            \
276       mlib_s32 bits2 = bits3 - bits;                            \
277       mlib_s32 bits1 = bits2 - bits;                            \
278       mlib_s32 bits0 = 8 - bits;                                \
279                                                                 \
280       for( j = 0; j < length; j++ )                             \
281       {                                                         \
282         dst[ j ] = table[ ( ( *c0 & mask ) << bits3 ) |         \
283           ( ( *c1 & mask ) << bits2 ) |                         \
284           ( ( *c2 & mask ) << bits1 ) |                         \
285           ( ( *c3 & mask ) >> bits0 ) ];                        \
286                                                                 \
287         c0 += 4;                                                \
288         c1 += 4;                                                \
289         c2 += 4;                                                \
290         c3 += 4;                                                \
291       }                                                         \
292       break;                                                    \
293     }                                                           \
294     case 7:                                                     \
295     {                                                           \
296       for( j = 0; j < length; j++ )                             \
297       {                                                         \
298         dst[ j ] = table[ ( ( *c0 & mask ) << 20 ) |            \
299           ( ( *c1 & mask ) << 13 ) |                            \
300           ( ( *c2 & mask ) << 6 ) |                             \
301           ( ( *c3 & mask ) >> 1 ) ];                            \
302                                                                 \
303         c0 += 4;                                                \
304         c1 += 4;                                                \
305         c2 += 4;                                                \
306         c3 += 4;                                                \
307       }                                                         \
308       break;                                                    \
309     }                                                           \
310     case 8: /* will never be called */                          \
311     {                                                           \
312       for( j = 0; j < length; j++ )                             \
313       {                                                         \
314         dst[ j ] = table[ ( ( *c0 & mask ) << 24 ) |            \
315           ( ( *c1 & mask ) << 16 ) |                            \
316           ( ( *c2 & mask ) << 8 ) |                             \
317           ( *c3 & mask ) ];                                     \
318                                                                 \
319         c0 += 4;                                                \
320         c1 += 4;                                                \
321         c2 += 4;                                                \
322         c3 += 4;                                                \
323       }                                                         \
324       break;                                                    \
325     }                                                           \
326   }                                                             \
327 }
328 
329 /***************************************************************/
330 #define COLOR_CUBE_S16_3_SEARCH( TABLE_TYPE, SHIFT, STEP )                 \
331 {                                                                          \
332   const mlib_s16 *c0, *c1, *c2;                                            \
333   mlib_s32 bits = s->bits;                                                 \
334   mlib_s32 nbits = 16 - bits;                                              \
335   mlib_s32 mask = ~( ( 1 << nbits ) - 1 );                                 \
336   TABLE_TYPE *table = s->table;                                            \
337   mlib_s32 j;                                                              \
338                                                                            \
339   c0 = src + SHIFT;                                                        \
340   c1 = src + 1 + SHIFT;                                                    \
341   c2 = src + 2 + SHIFT;                                                    \
342                                                                            \
343   switch( bits )                                                           \
344   {                                                                        \
345     case 1:                                                                \
346     case 2:                                                                \
347     case 3:                                                                \
348     case 4:                                                                \
349     case 5:                                                                \
350     {                                                                      \
351       mlib_s32 bits0 = 16 - bits;                                          \
352       mlib_s32 bits1 = bits0 - bits;                                       \
353       mlib_s32 bits2 = bits1 - bits;                                       \
354                                                                            \
355       for( j = 0; j < length; j++ )                                        \
356       {                                                                    \
357         dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) >> bits2 ) | \
358           ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> bits1 ) |                 \
359           ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits0 ) ];                \
360                                                                            \
361         c0 += STEP;                                                        \
362         c1 += STEP;                                                        \
363         c2 += STEP;                                                        \
364       }                                                                    \
365       break;                                                               \
366     }                                                                      \
367     case 6:                                                                \
368     case 7:                                                                \
369     {                                                                      \
370       mlib_s32 bits0 = 16 - bits;                                          \
371       mlib_s32 bits1 = bits0 - bits;                                       \
372       mlib_s32 bits2 = bits * 3 - 16;                                      \
373                                                                            \
374       for( j = 0; j < length; j++ )                                        \
375       {                                                                    \
376         dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << bits2 ) | \
377           ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> bits1 ) |                 \
378           ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits0 ) ];                \
379                                                                            \
380         c0 += STEP;                                                        \
381         c1 += STEP;                                                        \
382         c2 += STEP;                                                        \
383       }                                                                    \
384       break;                                                               \
385     }                                                                      \
386     case 8:                                                                \
387     {                                                                      \
388       for( j = 0; j < length; j++ )                                        \
389       {                                                                    \
390         dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << 8 ) |     \
391           ( ( *c1 - MLIB_S16_MIN ) & mask ) |                              \
392           ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> 8 ) ];                    \
393                                                                            \
394         c0 += STEP;                                                        \
395         c1 += STEP;                                                        \
396         c2 += STEP;                                                        \
397       }                                                                    \
398       break;                                                               \
399     }                                                                      \
400     case 9:                                                                \
401     case 10:                                                               \
402     {                                                                      \
403       mlib_s32 bits0 = 16 - bits;                                          \
404       mlib_s32 bits1 = 2 * bits - 16;                                      \
405       mlib_s32 bits2 = bits1 + bits;                                       \
406                                                                            \
407       for( j = 0; j < length; j++ )                                        \
408       {                                                                    \
409         dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << bits2 ) | \
410           ( ( ( *c1 - MLIB_S16_MIN ) & mask ) << bits1 ) |                 \
411           ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits0 ) ];                \
412                                                                            \
413         c0 += STEP;                                                        \
414         c1 += STEP;                                                        \
415         c2 += STEP;                                                        \
416       }                                                                    \
417       break;                                                               \
418     }                                                                      \
419     /* Other cases may not be considered as the table size will be more    \
420        than 2^32 */                                                        \
421   }                                                                        \
422 }
423 
424 /***************************************************************/
425 #define COLOR_CUBE_S16_4_SEARCH( TABLE_TYPE )                              \
426 {                                                                          \
427   const mlib_s16 *c0, *c1, *c2, *c3;                                       \
428   TABLE_TYPE *table = s->table;                                            \
429   mlib_s32 bits = s->bits;                                                 \
430   mlib_s32 nbits = 16 - bits;                                              \
431   mlib_s32 mask = ~( ( 1 << nbits ) - 1 );                                 \
432   mlib_s32 j;                                                              \
433                                                                            \
434   c0 = src;                                                                \
435   c1 = src + 1;                                                            \
436   c2 = src + 2;                                                            \
437   c3 = src + 3;                                                            \
438                                                                            \
439   switch( bits )                                                           \
440   {                                                                        \
441     case 1:                                                                \
442     case 2:                                                                \
443     case 3:                                                                \
444     {                                                                      \
445       mlib_s32 bits0 = 16 - bits;                                          \
446       mlib_s32 bits1 = bits0 - bits;                                       \
447       mlib_s32 bits2 = bits1 - bits;                                       \
448       mlib_s32 bits3 = bits2 - bits;                                       \
449                                                                            \
450       for( j = 0; j < length; j++ )                                        \
451       {                                                                    \
452         dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) >> bits3 ) | \
453           ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> bits2 ) |                 \
454           ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits1 ) |                 \
455           ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> bits0 ) ];                \
456                                                                            \
457         c0 += 4;                                                           \
458         c1 += 4;                                                           \
459         c2 += 4;                                                           \
460         c3 += 4;                                                           \
461       }                                                                    \
462       break;                                                               \
463     }                                                                      \
464     case 4:                                                                \
465     {                                                                      \
466       for( j = 0; j < length; j++ )                                        \
467       {                                                                    \
468         dst[ j ] = table[ ( ( *c0 - MLIB_S16_MIN ) & mask ) |              \
469           ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> 4 ) |                     \
470           ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> 8 ) |                     \
471           ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> 12 ) ];                   \
472                                                                            \
473         c0 += 4;                                                           \
474         c1 += 4;                                                           \
475         c2 += 4;                                                           \
476         c3 += 4;                                                           \
477       }                                                                    \
478       break;                                                               \
479     }                                                                      \
480     case 5:                                                                \
481     {                                                                      \
482       for( j = 0; j < length; j++ )                                        \
483       {                                                                    \
484         dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << 4 ) |     \
485           ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> 1 ) |                     \
486           ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> 6 ) |                     \
487           ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> 11 ) ];                   \
488                                                                            \
489         c0 += 4;                                                           \
490         c1 += 4;                                                           \
491         c2 += 4;                                                           \
492         c3 += 4;                                                           \
493       }                                                                    \
494       break;                                                               \
495     }                                                                      \
496     case 6:                                                                \
497     case 7:                                                                \
498     {                                                                      \
499       mlib_s32 bits0 = 16 - bits;                                          \
500       mlib_s32 bits1 = bits0 - bits;                                       \
501       mlib_s32 bits3 = bits * 4 - 16;                                      \
502       mlib_s32 bits2 = bits3 - bits;                                       \
503                                                                            \
504       for( j = 0; j < length; j++ )                                        \
505       {                                                                    \
506         dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << bits3 ) | \
507           ( ( ( *c1 - MLIB_S16_MIN ) & mask ) << bits2 ) |                 \
508           ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits1 ) |                 \
509           ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> bits0 ) ];                \
510                                                                            \
511         c0 += 4;                                                           \
512         c1 += 4;                                                           \
513         c2 += 4;                                                           \
514         c3 += 4;                                                           \
515       }                                                                    \
516       break;                                                               \
517     }                                                                      \
518     case 8:                                                                \
519     {                                                                      \
520       for( j = 0; j < length; j++ )                                        \
521       {                                                                    \
522         dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << 16 ) |    \
523           ( ( ( *c1 - MLIB_S16_MIN ) & mask ) << 8 ) |                     \
524           ( ( *c2 - MLIB_S16_MIN ) & mask ) |                              \
525           ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> 8 ) ];                    \
526                                                                            \
527         c0 += 4;                                                           \
528         c1 += 4;                                                           \
529         c2 += 4;                                                           \
530         c3 += 4;                                                           \
531       }                                                                    \
532       break;                                                               \
533     }                                                                      \
534     /* Other cases may not be considered as the table size will be more    \
535        than 2^32 */                                                        \
536   }                                                                        \
537 }
538 
539 /***************************************************************/
540 #define BINARY_TREE_SEARCH_RIGHT( POSITION, COLOR_MAX, SHIFT )  \
541 {                                                               \
542   if( ( distance >= ( ( ( position[ POSITION ] + current_size - \
543     c[ POSITION ] ) * ( position[ POSITION ] + current_size -   \
544     c[ POSITION ] ) ) >> SHIFT ) ) &&                           \
545     ( position[ POSITION ] + current_size != COLOR_MAX ) )      \
546     continue_up = 1;                                            \
547 }
548 
549 /***************************************************************/
550 #define BINARY_TREE_EXPLORE_RIGHT_3( POSITION, COLOR_MAX, IMAGE_TYPE,    \
551   FIRST_NEIBOUR, SECOND_NEIBOUR, SUBSTRACTION, SHIFT )                   \
552 {                                                                        \
553   if( distance >= ( ( ( position[ POSITION ] + current_size -            \
554     c[ POSITION ] ) * ( position[ POSITION ] +                           \
555       current_size - c[ POSITION ] ) ) >> SHIFT ) )                      \
556   {                                                                      \
557     if( distance < ( ( ( COLOR_MAX - c[ POSITION ] ) *                   \
558       ( COLOR_MAX - c[ POSITION ] ) ) >> SHIFT ) )                       \
559     {                                                                    \
560       if( distance < ( ( ( position[ POSITION ] +                        \
561         current_size * 2 - c[ POSITION ] ) *                             \
562         ( position[ POSITION ] + current_size * 2 -                      \
563           c[ POSITION ] ) ) >> SHIFT ) )                                 \
564       {                                                                  \
565         /* Check only a part of quadrant */                              \
566         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
567                                                                          \
568         check_neibours[ FIRST_NEIBOUR ] += 1;                            \
569         check_neibours[ SECOND_NEIBOUR ] += 1;                           \
570         check_corner += 1;                                               \
571         if( node->tag & ( 1 << qq ) )                                    \
572         {                                                                \
573           /* Here is another color cell.                                 \
574              Check the distance */                                       \
575           mlib_s32 new_found_color =                                     \
576             node->contents.index[ qq ];                                  \
577           mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
578             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
579             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
580             p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
581                                                                          \
582           if( newdistance < distance )                                   \
583           {                                                              \
584             found_color = new_found_color;                               \
585             distance = newdistance;                                      \
586           }                                                              \
587         }                                                                \
588         else if( node->contents.quadrants[ qq ] )                        \
589           /* Only a part of quadrant needs checking */                   \
590           distance =                                                     \
591             mlib_search_quadrant_part_to_left_##IMAGE_TYPE##_3(          \
592               node->contents.quadrants[ qq ],                            \
593               distance, &found_color, c, p,                              \
594               position[ POSITION ] + current_size, pass - 1, POSITION ); \
595       }                                                                  \
596       else /* Check whole quadrant */                                    \
597       {                                                                  \
598         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
599                                                                          \
600         check_neibours[ FIRST_NEIBOUR ] += 2;                            \
601         check_neibours[ SECOND_NEIBOUR ] += 2;                           \
602         check_corner += 2;                                               \
603         continue_up = 1;                                                 \
604         if( node->tag & ( 1 << qq ) )                                    \
605         {                                                                \
606           /* Here is another color cell.                                 \
607              Check the distance */                                       \
608           mlib_s32 new_found_color =                                     \
609             node->contents.index[ qq ];                                  \
610           mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
611             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
612             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
613             p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
614                                                                          \
615           if( newdistance < distance )                                   \
616           {                                                              \
617             found_color = new_found_color;                               \
618             distance = newdistance;                                      \
619           }                                                              \
620         }                                                                \
621         else if( node->contents.quadrants[ qq ] )                        \
622           /* Here is a full node. Just explore it */                     \
623           distance = mlib_search_quadrant_##IMAGE_TYPE##_3(              \
624             node->contents.quadrants[ qq ],                              \
625             distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], p );         \
626       }                                                                  \
627     }                                                                    \
628     else /* Cell is on the edge of the space */                          \
629     {                                                                    \
630       if( position[ POSITION ] + current_size * 2 ==                     \
631         COLOR_MAX )                                                      \
632       {                                                                  \
633         /* Check only a part of quadrant */                              \
634         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
635                                                                          \
636         check_neibours[ FIRST_NEIBOUR ] += 1;                            \
637         check_neibours[ SECOND_NEIBOUR ] += 1;                           \
638         check_corner += 1;                                               \
639         if( node->tag & ( 1 << qq ) )                                    \
640         {                                                                \
641           /* Here is another color cell.                                 \
642              Check the distance */                                       \
643           mlib_s32 new_found_color =                                     \
644             node->contents.index[ qq ];                                  \
645           mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
646             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
647             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
648             p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
649                                                                          \
650           if( newdistance < distance )                                   \
651           {                                                              \
652             found_color = new_found_color;                               \
653             distance = newdistance;                                      \
654           }                                                              \
655         }                                                                \
656         else if( node->contents.quadrants[ qq ] )                        \
657           /* Only a part of quadrant needs checking */                   \
658           distance =                                                     \
659             mlib_search_quadrant_part_to_left_##IMAGE_TYPE##_3(          \
660               node->contents.quadrants[ qq ],                            \
661               distance, &found_color, c, p,                              \
662               position[ POSITION ] + current_size,                       \
663               pass - 1, POSITION );                                      \
664       }                                                                  \
665       else /* Check whole quadrant */                                    \
666       {                                                                  \
667         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
668                                                                          \
669         check_neibours[ FIRST_NEIBOUR ] += 2;                            \
670         check_neibours[ SECOND_NEIBOUR ] += 2;                           \
671         check_corner += 2;                                               \
672         continue_up = 1;                                                 \
673         if( node->tag & ( 1 << qq ) )                                    \
674         {                                                                \
675           /* Here is another color cell.                                 \
676              Check the distance */                                       \
677           mlib_s32 new_found_color =                                     \
678             node->contents.index[ qq ];                                  \
679           mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
680             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
681             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
682             p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
683                                                                          \
684           if( newdistance < distance )                                   \
685           {                                                              \
686             found_color = new_found_color;                               \
687             distance = newdistance;                                      \
688           }                                                              \
689         }                                                                \
690         else if( node->contents.quadrants[ qq ] )                        \
691           /* Here is a full node. Just explore it */                     \
692           distance = mlib_search_quadrant_##IMAGE_TYPE##_3(              \
693             node->contents.quadrants[ qq ],                              \
694             distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], p );         \
695       }                                                                  \
696     }                                                                    \
697   }                                                                      \
698 }
699 
700 /***************************************************************/
701 #define BINARY_TREE_EXPLORE_RIGHT_4( POSITION, COLOR_MAX, IMAGE_TYPE,    \
702   FIRST_NEIBOUR, SECOND_NEIBOUR, THIRD_NEIBOUR, SUBSTRACTION, SHIFT )    \
703 {                                                                        \
704   if( distance >= ( ( ( position[ POSITION ] + current_size -            \
705     c[ POSITION ] ) * ( position[ POSITION ] +                           \
706       current_size - c[ POSITION ] ) ) >> SHIFT ) )                      \
707   {                                                                      \
708     if( distance < ( ( ( COLOR_MAX - c[ POSITION ] ) *                   \
709       ( COLOR_MAX - c[ POSITION ] ) ) >> SHIFT ) )                       \
710     {                                                                    \
711       if( distance < ( ( ( position[ POSITION ] +                        \
712         current_size * 2 - c[ POSITION ] ) *                             \
713         ( position[ POSITION ] + current_size * 2 -                      \
714           c[ POSITION ] ) ) >> SHIFT ) )                                 \
715       {                                                                  \
716         /* Check only a part of quadrant */                              \
717         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
718                                                                          \
719         check_neibours[ FIRST_NEIBOUR ] += 1;                            \
720         check_neibours[ SECOND_NEIBOUR ] += 1;                           \
721         check_neibours[ THIRD_NEIBOUR ] += 1;                            \
722         if( node->tag & ( 1 << qq ) )                                    \
723         {                                                                \
724           /* Here is another color cell.                                 \
725              Check the distance */                                       \
726           mlib_s32 new_found_color =                                     \
727             node->contents.index[ qq ];                                  \
728           mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
729             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
730             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
731             p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
732             p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
733                                                                          \
734           if( newdistance < distance )                                   \
735           {                                                              \
736             found_color = new_found_color;                               \
737             distance = newdistance;                                      \
738           }                                                              \
739         }                                                                \
740         else if( node->contents.quadrants[ qq ] )                        \
741           /* Only a part of quadrant needs checking */                   \
742           distance =                                                     \
743             mlib_search_quadrant_part_to_left_##IMAGE_TYPE##_4(          \
744               node->contents.quadrants[ qq ],                            \
745               distance, &found_color, c, p,                              \
746               position[ POSITION ] + current_size, pass - 1, POSITION ); \
747       }                                                                  \
748       else /* Check whole quadrant */                                    \
749       {                                                                  \
750         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
751                                                                          \
752         check_neibours[ FIRST_NEIBOUR ] += 2;                            \
753         check_neibours[ SECOND_NEIBOUR ] += 2;                           \
754         check_neibours[ THIRD_NEIBOUR ] += 2;                            \
755         continue_up = 1;                                                 \
756         if( node->tag & ( 1 << qq ) )                                    \
757         {                                                                \
758           /* Here is another color cell.                                 \
759              Check the distance */                                       \
760           mlib_s32 new_found_color =                                     \
761             node->contents.index[ qq ];                                  \
762           mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
763             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
764             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
765             p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
766             p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
767                                                                          \
768           if( newdistance < distance )                                   \
769           {                                                              \
770             found_color = new_found_color;                               \
771             distance = newdistance;                                      \
772           }                                                              \
773         }                                                                \
774         else if( node->contents.quadrants[ qq ] )                        \
775           /* Here is a full node. Just explore it */                     \
776           distance = mlib_search_quadrant_##IMAGE_TYPE##_4(              \
777             node->contents.quadrants[ qq ],                              \
778             distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p ); \
779       }                                                                  \
780     }                                                                    \
781     else /* Cell is on the edge of the space */                          \
782     {                                                                    \
783       if( position[ POSITION ] + current_size * 2 ==                     \
784         COLOR_MAX )                                                      \
785       {                                                                  \
786         /* Check only a part of quadrant */                              \
787         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
788                                                                          \
789         check_neibours[ FIRST_NEIBOUR ] += 1;                            \
790         check_neibours[ SECOND_NEIBOUR ] += 1;                           \
791         check_neibours[ THIRD_NEIBOUR ] += 1;                            \
792         if( node->tag & ( 1 << qq ) )                                    \
793         {                                                                \
794           /* Here is another color cell.                                 \
795              Check the distance */                                       \
796           mlib_s32 new_found_color =                                     \
797             node->contents.index[ qq ];                                  \
798           mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
799             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
800             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
801             p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
802             p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
803                                                                          \
804           if( newdistance < distance )                                   \
805           {                                                              \
806             found_color = new_found_color;                               \
807             distance = newdistance;                                      \
808           }                                                              \
809         }                                                                \
810         else if( node->contents.quadrants[ qq ] )                        \
811           /* Only a part of quadrant needs checking */                   \
812           distance =                                                     \
813             mlib_search_quadrant_part_to_left_##IMAGE_TYPE##_4(          \
814               node->contents.quadrants[ qq ],                            \
815               distance, &found_color, c, p,                              \
816               position[ POSITION ] + current_size,                       \
817               pass - 1, POSITION );                                      \
818       }                                                                  \
819       else /* Check whole quadrant */                                    \
820       {                                                                  \
821         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
822                                                                          \
823         check_neibours[ FIRST_NEIBOUR ] += 2;                            \
824         check_neibours[ SECOND_NEIBOUR ] += 2;                           \
825         check_neibours[ THIRD_NEIBOUR ] += 2;                            \
826         continue_up = 1;                                                 \
827         if( node->tag & ( 1 << qq ) )                                    \
828         {                                                                \
829           /* Here is another color cell.                                 \
830              Check the distance */                                       \
831           mlib_s32 new_found_color =                                     \
832             node->contents.index[ qq ];                                  \
833           mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
834             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
835             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
836             p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
837             p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
838                                                                          \
839           if( newdistance < distance )                                   \
840           {                                                              \
841             found_color = new_found_color;                               \
842             distance = newdistance;                                      \
843           }                                                              \
844         }                                                                \
845         else if( node->contents.quadrants[ qq ] )                        \
846           /* Here is a full node. Just explore it */                     \
847           distance = mlib_search_quadrant_##IMAGE_TYPE##_4(              \
848             node->contents.quadrants[ qq ],                              \
849             distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p ); \
850       }                                                                  \
851     }                                                                    \
852   }                                                                      \
853 }
854 
855 /***************************************************************/
856 #define BINARY_TREE_SEARCH_LEFT( POSITION, SHIFT )                \
857 {                                                                 \
858   if( ( distance > ( ( ( position[ POSITION ] - c[ POSITION ] ) * \
859     ( position[ POSITION ] - c[ POSITION ] ) ) >> SHIFT ) )  &&   \
860     position[ POSITION ] )                                        \
861     continue_up = 1;                                              \
862 }
863 
864 /***************************************************************/
865 #define BINARY_TREE_EXPLORE_LEFT_3( POSITION, IMAGE_TYPE,                \
866   FIRST_NEIBOUR, SECOND_NEIBOUR, SUBSTRACTION, SHIFT )                   \
867 {                                                                        \
868   if( distance >                                                         \
869     ( ( ( c[ POSITION ] - position[ POSITION ] ) *                       \
870     ( c[ POSITION ] - position[ POSITION ] ) ) >> SHIFT ) )              \
871   {                                                                      \
872     if( distance <= ( ( c[ POSITION ] * c[ POSITION ] ) >> SHIFT ) )     \
873     {                                                                    \
874       if( distance <= ( ( ( c[ POSITION ] + current_size -               \
875         position[ POSITION ] ) *                                         \
876         ( c[ POSITION ] + current_size -                                 \
877           position[ POSITION ] ) ) >> SHIFT ) )                          \
878       {                                                                  \
879         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
880                                                                          \
881         check_neibours[ FIRST_NEIBOUR ] += 1;                            \
882         check_neibours[ SECOND_NEIBOUR ] += 1;                           \
883         check_corner += 1;                                               \
884         if( node->tag & ( 1 << qq ) )                                    \
885         {                                                                \
886           /* Here is another color cell.                                 \
887              Check the distance */                                       \
888           mlib_s32 new_found_color =                                     \
889             node->contents.index[ qq ];                                  \
890           mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
891             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
892             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
893             p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
894                                                                          \
895           if( newdistance < distance )                                   \
896           {                                                              \
897             found_color = new_found_color;                               \
898             distance = newdistance;                                      \
899           }                                                              \
900         }                                                                \
901         else if( node->contents.quadrants[ qq ] )                        \
902           /* Only a part of quadrant needs checking */                   \
903           distance =                                                     \
904             mlib_search_quadrant_part_to_right_##IMAGE_TYPE##_3(         \
905               node->contents.quadrants[ qq ],                            \
906               distance, &found_color, c, p,                              \
907               position[ POSITION ] - current_size, pass - 1, POSITION ); \
908       }                                                                  \
909       else /* Check whole quadrant */                                    \
910       {                                                                  \
911         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
912                                                                          \
913         check_neibours[ FIRST_NEIBOUR ] += 2;                            \
914         check_neibours[ SECOND_NEIBOUR ] += 2;                           \
915         check_corner += 2;                                               \
916         continue_up = 1;                                                 \
917         if( node->tag & ( 1 << qq ) )                                    \
918         {                                                                \
919           /* Here is another color cell.                                 \
920              Check the distance */                                       \
921           mlib_s32 new_found_color =                                     \
922             node->contents.index[ qq ];                                  \
923           mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
924             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
925             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
926             p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
927                                                                          \
928           if( newdistance < distance )                                   \
929           {                                                              \
930             found_color = new_found_color;                               \
931             distance = newdistance;                                      \
932           }                                                              \
933         }                                                                \
934         else if( node->contents.quadrants[ qq ] )                        \
935           /* Here is a full node. Just explore it */                     \
936           distance = mlib_search_quadrant_##IMAGE_TYPE##_3(              \
937             node->contents.quadrants[ qq ],                              \
938             distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], p );         \
939       }                                                                  \
940     }                                                                    \
941     else                                                                 \
942     {                                                                    \
943       if( !( position[ POSITION ] - current_size ) )                     \
944       {                                                                  \
945         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
946                                                                          \
947         check_neibours[ FIRST_NEIBOUR ] += 1;                            \
948         check_neibours[ SECOND_NEIBOUR ] += 1;                           \
949         check_corner += 1;                                               \
950         if( node->tag & ( 1 << qq ) )                                    \
951         {                                                                \
952           /* Here is another color cell.                                 \
953              Check the distance */                                       \
954           mlib_s32 new_found_color =                                     \
955             node->contents.index[ qq ];                                  \
956           mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
957             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
958             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
959             p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
960                                                                          \
961           if( newdistance < distance )                                   \
962           {                                                              \
963             found_color = new_found_color;                               \
964             distance = newdistance;                                      \
965           }                                                              \
966         }                                                                \
967         else if( node->contents.quadrants[ qq ] )                        \
968           /* Only a part of quadrant needs checking */                   \
969           distance =                                                     \
970             mlib_search_quadrant_part_to_right_##IMAGE_TYPE##_3(         \
971               node->contents.quadrants[ qq ],                            \
972               distance, &found_color, c, p,                              \
973               position[ POSITION ] - current_size, pass - 1, POSITION ); \
974       }                                                                  \
975       else                                                               \
976       {                                                                  \
977         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
978                                                                          \
979         check_neibours[ FIRST_NEIBOUR ] += 2;                            \
980         check_neibours[ SECOND_NEIBOUR ] += 2;                           \
981         check_corner += 2;                                               \
982         continue_up = 1;                                                 \
983         if( node->tag & ( 1 << qq ) )                                    \
984         {                                                                \
985           /* Here is another color cell.                                 \
986              Check the distance */                                       \
987           mlib_s32 new_found_color =                                     \
988             node->contents.index[ qq ];                                  \
989           mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
990             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
991             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
992             p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
993                                                                          \
994           if( newdistance < distance )                                   \
995           {                                                              \
996             found_color = new_found_color;                               \
997             distance = newdistance;                                      \
998           }                                                              \
999         }                                                                \
1000         else if( node->contents.quadrants[ qq ] )                        \
1001           /* Here is a full node. Just explore it */                     \
1002           distance = mlib_search_quadrant_##IMAGE_TYPE##_3(              \
1003             node->contents.quadrants[ qq ],                              \
1004             distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], p );         \
1005       }                                                                  \
1006     }                                                                    \
1007   }                                                                      \
1008 }
1009 
1010 /***************************************************************/
1011 #define BINARY_TREE_EXPLORE_LEFT_4( POSITION, IMAGE_TYPE,                \
1012   FIRST_NEIBOUR, SECOND_NEIBOUR, THIRD_NEIBOUR, SUBSTRACTION, SHIFT )    \
1013 {                                                                        \
1014   if( distance >                                                         \
1015     ( ( ( c[ POSITION ] - position[ POSITION ] ) *                       \
1016     ( c[ POSITION ] - position[ POSITION ] ) ) >> SHIFT ) )              \
1017   {                                                                      \
1018     if( distance <= ( ( c[ POSITION ] * c[ POSITION ] ) >> SHIFT ) )     \
1019     {                                                                    \
1020       if( distance <= ( ( ( c[ POSITION ] + current_size -               \
1021         position[ POSITION ] ) *                                         \
1022         ( c[ POSITION ] + current_size -                                 \
1023           position[ POSITION ] ) ) >> SHIFT ) )                          \
1024       {                                                                  \
1025         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
1026                                                                          \
1027         check_neibours[ FIRST_NEIBOUR ] += 1;                            \
1028         check_neibours[ SECOND_NEIBOUR ] += 1;                           \
1029         check_neibours[ THIRD_NEIBOUR ] += 1;                            \
1030         if( node->tag & ( 1 << qq ) )                                    \
1031         {                                                                \
1032           /* Here is another color cell.                                 \
1033              Check the distance */                                       \
1034           mlib_s32 new_found_color =                                     \
1035             node->contents.index[ qq ];                                  \
1036           mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
1037             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
1038             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
1039             p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
1040             p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
1041                                                                          \
1042           if( newdistance < distance )                                   \
1043           {                                                              \
1044             found_color = new_found_color;                               \
1045             distance = newdistance;                                      \
1046           }                                                              \
1047         }                                                                \
1048         else if( node->contents.quadrants[ qq ] )                        \
1049           /* Only a part of quadrant needs checking */                   \
1050           distance =                                                     \
1051             mlib_search_quadrant_part_to_right_##IMAGE_TYPE##_4(         \
1052               node->contents.quadrants[ qq ],                            \
1053               distance, &found_color, c, p,                              \
1054               position[ POSITION ] - current_size, pass - 1, POSITION ); \
1055       }                                                                  \
1056       else /* Check whole quadrant */                                    \
1057       {                                                                  \
1058         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
1059                                                                          \
1060         check_neibours[ FIRST_NEIBOUR ] += 2;                            \
1061         check_neibours[ SECOND_NEIBOUR ] += 2;                           \
1062         check_neibours[ THIRD_NEIBOUR ] += 2;                            \
1063         continue_up = 1;                                                 \
1064         if( node->tag & ( 1 << qq ) )                                    \
1065         {                                                                \
1066           /* Here is another color cell.                                 \
1067              Check the distance */                                       \
1068           mlib_s32 new_found_color =                                     \
1069             node->contents.index[ qq ];                                  \
1070           mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
1071             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
1072             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
1073             p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
1074             p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
1075                                                                          \
1076           if( newdistance < distance )                                   \
1077           {                                                              \
1078             found_color = new_found_color;                               \
1079             distance = newdistance;                                      \
1080           }                                                              \
1081         }                                                                \
1082         else if( node->contents.quadrants[ qq ] )                        \
1083           /* Here is a full node. Just explore it */                     \
1084           distance = mlib_search_quadrant_##IMAGE_TYPE##_4(              \
1085             node->contents.quadrants[ qq ],                              \
1086             distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p ); \
1087       }                                                                  \
1088     }                                                                    \
1089     else                                                                 \
1090     {                                                                    \
1091       if( !( position[ POSITION ] - current_size ) )                     \
1092       {                                                                  \
1093         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
1094                                                                          \
1095         check_neibours[ FIRST_NEIBOUR ] += 1;                            \
1096         check_neibours[ SECOND_NEIBOUR ] += 1;                           \
1097         check_neibours[ THIRD_NEIBOUR ] += 1;                            \
1098         if( node->tag & ( 1 << qq ) )                                    \
1099         {                                                                \
1100           /* Here is another color cell.                                 \
1101              Check the distance */                                       \
1102           mlib_s32 new_found_color =                                     \
1103             node->contents.index[ qq ];                                  \
1104           mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
1105             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
1106             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
1107             p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
1108             p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
1109                                                                          \
1110           if( newdistance < distance )                                   \
1111           {                                                              \
1112             found_color = new_found_color;                               \
1113             distance = newdistance;                                      \
1114           }                                                              \
1115         }                                                                \
1116         else if( node->contents.quadrants[ qq ] )                        \
1117           /* Only a part of quadrant needs checking */                   \
1118           distance =                                                     \
1119             mlib_search_quadrant_part_to_right_##IMAGE_TYPE##_4(         \
1120               node->contents.quadrants[ qq ],                            \
1121               distance, &found_color, c, p,                              \
1122               position[ POSITION ] - current_size, pass - 1, POSITION ); \
1123       }                                                                  \
1124       else                                                               \
1125       {                                                                  \
1126         mlib_s32 qq = q ^ ( 1 << POSITION );                             \
1127                                                                          \
1128         check_neibours[ FIRST_NEIBOUR ] += 2;                            \
1129         check_neibours[ SECOND_NEIBOUR ] += 2;                           \
1130         check_neibours[ THIRD_NEIBOUR ] += 2;                            \
1131         continue_up = 1;                                                 \
1132         if( node->tag & ( 1 << qq ) )                                    \
1133         {                                                                \
1134           /* Here is another color cell.                                 \
1135              Check the distance */                                       \
1136           mlib_s32 new_found_color =                                     \
1137             node->contents.index[ qq ];                                  \
1138           mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
1139             p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
1140             p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
1141             p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
1142             p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
1143                                                                          \
1144           if( newdistance < distance )                                   \
1145           {                                                              \
1146             found_color = new_found_color;                               \
1147             distance = newdistance;                                      \
1148           }                                                              \
1149         }                                                                \
1150         else if( node->contents.quadrants[ qq ] )                        \
1151           /* Here is a full node. Just explore it */                     \
1152           distance = mlib_search_quadrant_##IMAGE_TYPE##_4(              \
1153             node->contents.quadrants[ qq ],                              \
1154             distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p ); \
1155       }                                                                  \
1156     }                                                                    \
1157   }                                                                      \
1158 }
1159 
1160 /***************************************************************/
1161 #define CHECK_QUADRANT_U8_3( qq )                               \
1162 {                                                               \
1163   if( node->tag & ( 1 << qq ) )                                 \
1164   {                                                             \
1165     /* Here is another color cell. Check the distance */        \
1166     mlib_s32 new_found_color = node->contents.index[ qq ];      \
1167     mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],             \
1168       p[ 0 ][ new_found_color ], c[ 1 ],                        \
1169       p[ 1 ][ new_found_color ], c[ 2 ],                        \
1170       p[ 2 ][ new_found_color ], 0 );                           \
1171                                                                 \
1172     if( newdistance < distance )                                \
1173     {                                                           \
1174       found_color = new_found_color;                            \
1175       distance = newdistance;                                   \
1176     }                                                           \
1177   }                                                             \
1178   else if( node->contents.quadrants[ qq ] )                     \
1179     /* Here is a full node. Just explore it all */              \
1180     distance = mlib_search_quadrant_U8_3(                       \
1181       node->contents.quadrants[ qq ], distance, &found_color,   \
1182       c[ 0 ], c[ 1 ], c[ 2 ], p );                              \
1183 /* Else there is just an empty cell */                          \
1184 }
1185 
1186 /***************************************************************/
1187 #define CHECK_QUADRANT_S16_3( qq )                              \
1188 {                                                               \
1189   if( node->tag & ( 1 << qq ) )                                 \
1190   {                                                             \
1191     /* Here is another color cell. Check the distance */        \
1192     mlib_s32 new_found_color = node->contents.index[ qq ];      \
1193     mlib_u32 palc0, palc1, palc2, newdistance;                  \
1194                                                                 \
1195     palc0 = p[ 0 ][ new_found_color ] - MLIB_S16_MIN;           \
1196     palc1 = p[ 1 ][ new_found_color ] - MLIB_S16_MIN;           \
1197     palc2 = p[ 2 ][ new_found_color ] - MLIB_S16_MIN;           \
1198                                                                 \
1199     newdistance = FIND_DISTANCE_3( c[ 0 ], palc0,               \
1200       c[ 1 ], palc1,                                            \
1201       c[ 2 ], palc2, 2 );                                       \
1202                                                                 \
1203     if( newdistance < distance )                                \
1204     {                                                           \
1205       found_color = new_found_color;                            \
1206       distance = newdistance;                                   \
1207     }                                                           \
1208   }                                                             \
1209   else if( node->contents.quadrants[ qq ] )                     \
1210     /* Here is a full node. Just explore it all */              \
1211     distance = mlib_search_quadrant_S16_3(                      \
1212       node->contents.quadrants[ qq ], distance, &found_color,   \
1213       c[ 0 ], c[ 1 ], c[ 2 ], p );                              \
1214 /* Else there is just an empty cell */                          \
1215 }
1216 
1217 /***************************************************************/
1218 #define BINARY_TREE_SEARCH_3( SOURCE_IMAGE, POINTER_TYPE, BITS,              \
1219   COLOR_MAX, SUBTRACTION, POINTER_SHIFT, STEP, SHIFT )                       \
1220 {                                                                            \
1221   const POINTER_TYPE *channels[ 3 ], *p[ 3 ];                                \
1222   mlib_u32 c[ 3 ];                                                           \
1223   mlib_s32 j;                                                                \
1224                                                                              \
1225   p[ 0 ] = s->lut[ 0 ];                                                      \
1226   p[ 1 ] = s->lut[ 1 ];                                                      \
1227   p[ 2 ] = s->lut[ 2 ];                                                      \
1228   channels[ 0 ] = src + POINTER_SHIFT;                                       \
1229   channels[ 1 ] = src + 1 + POINTER_SHIFT;                                   \
1230   channels[ 2 ] = src + 2 + POINTER_SHIFT;                                   \
1231                                                                              \
1232   for( j = 0; j < length; j++ )                                              \
1233   {                                                                          \
1234     mlib_s32 pass = BITS - 1;                                                \
1235     mlib_u32 position[ 3 ] = { 0, 0, 0 };                                    \
1236     mlib_s32 we_found_it = 0;                                                \
1237     struct lut_node_3 *node = s->table;                                      \
1238     /* Stack pointer pointers to the first free element of stack. */         \
1239     /* The node we are in is in the `node' */                                \
1240     struct                                                                   \
1241     {                                                                        \
1242       struct lut_node_3 *node;                                               \
1243       mlib_s32 q;                                                            \
1244     } stack[ BITS ];                                                         \
1245     mlib_s32 stack_pointer = 0;                                              \
1246                                                                              \
1247     c[ 0 ] = *channels[ 0 ] - SUBTRACTION;                                   \
1248     c[ 1 ] = *channels[ 1 ] - SUBTRACTION;                                   \
1249     c[ 2 ] = *channels[ 2 ] - SUBTRACTION;                                   \
1250                                                                              \
1251     do                                                                       \
1252     {                                                                        \
1253       mlib_s32 q;                                                            \
1254       mlib_u32 current_size = 1 << pass;                                     \
1255                                                                              \
1256       q = ( ( c[ 0 ] >> pass ) & 1 ) |                                       \
1257         ( ( ( c[ 1 ] << 1 ) >> pass ) & 2 ) |                                \
1258         ( ( ( c[ 2 ] << 2 ) >> pass ) & 4 );                                 \
1259                                                                              \
1260       position[ 0 ] |= c[ 0 ] & current_size;                                \
1261       position[ 1 ] |= c[ 1 ] & current_size;                                \
1262       position[ 2 ] |= c[ 2 ] & current_size;                                \
1263                                                                              \
1264       if( node->tag & ( 1 << q ) )                                           \
1265       {                                                                      \
1266         /*                                                                   \
1267           Here is a cell with one color. We need to be sure it's             \
1268           the one that is the closest to our color                           \
1269         */                                                                   \
1270         mlib_s32 palindex = node->contents.index[ q ];                       \
1271         mlib_u32 palc[ 3 ];                                                  \
1272         mlib_s32 identical;                                                  \
1273                                                                              \
1274         palc[ 0 ] = p[ 0 ][ palindex ] - SUBTRACTION;                        \
1275         palc[ 1 ] = p[ 1 ][ palindex ] - SUBTRACTION;                        \
1276         palc[ 2 ] = p[ 2 ][ palindex ] - SUBTRACTION;                        \
1277                                                                              \
1278         identical = ( palc[ 0 ] - c[ 0 ] ) | ( palc[ 1 ] - c[ 1 ] ) |        \
1279           ( palc[ 2 ] - c[ 2 ] );                                            \
1280                                                                              \
1281         if( !identical || BITS - pass == bits )                              \
1282         {                                                                    \
1283           /* Oh, here it is :) */                                            \
1284           dst[ j ] = palindex + s->offset;                                   \
1285           we_found_it = 1;                                                   \
1286         }                                                                    \
1287         else                                                                 \
1288         {                                                                    \
1289           mlib_u32 distance;                                                 \
1290           /* First index is the channel, second is the number of the         \
1291              side */                                                         \
1292           mlib_s32 found_color;                                              \
1293           mlib_s32 continue_up;                                              \
1294                                                                              \
1295           distance = FIND_DISTANCE_3( c[ 0 ], palc[ 0 ],                     \
1296             c[ 1 ], palc[ 1 ], c[ 2 ], palc[ 2 ], SHIFT );                   \
1297           found_color = palindex;                                            \
1298                                                                              \
1299           do                                                                 \
1300           {                                                                  \
1301             mlib_s32 check_corner;                                           \
1302                                                                              \
1303             /*                                                               \
1304               Neibours are enumerated in a cicle:                            \
1305               0 - between quadrants 0 and 1,                                 \
1306               1 - between quadrants 1 and 2 and                              \
1307               2 - between quadrants 2 and 0                                  \
1308             */                                                               \
1309             mlib_s32 check_neibours[ 3 ];                                    \
1310                                                                              \
1311             /*                                                               \
1312               Others are three two neibour quadrants                         \
1313                                                                              \
1314               Side number is [ <number of the coordinate >][ <the bit        \
1315               in the quadrant number of the corner, corresponding to         \
1316               this coordinate> ], e.g. 2 is 0..010b, so the sides it has     \
1317               near are:                                                      \
1318               [ 0 (coordinate number) ][ 0 (bit 0 in the number) ]           \
1319               [ 1 (coordinate number) ][ 1 (bit 1 in the number) ]           \
1320                                                                              \
1321               Now we can look in the three nearest quadrants. Do             \
1322               we really need it ? Check it.                                  \
1323             */                                                               \
1324                                                                              \
1325             check_corner = check_neibours[ 0 ] = check_neibours[ 1 ] =       \
1326               check_neibours[ 2 ] = 0;                                       \
1327             continue_up = 0;                                                 \
1328                                                                              \
1329             if( q & 1 )                                                      \
1330             {                                                                \
1331               BINARY_TREE_EXPLORE_LEFT_3( 0, SOURCE_IMAGE, 2, 0,             \
1332                 SUBTRACTION, SHIFT );                                        \
1333             }                                                                \
1334             else                                                             \
1335             {                                                                \
1336               BINARY_TREE_EXPLORE_RIGHT_3( 0, COLOR_MAX, SOURCE_IMAGE, 2, 0, \
1337                 SUBTRACTION, SHIFT );                                        \
1338             }                                                                \
1339                                                                              \
1340             if( q & 2 )                                                      \
1341             {                                                                \
1342               BINARY_TREE_EXPLORE_LEFT_3( 1, SOURCE_IMAGE, 0, 1,             \
1343                 SUBTRACTION, SHIFT );                                        \
1344             }                                                                \
1345             else                                                             \
1346             {                                                                \
1347               BINARY_TREE_EXPLORE_RIGHT_3( 1, COLOR_MAX, SOURCE_IMAGE, 0, 1, \
1348                 SUBTRACTION, SHIFT );                                        \
1349             }                                                                \
1350                                                                              \
1351             if( q & 4 )                                                      \
1352             {                                                                \
1353               BINARY_TREE_EXPLORE_LEFT_3( 2, SOURCE_IMAGE, 1, 2,             \
1354                 SUBTRACTION, SHIFT );                                        \
1355             }                                                                \
1356             else                                                             \
1357             {                                                                \
1358               BINARY_TREE_EXPLORE_RIGHT_3( 2, COLOR_MAX, SOURCE_IMAGE, 1, 2, \
1359                 SUBTRACTION, SHIFT );                                        \
1360             }                                                                \
1361                                                                              \
1362             if( check_neibours[ 0 ] >= 2 )                                   \
1363             {                                                                \
1364               mlib_s32 qq = q ^ 3;                                           \
1365               CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq );                       \
1366             }                                                                \
1367                                                                              \
1368             if( check_neibours[ 1 ] >= 2 )                                   \
1369             {                                                                \
1370               mlib_s32 qq = q ^ 6;                                           \
1371               CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq );                       \
1372             }                                                                \
1373                                                                              \
1374             if( check_neibours[ 2 ] >= 2 )                                   \
1375             {                                                                \
1376               mlib_s32 qq = q ^ 5;                                           \
1377               CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq );                       \
1378             }                                                                \
1379                                                                              \
1380             if( check_corner >= 3 )                                          \
1381             {                                                                \
1382               mlib_s32 qq = q ^ 7;                                           \
1383               CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq );                       \
1384             }                                                                \
1385                                                                              \
1386             if( q & 1 )                                                      \
1387             {                                                                \
1388               BINARY_TREE_SEARCH_RIGHT( 0, COLOR_MAX, SHIFT );               \
1389             }                                                                \
1390             else                                                             \
1391             {                                                                \
1392               BINARY_TREE_SEARCH_LEFT( 0, SHIFT );                           \
1393             }                                                                \
1394                                                                              \
1395             if( q & 2 )                                                      \
1396             {                                                                \
1397               BINARY_TREE_SEARCH_RIGHT( 1, COLOR_MAX, SHIFT );               \
1398             }                                                                \
1399             else                                                             \
1400             {                                                                \
1401               BINARY_TREE_SEARCH_LEFT( 1, SHIFT );                           \
1402             }                                                                \
1403                                                                              \
1404             if( q & 4 )                                                      \
1405             {                                                                \
1406               BINARY_TREE_SEARCH_RIGHT( 2, COLOR_MAX, SHIFT );               \
1407             }                                                                \
1408             else                                                             \
1409             {                                                                \
1410               BINARY_TREE_SEARCH_LEFT( 2, SHIFT );                           \
1411             }                                                                \
1412                                                                              \
1413             position[ 0 ] &= ~( c[ 0 ] & current_size );                     \
1414             position[ 1 ] &= ~( c[ 1 ] & current_size );                     \
1415             position[ 2 ] &= ~( c[ 2 ] & current_size );                     \
1416                                                                              \
1417             current_size <<= 1;                                              \
1418                                                                              \
1419             pass++;                                                          \
1420                                                                              \
1421             stack_pointer--;                                                 \
1422             q = stack[ stack_pointer ].q;                                    \
1423             node = stack[ stack_pointer ].node;                              \
1424           } while( continue_up );                                            \
1425                                                                              \
1426           dst[ j ] = found_color + s->offset;                                \
1427                                                                              \
1428           we_found_it = 1;                                                   \
1429         }                                                                    \
1430       }                                                                      \
1431       else if( node->contents.quadrants[ q ] )                               \
1432       {                                                                      \
1433         /* Descend one level */                                              \
1434         stack[ stack_pointer ].node = node;                                  \
1435         stack[ stack_pointer++ ].q = q;                                      \
1436         node = node->contents.quadrants[ q ];                                \
1437       }                                                                      \
1438       else                                                                   \
1439       {                                                                      \
1440         /* Found the empty quadrant. Look around */                          \
1441         mlib_u32 distance = MLIB_U32_MAX;                                    \
1442         mlib_s32 found_color;                                                \
1443         mlib_s32 continue_up;                                                \
1444                                                                              \
1445         /*                                                                   \
1446           As we had come to this level, it is warranted that there           \
1447           are other points on this level near the empty quadrant             \
1448         */                                                                   \
1449         do                                                                   \
1450         {                                                                    \
1451           mlib_s32 check_corner;                                             \
1452           mlib_s32 check_neibours[ 3 ];                                      \
1453                                                                              \
1454           check_corner = check_neibours[ 0 ] = check_neibours[ 1 ] =         \
1455             check_neibours[ 2 ] = 0;                                         \
1456           continue_up = 0;                                                   \
1457                                                                              \
1458           if( q & 1 )                                                        \
1459           {                                                                  \
1460             BINARY_TREE_EXPLORE_LEFT_3( 0, SOURCE_IMAGE, 2, 0,               \
1461               SUBTRACTION, SHIFT );                                          \
1462           }                                                                  \
1463           else                                                               \
1464           {                                                                  \
1465             BINARY_TREE_EXPLORE_RIGHT_3( 0, COLOR_MAX, SOURCE_IMAGE, 2, 0,   \
1466               SUBTRACTION, SHIFT );                                          \
1467           }                                                                  \
1468                                                                              \
1469           if( q & 2 )                                                        \
1470           {                                                                  \
1471             BINARY_TREE_EXPLORE_LEFT_3( 1, SOURCE_IMAGE, 0, 1,               \
1472               SUBTRACTION, SHIFT );                                          \
1473           }                                                                  \
1474           else                                                               \
1475           {                                                                  \
1476             BINARY_TREE_EXPLORE_RIGHT_3( 1, COLOR_MAX, SOURCE_IMAGE, 0, 1,   \
1477               SUBTRACTION, SHIFT );                                          \
1478           }                                                                  \
1479                                                                              \
1480           if( q & 4 )                                                        \
1481           {                                                                  \
1482             BINARY_TREE_EXPLORE_LEFT_3( 2, SOURCE_IMAGE, 1, 2,               \
1483               SUBTRACTION, SHIFT );                                          \
1484           }                                                                  \
1485           else                                                               \
1486           {                                                                  \
1487             BINARY_TREE_EXPLORE_RIGHT_3( 2, COLOR_MAX, SOURCE_IMAGE, 1, 2,   \
1488               SUBTRACTION, SHIFT );                                          \
1489           }                                                                  \
1490                                                                              \
1491           if( check_neibours[ 0 ] >= 2 )                                     \
1492           {                                                                  \
1493             mlib_s32 qq = q ^ 3;                                             \
1494             CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq );                         \
1495           }                                                                  \
1496                                                                              \
1497           if( check_neibours[ 1 ] >= 2 )                                     \
1498           {                                                                  \
1499             mlib_s32 qq = q ^ 6;                                             \
1500             CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq );                         \
1501           }                                                                  \
1502                                                                              \
1503           if( check_neibours[ 2 ] >= 2 )                                     \
1504           {                                                                  \
1505             mlib_s32 qq = q ^ 5;                                             \
1506             CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq );                         \
1507           }                                                                  \
1508                                                                              \
1509           if( check_corner >= 3 )                                            \
1510           {                                                                  \
1511             mlib_s32 qq = q ^ 7;                                             \
1512             CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq );                         \
1513           }                                                                  \
1514                                                                              \
1515           if( q & 1 )                                                        \
1516           {                                                                  \
1517             BINARY_TREE_SEARCH_RIGHT( 0, COLOR_MAX, SHIFT );                 \
1518           }                                                                  \
1519           else                                                               \
1520           {                                                                  \
1521             BINARY_TREE_SEARCH_LEFT( 0, SHIFT );                             \
1522           }                                                                  \
1523                                                                              \
1524           if( q & 2 )                                                        \
1525           {                                                                  \
1526             BINARY_TREE_SEARCH_RIGHT( 1, COLOR_MAX, SHIFT );                 \
1527           }                                                                  \
1528           else                                                               \
1529           {                                                                  \
1530             BINARY_TREE_SEARCH_LEFT( 1, SHIFT );                             \
1531           }                                                                  \
1532                                                                              \
1533           if( q & 4 )                                                        \
1534           {                                                                  \
1535             BINARY_TREE_SEARCH_RIGHT( 2, COLOR_MAX, SHIFT );                 \
1536           }                                                                  \
1537           else                                                               \
1538           {                                                                  \
1539             BINARY_TREE_SEARCH_LEFT( 2, SHIFT );                             \
1540           }                                                                  \
1541                                                                              \
1542           position[ 0 ] &= ~( c[ 0 ] & current_size );                       \
1543           position[ 1 ] &= ~( c[ 1 ] & current_size );                       \
1544           position[ 2 ] &= ~( c[ 2 ] & current_size );                       \
1545                                                                              \
1546           current_size <<= 1;                                                \
1547                                                                              \
1548           pass++;                                                            \
1549                                                                              \
1550           stack_pointer--;                                                   \
1551           q = stack[ stack_pointer ].q;                                      \
1552           node = stack[ stack_pointer ].node;                                \
1553         } while( continue_up );                                              \
1554                                                                              \
1555         dst[ j ] = found_color + s->offset;                                  \
1556         we_found_it = 1;                                                     \
1557       }                                                                      \
1558                                                                              \
1559       pass--;                                                                \
1560                                                                              \
1561     } while( !we_found_it );                                                 \
1562                                                                              \
1563     channels[ 0 ] += STEP;                                                   \
1564     channels[ 1 ] += STEP;                                                   \
1565     channels[ 2 ] += STEP;                                                   \
1566   }                                                                          \
1567 }
1568 
1569 /***************************************************************/
1570 #define CHECK_QUADRANT_U8_4( qq )                               \
1571 {                                                               \
1572   if( node->tag & ( 1 << qq ) )                                 \
1573   {                                                             \
1574     /* Here is another color cell. Check the distance */        \
1575     mlib_s32 new_found_color = node->contents.index[ qq ];      \
1576     mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],             \
1577       p[ 0 ][ new_found_color ], c[ 1 ],                        \
1578       p[ 1 ][ new_found_color ], c[ 2 ],                        \
1579       p[ 2 ][ new_found_color ], c[ 3 ],                        \
1580       p[ 3 ][ new_found_color ], 0 );                           \
1581                                                                 \
1582     if( newdistance < distance )                                \
1583     {                                                           \
1584       found_color = new_found_color;                            \
1585       distance = newdistance;                                   \
1586     }                                                           \
1587   }                                                             \
1588   else if( node->contents.quadrants[ qq ] )                     \
1589     /* Here is a full node. Just explore it all */              \
1590     distance = mlib_search_quadrant_U8_4(                       \
1591       node->contents.quadrants[ qq ], distance, &found_color,   \
1592       c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p );                      \
1593 /* Else there is just an empty cell */                          \
1594 }
1595 
1596 /***************************************************************/
1597 #define CHECK_QUADRANT_S16_4( qq )                              \
1598 {                                                               \
1599   if( node->tag & ( 1 << qq ) )                                 \
1600   {                                                             \
1601     /* Here is another color cell. Check the distance */        \
1602     mlib_s32 new_found_color = node->contents.index[ qq ];      \
1603     mlib_u32 palc0, palc1, palc2, palc3, newdistance;           \
1604                                                                 \
1605     palc0 = p[ 0 ][ new_found_color ] - MLIB_S16_MIN;           \
1606     palc1 = p[ 1 ][ new_found_color ] - MLIB_S16_MIN;           \
1607     palc2 = p[ 2 ][ new_found_color ] - MLIB_S16_MIN;           \
1608     palc3 = p[ 3 ][ new_found_color ] - MLIB_S16_MIN;           \
1609                                                                 \
1610     newdistance = FIND_DISTANCE_4( c[ 0 ], palc0,               \
1611       c[ 1 ], palc1,                                            \
1612       c[ 2 ], palc2,                                            \
1613       c[ 3 ], palc3, 2 );                                       \
1614                                                                 \
1615     if( newdistance < distance )                                \
1616     {                                                           \
1617       found_color = new_found_color;                            \
1618       distance = newdistance;                                   \
1619     }                                                           \
1620   }                                                             \
1621   else if( node->contents.quadrants[ qq ] )                     \
1622     /* Here is a full node. Just explore it all */              \
1623     distance = mlib_search_quadrant_S16_4(                      \
1624       node->contents.quadrants[ qq ], distance, &found_color,   \
1625       c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p );                      \
1626 /* Else there is just an empty cell */                          \
1627 }
1628 
1629 /***************************************************************/
1630 #define BINARY_TREE_SEARCH_4( SOURCE_IMAGE, POINTER_TYPE, BITS,               \
1631   COLOR_MAX, SUBTRACTION, SHIFT )                                             \
1632 {                                                                             \
1633   const POINTER_TYPE *channels[ 4 ], *p[ 4 ];                                 \
1634   mlib_u32 c[ 4 ];                                                            \
1635   mlib_s32 j;                                                                 \
1636                                                                               \
1637   p[ 0 ] = s->lut[ 0 ];                                                       \
1638   p[ 1 ] = s->lut[ 1 ];                                                       \
1639   p[ 2 ] = s->lut[ 2 ];                                                       \
1640   p[ 3 ] = s->lut[ 3 ];                                                       \
1641   channels[ 0 ] = src;                                                        \
1642   channels[ 1 ] = src + 1;                                                    \
1643   channels[ 2 ] = src + 2;                                                    \
1644   channels[ 3 ] = src + 3;                                                    \
1645                                                                               \
1646   for( j = 0; j < length; j++ )                                               \
1647   {                                                                           \
1648     mlib_s32 pass = BITS - 1;                                                 \
1649     mlib_u32 position[ 4 ] = { 0, 0, 0, 0 };                                  \
1650     mlib_s32 we_found_it = 0;                                                 \
1651     struct lut_node_4 *node = s->table;                                       \
1652     /* Stack pointer pointers to the first free element of stack. */          \
1653     /* The node we are in is in the `node' */                                 \
1654     struct                                                                    \
1655     {                                                                         \
1656       struct lut_node_4 *node;                                                \
1657       mlib_s32 q;                                                             \
1658     } stack[ BITS ];                                                          \
1659     mlib_s32 stack_pointer = 0;                                               \
1660                                                                               \
1661     c[ 0 ] = *channels[ 0 ] - SUBTRACTION;                                    \
1662     c[ 1 ] = *channels[ 1 ] - SUBTRACTION;                                    \
1663     c[ 2 ] = *channels[ 2 ] - SUBTRACTION;                                    \
1664     c[ 3 ] = *channels[ 3 ] - SUBTRACTION;                                    \
1665                                                                               \
1666     do                                                                        \
1667     {                                                                         \
1668       mlib_s32 q;                                                             \
1669       mlib_u32 current_size = 1 << pass;                                      \
1670                                                                               \
1671       q = ( ( c[ 0 ] >> pass ) & 1 ) |                                        \
1672         ( ( ( c[ 1 ] << 1 ) >> pass ) & 2 ) |                                 \
1673         ( ( ( c[ 2 ] << 2 ) >> pass ) & 4 ) |                                 \
1674         ( ( ( c[ 3 ] << 3 ) >> pass ) & 8 );                                  \
1675                                                                               \
1676       position[ 0 ] |= c[ 0 ] & current_size;                                 \
1677       position[ 1 ] |= c[ 1 ] & current_size;                                 \
1678       position[ 2 ] |= c[ 2 ] & current_size;                                 \
1679       position[ 3 ] |= c[ 3 ] & current_size;                                 \
1680                                                                               \
1681       if( node->tag & ( 1 << q ) )                                            \
1682       {                                                                       \
1683         /*                                                                    \
1684           Here is a cell with one color. We need to be sure it's              \
1685           the one that is the closest to our color                            \
1686         */                                                                    \
1687         mlib_s32 palindex = node->contents.index[ q ];                        \
1688         mlib_u32 palc[ 4 ];                                                   \
1689         mlib_s32 identical;                                                   \
1690                                                                               \
1691         palc[ 0 ] = p[ 0 ][ palindex ] - SUBTRACTION;                         \
1692         palc[ 1 ] = p[ 1 ][ palindex ] - SUBTRACTION;                         \
1693         palc[ 2 ] = p[ 2 ][ palindex ] - SUBTRACTION;                         \
1694         palc[ 3 ] = p[ 3 ][ palindex ] - SUBTRACTION;                         \
1695                                                                               \
1696         identical = ( palc[ 0 ] - c[ 0 ] ) | ( palc[ 1 ] - c[ 1 ] ) |         \
1697           ( palc[ 2 ] - c[ 2 ] ) | ( palc[ 3 ] - c[ 3 ] );                    \
1698                                                                               \
1699         if( !identical || BITS - pass == bits )                               \
1700         {                                                                     \
1701           /* Oh, here it is :) */                                             \
1702           dst[ j ] = palindex + s->offset;                                    \
1703           we_found_it = 1;                                                    \
1704         }                                                                     \
1705         else                                                                  \
1706         {                                                                     \
1707           mlib_u32 distance;                                                  \
1708           /* First index is the channel, second is the number of the          \
1709              side */                                                          \
1710           mlib_s32 found_color;                                               \
1711           mlib_s32 continue_up;                                               \
1712                                                                               \
1713           distance = FIND_DISTANCE_4( c[ 0 ], palc[ 0 ],                      \
1714             c[ 1 ], palc[ 1 ], c[ 2 ], palc[ 2 ], c[ 3 ], palc[ 3 ], SHIFT ); \
1715           found_color = palindex;                                             \
1716                                                                               \
1717           do                                                                  \
1718           {                                                                   \
1719             mlib_s32 check_corner;                                            \
1720             mlib_s32 check_neibours[ 6 ];                                     \
1721             mlib_s32 check_far_neibours[ 4 ];                                 \
1722                                                                               \
1723             /*                                                                \
1724               Check neibours: quadrants that are different by 2 bits          \
1725               from the quadrant, that we are in:                              \
1726               3 -  0                                                          \
1727               5 -  1                                                          \
1728               6 -  2                                                          \
1729               9 -  3                                                          \
1730               10 - 4                                                          \
1731               12 - 5                                                          \
1732               Far quadrants: different by 3 bits:                             \
1733               7  - 0                                                          \
1734               11 - 1                                                          \
1735               13 - 2                                                          \
1736               14 - 3                                                          \
1737             */                                                                \
1738                                                                               \
1739             check_neibours[ 0 ] = check_neibours[ 1 ] =                       \
1740               check_neibours[ 2 ] = check_neibours[ 3 ] =                     \
1741               check_neibours[ 4 ] = check_neibours[ 5 ] = 0;                  \
1742             continue_up = 0;                                                  \
1743                                                                               \
1744             if( q & 1 )                                                       \
1745             {                                                                 \
1746               BINARY_TREE_EXPLORE_LEFT_4( 0, SOURCE_IMAGE, 0, 1, 3,           \
1747                 SUBTRACTION, SHIFT );                                         \
1748             }                                                                 \
1749             else                                                              \
1750             {                                                                 \
1751               BINARY_TREE_EXPLORE_RIGHT_4( 0, COLOR_MAX, SOURCE_IMAGE,        \
1752                 0, 1, 3, SUBTRACTION, SHIFT );                                \
1753             }                                                                 \
1754                                                                               \
1755             if( q & 2 )                                                       \
1756             {                                                                 \
1757               BINARY_TREE_EXPLORE_LEFT_4( 1, SOURCE_IMAGE, 0, 2, 4,           \
1758                 SUBTRACTION, SHIFT );                                         \
1759             }                                                                 \
1760             else                                                              \
1761             {                                                                 \
1762               BINARY_TREE_EXPLORE_RIGHT_4( 1, COLOR_MAX, SOURCE_IMAGE,        \
1763                 0, 2, 4, SUBTRACTION, SHIFT );                                \
1764             }                                                                 \
1765                                                                               \
1766             if( q & 4 )                                                       \
1767             {                                                                 \
1768               BINARY_TREE_EXPLORE_LEFT_4( 2, SOURCE_IMAGE, 1, 2, 5,           \
1769                 SUBTRACTION, SHIFT );                                         \
1770             }                                                                 \
1771             else                                                              \
1772             {                                                                 \
1773               BINARY_TREE_EXPLORE_RIGHT_4( 2, COLOR_MAX, SOURCE_IMAGE,        \
1774                 1, 2, 5, SUBTRACTION, SHIFT );                                \
1775             }                                                                 \
1776                                                                               \
1777             if( q & 8 )                                                       \
1778             {                                                                 \
1779               BINARY_TREE_EXPLORE_LEFT_4( 3, SOURCE_IMAGE, 3, 4, 5,           \
1780                 SUBTRACTION, SHIFT );                                         \
1781             }                                                                 \
1782             else                                                              \
1783             {                                                                 \
1784               BINARY_TREE_EXPLORE_RIGHT_4( 3, COLOR_MAX, SOURCE_IMAGE,        \
1785                 3, 4, 5, SUBTRACTION, SHIFT );                                \
1786             }                                                                 \
1787                                                                               \
1788             check_far_neibours[ 0 ] = check_neibours[ 0 ] +                   \
1789               check_neibours[ 1 ] + check_neibours[ 2 ];                      \
1790             check_far_neibours[ 1 ] = check_neibours[ 0 ] +                   \
1791               check_neibours[ 3 ] + check_neibours[ 4 ];                      \
1792             check_far_neibours[ 2 ] = check_neibours[ 1 ] +                   \
1793               check_neibours[ 3 ] + check_neibours[ 5 ];                      \
1794             check_far_neibours[ 3 ] = check_neibours[ 2 ] +                   \
1795               check_neibours[ 4 ] + check_neibours[ 5 ];                      \
1796                                                                               \
1797             check_corner = check_far_neibours[ 0 ] +                          \
1798               check_far_neibours[ 1 ] +                                       \
1799               check_far_neibours[ 2 ] +                                       \
1800               check_far_neibours[ 3 ];                                        \
1801                                                                               \
1802             if( check_neibours[ 0 ] >= 2 )                                    \
1803             {                                                                 \
1804               mlib_s32 qq = q ^ 3;                                            \
1805               CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
1806             }                                                                 \
1807                                                                               \
1808             if( check_neibours[ 1 ] >= 2 )                                    \
1809             {                                                                 \
1810               mlib_s32 qq = q ^ 5;                                            \
1811               CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
1812             }                                                                 \
1813                                                                               \
1814             if( check_neibours[ 2 ] >= 2 )                                    \
1815             {                                                                 \
1816               mlib_s32 qq = q ^ 6;                                            \
1817               CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
1818             }                                                                 \
1819                                                                               \
1820             if( check_neibours[ 3 ] >= 2 )                                    \
1821             {                                                                 \
1822               mlib_s32 qq = q ^ 9;                                            \
1823               CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
1824             }                                                                 \
1825                                                                               \
1826             if( check_neibours[ 4 ] >= 2 )                                    \
1827             {                                                                 \
1828               mlib_s32 qq = q ^ 10;                                           \
1829               CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
1830             }                                                                 \
1831                                                                               \
1832             if( check_neibours[ 5 ] >= 2 )                                    \
1833             {                                                                 \
1834               mlib_s32 qq = q ^ 12;                                           \
1835               CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
1836             }                                                                 \
1837                                                                               \
1838             if( check_far_neibours[ 0 ] >= 3 )                                \
1839             {                                                                 \
1840               mlib_s32 qq = q ^ 7;                                            \
1841               CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
1842             }                                                                 \
1843                                                                               \
1844             if( check_far_neibours[ 1 ] >= 3 )                                \
1845             {                                                                 \
1846               mlib_s32 qq = q ^ 11;                                           \
1847               CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
1848             }                                                                 \
1849                                                                               \
1850             if( check_far_neibours[ 2 ] >= 3 )                                \
1851             {                                                                 \
1852               mlib_s32 qq = q ^ 13;                                           \
1853               CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
1854             }                                                                 \
1855                                                                               \
1856             if( check_far_neibours[ 3 ] >= 3 )                                \
1857             {                                                                 \
1858               mlib_s32 qq = q ^ 14;                                           \
1859               CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
1860             }                                                                 \
1861                                                                               \
1862             if( check_corner >= 4 )                                           \
1863             {                                                                 \
1864               mlib_s32 qq = q ^ 15;                                           \
1865               CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
1866             }                                                                 \
1867                                                                               \
1868             if( q & 1 )                                                       \
1869             {                                                                 \
1870               BINARY_TREE_SEARCH_RIGHT( 0, COLOR_MAX, SHIFT );                \
1871             }                                                                 \
1872             else                                                              \
1873             {                                                                 \
1874               BINARY_TREE_SEARCH_LEFT( 0, SHIFT );                            \
1875             }                                                                 \
1876                                                                               \
1877             if( q & 2 )                                                       \
1878             {                                                                 \
1879               BINARY_TREE_SEARCH_RIGHT( 1, COLOR_MAX, SHIFT );                \
1880             }                                                                 \
1881             else                                                              \
1882             {                                                                 \
1883               BINARY_TREE_SEARCH_LEFT( 1, SHIFT );                            \
1884             }                                                                 \
1885                                                                               \
1886             if( q & 4 )                                                       \
1887             {                                                                 \
1888               BINARY_TREE_SEARCH_RIGHT( 2, COLOR_MAX, SHIFT );                \
1889             }                                                                 \
1890             else                                                              \
1891             {                                                                 \
1892               BINARY_TREE_SEARCH_LEFT( 2, SHIFT );                            \
1893             }                                                                 \
1894                                                                               \
1895             if( q & 8 )                                                       \
1896             {                                                                 \
1897               BINARY_TREE_SEARCH_RIGHT( 3, COLOR_MAX, SHIFT );                \
1898             }                                                                 \
1899             else                                                              \
1900             {                                                                 \
1901               BINARY_TREE_SEARCH_LEFT( 3, SHIFT );                            \
1902             }                                                                 \
1903                                                                               \
1904             position[ 0 ] &= ~( c[ 0 ] & current_size );                      \
1905             position[ 1 ] &= ~( c[ 1 ] & current_size );                      \
1906             position[ 2 ] &= ~( c[ 2 ] & current_size );                      \
1907             position[ 3 ] &= ~( c[ 3 ] & current_size );                      \
1908                                                                               \
1909             current_size <<= 1;                                               \
1910                                                                               \
1911             pass++;                                                           \
1912                                                                               \
1913             stack_pointer--;                                                  \
1914             q = stack[ stack_pointer ].q;                                     \
1915             node = stack[ stack_pointer ].node;                               \
1916           } while( continue_up );                                             \
1917                                                                               \
1918           dst[ j ] = found_color + s->offset;                                 \
1919           we_found_it = 1;                                                    \
1920         }                                                                     \
1921       }                                                                       \
1922       else if( node->contents.quadrants[ q ] )                                \
1923       {                                                                       \
1924         /* Descend one level */                                               \
1925         stack[ stack_pointer ].node = node;                                   \
1926         stack[ stack_pointer++ ].q = q;                                       \
1927         node = node->contents.quadrants[ q ];                                 \
1928       }                                                                       \
1929       else                                                                    \
1930       {                                                                       \
1931         /* Found the empty quadrant. Look around */                           \
1932         mlib_u32 distance = MLIB_U32_MAX;                                     \
1933         mlib_s32 found_color;                                                 \
1934         mlib_s32 continue_up;                                                 \
1935                                                                               \
1936         /*                                                                    \
1937           As we had come to this level, it is warranted that there            \
1938           are other points on this level near the empty quadrant              \
1939         */                                                                    \
1940         do                                                                    \
1941         {                                                                     \
1942           mlib_s32 check_corner;                                              \
1943           mlib_s32 check_neibours[ 6 ];                                       \
1944           mlib_s32 check_far_neibours[ 4 ];                                   \
1945                                                                               \
1946           /*                                                                  \
1947             Check neibours: quadrants that are different by 2 bits            \
1948             from the quadrant, that we are in:                                \
1949             3 -  0                                                            \
1950             5 -  1                                                            \
1951             6 -  2                                                            \
1952             9 -  3                                                            \
1953             10 - 4                                                            \
1954             12 - 5                                                            \
1955             Far quadrants: different by 3 bits:                               \
1956             7  - 0                                                            \
1957             11 - 1                                                            \
1958             13 - 2                                                            \
1959             14 - 3                                                            \
1960           */                                                                  \
1961                                                                               \
1962           check_neibours[ 0 ] = check_neibours[ 1 ] =                         \
1963             check_neibours[ 2 ] = check_neibours[ 3 ] =                       \
1964             check_neibours[ 4 ] = check_neibours[ 5 ] = 0;                    \
1965           continue_up = 0;                                                    \
1966                                                                               \
1967           if( q & 1 )                                                         \
1968           {                                                                   \
1969             BINARY_TREE_EXPLORE_LEFT_4( 0, SOURCE_IMAGE, 0, 1, 3,             \
1970               SUBTRACTION, SHIFT );                                           \
1971           }                                                                   \
1972           else                                                                \
1973           {                                                                   \
1974             BINARY_TREE_EXPLORE_RIGHT_4( 0, COLOR_MAX, SOURCE_IMAGE,          \
1975               0, 1, 3, SUBTRACTION, SHIFT );                                  \
1976           }                                                                   \
1977                                                                               \
1978           if( q & 2 )                                                         \
1979           {                                                                   \
1980             BINARY_TREE_EXPLORE_LEFT_4( 1, SOURCE_IMAGE, 0, 2, 4,             \
1981               SUBTRACTION, SHIFT );                                           \
1982           }                                                                   \
1983           else                                                                \
1984           {                                                                   \
1985             BINARY_TREE_EXPLORE_RIGHT_4( 1, COLOR_MAX, SOURCE_IMAGE,          \
1986               0, 2, 4, SUBTRACTION, SHIFT );                                  \
1987           }                                                                   \
1988                                                                               \
1989           if( q & 4 )                                                         \
1990           {                                                                   \
1991             BINARY_TREE_EXPLORE_LEFT_4( 2, SOURCE_IMAGE, 1, 2, 5,             \
1992               SUBTRACTION, SHIFT );                                           \
1993           }                                                                   \
1994           else                                                                \
1995           {                                                                   \
1996             BINARY_TREE_EXPLORE_RIGHT_4( 2, COLOR_MAX, SOURCE_IMAGE,          \
1997               1, 2, 5, SUBTRACTION, SHIFT );                                  \
1998           }                                                                   \
1999                                                                               \
2000           if( q & 8 )                                                         \
2001           {                                                                   \
2002             BINARY_TREE_EXPLORE_LEFT_4( 3, SOURCE_IMAGE, 3, 4, 5,             \
2003               SUBTRACTION, SHIFT );                                           \
2004           }                                                                   \
2005           else                                                                \
2006           {                                                                   \
2007             BINARY_TREE_EXPLORE_RIGHT_4( 3, COLOR_MAX, SOURCE_IMAGE,          \
2008               3, 4, 5, SUBTRACTION, SHIFT );                                  \
2009           }                                                                   \
2010                                                                               \
2011           check_far_neibours[ 0 ] = check_neibours[ 0 ] +                     \
2012             check_neibours[ 1 ] + check_neibours[ 2 ];                        \
2013           check_far_neibours[ 1 ] = check_neibours[ 0 ] +                     \
2014             check_neibours[ 3 ] + check_neibours[ 4 ];                        \
2015           check_far_neibours[ 2 ] = check_neibours[ 1 ] +                     \
2016             check_neibours[ 3 ] + check_neibours[ 5 ];                        \
2017           check_far_neibours[ 3 ] = check_neibours[ 2 ] +                     \
2018             check_neibours[ 4 ] + check_neibours[ 5 ];                        \
2019                                                                               \
2020           check_corner = check_far_neibours[ 0 ] +                            \
2021             check_far_neibours[ 1 ] +                                         \
2022             check_far_neibours[ 2 ] +                                         \
2023             check_far_neibours[ 3 ];                                          \
2024                                                                               \
2025           if( check_neibours[ 0 ] >= 2 )                                      \
2026           {                                                                   \
2027             mlib_s32 qq = q ^ 3;                                              \
2028             CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
2029           }                                                                   \
2030                                                                               \
2031           if( check_neibours[ 1 ] >= 2 )                                      \
2032           {                                                                   \
2033             mlib_s32 qq = q ^ 5;                                              \
2034             CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
2035           }                                                                   \
2036                                                                               \
2037           if( check_neibours[ 2 ] >= 2 )                                      \
2038           {                                                                   \
2039             mlib_s32 qq = q ^ 6;                                              \
2040             CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
2041           }                                                                   \
2042                                                                               \
2043           if( check_neibours[ 3 ] >= 2 )                                      \
2044           {                                                                   \
2045             mlib_s32 qq = q ^ 9;                                              \
2046             CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
2047           }                                                                   \
2048                                                                               \
2049           if( check_neibours[ 4 ] >= 2 )                                      \
2050           {                                                                   \
2051             mlib_s32 qq = q ^ 10;                                             \
2052             CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
2053           }                                                                   \
2054                                                                               \
2055           if( check_neibours[ 5 ] >= 2 )                                      \
2056           {                                                                   \
2057             mlib_s32 qq = q ^ 12;                                             \
2058             CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
2059           }                                                                   \
2060                                                                               \
2061           if( check_far_neibours[ 0 ] >= 3 )                                  \
2062           {                                                                   \
2063             mlib_s32 qq = q ^ 7;                                              \
2064             CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
2065           }                                                                   \
2066                                                                               \
2067           if( check_far_neibours[ 1 ] >= 3 )                                  \
2068           {                                                                   \
2069             mlib_s32 qq = q ^ 11;                                             \
2070             CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
2071           }                                                                   \
2072                                                                               \
2073           if( check_far_neibours[ 2 ] >= 3 )                                  \
2074           {                                                                   \
2075             mlib_s32 qq = q ^ 13;                                             \
2076             CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
2077           }                                                                   \
2078                                                                               \
2079           if( check_far_neibours[ 3 ] >= 3 )                                  \
2080           {                                                                   \
2081             mlib_s32 qq = q ^ 14;                                             \
2082             CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
2083           }                                                                   \
2084                                                                               \
2085           if( check_corner >= 4 )                                             \
2086           {                                                                   \
2087             mlib_s32 qq = q ^ 15;                                             \
2088             CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
2089           }                                                                   \
2090                                                                               \
2091           if( q & 1 )                                                         \
2092           {                                                                   \
2093             BINARY_TREE_SEARCH_RIGHT( 0, COLOR_MAX, SHIFT );                  \
2094           }                                                                   \
2095           else                                                                \
2096           {                                                                   \
2097             BINARY_TREE_SEARCH_LEFT( 0, SHIFT );                              \
2098           }                                                                   \
2099                                                                               \
2100           if( q & 2 )                                                         \
2101           {                                                                   \
2102             BINARY_TREE_SEARCH_RIGHT( 1, COLOR_MAX, SHIFT );                  \
2103           }                                                                   \
2104           else                                                                \
2105           {                                                                   \
2106             BINARY_TREE_SEARCH_LEFT( 1, SHIFT );                              \
2107           }                                                                   \
2108                                                                               \
2109           if( q & 4 )                                                         \
2110           {                                                                   \
2111             BINARY_TREE_SEARCH_RIGHT( 2, COLOR_MAX, SHIFT );                  \
2112           }                                                                   \
2113           else                                                                \
2114           {                                                                   \
2115             BINARY_TREE_SEARCH_LEFT( 2, SHIFT );                              \
2116           }                                                                   \
2117                                                                               \
2118           if( q & 8 )                                                         \
2119           {                                                                   \
2120             BINARY_TREE_SEARCH_RIGHT( 3, COLOR_MAX, SHIFT );                  \
2121           }                                                                   \
2122           else                                                                \
2123           {                                                                   \
2124             BINARY_TREE_SEARCH_LEFT( 3, SHIFT );                              \
2125           }                                                                   \
2126                                                                               \
2127           position[ 0 ] &= ~( c[ 0 ] & current_size );                        \
2128           position[ 1 ] &= ~( c[ 1 ] & current_size );                        \
2129           position[ 2 ] &= ~( c[ 2 ] & current_size );                        \
2130           position[ 3 ] &= ~( c[ 3 ] & current_size );                        \
2131                                                                               \
2132           current_size <<= 1;                                                 \
2133                                                                               \
2134           pass++;                                                             \
2135                                                                               \
2136           stack_pointer--;                                                    \
2137           q = stack[ stack_pointer ].q;                                       \
2138           node = stack[ stack_pointer ].node;                                 \
2139         } while( continue_up );                                               \
2140                                                                               \
2141         dst[ j ] = found_color + s->offset;                                   \
2142         we_found_it = 1;                                                      \
2143       }                                                                       \
2144                                                                               \
2145       pass--;                                                                 \
2146                                                                               \
2147     } while( !we_found_it );                                                  \
2148                                                                               \
2149     channels[ 0 ] += 4;                                                       \
2150     channels[ 1 ] += 4;                                                       \
2151     channels[ 2 ] += 4;                                                       \
2152     channels[ 3 ] += 4;                                                       \
2153   }                                                                           \
2154 }
2155 
2156 /***************************************************************/
2157 #define FIND_NEAREST_U8_3_C( SHIFT, STEP )                      \
2158   mlib_s32 i, k, k_min, min_dist, diff, mask;                   \
2159   mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1;            \
2160   mlib_s32 entries = s -> lutlength;                            \
2161   mlib_d64 *double_lut = mlib_ImageGetLutDoubleData( s );       \
2162   mlib_d64 col0, col1, col2;                                    \
2163   mlib_d64 dist, len0, len1, len2;                              \
2164                                                                 \
2165   for ( i = 0; i < length; i++ ) {                              \
2166     col0 = src[ STEP * i + SHIFT ];                             \
2167     col1 = src[ STEP * i + 1 + SHIFT ];                         \
2168     col2 = src[ STEP * i + 2 + SHIFT ];                         \
2169     min_dist = MLIB_S32_MAX;                                    \
2170     k_min = 1;                                                  \
2171     len0 = double_lut[ 0 ] - col0;                              \
2172     len1 = double_lut[ 1 ] - col1;                              \
2173     len2 = double_lut[ 2 ] - col2;                              \
2174                                                                 \
2175     for ( k = 1; k <= entries; k++ ) {                          \
2176       dist = len0 * len0;                                       \
2177       len0 = double_lut[ 3 * k ] - col0;                        \
2178       dist += len1 * len1;                                      \
2179       len1 = double_lut[ 3 * k + 1 ] - col1;                    \
2180       dist += len2 * len2;                                      \
2181       len2 = double_lut[ 3 * k + 2 ] - col2;                    \
2182       diff = ( mlib_s32 )dist - min_dist;                       \
2183       mask = diff >> 31;                                        \
2184       min_dist += diff & mask;                                  \
2185       k_min += ( k - k_min ) & mask;                            \
2186     }                                                           \
2187                                                                 \
2188     dst[ i ] = k_min + offset;                                  \
2189   }
2190 
2191 /***************************************************************/
2192 #define FIND_NEAREST_U8_4_C                                     \
2193   mlib_s32 i, k, k_min, min_dist, diff, mask;                   \
2194   mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1;            \
2195   mlib_s32 entries = s -> lutlength;                            \
2196   mlib_d64 *double_lut = mlib_ImageGetLutDoubleData( s );       \
2197   mlib_d64 col0, col1, col2, col3;                              \
2198   mlib_d64 dist, len0, len1, len2, len3;                        \
2199                                                                 \
2200   for ( i = 0; i < length; i++ ) {                              \
2201     col0 = src[ 4 * i ];                                        \
2202     col1 = src[ 4 * i + 1 ];                                    \
2203     col2 = src[ 4 * i + 2 ];                                    \
2204     col3 = src[ 4 * i + 3 ];                                    \
2205     min_dist = MLIB_S32_MAX;                                    \
2206     k_min = 1;                                                  \
2207     len0 = double_lut[ 0 ] - col0;                              \
2208     len1 = double_lut[ 1 ] - col1;                              \
2209     len2 = double_lut[ 2 ] - col2;                              \
2210     len3 = double_lut[ 3 ] - col3;                              \
2211                                                                 \
2212     for ( k = 1; k <= entries; k++ ) {                          \
2213       dist = len0 * len0;                                       \
2214       len0 =  double_lut[ 4 * k ] - col0;                       \
2215       dist += len1 * len1;                                      \
2216       len1 = double_lut[ 4 * k + 1 ] - col1;                    \
2217       dist += len2 * len2;                                      \
2218       len2 =  double_lut[ 4 * k + 2 ] - col2;                   \
2219       dist += len3 * len3;                                      \
2220       len3 =  double_lut[ 4 * k + 3 ] - col3;                   \
2221       diff = ( mlib_s32 )dist - min_dist;                       \
2222       mask = diff >> 31;                                        \
2223       min_dist += diff & mask;                                  \
2224       k_min += ( k - k_min ) & mask;                            \
2225     }                                                           \
2226                                                                 \
2227     dst[ i ] = k_min + offset;                                  \
2228   }
2229 
2230 /***************************************************************/
2231 #define FSQR_S16_HI(dsrc)                                                   \
2232   vis_fpadd32( vis_fmuld8ulx16( vis_read_hi( dsrc ), vis_read_hi( dsrc ) ), \
2233     vis_fmuld8sux16( vis_read_hi( dsrc ), vis_read_hi( dsrc ) ) )
2234 
2235 /***************************************************************/
2236 #define FSQR_S16_LO(dsrc)                                                  \
2237   vis_fpadd32( vis_fmuld8ulx16( vis_read_lo( dsrc ), vis_read_lo( dsrc) ), \
2238     vis_fmuld8sux16( vis_read_lo( dsrc ), vis_read_lo( dsrc ) ) )
2239 
2240 /***************************************************************/
2241 #define FIND_NEAREST_U8_3                                             \
2242 {                                                                     \
2243   mlib_d64 *dpsrc, dsrc, dsrc1, ddist, ddist1, ddist2, ddist3;        \
2244   mlib_d64 dcolor, dind, dres, dres1, dpind[1], dpmin[1];             \
2245   mlib_d64 done = vis_to_double_dup( 1 ),                             \
2246            dmax = vis_to_double_dup( MLIB_S32_MAX );                  \
2247   mlib_f32 *lut = ( mlib_f32 * )mlib_ImageGetLutNormalTable( s );     \
2248   mlib_f32 fone = vis_to_float( 0x100 );                              \
2249   mlib_s32 i, k, mask;                                                \
2250   mlib_s32 gsr[1];                                                    \
2251   mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1;                  \
2252   mlib_s32 entries = s->lutlength;                                    \
2253                                                                       \
2254   gsr[0] = vis_read_gsr();                                            \
2255   for( i = 0; i <= ( length-2 ); i += 2 )                             \
2256   {                                                                   \
2257     dpsrc = VIS_ALIGNADDR( src, -1 );                                 \
2258     src += 6;                                                         \
2259     dsrc = dpsrc[ 0 ];                                                \
2260     dsrc1 = dpsrc[ 1 ];                                               \
2261     dsrc1 = vis_faligndata( dsrc, dsrc1 );                            \
2262     dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone );              \
2263     VIS_ALIGNADDR( dpsrc, 3 );                                        \
2264     dsrc1 = vis_faligndata( dsrc1, dsrc1 );                           \
2265     dsrc1 = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone );             \
2266     dpind[ 0 ] = dind = done;                                         \
2267     dpmin[ 0 ] = dmax;                                                \
2268     dcolor = vis_fmul8x16al( lut[ 0 ], fone );                        \
2269     for( k = 1; k <= entries; k++ )                                   \
2270     {                                                                 \
2271       ddist1 = vis_fpsub16( dcolor, dsrc );                           \
2272       ddist = FSQR_S16_HI( ddist1 );                                  \
2273       ddist1 = FSQR_S16_LO( ddist1 );                                 \
2274       dres = vis_fpadd32( ddist, ddist1 );                            \
2275       ddist3 = vis_fpsub16( dcolor, dsrc1 );                          \
2276       ddist2 = FSQR_S16_HI( ddist3 );                                 \
2277       ddist3 = FSQR_S16_LO( ddist3 );                                 \
2278       dres1 = vis_fpadd32( ddist2, ddist3 );                          \
2279       dcolor = vis_fmul8x16al( lut[ k ], fone );                      \
2280       dres = vis_freg_pair(                                           \
2281         vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ),     \
2282         vis_fpadd32s( vis_read_hi( dres1 ), vis_read_lo( dres1 ) ) ); \
2283       mask = vis_fcmplt32( dres, dpmin[ 0 ] );                        \
2284       vis_pst_32( dind, ( void * )dpind, mask );                      \
2285       dind = vis_fpadd32( dind, done );                               \
2286       vis_pst_32( dres, ( void * )dpmin, mask );                      \
2287     }                                                                 \
2288     dst[ i ] = ( ( mlib_s32 * )dpind )[ 0 ] + offset;                 \
2289     dst[ i + 1 ] = ( ( mlib_s32 * )dpind)[ 1 ] + offset;              \
2290   }                                                                   \
2291   if( i < length )                                                    \
2292   {                                                                   \
2293     dpsrc = VIS_ALIGNADDR( src, -1 );                                 \
2294     dsrc = dpsrc[ 0 ];                                                \
2295     dsrc1 = dpsrc[ 1 ];                                               \
2296     dsrc1 = vis_faligndata( dsrc, dsrc1 );                            \
2297     dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone );              \
2298     dpind[ 0 ] = dind = done;                                         \
2299     dpmin[ 0 ] = dmax;                                                \
2300     for( k = 0; k < entries; k++ )                                    \
2301     {                                                                 \
2302       dcolor = vis_fmul8x16al( lut[ k ], fone );                      \
2303       ddist1 = vis_fpsub16( dcolor, dsrc );                           \
2304       ddist = FSQR_S16_HI( ddist1 );                                  \
2305       ddist1 = FSQR_S16_LO( ddist1 );                                 \
2306       dres = vis_fpadd32( ddist, ddist1 );                            \
2307       dres = vis_write_lo( dres,                                      \
2308         vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ) );   \
2309       mask = vis_fcmplt32( dres, dpmin[ 0 ] );                        \
2310       vis_pst_32( dind, ( void * )dpind, mask );                      \
2311       dind = vis_fpadd32( dind, done );                               \
2312       vis_pst_32( dres, ( void * )dpmin, mask );                      \
2313     }                                                                 \
2314     dst[ i ] = ( ( mlib_s32 * )dpind)[ 1 ] + offset;                  \
2315   }                                                                   \
2316   vis_write_gsr(gsr[0]);                                              \
2317 }
2318 
2319 /***************************************************************/
2320 #define FIND_NEAREST_U8_3_IN4                                         \
2321 {                                                                     \
2322   mlib_d64 *dpsrc, dsrc, dsrc1, ddist, ddist1, ddist2, ddist3;        \
2323   mlib_d64 dcolor, dind, dres, dres1, dpind[1], dpmin[1];             \
2324   mlib_d64 done = vis_to_double_dup( 1 ),                             \
2325            dmax = vis_to_double_dup( MLIB_S32_MAX );                  \
2326   mlib_f32 *lut = ( mlib_f32 * )mlib_ImageGetLutNormalTable( s );     \
2327   mlib_f32 fone = vis_to_float( 0x100 );                              \
2328   mlib_s32 i, k, mask, gsr[1];                                        \
2329   mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1;                  \
2330   mlib_s32 entries = s->lutlength;                                    \
2331                                                                       \
2332   gsr[0] = vis_read_gsr();                                            \
2333   dpsrc = VIS_ALIGNADDR( src, 0 );                                    \
2334   for( i = 0; i <= ( length-2 ); i += 2 )                             \
2335   {                                                                   \
2336     dsrc = dpsrc[ 0 ];                                                \
2337     dsrc1 = dpsrc[ 1 ];                                               \
2338     dsrc1 = vis_faligndata( dsrc, dsrc1 );                            \
2339     dpsrc++;                                                          \
2340     dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone );              \
2341     dsrc1 = vis_fmul8x16al( vis_read_lo( dsrc1 ), fone );             \
2342     dpind[ 0 ] = dind = done;                                         \
2343     dpmin[ 0 ] = dmax;                                                \
2344     dcolor = vis_fmul8x16al( lut[ 0 ], fone );                        \
2345     for( k = 1; k <= entries; k++ )                                   \
2346     {                                                                 \
2347       ddist1 = vis_fpsub16( dcolor, dsrc );                           \
2348       ddist = FSQR_S16_HI( ddist1 );                                  \
2349       ddist1 = FSQR_S16_LO( ddist1 );                                 \
2350       dres = vis_fpadd32( ddist, ddist1 );                            \
2351       ddist3 = vis_fpsub16( dcolor, dsrc1 );                          \
2352       ddist2 = FSQR_S16_HI( ddist3 );                                 \
2353       ddist3 = FSQR_S16_LO( ddist3 );                                 \
2354       dres1 = vis_fpadd32( ddist2, ddist3 );                          \
2355       dcolor = vis_fmul8x16al( lut[ k ], fone );                      \
2356       dres = vis_freg_pair(                                           \
2357         vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ),     \
2358         vis_fpadd32s( vis_read_hi( dres1 ), vis_read_lo( dres1 ) ) ); \
2359       mask = vis_fcmplt32( dres, dpmin[ 0 ] );                        \
2360       vis_pst_32( dind, ( void * )dpind, mask );                      \
2361       dind = vis_fpadd32( dind, done );                               \
2362       vis_pst_32( dres, ( void * )dpmin, mask );                      \
2363     }                                                                 \
2364     dst[ i ] = ( ( mlib_s32 * )dpind )[ 0 ] + offset;                 \
2365     dst[ i + 1 ] = ( ( mlib_s32 * )dpind)[ 1 ] + offset;              \
2366   }                                                                   \
2367   if( i < length )                                                    \
2368   {                                                                   \
2369     dsrc = dpsrc[ 0 ];                                                \
2370     dsrc1 = dpsrc[ 1 ];                                               \
2371     dsrc1 = vis_faligndata( dsrc, dsrc1 );                            \
2372     dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone );              \
2373     dpind[ 0 ] = dind = done;                                         \
2374     dpmin[ 0 ] = dmax;                                                \
2375     for( k = 0; k < entries; k++ )                                    \
2376     {                                                                 \
2377       dcolor = vis_fmul8x16al( lut[ k ], fone );                      \
2378       ddist1 = vis_fpsub16( dcolor, dsrc );                           \
2379       ddist = FSQR_S16_HI( ddist1 );                                  \
2380       ddist1 = FSQR_S16_LO( ddist1 );                                 \
2381       dres = vis_fpadd32( ddist, ddist1 );                            \
2382       dres = vis_write_lo( dres,                                      \
2383         vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ) );   \
2384       mask = vis_fcmplt32( dres, dpmin[ 0 ] );                        \
2385       vis_pst_32( dind, ( void * )dpind, mask );                      \
2386       dind = vis_fpadd32( dind, done );                               \
2387       vis_pst_32( dres, ( void * )dpmin, mask );                      \
2388     }                                                                 \
2389     dst[ i ] = ( ( mlib_s32 * )dpind)[ 1 ] + offset;                  \
2390   }                                                                   \
2391   vis_write_gsr(gsr[0]);                                              \
2392 }
2393 
2394 /***************************************************************/
2395 #define FIND_NEAREST_U8_4                                             \
2396 {                                                                     \
2397   mlib_d64 *dpsrc, dsrc, dsrc1, ddist, ddist1, ddist2, ddist3;        \
2398   mlib_d64 dcolor, dind, dres, dres1, dpind[ 1 ], dpmin[ 1 ];         \
2399   mlib_d64 done = vis_to_double_dup( 1 ),                             \
2400            dmax = vis_to_double_dup( MLIB_S32_MAX );                  \
2401   mlib_f32 *lut = ( mlib_f32 * )mlib_ImageGetLutNormalTable( s );     \
2402   mlib_f32 fone = vis_to_float( 0x100 );                              \
2403   mlib_s32 i, k, mask, gsr[1];                                        \
2404   mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1;                  \
2405   mlib_s32 entries = s->lutlength;                                    \
2406                                                                       \
2407   gsr[0] = vis_read_gsr();                                            \
2408   dpsrc = VIS_ALIGNADDR( src, 0 );                                    \
2409   for( i = 0; i <= ( length-2 ); i += 2 )                             \
2410   {                                                                   \
2411     dsrc = dpsrc[ 0 ];                                                \
2412     dsrc1 = dpsrc[ 1 ];                                               \
2413     dsrc1 = vis_faligndata( dsrc, dsrc1 );                            \
2414     dpsrc++;                                                          \
2415     dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone );              \
2416     dsrc1 = vis_fmul8x16al( vis_read_lo( dsrc1 ), fone );             \
2417     dpind[ 0 ] = dind = done;                                         \
2418     dpmin[ 0 ] = dmax;                                                \
2419     dcolor = vis_fmul8x16al(lut[0], fone);                            \
2420     for( k = 1; k <= entries; k++ )                                   \
2421     {                                                                 \
2422       ddist1 = vis_fpsub16( dcolor, dsrc );                           \
2423       ddist = FSQR_S16_HI( ddist1 );                                  \
2424       ddist1 = FSQR_S16_LO( ddist1 );                                 \
2425       dres = vis_fpadd32( ddist, ddist1 );                            \
2426       ddist3 = vis_fpsub16( dcolor, dsrc1 );                          \
2427       ddist2 = FSQR_S16_HI( ddist3 );                                 \
2428       ddist3 = FSQR_S16_LO( ddist3 );                                 \
2429       dres1 = vis_fpadd32( ddist2, ddist3 );                          \
2430       dcolor = vis_fmul8x16al( lut[ k ], fone );                      \
2431       dres = vis_freg_pair(                                           \
2432         vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ),     \
2433         vis_fpadd32s( vis_read_hi( dres1 ), vis_read_lo( dres1 ) ) ); \
2434       mask = vis_fcmplt32( dres, dpmin[ 0 ] );                        \
2435       vis_pst_32( dind, ( void * )dpind, mask );                      \
2436       dind = vis_fpadd32( dind, done );                               \
2437       vis_pst_32( dres, ( void * )dpmin, mask );                      \
2438     }                                                                 \
2439     dst[ i ] = ( ( mlib_s32 * )dpind )[ 0 ] + offset;                 \
2440     dst[ i + 1 ] = ( ( mlib_s32 * )dpind )[ 1 ] + offset;             \
2441   }                                                                   \
2442   if( i < length )                                                    \
2443   {                                                                   \
2444     dsrc = dpsrc[ 0 ];                                                \
2445     dsrc1 = dpsrc[ 1 ];                                               \
2446     dsrc1 = vis_faligndata( dsrc, dsrc1 );                            \
2447     dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone );              \
2448     dpind[ 0 ] = dind = done;                                         \
2449     dpmin[ 0 ] = dmax;                                                \
2450     for( k = 0; k < entries; k++ )                                    \
2451     {                                                                 \
2452       dcolor = vis_fmul8x16al( lut[ k ], fone );                      \
2453       ddist1 = vis_fpsub16( dcolor, dsrc );                           \
2454       ddist = FSQR_S16_HI( ddist1 );                                  \
2455       ddist1 = FSQR_S16_LO( ddist1 );                                 \
2456       dres = vis_fpadd32( ddist, ddist1 );                            \
2457       dres = vis_write_lo( dres,                                      \
2458         vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ) );   \
2459       mask = vis_fcmplt32( dres, dpmin[ 0 ] );                        \
2460       vis_pst_32( dind, ( void * )dpind, mask );                      \
2461       dind = vis_fpadd32( dind, done );                               \
2462       vis_pst_32( dres, ( void * )dpmin, mask );                      \
2463     }                                                                 \
2464     dst[ i ] = ( ( mlib_s32 * )dpind )[ 1 ] + offset;                 \
2465   }                                                                   \
2466   vis_write_gsr(gsr[0]);                                              \
2467 }
2468 
2469 /***************************************************************/
2470 #define FIND_NEAREST_S16_3( SHIFT, STEP )                       \
2471   mlib_s32 i, k, k_min, min_dist, diff, mask;                   \
2472   mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1;            \
2473   mlib_s32 entries = s->lutlength;                              \
2474   mlib_d64 *double_lut = mlib_ImageGetLutDoubleData( s );       \
2475   mlib_d64 col0, col1, col2;                                    \
2476   mlib_d64 dist, len0, len1, len2;                              \
2477                                                                 \
2478   for( i = 0; i < length; i++ )                                 \
2479   {                                                             \
2480     col0 = src[ STEP * i + SHIFT ];                             \
2481     col1 = src[ STEP * i + 1 + SHIFT ];                         \
2482     col2 = src[ STEP * i + 2 + SHIFT ];                         \
2483     min_dist = MLIB_S32_MAX;                                    \
2484     k_min = 1;                                                  \
2485     len0 = double_lut[ 0 ] - col0;                              \
2486     len1 = double_lut[ 1 ] - col1;                              \
2487     len2 = double_lut[ 2 ] - col2;                              \
2488     for( k = 1; k <= entries; k++ )                             \
2489     {                                                           \
2490       dist = len0 * len0;                                       \
2491       len0 = double_lut[ 3 * k ] - col0;                        \
2492       dist += len1 * len1;                                      \
2493       len1 = double_lut[ 3 * k + 1 ] - col1;                    \
2494       dist += len2 * len2;                                      \
2495       len2 = double_lut[ 3 * k + 2 ] - col2;                    \
2496       diff = ( mlib_s32 )( dist * 0.125 ) - min_dist;           \
2497       mask = diff >> 31;                                        \
2498       min_dist += diff & mask;                                  \
2499       k_min += ( k - k_min ) & mask;                            \
2500     }                                                           \
2501     dst[ i ] = k_min + offset;                                  \
2502   }
2503 
2504 /***************************************************************/
2505 #define FIND_NEAREST_S16_4                                      \
2506   mlib_s32 i, k, k_min, min_dist, diff, mask;                   \
2507   mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1;            \
2508   mlib_s32 entries = s->lutlength;                              \
2509   mlib_d64 *double_lut = mlib_ImageGetLutDoubleData( s );       \
2510   mlib_d64 col0, col1, col2, col3;                              \
2511   mlib_d64 dist, len0, len1, len2, len3;                        \
2512                                                                 \
2513   for( i = 0; i < length; i++ )                                 \
2514   {                                                             \
2515     col0 = src[ 4 * i ];                                        \
2516     col1 = src[ 4 * i + 1 ];                                    \
2517     col2 = src[ 4 * i + 2 ];                                    \
2518     col3 = src[ 4 * i + 3 ];                                    \
2519     min_dist = MLIB_S32_MAX;                                    \
2520     k_min = 1;                                                  \
2521     len0 = double_lut[ 0 ] - col0;                              \
2522     len1 = double_lut[ 1 ] - col1;                              \
2523     len2 = double_lut[ 2 ] - col2;                              \
2524     len3 = double_lut[ 3 ] - col3;                              \
2525     for( k = 1; k <= entries; k++ )                             \
2526     {                                                           \
2527       dist = len0 * len0;                                       \
2528       len0 =  double_lut[ 4 * k ] - col0;                       \
2529       dist += len1 * len1;                                      \
2530       len1 = double_lut[ 4 * k + 1 ] - col1;                    \
2531       dist += len2 * len2;                                      \
2532       len2 =  double_lut[ 4 * k + 2 ] - col2;                   \
2533       dist += len3 * len3;                                      \
2534       len3 =  double_lut[ 4 * k + 3 ] - col3;                   \
2535       diff = ( mlib_s32 )( dist * 0.125 ) - min_dist;           \
2536       mask = diff >> 31;                                        \
2537       min_dist += diff & mask;                                  \
2538       k_min += ( k - k_min ) & mask;                            \
2539     }                                                           \
2540     dst[ i ] = k_min + offset;                                  \
2541   }
2542 
2543 /***************************************************************/
mlib_ImageColorTrue2Index(mlib_image * dst,const mlib_image * src,const void * colormap)2544 mlib_status mlib_ImageColorTrue2Index(mlib_image       *dst,
2545                                       const mlib_image *src,
2546                                       const void       *colormap)
2547 {
2548   mlib_s32 y, width, height, sstride, dstride, schann;
2549   mlib_colormap *s = (mlib_colormap *)colormap;
2550   mlib_s32 channels;
2551   mlib_type stype, dtype;
2552 
2553   MLIB_IMAGE_CHECK(src);
2554   MLIB_IMAGE_CHECK(dst);
2555   MLIB_IMAGE_SIZE_EQUAL(src, dst);
2556   MLIB_IMAGE_HAVE_CHAN(dst, 1);
2557 
2558   if (!colormap)
2559     return MLIB_NULLPOINTER;
2560 
2561   channels = s->channels;
2562   stype = mlib_ImageGetType(src);
2563   dtype = mlib_ImageGetType(dst);
2564   width = mlib_ImageGetWidth(src);
2565   height = mlib_ImageGetHeight(src);
2566   sstride = mlib_ImageGetStride(src);
2567   dstride = mlib_ImageGetStride(dst);
2568   schann = mlib_ImageGetChannels(src);
2569 
2570   if (stype != s->intype || dtype != s->outtype)
2571     return MLIB_FAILURE;
2572 
2573   if (channels != schann)
2574     return MLIB_FAILURE;
2575 
2576   switch (stype) {
2577     case MLIB_BYTE:
2578       {
2579         mlib_u8 *sdata = mlib_ImageGetData(src);
2580 
2581         switch (dtype) {
2582           case MLIB_BYTE:
2583             {
2584               mlib_u8 *ddata = mlib_ImageGetData(dst);
2585 
2586               switch (channels) {
2587                 case 3:
2588                   {
2589                     MAIN_COLORTRUE2INDEX_LOOP(U8, U8, 3);
2590                     return MLIB_SUCCESS;
2591                   }
2592 
2593                 case 4:
2594                   {
2595                     MAIN_COLORTRUE2INDEX_LOOP(U8, U8, 4);
2596                     return MLIB_SUCCESS;
2597                   }
2598 
2599                 default:
2600                   return MLIB_FAILURE;
2601               }
2602             }
2603 
2604           case MLIB_SHORT:
2605             {
2606               mlib_s16 *ddata = mlib_ImageGetData(dst);
2607 
2608               dstride /= 2;
2609               switch (channels) {
2610                 case 3:
2611                   {
2612                     MAIN_COLORTRUE2INDEX_LOOP(U8, S16, 3);
2613                     return MLIB_SUCCESS;
2614                   }
2615 
2616                 case 4:
2617                   {
2618                     MAIN_COLORTRUE2INDEX_LOOP(U8, S16, 4);
2619                     return MLIB_SUCCESS;
2620                   }
2621 
2622                 default:
2623                   return MLIB_FAILURE;
2624               }
2625             }
2626         default:
2627           /* Unsupported type of destination image */
2628           return MLIB_FAILURE;
2629         }
2630       }
2631 
2632     case MLIB_SHORT:
2633       {
2634         mlib_s16 *sdata = mlib_ImageGetData(src);
2635 
2636         sstride /= 2;
2637         switch (dtype) {
2638           case MLIB_BYTE:
2639             {
2640               mlib_u8 *ddata = mlib_ImageGetData(dst);
2641 
2642               switch (channels) {
2643                 case 3:
2644                   {
2645                     MAIN_COLORTRUE2INDEX_LOOP(S16, U8, 3);
2646                     return MLIB_SUCCESS;
2647                   }
2648 
2649                 case 4:
2650                   {
2651                     MAIN_COLORTRUE2INDEX_LOOP(S16, U8, 4);
2652                     return MLIB_SUCCESS;
2653                   }
2654 
2655                 default:
2656                   return MLIB_FAILURE;
2657               }
2658             }
2659 
2660           case MLIB_SHORT:
2661             {
2662               mlib_s16 *ddata = mlib_ImageGetData(dst);
2663 
2664               dstride /= 2;
2665               switch (channels) {
2666                 case 3:
2667                   {
2668                     MAIN_COLORTRUE2INDEX_LOOP(S16, S16, 3);
2669                     return MLIB_SUCCESS;
2670                   }
2671 
2672                 case 4:
2673                   {
2674                     MAIN_COLORTRUE2INDEX_LOOP(S16, S16, 4);
2675                     return MLIB_SUCCESS;
2676                   }
2677 
2678                 default:
2679                   return MLIB_FAILURE;
2680               }
2681             }
2682         default:
2683           /* Unsupported type of destination image */
2684           return MLIB_FAILURE;
2685         }
2686       }
2687 
2688     default:
2689       return MLIB_FAILURE;
2690   }
2691 }
2692 
2693 /***************************************************************/
mlib_search_quadrant_U8_3(struct lut_node_3 * node,mlib_u32 distance,mlib_s32 * found_color,mlib_u32 c0,mlib_u32 c1,mlib_u32 c2,const mlib_u8 ** base)2694 mlib_u32 mlib_search_quadrant_U8_3(struct lut_node_3 *node,
2695                                    mlib_u32          distance,
2696                                     mlib_s32    *found_color,
2697                                    mlib_u32          c0,
2698                                    mlib_u32          c1,
2699                                    mlib_u32          c2,
2700                                    const mlib_u8     **base)
2701 {
2702   mlib_s32 i;
2703 
2704   for (i = 0; i < 8; i++) {
2705 
2706     if (node->tag & (1 << i)) {
2707       /* Here is alone color cell. Check the distance */
2708       mlib_s32 newindex = node->contents.index[i];
2709       mlib_u32 newpalc0, newpalc1, newpalc2;
2710       mlib_u32 newdistance;
2711 
2712       newpalc0 = base[0][newindex];
2713       newpalc1 = base[1][newindex];
2714       newpalc2 = base[2][newindex];
2715       newdistance = FIND_DISTANCE_3(c0, newpalc0, c1, newpalc1, c2, newpalc2, 0);
2716 
2717       if (distance > newdistance) {
2718         *found_color = newindex;
2719         distance = newdistance;
2720       }
2721     }
2722     else if (node->contents.quadrants[i])
2723       distance =
2724         mlib_search_quadrant_U8_3(node->contents.quadrants[i], distance,
2725                                   found_color, c0, c1, c2, base);
2726   }
2727 
2728   return distance;
2729 }
2730 
2731 /***************************************************************/
mlib_search_quadrant_part_to_left_U8_3(struct lut_node_3 * node,mlib_u32 distance,mlib_s32 * found_color,const mlib_u32 * c,const mlib_u8 ** base,mlib_u32 position,mlib_s32 pass,mlib_s32 dir_bit)2732 mlib_u32 mlib_search_quadrant_part_to_left_U8_3(struct lut_node_3 *node,
2733                                                 mlib_u32          distance,
2734                                                  mlib_s32    *found_color,
2735                                                 const mlib_u32    *c,
2736                                                 const mlib_u8     **base,
2737                                                 mlib_u32          position,
2738                                                 mlib_s32          pass,
2739                                                 mlib_s32          dir_bit)
2740 {
2741   mlib_u32 current_size = 1 << pass;
2742   mlib_s32 i;
2743   static mlib_s32 opposite_quadrants[3][4] = {
2744     {0, 2, 4, 6},
2745     {0, 1, 4, 5},
2746     {0, 1, 2, 3}
2747   };
2748 
2749 /* Search only quadrant's half untill it is necessary to check the
2750   whole quadrant */
2751 
2752   if (distance < (position + current_size - c[dir_bit]) * (position + current_size - c[dir_bit])) { /* Search half of quadrant */
2753     for (i = 0; i < 4; i++) {
2754       mlib_s32 qq = opposite_quadrants[dir_bit][i];
2755 
2756       if (node->tag & (1 << qq)) {
2757         /* Here is alone color cell. Check the distance */
2758         mlib_s32 newindex = node->contents.index[qq];
2759         mlib_u32 newpalc0, newpalc1, newpalc2;
2760         mlib_u32 newdistance;
2761 
2762         newpalc0 = base[0][newindex];
2763         newpalc1 = base[1][newindex];
2764         newpalc2 = base[2][newindex];
2765         newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 0);
2766 
2767         if (distance > newdistance) {
2768           *found_color = newindex;
2769           distance = newdistance;
2770         }
2771       }
2772       else if (node->contents.quadrants[qq])
2773         distance =
2774           mlib_search_quadrant_part_to_left_U8_3(node->contents.quadrants[qq],
2775                                                  distance, found_color, c, base,
2776                                                  position, pass - 1, dir_bit);
2777     }
2778   }
2779   else {                                    /* Search whole quadrant */
2780 
2781     mlib_s32 mask = 1 << dir_bit;
2782 
2783     for (i = 0; i < 8; i++) {
2784 
2785       if (node->tag & (1 << i)) {
2786         /* Here is alone color cell. Check the distance */
2787         mlib_s32 newindex = node->contents.index[i];
2788         mlib_u32 newpalc0, newpalc1, newpalc2;
2789         mlib_u32 newdistance;
2790 
2791         newpalc0 = base[0][newindex];
2792         newpalc1 = base[1][newindex];
2793         newpalc2 = base[2][newindex];
2794         newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 0);
2795 
2796         if (distance > newdistance) {
2797           *found_color = newindex;
2798           distance = newdistance;
2799         }
2800       }
2801       else if (node->contents.quadrants[i]) {
2802 
2803         if (i & mask)
2804           /* This quadrant may require partial checking */
2805           distance =
2806             mlib_search_quadrant_part_to_left_U8_3(node->contents.quadrants[i],
2807                                                    distance, found_color, c,
2808                                                    base,
2809                                                    position + current_size,
2810                                                    pass - 1, dir_bit);
2811         else
2812           /* Here we should check all */
2813           distance =
2814             mlib_search_quadrant_U8_3(node->contents.quadrants[i], distance,
2815                                       found_color, c[0], c[1], c[2], base);
2816       }
2817     }
2818   }
2819 
2820   return distance;
2821 }
2822 
2823 /***************************************************************/
mlib_search_quadrant_part_to_right_U8_3(struct lut_node_3 * node,mlib_u32 distance,mlib_s32 * found_color,const mlib_u32 * c,const mlib_u8 ** base,mlib_u32 position,mlib_s32 pass,mlib_s32 dir_bit)2824 mlib_u32 mlib_search_quadrant_part_to_right_U8_3(struct lut_node_3 *node,
2825                                                  mlib_u32          distance,
2826                                                   mlib_s32    *found_color,
2827                                                  const mlib_u32    *c,
2828                                                  const mlib_u8     **base,
2829                                                  mlib_u32          position,
2830                                                  mlib_s32          pass,
2831                                                  mlib_s32          dir_bit)
2832 {
2833   mlib_u32 current_size = 1 << pass;
2834   mlib_s32 i;
2835   static mlib_s32 opposite_quadrants[3][4] = {
2836     {1, 3, 5, 7},
2837     {2, 3, 6, 7},
2838     {4, 5, 6, 7}
2839   };
2840 
2841 /* Search only quadrant's half untill it is necessary to check the
2842   whole quadrant */
2843 
2844   if (distance <= (c[dir_bit] - position - current_size) * (c[dir_bit] - position - current_size)) { /* Search half of quadrant */
2845     for (i = 0; i < 4; i++) {
2846       mlib_s32 qq = opposite_quadrants[dir_bit][i];
2847 
2848       if (node->tag & (1 << qq)) {
2849         /* Here is alone color cell. Check the distance */
2850         mlib_s32 newindex = node->contents.index[qq];
2851         mlib_u32 newpalc0, newpalc1, newpalc2;
2852         mlib_u32 newdistance;
2853 
2854         newpalc0 = base[0][newindex];
2855         newpalc1 = base[1][newindex];
2856         newpalc2 = base[2][newindex];
2857         newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 0);
2858 
2859         if (distance > newdistance) {
2860           *found_color = newindex;
2861           distance = newdistance;
2862         }
2863       }
2864       else if (node->contents.quadrants[qq])
2865         distance =
2866           mlib_search_quadrant_part_to_right_U8_3(node->contents.quadrants[qq],
2867                                                   distance, found_color, c,
2868                                                   base, position + current_size,
2869                                                   pass - 1, dir_bit);
2870     }
2871   }
2872   else {                                    /* Search whole quadrant */
2873 
2874     mlib_s32 mask = 1 << dir_bit;
2875 
2876     for (i = 0; i < 8; i++) {
2877 
2878       if (node->tag & (1 << i)) {
2879         /* Here is alone color cell. Check the distance */
2880         mlib_s32 newindex = node->contents.index[i];
2881         mlib_u32 newpalc0, newpalc1, newpalc2;
2882         mlib_u32 newdistance;
2883 
2884         newpalc0 = base[0][newindex];
2885         newpalc1 = base[1][newindex];
2886         newpalc2 = base[2][newindex];
2887         newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 0);
2888 
2889         if (distance > newdistance) {
2890           *found_color = newindex;
2891           distance = newdistance;
2892         }
2893       }
2894       else if (node->contents.quadrants[i]) {
2895 
2896         if (i & mask)
2897           /* Here we should check all */
2898           distance =
2899             mlib_search_quadrant_U8_3(node->contents.quadrants[i], distance,
2900                                       found_color, c[0], c[1], c[2], base);
2901         else
2902           /* This quadrant may require partial checking */
2903           distance =
2904             mlib_search_quadrant_part_to_right_U8_3(node->contents.quadrants[i],
2905                                                     distance, found_color, c,
2906                                                     base, position, pass - 1, dir_bit);
2907       }
2908     }
2909   }
2910 
2911   return distance;
2912 }
2913 
2914 /***************************************************************/
mlib_search_quadrant_S16_3(struct lut_node_3 * node,mlib_u32 distance,mlib_s32 * found_color,mlib_u32 c0,mlib_u32 c1,mlib_u32 c2,const mlib_s16 ** base)2915 mlib_u32 mlib_search_quadrant_S16_3(struct lut_node_3 *node,
2916                                     mlib_u32          distance,
2917                                      mlib_s32    *found_color,
2918                                     mlib_u32          c0,
2919                                     mlib_u32          c1,
2920                                     mlib_u32          c2,
2921                                     const mlib_s16    **base)
2922 {
2923   mlib_s32 i;
2924 
2925   for (i = 0; i < 8; i++) {
2926 
2927     if (node->tag & (1 << i)) {
2928       /* Here is alone color cell. Check the distance */
2929       mlib_s32 newindex = node->contents.index[i];
2930       mlib_u32 newpalc0, newpalc1, newpalc2;
2931       mlib_u32 newdistance;
2932 
2933       newpalc0 = base[0][newindex] - MLIB_S16_MIN;
2934       newpalc1 = base[1][newindex] - MLIB_S16_MIN;
2935       newpalc2 = base[2][newindex] - MLIB_S16_MIN;
2936       newdistance = FIND_DISTANCE_3(c0, newpalc0, c1, newpalc1, c2, newpalc2, 2);
2937 
2938       if (distance > newdistance) {
2939         *found_color = newindex;
2940         distance = newdistance;
2941       }
2942     }
2943     else if (node->contents.quadrants[i])
2944       distance =
2945         mlib_search_quadrant_S16_3(node->contents.quadrants[i], distance,
2946                                    found_color, c0, c1, c2, base);
2947   }
2948 
2949   return distance;
2950 }
2951 
2952 /***************************************************************/
mlib_search_quadrant_part_to_left_S16_3(struct lut_node_3 * node,mlib_u32 distance,mlib_s32 * found_color,const mlib_u32 * c,const mlib_s16 ** base,mlib_u32 position,mlib_s32 pass,mlib_s32 dir_bit)2953 mlib_u32 mlib_search_quadrant_part_to_left_S16_3(struct lut_node_3 *node,
2954                                                  mlib_u32          distance,
2955                                                   mlib_s32    *found_color,
2956                                                  const mlib_u32    *c,
2957                                                  const mlib_s16    **base,
2958                                                  mlib_u32          position,
2959                                                  mlib_s32          pass,
2960                                                  mlib_s32          dir_bit)
2961 {
2962   mlib_u32 current_size = 1 << pass;
2963   mlib_s32 i;
2964   static mlib_s32 opposite_quadrants[3][4] = {
2965     {0, 2, 4, 6},
2966     {0, 1, 4, 5},
2967     {0, 1, 2, 3}
2968   };
2969 
2970 /* Search only quadrant's half untill it is necessary to check the
2971   whole quadrant */
2972 
2973   if (distance < (((position + current_size - c[dir_bit]) * (position + current_size - c[dir_bit])) >> 2)) { /* Search half of quadrant */
2974     for (i = 0; i < 4; i++) {
2975       mlib_s32 qq = opposite_quadrants[dir_bit][i];
2976 
2977       if (node->tag & (1 << qq)) {
2978         /* Here is alone color cell. Check the distance */
2979         mlib_s32 newindex = node->contents.index[qq];
2980         mlib_u32 newpalc0, newpalc1, newpalc2;
2981         mlib_u32 newdistance;
2982 
2983         newpalc0 = base[0][newindex] - MLIB_S16_MIN;
2984         newpalc1 = base[1][newindex] - MLIB_S16_MIN;
2985         newpalc2 = base[2][newindex] - MLIB_S16_MIN;
2986         newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 2);
2987 
2988         if (distance > newdistance) {
2989           *found_color = newindex;
2990           distance = newdistance;
2991         }
2992       }
2993       else if (node->contents.quadrants[qq])
2994         distance =
2995           mlib_search_quadrant_part_to_left_S16_3(node->contents.quadrants[qq],
2996                                                   distance, found_color, c,
2997                                                   base, position, pass - 1, dir_bit);
2998     }
2999   }
3000   else {                                    /* Search whole quadrant */
3001 
3002     mlib_s32 mask = 1 << dir_bit;
3003 
3004     for (i = 0; i < 8; i++) {
3005 
3006       if (node->tag & (1 << i)) {
3007         /* Here is alone color cell. Check the distance */
3008         mlib_s32 newindex = node->contents.index[i];
3009         mlib_u32 newpalc0, newpalc1, newpalc2;
3010         mlib_u32 newdistance;
3011 
3012         newpalc0 = base[0][newindex] - MLIB_S16_MIN;
3013         newpalc1 = base[1][newindex] - MLIB_S16_MIN;
3014         newpalc2 = base[2][newindex] - MLIB_S16_MIN;
3015         newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 2);
3016 
3017         if (distance > newdistance) {
3018           *found_color = newindex;
3019           distance = newdistance;
3020         }
3021       }
3022       else if (node->contents.quadrants[i]) {
3023 
3024         if (i & mask)
3025           /* This quadrant may require partial checking */
3026           distance =
3027             mlib_search_quadrant_part_to_left_S16_3(node->contents.quadrants[i],
3028                                                     distance, found_color, c,
3029                                                     base,
3030                                                     position + current_size,
3031                                                     pass - 1, dir_bit);
3032         else
3033           /* Here we should check all */
3034           distance =
3035             mlib_search_quadrant_S16_3(node->contents.quadrants[i], distance,
3036                                        found_color, c[0], c[1], c[2], base);
3037       }
3038     }
3039   }
3040 
3041   return distance;
3042 }
3043 
3044 /***************************************************************/
mlib_search_quadrant_part_to_right_S16_3(struct lut_node_3 * node,mlib_u32 distance,mlib_s32 * found_color,const mlib_u32 * c,const mlib_s16 ** base,mlib_u32 position,mlib_s32 pass,mlib_s32 dir_bit)3045 mlib_u32 mlib_search_quadrant_part_to_right_S16_3(struct lut_node_3 *node,
3046                                                   mlib_u32          distance,
3047                                                    mlib_s32    *found_color,
3048                                                   const mlib_u32    *c,
3049                                                   const mlib_s16    **base,
3050                                                   mlib_u32          position,
3051                                                   mlib_s32          pass,
3052                                                   mlib_s32          dir_bit)
3053 {
3054   mlib_u32 current_size = 1 << pass;
3055   mlib_s32 i;
3056   static mlib_s32 opposite_quadrants[3][4] = {
3057     {1, 3, 5, 7},
3058     {2, 3, 6, 7},
3059     {4, 5, 6, 7}
3060   };
3061 
3062 /* Search only quadrant's half untill it is necessary to check the
3063   whole quadrant */
3064 
3065   if (distance <= (((c[dir_bit] - position - current_size) * (c[dir_bit] - position - current_size)) >> 2)) { /* Search half of quadrant */
3066     for (i = 0; i < 4; i++) {
3067       mlib_s32 qq = opposite_quadrants[dir_bit][i];
3068 
3069       if (node->tag & (1 << qq)) {
3070         /* Here is alone color cell. Check the distance */
3071         mlib_s32 newindex = node->contents.index[qq];
3072         mlib_u32 newpalc0, newpalc1, newpalc2;
3073         mlib_u32 newdistance;
3074 
3075         newpalc0 = base[0][newindex] - MLIB_S16_MIN;
3076         newpalc1 = base[1][newindex] - MLIB_S16_MIN;
3077         newpalc2 = base[2][newindex] - MLIB_S16_MIN;
3078         newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 2);
3079 
3080         if (distance > newdistance) {
3081           *found_color = newindex;
3082           distance = newdistance;
3083         }
3084       }
3085       else if (node->contents.quadrants[qq])
3086         distance =
3087           mlib_search_quadrant_part_to_right_S16_3(node->contents.quadrants[qq],
3088                                                    distance, found_color, c,
3089                                                    base,
3090                                                    position + current_size,
3091                                                    pass - 1, dir_bit);
3092     }
3093   }
3094   else {                                    /* Search whole quadrant */
3095 
3096     mlib_s32 mask = 1 << dir_bit;
3097 
3098     for (i = 0; i < 8; i++) {
3099 
3100       if (node->tag & (1 << i)) {
3101         /* Here is alone color cell. Check the distance */
3102         mlib_s32 newindex = node->contents.index[i];
3103         mlib_u32 newpalc0, newpalc1, newpalc2;
3104         mlib_u32 newdistance;
3105 
3106         newpalc0 = base[0][newindex] - MLIB_S16_MIN;
3107         newpalc1 = base[1][newindex] - MLIB_S16_MIN;
3108         newpalc2 = base[2][newindex] - MLIB_S16_MIN;
3109         newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 2);
3110 
3111         if (distance > newdistance) {
3112           *found_color = newindex;
3113           distance = newdistance;
3114         }
3115       }
3116       else if (node->contents.quadrants[i]) {
3117 
3118         if (i & mask)
3119           /* Here we should check all */
3120           distance =
3121             mlib_search_quadrant_S16_3(node->contents.quadrants[i], distance,
3122                                        found_color, c[0], c[1], c[2], base);
3123         else
3124           /* This quadrant may require partial checking */
3125           distance =
3126             mlib_search_quadrant_part_to_right_S16_3(node->contents.
3127                                                      quadrants[i], distance,
3128                                                      found_color, c, base,
3129                                                      position, pass - 1, dir_bit);
3130       }
3131     }
3132   }
3133 
3134   return distance;
3135 }
3136 
3137 /***************************************************************/
mlib_search_quadrant_U8_4(struct lut_node_4 * node,mlib_u32 distance,mlib_s32 * found_color,mlib_u32 c0,mlib_u32 c1,mlib_u32 c2,mlib_u32 c3,const mlib_u8 ** base)3138 mlib_u32 mlib_search_quadrant_U8_4(struct lut_node_4 *node,
3139                                    mlib_u32          distance,
3140                                     mlib_s32    *found_color,
3141                                    mlib_u32          c0,
3142                                    mlib_u32          c1,
3143                                    mlib_u32          c2,
3144                                    mlib_u32          c3,
3145                                    const mlib_u8     **base)
3146 {
3147   mlib_s32 i;
3148 
3149   for (i = 0; i < 16; i++) {
3150 
3151     if (node->tag & (1 << i)) {
3152       /* Here is alone color cell. Check the distance */
3153       mlib_s32 newindex = node->contents.index[i];
3154       mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
3155       mlib_u32 newdistance;
3156 
3157       newpalc0 = base[0][newindex];
3158       newpalc1 = base[1][newindex];
3159       newpalc2 = base[2][newindex];
3160       newpalc3 = base[3][newindex];
3161       newdistance = FIND_DISTANCE_4(c0, newpalc0,
3162                                     c1, newpalc1, c2, newpalc2, c3, newpalc3, 0);
3163 
3164       if (distance > newdistance) {
3165         *found_color = newindex;
3166         distance = newdistance;
3167       }
3168     }
3169     else if (node->contents.quadrants[i])
3170       distance =
3171         mlib_search_quadrant_U8_4(node->contents.quadrants[i], distance,
3172                                   found_color, c0, c1, c2, c3, base);
3173   }
3174 
3175   return distance;
3176 }
3177 
3178 /***************************************************************/
mlib_search_quadrant_part_to_left_U8_4(struct lut_node_4 * node,mlib_u32 distance,mlib_s32 * found_color,const mlib_u32 * c,const mlib_u8 ** base,mlib_u32 position,mlib_s32 pass,mlib_s32 dir_bit)3179 mlib_u32 mlib_search_quadrant_part_to_left_U8_4(struct lut_node_4 *node,
3180                                                 mlib_u32          distance,
3181                                                  mlib_s32    *found_color,
3182                                                 const mlib_u32    *c,
3183                                                 const mlib_u8     **base,
3184                                                 mlib_u32          position,
3185                                                 mlib_s32          pass,
3186                                                 mlib_s32          dir_bit)
3187 {
3188   mlib_u32 current_size = 1 << pass;
3189   mlib_s32 i;
3190   static mlib_s32 opposite_quadrants[4][8] = {
3191     {0, 2, 4, 6, 8, 10, 12, 14},
3192     {0, 1, 4, 5, 8, 9, 12, 13},
3193     {0, 1, 2, 3, 8, 9, 10, 11},
3194     {0, 1, 2, 3, 4, 5, 6, 7}
3195   };
3196 
3197 /* Search only quadrant's half untill it is necessary to check the
3198   whole quadrant */
3199 
3200   if (distance < (position + current_size - c[dir_bit]) * (position + current_size - c[dir_bit])) { /* Search half of quadrant */
3201     for (i = 0; i < 8; i++) {
3202       mlib_s32 qq = opposite_quadrants[dir_bit][i];
3203 
3204       if (node->tag & (1 << qq)) {
3205         /* Here is alone color cell. Check the distance */
3206         mlib_s32 newindex = node->contents.index[qq];
3207         mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
3208         mlib_u32 newdistance;
3209 
3210         newpalc0 = base[0][newindex];
3211         newpalc1 = base[1][newindex];
3212         newpalc2 = base[2][newindex];
3213         newpalc3 = base[3][newindex];
3214         newdistance = FIND_DISTANCE_4(c[0], newpalc0,
3215                                       c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 0);
3216 
3217         if (distance > newdistance) {
3218           *found_color = newindex;
3219           distance = newdistance;
3220         }
3221       }
3222       else if (node->contents.quadrants[qq])
3223         distance =
3224           mlib_search_quadrant_part_to_left_U8_4(node->contents.quadrants[qq],
3225                                                  distance, found_color, c, base,
3226                                                  position, pass - 1, dir_bit);
3227     }
3228   }
3229   else {                                    /* Search whole quadrant */
3230 
3231     mlib_s32 mask = 1 << dir_bit;
3232 
3233     for (i = 0; i < 16; i++) {
3234 
3235       if (node->tag & (1 << i)) {
3236         /* Here is alone color cell. Check the distance */
3237         mlib_s32 newindex = node->contents.index[i];
3238         mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
3239         mlib_u32 newdistance;
3240 
3241         newpalc0 = base[0][newindex];
3242         newpalc1 = base[1][newindex];
3243         newpalc2 = base[2][newindex];
3244         newpalc3 = base[3][newindex];
3245         newdistance = FIND_DISTANCE_4(c[0], newpalc0,
3246                                       c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 0);
3247 
3248         if (distance > newdistance) {
3249           *found_color = newindex;
3250           distance = newdistance;
3251         }
3252       }
3253       else if (node->contents.quadrants[i]) {
3254 
3255         if (i & mask)
3256           /* This quadrant may require partial checking */
3257           distance =
3258             mlib_search_quadrant_part_to_left_U8_4(node->contents.quadrants[i],
3259                                                    distance, found_color, c,
3260                                                    base,
3261                                                    position + current_size,
3262                                                    pass - 1, dir_bit);
3263         else
3264           /* Here we should check all */
3265           distance =
3266             mlib_search_quadrant_U8_4(node->contents.quadrants[i], distance,
3267                                       found_color, c[0], c[1], c[2], c[3], base);
3268       }
3269     }
3270   }
3271 
3272   return distance;
3273 }
3274 
3275 /***************************************************************/
mlib_search_quadrant_part_to_right_U8_4(struct lut_node_4 * node,mlib_u32 distance,mlib_s32 * found_color,const mlib_u32 * c,const mlib_u8 ** base,mlib_u32 position,mlib_s32 pass,mlib_s32 dir_bit)3276 mlib_u32 mlib_search_quadrant_part_to_right_U8_4(struct lut_node_4 *node,
3277                                                  mlib_u32          distance,
3278                                                   mlib_s32    *found_color,
3279                                                  const mlib_u32    *c,
3280                                                  const mlib_u8     **base,
3281                                                  mlib_u32          position,
3282                                                  mlib_s32          pass,
3283                                                  mlib_s32          dir_bit)
3284 {
3285   mlib_u32 current_size = 1 << pass;
3286   mlib_s32 i;
3287   static mlib_s32 opposite_quadrants[4][8] = {
3288     {1, 3, 5, 7, 9, 11, 13, 15},
3289     {2, 3, 6, 7, 10, 11, 14, 15},
3290     {4, 5, 6, 7, 12, 13, 14, 15},
3291     {8, 9, 10, 11, 12, 13, 14, 15}
3292   };
3293 
3294 /* Search only quadrant's half untill it is necessary to check the
3295   whole quadrant */
3296 
3297   if (distance <= (c[dir_bit] - position - current_size) * (c[dir_bit] - position - current_size)) { /* Search half of quadrant */
3298     for (i = 0; i < 8; i++) {
3299       mlib_s32 qq = opposite_quadrants[dir_bit][i];
3300 
3301       if (node->tag & (1 << qq)) {
3302         /* Here is alone color cell. Check the distance */
3303         mlib_s32 newindex = node->contents.index[qq];
3304         mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
3305         mlib_u32 newdistance;
3306 
3307         newpalc0 = base[0][newindex];
3308         newpalc1 = base[1][newindex];
3309         newpalc2 = base[2][newindex];
3310         newpalc3 = base[3][newindex];
3311         newdistance = FIND_DISTANCE_4(c[0], newpalc0,
3312                                       c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 0);
3313 
3314         if (distance > newdistance) {
3315           *found_color = newindex;
3316           distance = newdistance;
3317         }
3318       }
3319       else if (node->contents.quadrants[qq])
3320         distance =
3321           mlib_search_quadrant_part_to_right_U8_4(node->contents.quadrants[qq],
3322                                                   distance, found_color, c,
3323                                                   base, position + current_size,
3324                                                   pass - 1, dir_bit);
3325     }
3326   }
3327   else {                                    /* Search whole quadrant */
3328 
3329     mlib_s32 mask = 1 << dir_bit;
3330 
3331     for (i = 0; i < 16; i++) {
3332 
3333       if (node->tag & (1 << i)) {
3334         /* Here is alone color cell. Check the distance */
3335         mlib_s32 newindex = node->contents.index[i];
3336         mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
3337         mlib_u32 newdistance;
3338 
3339         newpalc0 = base[0][newindex];
3340         newpalc1 = base[1][newindex];
3341         newpalc2 = base[2][newindex];
3342         newpalc3 = base[3][newindex];
3343         newdistance = FIND_DISTANCE_4(c[0], newpalc0,
3344                                       c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 0);
3345 
3346         if (distance > newdistance) {
3347           *found_color = newindex;
3348           distance = newdistance;
3349         }
3350       }
3351       else if (node->contents.quadrants[i]) {
3352 
3353         if (i & mask)
3354           /* Here we should check all */
3355           distance =
3356             mlib_search_quadrant_U8_4(node->contents.quadrants[i], distance,
3357                                       found_color, c[0], c[1], c[2], c[3], base);
3358         else
3359           /* This quadrant may require partial checking */
3360           distance =
3361             mlib_search_quadrant_part_to_right_U8_4(node->contents.quadrants[i],
3362                                                     distance, found_color, c,
3363                                                     base, position, pass - 1, dir_bit);
3364       }
3365     }
3366   }
3367 
3368   return distance;
3369 }
3370 
3371 /***************************************************************/
mlib_search_quadrant_S16_4(struct lut_node_4 * node,mlib_u32 distance,mlib_s32 * found_color,mlib_u32 c0,mlib_u32 c1,mlib_u32 c2,mlib_u32 c3,const mlib_s16 ** base)3372 mlib_u32 mlib_search_quadrant_S16_4(struct lut_node_4 *node,
3373                                     mlib_u32          distance,
3374                                      mlib_s32    *found_color,
3375                                     mlib_u32          c0,
3376                                     mlib_u32          c1,
3377                                     mlib_u32          c2,
3378                                     mlib_u32          c3,
3379                                     const mlib_s16    **base)
3380 {
3381   mlib_s32 i;
3382 
3383   for (i = 0; i < 16; i++) {
3384 
3385     if (node->tag & (1 << i)) {
3386       /* Here is alone color cell. Check the distance */
3387       mlib_s32 newindex = node->contents.index[i];
3388       mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
3389       mlib_u32 newdistance;
3390 
3391       newpalc0 = base[0][newindex] - MLIB_S16_MIN;
3392       newpalc1 = base[1][newindex] - MLIB_S16_MIN;
3393       newpalc2 = base[2][newindex] - MLIB_S16_MIN;
3394       newpalc3 = base[3][newindex] - MLIB_S16_MIN;
3395       newdistance = FIND_DISTANCE_4(c0, newpalc0,
3396                                     c1, newpalc1, c2, newpalc2, c3, newpalc3, 2);
3397 
3398       if (distance > newdistance) {
3399         *found_color = newindex;
3400         distance = newdistance;
3401       }
3402     }
3403     else if (node->contents.quadrants[i])
3404       distance =
3405         mlib_search_quadrant_S16_4(node->contents.quadrants[i], distance,
3406                                    found_color, c0, c1, c2, c3, base);
3407   }
3408 
3409   return distance;
3410 }
3411 
3412 /***************************************************************/
mlib_search_quadrant_part_to_left_S16_4(struct lut_node_4 * node,mlib_u32 distance,mlib_s32 * found_color,const mlib_u32 * c,const mlib_s16 ** base,mlib_u32 position,mlib_s32 pass,mlib_s32 dir_bit)3413 mlib_u32 mlib_search_quadrant_part_to_left_S16_4(struct lut_node_4 *node,
3414                                                  mlib_u32          distance,
3415                                                   mlib_s32    *found_color,
3416                                                  const mlib_u32    *c,
3417                                                  const mlib_s16    **base,
3418                                                  mlib_u32          position,
3419                                                  mlib_s32          pass,
3420                                                  mlib_s32          dir_bit)
3421 {
3422   mlib_u32 current_size = 1 << pass;
3423   mlib_s32 i;
3424   static mlib_s32 opposite_quadrants[4][8] = {
3425     {0, 2, 4, 6, 8, 10, 12, 14},
3426     {0, 1, 4, 5, 8, 9, 12, 13},
3427     {0, 1, 2, 3, 8, 9, 10, 11},
3428     {0, 1, 2, 3, 4, 5, 6, 7}
3429   };
3430 
3431 /* Search only quadrant's half untill it is necessary to check the
3432   whole quadrant */
3433 
3434   if (distance < (((position + current_size - c[dir_bit]) * (position + current_size - c[dir_bit])) >> 2)) { /* Search half of quadrant */
3435     for (i = 0; i < 8; i++) {
3436       mlib_s32 qq = opposite_quadrants[dir_bit][i];
3437 
3438       if (node->tag & (1 << qq)) {
3439         /* Here is alone color cell. Check the distance */
3440         mlib_s32 newindex = node->contents.index[qq];
3441         mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
3442         mlib_u32 newdistance;
3443 
3444         newpalc0 = base[0][newindex] - MLIB_S16_MIN;
3445         newpalc1 = base[1][newindex] - MLIB_S16_MIN;
3446         newpalc2 = base[2][newindex] - MLIB_S16_MIN;
3447         newpalc3 = base[3][newindex] - MLIB_S16_MIN;
3448         newdistance = FIND_DISTANCE_4(c[0], newpalc0,
3449                                       c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 2);
3450 
3451         if (distance > newdistance) {
3452           *found_color = newindex;
3453           distance = newdistance;
3454         }
3455       }
3456       else if (node->contents.quadrants[qq])
3457         distance =
3458           mlib_search_quadrant_part_to_left_S16_4(node->contents.quadrants[qq],
3459                                                   distance, found_color, c,
3460                                                   base, position, pass - 1, dir_bit);
3461     }
3462   }
3463   else {                                    /* Search whole quadrant */
3464 
3465     mlib_s32 mask = 1 << dir_bit;
3466 
3467     for (i = 0; i < 16; i++) {
3468 
3469       if (node->tag & (1 << i)) {
3470         /* Here is alone color cell. Check the distance */
3471         mlib_s32 newindex = node->contents.index[i];
3472         mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
3473         mlib_u32 newdistance;
3474 
3475         newpalc0 = base[0][newindex] - MLIB_S16_MIN;
3476         newpalc1 = base[1][newindex] - MLIB_S16_MIN;
3477         newpalc2 = base[2][newindex] - MLIB_S16_MIN;
3478         newpalc3 = base[3][newindex] - MLIB_S16_MIN;
3479         newdistance = FIND_DISTANCE_4(c[0], newpalc0,
3480                                       c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 2);
3481 
3482         if (distance > newdistance) {
3483           *found_color = newindex;
3484           distance = newdistance;
3485         }
3486       }
3487       else if (node->contents.quadrants[i]) {
3488 
3489         if (i & mask)
3490           /* This quadrant may require partial checking */
3491           distance =
3492             mlib_search_quadrant_part_to_left_S16_4(node->contents.quadrants[i],
3493                                                     distance, found_color, c,
3494                                                     base,
3495                                                     position + current_size,
3496                                                     pass - 1, dir_bit);
3497         else
3498           /* Here we should check all */
3499           distance =
3500             mlib_search_quadrant_S16_4(node->contents.quadrants[i], distance,
3501                                        found_color, c[0], c[1], c[2], c[3], base);
3502       }
3503     }
3504   }
3505 
3506   return distance;
3507 }
3508 
3509 /***************************************************************/
mlib_search_quadrant_part_to_right_S16_4(struct lut_node_4 * node,mlib_u32 distance,mlib_s32 * found_color,const mlib_u32 * c,const mlib_s16 ** base,mlib_u32 position,mlib_s32 pass,mlib_s32 dir_bit)3510 mlib_u32 mlib_search_quadrant_part_to_right_S16_4(struct lut_node_4 *node,
3511                                                   mlib_u32          distance,
3512                                                    mlib_s32    *found_color,
3513                                                   const mlib_u32    *c,
3514                                                   const mlib_s16    **base,
3515                                                   mlib_u32          position,
3516                                                   mlib_s32          pass,
3517                                                   mlib_s32          dir_bit)
3518 {
3519   mlib_u32 current_size = 1 << pass;
3520   mlib_s32 i;
3521   static mlib_s32 opposite_quadrants[4][8] = {
3522     {1, 3, 5, 7, 9, 11, 13, 15},
3523     {2, 3, 6, 7, 10, 11, 14, 15},
3524     {4, 5, 6, 7, 12, 13, 14, 15},
3525     {8, 9, 10, 11, 12, 13, 14, 15}
3526   };
3527 
3528 /* Search only quadrant's half untill it is necessary to check the
3529   whole quadrant */
3530 
3531   if (distance <= (((c[dir_bit] - position - current_size) * (c[dir_bit] - position - current_size)) >> 2)) { /* Search half of quadrant */
3532     for (i = 0; i < 8; i++) {
3533       mlib_s32 qq = opposite_quadrants[dir_bit][i];
3534 
3535       if (node->tag & (1 << qq)) {
3536         /* Here is alone color cell. Check the distance */
3537         mlib_s32 newindex = node->contents.index[qq];
3538         mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
3539         mlib_u32 newdistance;
3540 
3541         newpalc0 = base[0][newindex] - MLIB_S16_MIN;
3542         newpalc1 = base[1][newindex] - MLIB_S16_MIN;
3543         newpalc2 = base[2][newindex] - MLIB_S16_MIN;
3544         newpalc3 = base[3][newindex] - MLIB_S16_MIN;
3545         newdistance = FIND_DISTANCE_4(c[0], newpalc0,
3546                                       c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 2);
3547 
3548         if (distance > newdistance) {
3549           *found_color = newindex;
3550           distance = newdistance;
3551         }
3552       }
3553       else if (node->contents.quadrants[qq])
3554         distance =
3555           mlib_search_quadrant_part_to_right_S16_4(node->contents.quadrants[qq],
3556                                                    distance, found_color, c,
3557                                                    base,
3558                                                    position + current_size,
3559                                                    pass - 1, dir_bit);
3560     }
3561   }
3562   else {                                    /* Search whole quadrant */
3563 
3564     mlib_s32 mask = 1 << dir_bit;
3565 
3566     for (i = 0; i < 16; i++) {
3567 
3568       if (node->tag & (1 << i)) {
3569         /* Here is alone color cell. Check the distance */
3570         mlib_s32 newindex = node->contents.index[i];
3571         mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
3572         mlib_u32 newdistance;
3573 
3574         newpalc0 = base[0][newindex] - MLIB_S16_MIN;
3575         newpalc1 = base[1][newindex] - MLIB_S16_MIN;
3576         newpalc2 = base[2][newindex] - MLIB_S16_MIN;
3577         newpalc3 = base[3][newindex] - MLIB_S16_MIN;
3578         newdistance = FIND_DISTANCE_4(c[0], newpalc0,
3579                                       c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 2);
3580 
3581         if (distance > newdistance) {
3582           *found_color = newindex;
3583           distance = newdistance;
3584         }
3585       }
3586       else if (node->contents.quadrants[i]) {
3587 
3588         if (i & mask)
3589           /* Here we should check all */
3590           distance =
3591             mlib_search_quadrant_S16_4(node->contents.quadrants[i], distance,
3592                                        found_color, c[0], c[1], c[2], c[3], base);
3593         else
3594           /* This quadrant may require partial checking */
3595           distance =
3596             mlib_search_quadrant_part_to_right_S16_4(node->contents.
3597                                                      quadrants[i], distance,
3598                                                      found_color, c, base,
3599                                                      position, pass - 1, dir_bit);
3600       }
3601     }
3602   }
3603 
3604   return distance;
3605 }
3606 
3607 /***************************************************************/
3608 
3609 #define TAB_SIZE_mlib_u8   256
3610 #define TAB_SIZE_mlib_s16 1024
3611 
3612 #define SRC_mlib_u8(i)    src[i]
3613 #define SRC_mlib_s16(i)   (((mlib_u16*)src)[i] >> 6)
3614 
3615 /***************************************************************/
3616 
3617 #define DIMENSIONS_SEARCH_3(STYPE, DTYPE, STEP)                 \
3618 {                                                               \
3619   DTYPE  *tab0 = ((mlib_colormap *)state)->table;               \
3620   DTYPE  *tab1 = tab0 + TAB_SIZE_##STYPE;                       \
3621   DTYPE  *tab2 = tab1 + TAB_SIZE_##STYPE;                       \
3622   mlib_s32 i;                                                   \
3623                                                                 \
3624   for (i = 0; i < length; i++) {                                \
3625     dst[i] = tab0[SRC_##STYPE(0)] + tab1[SRC_##STYPE(1)] +      \
3626              tab2[SRC_##STYPE(2)];                              \
3627     src += STEP;                                                \
3628   }                                                             \
3629 }
3630 
3631 /***************************************************************/
3632 
3633 #define DIMENSIONS_SEARCH_4(STYPE, DTYPE)                       \
3634 {                                                               \
3635   DTYPE  *tab0 = ((mlib_colormap *)state)->table;               \
3636   DTYPE  *tab1 = tab0 + TAB_SIZE_##STYPE;                       \
3637   DTYPE  *tab2 = tab1 + TAB_SIZE_##STYPE;                       \
3638   DTYPE  *tab3 = tab2 + TAB_SIZE_##STYPE;                       \
3639   mlib_s32 i;                                                   \
3640                                                                 \
3641   for (i = 0; i < length; i++) {                                \
3642     dst[i] = tab0[SRC_##STYPE(0)] + tab1[SRC_##STYPE(1)] +      \
3643              tab2[SRC_##STYPE(2)] + tab3[SRC_##STYPE(3)];       \
3644     src += 4;                                                   \
3645   }                                                             \
3646 }
3647 
3648 /***************************************************************/
mlib_ImageColorTrue2IndexLine_U8_U8_3(const mlib_u8 * src,mlib_u8 * dst,mlib_s32 length,const void * state)3649 void mlib_ImageColorTrue2IndexLine_U8_U8_3(const mlib_u8 *src,
3650                                            mlib_u8       *dst,
3651                                            mlib_s32      length,
3652                                            const void    *state)
3653 {
3654   mlib_colormap *s = (mlib_colormap *)state;
3655 
3656   switch (s->method) {
3657 #if LUT_BYTE_COLORS_3CHANNELS <= 256
3658     case LUT_BINARY_TREE_SEARCH:
3659       {
3660         mlib_s32 bits = s->bits;
3661         BINARY_TREE_SEARCH_3(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 0, 3, 0);
3662       }
3663       break;
3664 
3665 #endif /* LUT_BYTE_COLORS_3CHANNELS <= 256 */
3666     case LUT_COLOR_CUBE_SEARCH:
3667       {
3668         COLOR_CUBE_U8_3_SEARCH(mlib_u8, 0, 3);
3669       }
3670       break;
3671 
3672     case LUT_STUPID_SEARCH:
3673       {
3674 #ifdef USE_VIS_CODE
3675         FIND_NEAREST_U8_3;
3676 #else
3677         FIND_NEAREST_U8_3_C(0, 3);
3678 #endif
3679       }
3680       break;
3681 
3682     case LUT_COLOR_DIMENSIONS:
3683       DIMENSIONS_SEARCH_3(mlib_u8, mlib_u8, 3)
3684       break;
3685   }
3686 }
3687 
3688 /***************************************************************/
mlib_ImageColorTrue2IndexLine_U8_U8_3_in_4(const mlib_u8 * src,mlib_u8 * dst,mlib_s32 length,const void * state)3689 void mlib_ImageColorTrue2IndexLine_U8_U8_3_in_4(const mlib_u8 *src,
3690                                                 mlib_u8       *dst,
3691                                                 mlib_s32      length,
3692                                                 const void    *state)
3693 {
3694   mlib_colormap *s = (mlib_colormap *)state;
3695 
3696   switch (s->method) {
3697 #if LUT_BYTE_COLORS_3CHANNELS <= 256
3698     case LUT_BINARY_TREE_SEARCH:
3699       {
3700         mlib_s32 bits = s->bits;
3701         BINARY_TREE_SEARCH_3(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 1, 4, 0);
3702         break;
3703       }
3704 
3705 #endif /* LUT_BYTE_COLORS_3CHANNELS <= 256 */
3706     case LUT_COLOR_CUBE_SEARCH:
3707       {
3708         COLOR_CUBE_U8_3_SEARCH(mlib_u8, 1, 4);
3709         break;
3710       }
3711 
3712     case LUT_STUPID_SEARCH:
3713       {
3714 #ifdef USE_VIS_CODE
3715         FIND_NEAREST_U8_3_IN4;
3716 #else
3717         FIND_NEAREST_U8_3_C(1, 4);
3718 #endif
3719         break;
3720       }
3721 
3722     case LUT_COLOR_DIMENSIONS:
3723       src++;
3724       DIMENSIONS_SEARCH_3(mlib_u8, mlib_u8, 4)
3725       break;
3726   }
3727 }
3728 
3729 /***************************************************************/
mlib_ImageColorTrue2IndexLine_U8_U8_4(const mlib_u8 * src,mlib_u8 * dst,mlib_s32 length,const void * state)3730 void mlib_ImageColorTrue2IndexLine_U8_U8_4(const mlib_u8 *src,
3731                                            mlib_u8       *dst,
3732                                            mlib_s32      length,
3733                                            const void    *state)
3734 {
3735   mlib_colormap *s = (mlib_colormap *)state;
3736 
3737   switch (s->method) {
3738 #if LUT_BYTE_COLORS_4CHANNELS <= 256
3739     case LUT_BINARY_TREE_SEARCH:
3740       {
3741         mlib_s32 bits = s->bits;
3742         BINARY_TREE_SEARCH_4(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 0);
3743         break;
3744       }
3745 
3746 #endif /* LUT_BYTE_COLORS_4CHANNELS <= 256 */
3747     case LUT_COLOR_CUBE_SEARCH:
3748       {
3749         COLOR_CUBE_U8_4_SEARCH(mlib_u8);
3750         break;
3751       }
3752 
3753     case LUT_STUPID_SEARCH:
3754       {
3755 #ifdef USE_VIS_CODE
3756         FIND_NEAREST_U8_4;
3757 #else
3758         FIND_NEAREST_U8_4_C;
3759 #endif
3760         break;
3761       }
3762 
3763     case LUT_COLOR_DIMENSIONS:
3764       DIMENSIONS_SEARCH_4(mlib_u8, mlib_u8)
3765       break;
3766   }
3767 }
3768 
3769 /***************************************************************/
mlib_ImageColorTrue2IndexLine_U8_S16_3(const mlib_u8 * src,mlib_s16 * dst,mlib_s32 length,const void * state)3770 void mlib_ImageColorTrue2IndexLine_U8_S16_3(const mlib_u8 *src,
3771                                             mlib_s16      *dst,
3772                                             mlib_s32      length,
3773                                             const void    *state)
3774 {
3775   mlib_colormap *s = (mlib_colormap *)state;
3776   mlib_s32 bits = s->bits;
3777 
3778   switch (s->method) {
3779     case LUT_BINARY_TREE_SEARCH:
3780       {
3781         BINARY_TREE_SEARCH_3(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 0, 3, 0);
3782         break;
3783       }
3784 
3785     case LUT_COLOR_CUBE_SEARCH:
3786       {
3787         switch (s->indexsize) {
3788           case 1:
3789             {
3790               COLOR_CUBE_U8_3_SEARCH(mlib_u8, 0, 3);
3791               break;
3792             }
3793 
3794           case 2:
3795             {
3796               COLOR_CUBE_U8_3_SEARCH(mlib_s16, 0, 3);
3797               break;
3798             }
3799         }
3800 
3801         break;
3802       }
3803 
3804     case LUT_STUPID_SEARCH:
3805       {
3806 #ifdef USE_VIS_CODE
3807         FIND_NEAREST_U8_3;
3808 #else
3809         FIND_NEAREST_U8_3_C(0, 3);
3810 #endif
3811         break;
3812       }
3813 
3814     case LUT_COLOR_DIMENSIONS:
3815       DIMENSIONS_SEARCH_3(mlib_u8, mlib_s16, 3)
3816       break;
3817   }
3818 }
3819 
3820 /***************************************************************/
mlib_ImageColorTrue2IndexLine_U8_S16_3_in_4(const mlib_u8 * src,mlib_s16 * dst,mlib_s32 length,const void * state)3821 void mlib_ImageColorTrue2IndexLine_U8_S16_3_in_4(const mlib_u8 *src,
3822                                                  mlib_s16      *dst,
3823                                                  mlib_s32      length,
3824                                                  const void    *state)
3825 {
3826   mlib_colormap *s = (mlib_colormap *)state;
3827   mlib_s32 bits = s->bits;
3828 
3829   switch (s->method) {
3830     case LUT_BINARY_TREE_SEARCH:
3831       {
3832         BINARY_TREE_SEARCH_3(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 1, 4, 0);
3833         break;
3834       }
3835 
3836     case LUT_COLOR_CUBE_SEARCH:
3837       {
3838         switch (s->indexsize) {
3839           case 1:
3840             {
3841               COLOR_CUBE_U8_3_SEARCH(mlib_u8, 1, 4);
3842               break;
3843             }
3844 
3845           case 2:
3846             {
3847               COLOR_CUBE_U8_3_SEARCH(mlib_s16, 1, 4);
3848               break;
3849             }
3850         }
3851 
3852         break;
3853       }
3854 
3855     case LUT_STUPID_SEARCH:
3856       {
3857 #ifdef USE_VIS_CODE
3858         FIND_NEAREST_U8_3_IN4;
3859 #else
3860         FIND_NEAREST_U8_3_C(1, 4);
3861 #endif
3862         break;
3863       }
3864 
3865     case LUT_COLOR_DIMENSIONS:
3866       src++;
3867       DIMENSIONS_SEARCH_3(mlib_u8, mlib_s16, 4)
3868       break;
3869   }
3870 }
3871 
3872 /***************************************************************/
mlib_ImageColorTrue2IndexLine_U8_S16_4(const mlib_u8 * src,mlib_s16 * dst,mlib_s32 length,const void * state)3873 void mlib_ImageColorTrue2IndexLine_U8_S16_4(const mlib_u8 *src,
3874                                             mlib_s16      *dst,
3875                                             mlib_s32      length,
3876                                             const void    *state)
3877 {
3878   mlib_colormap *s = (mlib_colormap *)state;
3879   mlib_s32 bits = s->bits;
3880 
3881   switch (s->method) {
3882     case LUT_BINARY_TREE_SEARCH:
3883       {
3884         BINARY_TREE_SEARCH_4(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 0);
3885         break;
3886       }
3887 
3888     case LUT_COLOR_CUBE_SEARCH:
3889       {
3890         switch (s->indexsize) {
3891           case 1:
3892             {
3893               COLOR_CUBE_U8_4_SEARCH(mlib_u8);
3894               break;
3895             }
3896 
3897           case 2:
3898             {
3899               COLOR_CUBE_U8_4_SEARCH(mlib_s16);
3900               break;
3901             }
3902         }
3903 
3904         break;
3905       }
3906 
3907     case LUT_STUPID_SEARCH:
3908       {
3909 #ifdef USE_VIS_CODE
3910         FIND_NEAREST_U8_4;
3911 #else
3912         FIND_NEAREST_U8_4_C;
3913 #endif
3914         break;
3915       }
3916 
3917     case LUT_COLOR_DIMENSIONS:
3918       DIMENSIONS_SEARCH_4(mlib_u8, mlib_s16)
3919       break;
3920   }
3921 }
3922 
3923 /***************************************************************/
mlib_ImageColorTrue2IndexLine_S16_S16_3(const mlib_s16 * src,mlib_s16 * dst,mlib_s32 length,const void * state)3924 void mlib_ImageColorTrue2IndexLine_S16_S16_3(const mlib_s16 *src,
3925                                              mlib_s16       *dst,
3926                                              mlib_s32       length,
3927                                              const void     *state)
3928 {
3929   mlib_colormap *s = (mlib_colormap *)state;
3930   mlib_s32 bits = s->bits;
3931 
3932   switch (s->method) {
3933     case LUT_BINARY_TREE_SEARCH:
3934       {
3935         BINARY_TREE_SEARCH_3(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
3936                              MLIB_S16_MIN, 0, 3, 2);
3937         break;
3938       }
3939 
3940     case LUT_COLOR_CUBE_SEARCH:
3941       {
3942         switch (s->indexsize) {
3943           case 1:
3944             {
3945               COLOR_CUBE_S16_3_SEARCH(mlib_u8, 0, 3);
3946               break;
3947             }
3948 
3949           case 2:
3950             {
3951               COLOR_CUBE_S16_3_SEARCH(mlib_s16, 0, 3);
3952               break;
3953             }
3954         }
3955 
3956         break;
3957       }
3958 
3959     case LUT_STUPID_SEARCH:
3960       {
3961         FIND_NEAREST_S16_3(0, 3);
3962         break;
3963       }
3964 
3965     case LUT_COLOR_DIMENSIONS:
3966       DIMENSIONS_SEARCH_3(mlib_s16, mlib_s16, 3)
3967       break;
3968   }
3969 }
3970 
3971 /***************************************************************/
mlib_ImageColorTrue2IndexLine_S16_S16_3_in_4(const mlib_s16 * src,mlib_s16 * dst,mlib_s32 length,const void * state)3972 void mlib_ImageColorTrue2IndexLine_S16_S16_3_in_4(const mlib_s16 *src,
3973                                                   mlib_s16       *dst,
3974                                                   mlib_s32       length,
3975                                                   const void     *state)
3976 {
3977   mlib_colormap *s = (mlib_colormap *)state;
3978   mlib_s32 bits = s->bits;
3979 
3980   switch (s->method) {
3981     case LUT_BINARY_TREE_SEARCH:
3982       {
3983         BINARY_TREE_SEARCH_3(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
3984                              MLIB_S16_MIN, 1, 4, 2);
3985         break;
3986       }
3987 
3988     case LUT_COLOR_CUBE_SEARCH:
3989       {
3990         switch (s->indexsize) {
3991           case 1:
3992             {
3993               COLOR_CUBE_S16_3_SEARCH(mlib_u8, 1, 4);
3994               break;
3995             }
3996 
3997           case 2:
3998             {
3999               COLOR_CUBE_S16_3_SEARCH(mlib_s16, 1, 4);
4000               break;
4001             }
4002         }
4003 
4004         break;
4005       }
4006 
4007     case LUT_STUPID_SEARCH:
4008       {
4009         FIND_NEAREST_S16_3(1, 4);
4010         break;
4011       }
4012 
4013     case LUT_COLOR_DIMENSIONS:
4014       src++;
4015       DIMENSIONS_SEARCH_3(mlib_s16, mlib_s16, 4)
4016       break;
4017   }
4018 }
4019 
4020 /***************************************************************/
mlib_ImageColorTrue2IndexLine_S16_S16_4(const mlib_s16 * src,mlib_s16 * dst,mlib_s32 length,const void * state)4021 void mlib_ImageColorTrue2IndexLine_S16_S16_4(const mlib_s16 *src,
4022                                              mlib_s16       *dst,
4023                                              mlib_s32       length,
4024                                              const void     *state)
4025 {
4026   mlib_colormap *s = (mlib_colormap *)state;
4027   mlib_s32 bits = s->bits;
4028 
4029   switch (s->method) {
4030     case LUT_BINARY_TREE_SEARCH:
4031       {
4032         BINARY_TREE_SEARCH_4(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
4033                              MLIB_S16_MIN, 2);
4034         break;
4035       }
4036 
4037     case LUT_COLOR_CUBE_SEARCH:
4038       {
4039         switch (s->indexsize) {
4040           case 1:
4041             {
4042               COLOR_CUBE_S16_4_SEARCH(mlib_u8);
4043               break;
4044             }
4045 
4046           case 2:
4047             {
4048               COLOR_CUBE_S16_4_SEARCH(mlib_s16);
4049               break;
4050             }
4051         }
4052 
4053         break;
4054       }
4055 
4056     case LUT_STUPID_SEARCH:
4057       {
4058         FIND_NEAREST_S16_4;
4059         break;
4060       }
4061 
4062     case LUT_COLOR_DIMENSIONS:
4063       DIMENSIONS_SEARCH_4(mlib_s16, mlib_s16)
4064       break;
4065   }
4066 }
4067 
4068 /***************************************************************/
mlib_ImageColorTrue2IndexLine_S16_U8_3(const mlib_s16 * src,mlib_u8 * dst,mlib_s32 length,const void * state)4069 void mlib_ImageColorTrue2IndexLine_S16_U8_3(const mlib_s16 *src,
4070                                             mlib_u8        *dst,
4071                                             mlib_s32       length,
4072                                             const void     *state)
4073 {
4074   mlib_colormap *s = (mlib_colormap *)state;
4075 
4076   switch (s->method) {
4077 #if LUT_SHORT_COLORS_3CHANNELS <= 256
4078     case LUT_BINARY_TREE_SEARCH:
4079       {
4080         mlib_s32 bits = s->bits;
4081         BINARY_TREE_SEARCH_3(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
4082                              MLIB_S16_MIN, 0, 3, 2);
4083         break;
4084       }
4085 
4086 #endif /* LUT_SHORT_COLORS_3CHANNELS <= 256 */
4087     case LUT_COLOR_CUBE_SEARCH:
4088       {
4089         COLOR_CUBE_S16_3_SEARCH(mlib_u8, 0, 3);
4090         break;
4091       }
4092 
4093     case LUT_STUPID_SEARCH:
4094       {
4095         FIND_NEAREST_S16_3(0, 3);
4096         break;
4097       }
4098 
4099     case LUT_COLOR_DIMENSIONS:
4100       DIMENSIONS_SEARCH_3(mlib_s16, mlib_u8, 3)
4101       break;
4102   }
4103 }
4104 
4105 /***************************************************************/
mlib_ImageColorTrue2IndexLine_S16_U8_3_in_4(const mlib_s16 * src,mlib_u8 * dst,mlib_s32 length,const void * state)4106 void mlib_ImageColorTrue2IndexLine_S16_U8_3_in_4(const mlib_s16 *src,
4107                                                  mlib_u8        *dst,
4108                                                  mlib_s32       length,
4109                                                  const void     *state)
4110 {
4111   mlib_colormap *s = (mlib_colormap *)state;
4112 
4113   switch (s->method) {
4114 #if LUT_SHORT_COLORS_3CHANNELS <= 256
4115     case LUT_BINARY_TREE_SEARCH:
4116       {
4117         mlib_s32 bits = s->bits;
4118         BINARY_TREE_SEARCH_3(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
4119                              MLIB_S16_MIN, 1, 4, 2);
4120         break;
4121       }
4122 
4123 #endif /* LUT_SHORT_COLORS_3CHANNELS <= 256 */
4124     case LUT_COLOR_CUBE_SEARCH:
4125       {
4126         COLOR_CUBE_S16_3_SEARCH(mlib_u8, 1, 4);
4127         break;
4128       }
4129 
4130     case LUT_STUPID_SEARCH:
4131       {
4132         FIND_NEAREST_S16_3(1, 4);
4133         break;
4134       }
4135 
4136     case LUT_COLOR_DIMENSIONS:
4137       src++;
4138       DIMENSIONS_SEARCH_3(mlib_s16, mlib_u8, 4)
4139       break;
4140   }
4141 }
4142 
4143 /***************************************************************/
mlib_ImageColorTrue2IndexLine_S16_U8_4(const mlib_s16 * src,mlib_u8 * dst,mlib_s32 length,const void * state)4144 void mlib_ImageColorTrue2IndexLine_S16_U8_4(const mlib_s16 *src,
4145                                             mlib_u8        *dst,
4146                                             mlib_s32       length,
4147                                             const void     *state)
4148 {
4149   mlib_colormap *s = (mlib_colormap *)state;
4150 
4151   switch (s->method) {
4152 #if LUT_SHORT_COLORS_4CHANNELS <= 256
4153     case LUT_BINARY_TREE_SEARCH:
4154       {
4155         mlib_s32 bits = s->bits;
4156         BINARY_TREE_SEARCH_4(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
4157                              MLIB_S16_MIN, 2);
4158         break;
4159       }
4160 
4161 #endif /* LUT_SHORT_COLORS_4CHANNELS <= 256 */
4162     case LUT_COLOR_CUBE_SEARCH:
4163       {
4164         COLOR_CUBE_S16_4_SEARCH(mlib_u8);
4165         break;
4166       }
4167 
4168     case LUT_STUPID_SEARCH:
4169       {
4170         FIND_NEAREST_S16_4;
4171         break;
4172       }
4173 
4174     case LUT_COLOR_DIMENSIONS:
4175       DIMENSIONS_SEARCH_4(mlib_s16, mlib_u8)
4176       break;
4177   }
4178 }
4179 
4180 /***************************************************************/
4181 
4182 #ifndef VIS
4183 
4184 void mlib_c_ImageThresh1_U81_1B(void     *psrc,
4185                                 void     *pdst,
4186                                 mlib_s32 src_stride,
4187                                 mlib_s32 dst_stride,
4188                                 mlib_s32 width,
4189                                 mlib_s32 height,
4190                                 void     *thresh,
4191                                 void     *ghigh,
4192                                 void     *glow,
4193                                 mlib_s32 dbit_off);
4194 
4195 /***************************************************************/
4196 
mlib_ImageColorTrue2IndexLine_U8_BIT_1(const mlib_u8 * src,mlib_u8 * dst,mlib_s32 bit_offset,mlib_s32 length,const void * state)4197 void mlib_ImageColorTrue2IndexLine_U8_BIT_1(const mlib_u8 *src,
4198                                             mlib_u8       *dst,
4199                                             mlib_s32      bit_offset,
4200                                             mlib_s32      length,
4201                                             const void    *state)
4202 {
4203   mlib_u8  *lut = ((mlib_colormap *)state)->table;
4204   mlib_s32 thresh[1];
4205   mlib_s32 ghigh[1];
4206   mlib_s32 glow[1];
4207 
4208   thresh[0] = lut[2];
4209 
4210   glow[0]  = lut[0] - lut[1];
4211   ghigh[0] = lut[1] - lut[0];
4212 
4213   mlib_c_ImageThresh1_U81_1B((void*)src, dst, 0, 0, length, 1,
4214                              thresh, ghigh, glow, bit_offset);
4215 }
4216 
4217 #else
4218 
4219 /***************************************************************/
4220 
4221 void mlib_v_ImageThresh1B_U8_1(const mlib_u8  *src,
4222                                mlib_s32       slb,
4223                                mlib_u8        *dst,
4224                                mlib_s32       dlb,
4225                                mlib_s32       xsize,
4226                                mlib_s32       ysize,
4227                                mlib_s32       dbit_off,
4228                                const mlib_s32 *th,
4229                                mlib_s32       hc,
4230                                mlib_s32       lc);
4231 
4232 /***************************************************************/
4233 
mlib_ImageColorTrue2IndexLine_U8_BIT_1(const mlib_u8 * src,mlib_u8 * dst,mlib_s32 bit_offset,mlib_s32 length,const void * state)4234 void mlib_ImageColorTrue2IndexLine_U8_BIT_1(const mlib_u8 *src,
4235                                             mlib_u8       *dst,
4236                                             mlib_s32      bit_offset,
4237                                             mlib_s32      length,
4238                                             const void    *state)
4239 {
4240   mlib_u8  *lut = ((mlib_colormap *)state)->table;
4241   mlib_s32 thresh[4];
4242   mlib_s32 ghigh[1];
4243   mlib_s32 glow[1];
4244 
4245   thresh[0] = thresh[1] = thresh[2] = thresh[3] = lut[2];
4246 
4247   glow[0]  = (lut[1] < lut[0]) ? 0xFF : 0;
4248   ghigh[0] = (lut[1] < lut[0]) ? 0 : 0xFF;
4249 
4250   mlib_v_ImageThresh1B_U8_1((void*)src, 0, dst, 0, length, 1,
4251                             bit_offset, thresh, ghigh[0], glow[0]);
4252 }
4253 
4254 /***************************************************************/
4255 
4256 #endif
4257