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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 /***************************************************************/ |
|
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 |
|
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 |
|
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 |
|