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