0N/A/*
2362N/A * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A * FUNCTION
0N/A * mlib_ImageColorTrue2Index - convert a true color image to an indexed
0N/A * color image
0N/A *
0N/A * SYNOPSIS
0N/A * mlib_status mlib_ImageColorTrue2Index(mlib_image *dst,
0N/A * const mlib_image *src,
0N/A * const void *colormap)
0N/A *
0N/A * ARGUMENTS
0N/A * colormap Internal data structure for inverse color mapping.
0N/A * dst Pointer to destination image.
0N/A * src Pointer to source image.
0N/A *
0N/A * DESCRIPTION
0N/A * Convert a true color image to a pseudo color image with the method
0N/A * of finding the nearest matched lut entry for each pixel.
0N/A *
0N/A * The src can be an MLIB_BYTE or MLIB_SHORT image with 3 or 4 channels.
0N/A * The dst must be a 1-channel MLIB_BYTE or MLIB_SHORT image.
0N/A *
0N/A * The lut might have either 3 or 4 channels. The type of the lut can be
0N/A * one of the following:
0N/A * MLIB_BYTE in, MLIB_BYTE out (i.e., BYTE-to-BYTE)
0N/A * MLIB_BYTE in, MLIB_SHORT out (i.e., BYTE-to-SHORT)
0N/A * MLIB_SHORT in, MLIB_SHORT out (i.e., SHORT-to-SHORT)
0N/A * MLIB_SHORT in, MLIB_BYTE out (i.e., SHORT-to-BYTE)
0N/A *
0N/A * The src image and the lut must have same number of channels.
0N/A */
0N/A
0N/A#include "mlib_image.h"
0N/A#include "mlib_ImageColormap.h"
0N/A#include "mlib_ImageCheck.h"
0N/A
0N/A/***************************************************************/
0N/A
0N/A/*#define USE_VIS_CODE*/
0N/A
0N/A#ifdef USE_VIS_CODE
0N/A#include "vis_proto.h"
0N/A#define VIS_ALIGNADDR(X, Y) vis_alignaddr((void *)(X), (Y))
0N/A#endif
0N/A
0N/A/***************************************************************/
0N/A
0N/A#define LUT_BYTE_COLORS_3CHANNELS 1000
0N/A#define LUT_BYTE_COLORS_4CHANNELS 3000
0N/A#define LUT_SHORT_COLORS_3CHANNELS 1000
0N/A#define LUT_SHORT_COLORS_4CHANNELS 1000
0N/A
0N/A/***************************************************************/
0N/A
0N/A#define MAIN_COLORTRUE2INDEX_LOOP( FROM_TYPE, TO_TYPE, NCHANNELS ) \
0N/A for( y = 0; y < height; y++ ) \
0N/A { \
0N/A mlib_ImageColorTrue2IndexLine_##FROM_TYPE##_##TO_TYPE##_##NCHANNELS( \
0N/A sdata, ddata, width, colormap ); \
0N/A \
0N/A sdata += sstride; \
0N/A ddata += dstride; \
0N/A }
0N/A
0N/A/***************************************************************/
0N/A
0N/A#define COLOR_CUBE_U8_3_SEARCH( TABLE_POINTER_TYPE, SHIFT, STEP ) \
0N/A{ \
0N/A const mlib_u8 *c0, *c1, *c2; \
0N/A TABLE_POINTER_TYPE *table = s->table; \
0N/A mlib_s32 bits = s->bits; \
0N/A mlib_s32 nbits = 8 - bits; \
0N/A mlib_s32 mask = ~( ( 1 << nbits ) - 1 ); \
0N/A mlib_s32 j; \
0N/A \
0N/A c0 = src + SHIFT; \
0N/A c1 = src + 1 + SHIFT; \
0N/A c2 = src + 2 + SHIFT; \
0N/A \
0N/A switch( bits ) \
0N/A { \
0N/A case 1: \
0N/A case 2: \
0N/A { \
0N/A mlib_s32 bits0 = 8 - bits; \
0N/A mlib_s32 bits1 = bits0 - bits; \
0N/A mlib_s32 bits2 = bits1 - bits; \
0N/A \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( *c0 & mask ) >> bits2 ) | \
0N/A ( ( *c1 & mask ) >> bits1 ) | \
0N/A ( ( *c2 & mask ) >> bits0 ) ]; \
0N/A \
0N/A c0 += STEP; \
0N/A c1 += STEP; \
0N/A c2 += STEP; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 3: \
0N/A { \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( *c0 & mask ) << 1 ) | \
0N/A ( ( *c1 & mask ) >> 2 ) | \
0N/A ( ( *c2 & mask ) >> 5 ) ]; \
0N/A \
0N/A c0 += STEP; \
0N/A c1 += STEP; \
0N/A c2 += STEP; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 4: \
0N/A { \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( *c0 & mask ) << 4 ) | \
0N/A ( *c1 & mask ) | \
0N/A ( ( *c2 & mask ) >> 4 ) ]; \
0N/A \
0N/A c0 += STEP; \
0N/A c1 += STEP; \
0N/A c2 += STEP; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 5: \
0N/A case 6: \
0N/A case 7: \
0N/A { \
0N/A mlib_s32 bits0 = 8 - bits; \
0N/A mlib_s32 bits1 = bits * 2 - 8; \
0N/A mlib_s32 bits2 = bits1 + bits; \
0N/A \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( *c0 & mask ) << bits2 ) | \
0N/A ( ( *c1 & mask ) << bits1 ) | \
0N/A ( ( *c2 & mask ) >> bits0 ) ]; \
0N/A \
0N/A c0 += STEP; \
0N/A c1 += STEP; \
0N/A c2 += STEP; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 8: \
0N/A { \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( *c0 & mask ) << 16 ) | \
0N/A ( ( *c1 & mask ) << 8 ) | \
0N/A ( *c2 & mask ) ]; \
0N/A \
0N/A c0 += STEP; \
0N/A c1 += STEP; \
0N/A c2 += STEP; \
0N/A } \
0N/A break; \
0N/A } \
0N/A } \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define COLOR_CUBE_U8_4_SEARCH( TABLE_TYPE ) \
0N/A{ \
0N/A const mlib_u8 *c0, *c1, *c2, *c3; \
0N/A TABLE_TYPE *table = s->table; \
0N/A mlib_s32 bits = s->bits; \
0N/A mlib_s32 nbits = 8 - bits; \
0N/A mlib_s32 mask = ~( ( 1 << nbits ) - 1 ); \
0N/A mlib_s32 j; \
0N/A \
0N/A c0 = src; \
0N/A c1 = src + 1; \
0N/A c2 = src + 2; \
0N/A c3 = src + 3; \
0N/A \
0N/A switch( bits ) \
0N/A { \
0N/A case 1: \
0N/A { \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( *c0 & mask ) >> 4 ) | \
0N/A ( ( *c1 & mask ) >> 5 ) | \
0N/A ( ( *c2 & mask ) >> 6 ) | \
0N/A ( ( *c3 & mask ) >> 7 ) ]; \
0N/A \
0N/A c0 += 4; \
0N/A c1 += 4; \
0N/A c2 += 4; \
0N/A c3 += 4; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 2: \
0N/A { \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( *c0 & mask ) | \
0N/A ( ( *c1 & mask ) >> 2 ) | \
0N/A ( ( *c2 & mask ) >> 4 ) | \
0N/A ( ( *c3 & mask ) >> 6 ) ]; \
0N/A \
0N/A c0 += 4; \
0N/A c1 += 4; \
0N/A c2 += 4; \
0N/A c3 += 4; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 3: \
0N/A { \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( *c0 & mask ) << 4 ) | \
0N/A ( ( *c1 & mask ) << 1 ) | \
0N/A ( ( *c2 & mask ) >> 2 ) | \
0N/A ( ( *c3 & mask ) >> 5 ) ]; \
0N/A \
0N/A c0 += 4; \
0N/A c1 += 4; \
0N/A c2 += 4; \
0N/A c3 += 4; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 4: \
0N/A { \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( *c0 & mask ) << 8 ) | \
0N/A ( ( *c1 & mask ) << 4 ) | \
0N/A ( *c2 & mask ) | \
0N/A ( ( *c3 & mask ) >> 4 ) ]; \
0N/A \
0N/A c0 += 4; \
0N/A c1 += 4; \
0N/A c2 += 4; \
0N/A c3 += 4; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 5: \
0N/A case 6: \
0N/A { \
0N/A mlib_s32 bits3 = bits * 4 - 8; \
0N/A mlib_s32 bits2 = bits3 - bits; \
0N/A mlib_s32 bits1 = bits2 - bits; \
0N/A mlib_s32 bits0 = 8 - bits; \
0N/A \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( *c0 & mask ) << bits3 ) | \
0N/A ( ( *c1 & mask ) << bits2 ) | \
0N/A ( ( *c2 & mask ) << bits1 ) | \
0N/A ( ( *c3 & mask ) >> bits0 ) ]; \
0N/A \
0N/A c0 += 4; \
0N/A c1 += 4; \
0N/A c2 += 4; \
0N/A c3 += 4; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 7: \
0N/A { \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( *c0 & mask ) << 20 ) | \
0N/A ( ( *c1 & mask ) << 13 ) | \
0N/A ( ( *c2 & mask ) << 6 ) | \
0N/A ( ( *c3 & mask ) >> 1 ) ]; \
0N/A \
0N/A c0 += 4; \
0N/A c1 += 4; \
0N/A c2 += 4; \
0N/A c3 += 4; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 8: /* will never be called */ \
0N/A { \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( *c0 & mask ) << 24 ) | \
0N/A ( ( *c1 & mask ) << 16 ) | \
0N/A ( ( *c2 & mask ) << 8 ) | \
0N/A ( *c3 & mask ) ]; \
0N/A \
0N/A c0 += 4; \
0N/A c1 += 4; \
0N/A c2 += 4; \
0N/A c3 += 4; \
0N/A } \
0N/A break; \
0N/A } \
0N/A } \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define COLOR_CUBE_S16_3_SEARCH( TABLE_TYPE, SHIFT, STEP ) \
0N/A{ \
0N/A const mlib_s16 *c0, *c1, *c2; \
0N/A mlib_s32 bits = s->bits; \
0N/A mlib_s32 nbits = 16 - bits; \
0N/A mlib_s32 mask = ~( ( 1 << nbits ) - 1 ); \
0N/A TABLE_TYPE *table = s->table; \
0N/A mlib_s32 j; \
0N/A \
0N/A c0 = src + SHIFT; \
0N/A c1 = src + 1 + SHIFT; \
0N/A c2 = src + 2 + SHIFT; \
0N/A \
0N/A switch( bits ) \
0N/A { \
0N/A case 1: \
0N/A case 2: \
0N/A case 3: \
0N/A case 4: \
0N/A case 5: \
0N/A { \
0N/A mlib_s32 bits0 = 16 - bits; \
0N/A mlib_s32 bits1 = bits0 - bits; \
0N/A mlib_s32 bits2 = bits1 - bits; \
0N/A \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) >> bits2 ) | \
0N/A ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> bits1 ) | \
0N/A ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits0 ) ]; \
0N/A \
0N/A c0 += STEP; \
0N/A c1 += STEP; \
0N/A c2 += STEP; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 6: \
0N/A case 7: \
0N/A { \
0N/A mlib_s32 bits0 = 16 - bits; \
0N/A mlib_s32 bits1 = bits0 - bits; \
0N/A mlib_s32 bits2 = bits * 3 - 16; \
0N/A \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << bits2 ) | \
0N/A ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> bits1 ) | \
0N/A ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits0 ) ]; \
0N/A \
0N/A c0 += STEP; \
0N/A c1 += STEP; \
0N/A c2 += STEP; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 8: \
0N/A { \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << 8 ) | \
0N/A ( ( *c1 - MLIB_S16_MIN ) & mask ) | \
0N/A ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> 8 ) ]; \
0N/A \
0N/A c0 += STEP; \
0N/A c1 += STEP; \
0N/A c2 += STEP; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 9: \
0N/A case 10: \
0N/A { \
0N/A mlib_s32 bits0 = 16 - bits; \
0N/A mlib_s32 bits1 = 2 * bits - 16; \
0N/A mlib_s32 bits2 = bits1 + bits; \
0N/A \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << bits2 ) | \
0N/A ( ( ( *c1 - MLIB_S16_MIN ) & mask ) << bits1 ) | \
0N/A ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits0 ) ]; \
0N/A \
0N/A c0 += STEP; \
0N/A c1 += STEP; \
0N/A c2 += STEP; \
0N/A } \
0N/A break; \
0N/A } \
0N/A /* Other cases may not be considered as the table size will be more \
0N/A than 2^32 */ \
0N/A } \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define COLOR_CUBE_S16_4_SEARCH( TABLE_TYPE ) \
0N/A{ \
0N/A const mlib_s16 *c0, *c1, *c2, *c3; \
0N/A TABLE_TYPE *table = s->table; \
0N/A mlib_s32 bits = s->bits; \
0N/A mlib_s32 nbits = 16 - bits; \
0N/A mlib_s32 mask = ~( ( 1 << nbits ) - 1 ); \
0N/A mlib_s32 j; \
0N/A \
0N/A c0 = src; \
0N/A c1 = src + 1; \
0N/A c2 = src + 2; \
0N/A c3 = src + 3; \
0N/A \
0N/A switch( bits ) \
0N/A { \
0N/A case 1: \
0N/A case 2: \
0N/A case 3: \
0N/A { \
0N/A mlib_s32 bits0 = 16 - bits; \
0N/A mlib_s32 bits1 = bits0 - bits; \
0N/A mlib_s32 bits2 = bits1 - bits; \
0N/A mlib_s32 bits3 = bits2 - bits; \
0N/A \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) >> bits3 ) | \
0N/A ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> bits2 ) | \
0N/A ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits1 ) | \
0N/A ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> bits0 ) ]; \
0N/A \
0N/A c0 += 4; \
0N/A c1 += 4; \
0N/A c2 += 4; \
0N/A c3 += 4; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 4: \
0N/A { \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( *c0 - MLIB_S16_MIN ) & mask ) | \
0N/A ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> 4 ) | \
0N/A ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> 8 ) | \
0N/A ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> 12 ) ]; \
0N/A \
0N/A c0 += 4; \
0N/A c1 += 4; \
0N/A c2 += 4; \
0N/A c3 += 4; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 5: \
0N/A { \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << 4 ) | \
0N/A ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> 1 ) | \
0N/A ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> 6 ) | \
0N/A ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> 11 ) ]; \
0N/A \
0N/A c0 += 4; \
0N/A c1 += 4; \
0N/A c2 += 4; \
0N/A c3 += 4; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 6: \
0N/A case 7: \
0N/A { \
0N/A mlib_s32 bits0 = 16 - bits; \
0N/A mlib_s32 bits1 = bits0 - bits; \
0N/A mlib_s32 bits3 = bits * 4 - 16; \
0N/A mlib_s32 bits2 = bits3 - bits; \
0N/A \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << bits3 ) | \
0N/A ( ( ( *c1 - MLIB_S16_MIN ) & mask ) << bits2 ) | \
0N/A ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits1 ) | \
0N/A ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> bits0 ) ]; \
0N/A \
0N/A c0 += 4; \
0N/A c1 += 4; \
0N/A c2 += 4; \
0N/A c3 += 4; \
0N/A } \
0N/A break; \
0N/A } \
0N/A case 8: \
0N/A { \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << 16 ) | \
0N/A ( ( ( *c1 - MLIB_S16_MIN ) & mask ) << 8 ) | \
0N/A ( ( *c2 - MLIB_S16_MIN ) & mask ) | \
0N/A ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> 8 ) ]; \
0N/A \
0N/A c0 += 4; \
0N/A c1 += 4; \
0N/A c2 += 4; \
0N/A c3 += 4; \
0N/A } \
0N/A break; \
0N/A } \
0N/A /* Other cases may not be considered as the table size will be more \
0N/A than 2^32 */ \
0N/A } \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define BINARY_TREE_SEARCH_RIGHT( POSITION, COLOR_MAX, SHIFT ) \
0N/A{ \
0N/A if( ( distance >= ( ( ( position[ POSITION ] + current_size - \
0N/A c[ POSITION ] ) * ( position[ POSITION ] + current_size - \
0N/A c[ POSITION ] ) ) >> SHIFT ) ) && \
0N/A ( position[ POSITION ] + current_size != COLOR_MAX ) ) \
0N/A continue_up = 1; \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define BINARY_TREE_EXPLORE_RIGHT_3( POSITION, COLOR_MAX, IMAGE_TYPE, \
0N/A FIRST_NEIBOUR, SECOND_NEIBOUR, SUBSTRACTION, SHIFT ) \
0N/A{ \
0N/A if( distance >= ( ( ( position[ POSITION ] + current_size - \
0N/A c[ POSITION ] ) * ( position[ POSITION ] + \
0N/A current_size - c[ POSITION ] ) ) >> SHIFT ) ) \
0N/A { \
0N/A if( distance < ( ( ( COLOR_MAX - c[ POSITION ] ) * \
0N/A ( COLOR_MAX - c[ POSITION ] ) ) >> SHIFT ) ) \
0N/A { \
0N/A if( distance < ( ( ( position[ POSITION ] + \
0N/A current_size * 2 - c[ POSITION ] ) * \
0N/A ( position[ POSITION ] + current_size * 2 - \
0N/A c[ POSITION ] ) ) >> SHIFT ) ) \
0N/A { \
0N/A /* Check only a part of quadrant */ \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 1; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 1; \
0N/A check_corner += 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Only a part of quadrant needs checking */ \
0N/A distance = \
0N/A mlib_search_quadrant_part_to_left_##IMAGE_TYPE##_3( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c, p, \
0N/A position[ POSITION ] + current_size, pass - 1, POSITION ); \
0N/A } \
0N/A else /* Check whole quadrant */ \
0N/A { \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 2; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 2; \
0N/A check_corner += 2; \
0N/A continue_up = 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Here is a full node. Just explore it */ \
0N/A distance = mlib_search_quadrant_##IMAGE_TYPE##_3( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], p ); \
0N/A } \
0N/A } \
0N/A else /* Cell is on the edge of the space */ \
0N/A { \
0N/A if( position[ POSITION ] + current_size * 2 == \
0N/A COLOR_MAX ) \
0N/A { \
0N/A /* Check only a part of quadrant */ \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 1; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 1; \
0N/A check_corner += 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Only a part of quadrant needs checking */ \
0N/A distance = \
0N/A mlib_search_quadrant_part_to_left_##IMAGE_TYPE##_3( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c, p, \
0N/A position[ POSITION ] + current_size, \
0N/A pass - 1, POSITION ); \
0N/A } \
0N/A else /* Check whole quadrant */ \
0N/A { \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 2; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 2; \
0N/A check_corner += 2; \
0N/A continue_up = 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Here is a full node. Just explore it */ \
0N/A distance = mlib_search_quadrant_##IMAGE_TYPE##_3( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], p ); \
0N/A } \
0N/A } \
0N/A } \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define BINARY_TREE_EXPLORE_RIGHT_4( POSITION, COLOR_MAX, IMAGE_TYPE, \
0N/A FIRST_NEIBOUR, SECOND_NEIBOUR, THIRD_NEIBOUR, SUBSTRACTION, SHIFT ) \
0N/A{ \
0N/A if( distance >= ( ( ( position[ POSITION ] + current_size - \
0N/A c[ POSITION ] ) * ( position[ POSITION ] + \
0N/A current_size - c[ POSITION ] ) ) >> SHIFT ) ) \
0N/A { \
0N/A if( distance < ( ( ( COLOR_MAX - c[ POSITION ] ) * \
0N/A ( COLOR_MAX - c[ POSITION ] ) ) >> SHIFT ) ) \
0N/A { \
0N/A if( distance < ( ( ( position[ POSITION ] + \
0N/A current_size * 2 - c[ POSITION ] ) * \
0N/A ( position[ POSITION ] + current_size * 2 - \
0N/A c[ POSITION ] ) ) >> SHIFT ) ) \
0N/A { \
0N/A /* Check only a part of quadrant */ \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 1; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 1; \
0N/A check_neibours[ THIRD_NEIBOUR ] += 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ], \
0N/A p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Only a part of quadrant needs checking */ \
0N/A distance = \
0N/A mlib_search_quadrant_part_to_left_##IMAGE_TYPE##_4( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c, p, \
0N/A position[ POSITION ] + current_size, pass - 1, POSITION ); \
0N/A } \
0N/A else /* Check whole quadrant */ \
0N/A { \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 2; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 2; \
0N/A check_neibours[ THIRD_NEIBOUR ] += 2; \
0N/A continue_up = 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ], \
0N/A p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Here is a full node. Just explore it */ \
0N/A distance = mlib_search_quadrant_##IMAGE_TYPE##_4( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p ); \
0N/A } \
0N/A } \
0N/A else /* Cell is on the edge of the space */ \
0N/A { \
0N/A if( position[ POSITION ] + current_size * 2 == \
0N/A COLOR_MAX ) \
0N/A { \
0N/A /* Check only a part of quadrant */ \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 1; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 1; \
0N/A check_neibours[ THIRD_NEIBOUR ] += 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ], \
0N/A p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Only a part of quadrant needs checking */ \
0N/A distance = \
0N/A mlib_search_quadrant_part_to_left_##IMAGE_TYPE##_4( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c, p, \
0N/A position[ POSITION ] + current_size, \
0N/A pass - 1, POSITION ); \
0N/A } \
0N/A else /* Check whole quadrant */ \
0N/A { \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 2; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 2; \
0N/A check_neibours[ THIRD_NEIBOUR ] += 2; \
0N/A continue_up = 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ], \
0N/A p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Here is a full node. Just explore it */ \
0N/A distance = mlib_search_quadrant_##IMAGE_TYPE##_4( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p ); \
0N/A } \
0N/A } \
0N/A } \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define BINARY_TREE_SEARCH_LEFT( POSITION, SHIFT ) \
0N/A{ \
0N/A if( ( distance > ( ( ( position[ POSITION ] - c[ POSITION ] ) * \
0N/A ( position[ POSITION ] - c[ POSITION ] ) ) >> SHIFT ) ) && \
0N/A position[ POSITION ] ) \
0N/A continue_up = 1; \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define BINARY_TREE_EXPLORE_LEFT_3( POSITION, IMAGE_TYPE, \
0N/A FIRST_NEIBOUR, SECOND_NEIBOUR, SUBSTRACTION, SHIFT ) \
0N/A{ \
0N/A if( distance > \
0N/A ( ( ( c[ POSITION ] - position[ POSITION ] ) * \
0N/A ( c[ POSITION ] - position[ POSITION ] ) ) >> SHIFT ) ) \
0N/A { \
0N/A if( distance <= ( ( c[ POSITION ] * c[ POSITION ] ) >> SHIFT ) ) \
0N/A { \
0N/A if( distance <= ( ( ( c[ POSITION ] + current_size - \
0N/A position[ POSITION ] ) * \
0N/A ( c[ POSITION ] + current_size - \
0N/A position[ POSITION ] ) ) >> SHIFT ) ) \
0N/A { \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 1; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 1; \
0N/A check_corner += 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Only a part of quadrant needs checking */ \
0N/A distance = \
0N/A mlib_search_quadrant_part_to_right_##IMAGE_TYPE##_3( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c, p, \
0N/A position[ POSITION ] - current_size, pass - 1, POSITION ); \
0N/A } \
0N/A else /* Check whole quadrant */ \
0N/A { \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 2; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 2; \
0N/A check_corner += 2; \
0N/A continue_up = 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Here is a full node. Just explore it */ \
0N/A distance = mlib_search_quadrant_##IMAGE_TYPE##_3( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], p ); \
0N/A } \
0N/A } \
0N/A else \
0N/A { \
0N/A if( !( position[ POSITION ] - current_size ) ) \
0N/A { \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 1; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 1; \
0N/A check_corner += 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Only a part of quadrant needs checking */ \
0N/A distance = \
0N/A mlib_search_quadrant_part_to_right_##IMAGE_TYPE##_3( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c, p, \
0N/A position[ POSITION ] - current_size, pass - 1, POSITION ); \
0N/A } \
0N/A else \
0N/A { \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 2; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 2; \
0N/A check_corner += 2; \
0N/A continue_up = 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Here is a full node. Just explore it */ \
0N/A distance = mlib_search_quadrant_##IMAGE_TYPE##_3( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], p ); \
0N/A } \
0N/A } \
0N/A } \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define BINARY_TREE_EXPLORE_LEFT_4( POSITION, IMAGE_TYPE, \
0N/A FIRST_NEIBOUR, SECOND_NEIBOUR, THIRD_NEIBOUR, SUBSTRACTION, SHIFT ) \
0N/A{ \
0N/A if( distance > \
0N/A ( ( ( c[ POSITION ] - position[ POSITION ] ) * \
0N/A ( c[ POSITION ] - position[ POSITION ] ) ) >> SHIFT ) ) \
0N/A { \
0N/A if( distance <= ( ( c[ POSITION ] * c[ POSITION ] ) >> SHIFT ) ) \
0N/A { \
0N/A if( distance <= ( ( ( c[ POSITION ] + current_size - \
0N/A position[ POSITION ] ) * \
0N/A ( c[ POSITION ] + current_size - \
0N/A position[ POSITION ] ) ) >> SHIFT ) ) \
0N/A { \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 1; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 1; \
0N/A check_neibours[ THIRD_NEIBOUR ] += 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ], \
0N/A p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Only a part of quadrant needs checking */ \
0N/A distance = \
0N/A mlib_search_quadrant_part_to_right_##IMAGE_TYPE##_4( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c, p, \
0N/A position[ POSITION ] - current_size, pass - 1, POSITION ); \
0N/A } \
0N/A else /* Check whole quadrant */ \
0N/A { \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 2; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 2; \
0N/A check_neibours[ THIRD_NEIBOUR ] += 2; \
0N/A continue_up = 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ], \
0N/A p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Here is a full node. Just explore it */ \
0N/A distance = mlib_search_quadrant_##IMAGE_TYPE##_4( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p ); \
0N/A } \
0N/A } \
0N/A else \
0N/A { \
0N/A if( !( position[ POSITION ] - current_size ) ) \
0N/A { \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 1; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 1; \
0N/A check_neibours[ THIRD_NEIBOUR ] += 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ], \
0N/A p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Only a part of quadrant needs checking */ \
0N/A distance = \
0N/A mlib_search_quadrant_part_to_right_##IMAGE_TYPE##_4( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c, p, \
0N/A position[ POSITION ] - current_size, pass - 1, POSITION ); \
0N/A } \
0N/A else \
0N/A { \
0N/A mlib_s32 qq = q ^ ( 1 << POSITION ); \
0N/A \
0N/A check_neibours[ FIRST_NEIBOUR ] += 2; \
0N/A check_neibours[ SECOND_NEIBOUR ] += 2; \
0N/A check_neibours[ THIRD_NEIBOUR ] += 2; \
0N/A continue_up = 1; \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. \
0N/A Check the distance */ \
0N/A mlib_s32 new_found_color = \
0N/A node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ], \
0N/A p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ], \
0N/A p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ], \
0N/A p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Here is a full node. Just explore it */ \
0N/A distance = mlib_search_quadrant_##IMAGE_TYPE##_4( \
0N/A node->contents.quadrants[ qq ], \
0N/A distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p ); \
0N/A } \
0N/A } \
0N/A } \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define CHECK_QUADRANT_U8_3( qq ) \
0N/A{ \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. Check the distance */ \
0N/A mlib_s32 new_found_color = node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ], c[ 1 ], \
0N/A p[ 1 ][ new_found_color ], c[ 2 ], \
0N/A p[ 2 ][ new_found_color ], 0 ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Here is a full node. Just explore it all */ \
0N/A distance = mlib_search_quadrant_U8_3( \
0N/A node->contents.quadrants[ qq ], distance, &found_color, \
0N/A c[ 0 ], c[ 1 ], c[ 2 ], p ); \
0N/A/* Else there is just an empty cell */ \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define CHECK_QUADRANT_S16_3( qq ) \
0N/A{ \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. Check the distance */ \
0N/A mlib_s32 new_found_color = node->contents.index[ qq ]; \
0N/A mlib_u32 palc0, palc1, palc2, newdistance; \
0N/A \
0N/A palc0 = p[ 0 ][ new_found_color ] - MLIB_S16_MIN; \
0N/A palc1 = p[ 1 ][ new_found_color ] - MLIB_S16_MIN; \
0N/A palc2 = p[ 2 ][ new_found_color ] - MLIB_S16_MIN; \
0N/A \
0N/A newdistance = FIND_DISTANCE_3( c[ 0 ], palc0, \
0N/A c[ 1 ], palc1, \
0N/A c[ 2 ], palc2, 2 ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Here is a full node. Just explore it all */ \
0N/A distance = mlib_search_quadrant_S16_3( \
0N/A node->contents.quadrants[ qq ], distance, &found_color, \
0N/A c[ 0 ], c[ 1 ], c[ 2 ], p ); \
0N/A/* Else there is just an empty cell */ \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define BINARY_TREE_SEARCH_3( SOURCE_IMAGE, POINTER_TYPE, BITS, \
0N/A COLOR_MAX, SUBTRACTION, POINTER_SHIFT, STEP, SHIFT ) \
0N/A{ \
0N/A const POINTER_TYPE *channels[ 3 ], *p[ 3 ]; \
0N/A mlib_u32 c[ 3 ]; \
0N/A mlib_s32 j; \
0N/A \
0N/A p[ 0 ] = s->lut[ 0 ]; \
0N/A p[ 1 ] = s->lut[ 1 ]; \
0N/A p[ 2 ] = s->lut[ 2 ]; \
0N/A channels[ 0 ] = src + POINTER_SHIFT; \
0N/A channels[ 1 ] = src + 1 + POINTER_SHIFT; \
0N/A channels[ 2 ] = src + 2 + POINTER_SHIFT; \
0N/A \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A mlib_s32 pass = BITS - 1; \
0N/A mlib_u32 position[ 3 ] = { 0, 0, 0 }; \
0N/A mlib_s32 we_found_it = 0; \
0N/A struct lut_node_3 *node = s->table; \
0N/A /* Stack pointer pointers to the first free element of stack. */ \
0N/A /* The node we are in is in the `node' */ \
0N/A struct \
0N/A { \
0N/A struct lut_node_3 *node; \
0N/A mlib_s32 q; \
0N/A } stack[ BITS ]; \
0N/A mlib_s32 stack_pointer = 0; \
0N/A \
0N/A c[ 0 ] = *channels[ 0 ] - SUBTRACTION; \
0N/A c[ 1 ] = *channels[ 1 ] - SUBTRACTION; \
0N/A c[ 2 ] = *channels[ 2 ] - SUBTRACTION; \
0N/A \
0N/A do \
0N/A { \
0N/A mlib_s32 q; \
0N/A mlib_u32 current_size = 1 << pass; \
0N/A \
0N/A q = ( ( c[ 0 ] >> pass ) & 1 ) | \
0N/A ( ( ( c[ 1 ] << 1 ) >> pass ) & 2 ) | \
0N/A ( ( ( c[ 2 ] << 2 ) >> pass ) & 4 ); \
0N/A \
0N/A position[ 0 ] |= c[ 0 ] & current_size; \
0N/A position[ 1 ] |= c[ 1 ] & current_size; \
0N/A position[ 2 ] |= c[ 2 ] & current_size; \
0N/A \
0N/A if( node->tag & ( 1 << q ) ) \
0N/A { \
0N/A /* \
0N/A Here is a cell with one color. We need to be sure it's \
0N/A the one that is the closest to our color \
0N/A */ \
0N/A mlib_s32 palindex = node->contents.index[ q ]; \
0N/A mlib_u32 palc[ 3 ]; \
0N/A mlib_s32 identical; \
0N/A \
0N/A palc[ 0 ] = p[ 0 ][ palindex ] - SUBTRACTION; \
0N/A palc[ 1 ] = p[ 1 ][ palindex ] - SUBTRACTION; \
0N/A palc[ 2 ] = p[ 2 ][ palindex ] - SUBTRACTION; \
0N/A \
0N/A identical = ( palc[ 0 ] - c[ 0 ] ) | ( palc[ 1 ] - c[ 1 ] ) | \
0N/A ( palc[ 2 ] - c[ 2 ] ); \
0N/A \
0N/A if( !identical || BITS - pass == bits ) \
0N/A { \
0N/A /* Oh, here it is :) */ \
0N/A dst[ j ] = palindex + s->offset; \
0N/A we_found_it = 1; \
0N/A } \
0N/A else \
0N/A { \
0N/A mlib_u32 distance; \
0N/A /* First index is the channel, second is the number of the \
0N/A side */ \
0N/A mlib_s32 found_color; \
0N/A mlib_s32 continue_up; \
0N/A \
0N/A distance = FIND_DISTANCE_3( c[ 0 ], palc[ 0 ], \
0N/A c[ 1 ], palc[ 1 ], c[ 2 ], palc[ 2 ], SHIFT ); \
0N/A found_color = palindex; \
0N/A \
0N/A do \
0N/A { \
0N/A mlib_s32 check_corner; \
0N/A \
0N/A /* \
0N/A Neibours are enumerated in a cicle: \
0N/A 0 - between quadrants 0 and 1, \
0N/A 1 - between quadrants 1 and 2 and \
0N/A 2 - between quadrants 2 and 0 \
0N/A */ \
0N/A mlib_s32 check_neibours[ 3 ]; \
0N/A \
0N/A /* \
0N/A Others are three two neibour quadrants \
0N/A \
0N/A Side number is [ <number of the coordinate >][ <the bit \
0N/A in the quadrant number of the corner, corresponding to \
0N/A this coordinate> ], e.g. 2 is 0..010b, so the sides it has \
0N/A near are: \
0N/A [ 0 (coordinate number) ][ 0 (bit 0 in the number) ] \
0N/A [ 1 (coordinate number) ][ 1 (bit 1 in the number) ] \
0N/A \
0N/A Now we can look in the three nearest quadrants. Do \
0N/A we really need it ? Check it. \
0N/A */ \
0N/A \
0N/A check_corner = check_neibours[ 0 ] = check_neibours[ 1 ] = \
0N/A check_neibours[ 2 ] = 0; \
0N/A continue_up = 0; \
0N/A \
0N/A if( q & 1 ) \
0N/A { \
0N/A BINARY_TREE_EXPLORE_LEFT_3( 0, SOURCE_IMAGE, 2, 0, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_EXPLORE_RIGHT_3( 0, COLOR_MAX, SOURCE_IMAGE, 2, 0, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 2 ) \
0N/A { \
0N/A BINARY_TREE_EXPLORE_LEFT_3( 1, SOURCE_IMAGE, 0, 1, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_EXPLORE_RIGHT_3( 1, COLOR_MAX, SOURCE_IMAGE, 0, 1, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 4 ) \
0N/A { \
0N/A BINARY_TREE_EXPLORE_LEFT_3( 2, SOURCE_IMAGE, 1, 2, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_EXPLORE_RIGHT_3( 2, COLOR_MAX, SOURCE_IMAGE, 1, 2, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 0 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 3; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 1 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 6; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 2 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 5; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq ); \
0N/A } \
0N/A \
0N/A if( check_corner >= 3 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 7; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq ); \
0N/A } \
0N/A \
0N/A if( q & 1 ) \
0N/A { \
0N/A BINARY_TREE_SEARCH_RIGHT( 0, COLOR_MAX, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_SEARCH_LEFT( 0, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 2 ) \
0N/A { \
0N/A BINARY_TREE_SEARCH_RIGHT( 1, COLOR_MAX, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_SEARCH_LEFT( 1, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 4 ) \
0N/A { \
0N/A BINARY_TREE_SEARCH_RIGHT( 2, COLOR_MAX, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_SEARCH_LEFT( 2, SHIFT ); \
0N/A } \
0N/A \
0N/A position[ 0 ] &= ~( c[ 0 ] & current_size ); \
0N/A position[ 1 ] &= ~( c[ 1 ] & current_size ); \
0N/A position[ 2 ] &= ~( c[ 2 ] & current_size ); \
0N/A \
0N/A current_size <<= 1; \
0N/A \
0N/A pass++; \
0N/A \
0N/A stack_pointer--; \
0N/A q = stack[ stack_pointer ].q; \
0N/A node = stack[ stack_pointer ].node; \
0N/A } while( continue_up ); \
0N/A \
0N/A dst[ j ] = found_color + s->offset; \
0N/A \
0N/A we_found_it = 1; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ q ] ) \
0N/A { \
0N/A /* Descend one level */ \
0N/A stack[ stack_pointer ].node = node; \
0N/A stack[ stack_pointer++ ].q = q; \
0N/A node = node->contents.quadrants[ q ]; \
0N/A } \
0N/A else \
0N/A { \
0N/A /* Found the empty quadrant. Look around */ \
0N/A mlib_u32 distance = MLIB_U32_MAX; \
0N/A mlib_s32 found_color; \
0N/A mlib_s32 continue_up; \
0N/A \
0N/A /* \
0N/A As we had come to this level, it is warranted that there \
0N/A are other points on this level near the empty quadrant \
0N/A */ \
0N/A do \
0N/A { \
0N/A mlib_s32 check_corner; \
0N/A mlib_s32 check_neibours[ 3 ]; \
0N/A \
0N/A check_corner = check_neibours[ 0 ] = check_neibours[ 1 ] = \
0N/A check_neibours[ 2 ] = 0; \
0N/A continue_up = 0; \
0N/A \
0N/A if( q & 1 ) \
0N/A { \
0N/A BINARY_TREE_EXPLORE_LEFT_3( 0, SOURCE_IMAGE, 2, 0, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_EXPLORE_RIGHT_3( 0, COLOR_MAX, SOURCE_IMAGE, 2, 0, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 2 ) \
0N/A { \
0N/A BINARY_TREE_EXPLORE_LEFT_3( 1, SOURCE_IMAGE, 0, 1, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_EXPLORE_RIGHT_3( 1, COLOR_MAX, SOURCE_IMAGE, 0, 1, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 4 ) \
0N/A { \
0N/A BINARY_TREE_EXPLORE_LEFT_3( 2, SOURCE_IMAGE, 1, 2, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_EXPLORE_RIGHT_3( 2, COLOR_MAX, SOURCE_IMAGE, 1, 2, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 0 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 3; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 1 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 6; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 2 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 5; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq ); \
0N/A } \
0N/A \
0N/A if( check_corner >= 3 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 7; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_3( qq ); \
0N/A } \
0N/A \
0N/A if( q & 1 ) \
0N/A { \
0N/A BINARY_TREE_SEARCH_RIGHT( 0, COLOR_MAX, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_SEARCH_LEFT( 0, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 2 ) \
0N/A { \
0N/A BINARY_TREE_SEARCH_RIGHT( 1, COLOR_MAX, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_SEARCH_LEFT( 1, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 4 ) \
0N/A { \
0N/A BINARY_TREE_SEARCH_RIGHT( 2, COLOR_MAX, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_SEARCH_LEFT( 2, SHIFT ); \
0N/A } \
0N/A \
0N/A position[ 0 ] &= ~( c[ 0 ] & current_size ); \
0N/A position[ 1 ] &= ~( c[ 1 ] & current_size ); \
0N/A position[ 2 ] &= ~( c[ 2 ] & current_size ); \
0N/A \
0N/A current_size <<= 1; \
0N/A \
0N/A pass++; \
0N/A \
0N/A stack_pointer--; \
0N/A q = stack[ stack_pointer ].q; \
0N/A node = stack[ stack_pointer ].node; \
0N/A } while( continue_up ); \
0N/A \
0N/A dst[ j ] = found_color + s->offset; \
0N/A we_found_it = 1; \
0N/A } \
0N/A \
0N/A pass--; \
0N/A \
0N/A } while( !we_found_it ); \
0N/A \
0N/A channels[ 0 ] += STEP; \
0N/A channels[ 1 ] += STEP; \
0N/A channels[ 2 ] += STEP; \
0N/A } \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define CHECK_QUADRANT_U8_4( qq ) \
0N/A{ \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. Check the distance */ \
0N/A mlib_s32 new_found_color = node->contents.index[ qq ]; \
0N/A mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ], \
0N/A p[ 0 ][ new_found_color ], c[ 1 ], \
0N/A p[ 1 ][ new_found_color ], c[ 2 ], \
0N/A p[ 2 ][ new_found_color ], c[ 3 ], \
0N/A p[ 3 ][ new_found_color ], 0 ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Here is a full node. Just explore it all */ \
0N/A distance = mlib_search_quadrant_U8_4( \
0N/A node->contents.quadrants[ qq ], distance, &found_color, \
0N/A c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p ); \
0N/A/* Else there is just an empty cell */ \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define CHECK_QUADRANT_S16_4( qq ) \
0N/A{ \
0N/A if( node->tag & ( 1 << qq ) ) \
0N/A { \
0N/A /* Here is another color cell. Check the distance */ \
0N/A mlib_s32 new_found_color = node->contents.index[ qq ]; \
0N/A mlib_u32 palc0, palc1, palc2, palc3, newdistance; \
0N/A \
0N/A palc0 = p[ 0 ][ new_found_color ] - MLIB_S16_MIN; \
0N/A palc1 = p[ 1 ][ new_found_color ] - MLIB_S16_MIN; \
0N/A palc2 = p[ 2 ][ new_found_color ] - MLIB_S16_MIN; \
0N/A palc3 = p[ 3 ][ new_found_color ] - MLIB_S16_MIN; \
0N/A \
0N/A newdistance = FIND_DISTANCE_4( c[ 0 ], palc0, \
0N/A c[ 1 ], palc1, \
0N/A c[ 2 ], palc2, \
0N/A c[ 3 ], palc3, 2 ); \
0N/A \
0N/A if( newdistance < distance ) \
0N/A { \
0N/A found_color = new_found_color; \
0N/A distance = newdistance; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ qq ] ) \
0N/A /* Here is a full node. Just explore it all */ \
0N/A distance = mlib_search_quadrant_S16_4( \
0N/A node->contents.quadrants[ qq ], distance, &found_color, \
0N/A c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p ); \
0N/A/* Else there is just an empty cell */ \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define BINARY_TREE_SEARCH_4( SOURCE_IMAGE, POINTER_TYPE, BITS, \
0N/A COLOR_MAX, SUBTRACTION, SHIFT ) \
0N/A{ \
0N/A const POINTER_TYPE *channels[ 4 ], *p[ 4 ]; \
0N/A mlib_u32 c[ 4 ]; \
0N/A mlib_s32 j; \
0N/A \
0N/A p[ 0 ] = s->lut[ 0 ]; \
0N/A p[ 1 ] = s->lut[ 1 ]; \
0N/A p[ 2 ] = s->lut[ 2 ]; \
0N/A p[ 3 ] = s->lut[ 3 ]; \
0N/A channels[ 0 ] = src; \
0N/A channels[ 1 ] = src + 1; \
0N/A channels[ 2 ] = src + 2; \
0N/A channels[ 3 ] = src + 3; \
0N/A \
0N/A for( j = 0; j < length; j++ ) \
0N/A { \
0N/A mlib_s32 pass = BITS - 1; \
0N/A mlib_u32 position[ 4 ] = { 0, 0, 0, 0 }; \
0N/A mlib_s32 we_found_it = 0; \
0N/A struct lut_node_4 *node = s->table; \
0N/A /* Stack pointer pointers to the first free element of stack. */ \
0N/A /* The node we are in is in the `node' */ \
0N/A struct \
0N/A { \
0N/A struct lut_node_4 *node; \
0N/A mlib_s32 q; \
0N/A } stack[ BITS ]; \
0N/A mlib_s32 stack_pointer = 0; \
0N/A \
0N/A c[ 0 ] = *channels[ 0 ] - SUBTRACTION; \
0N/A c[ 1 ] = *channels[ 1 ] - SUBTRACTION; \
0N/A c[ 2 ] = *channels[ 2 ] - SUBTRACTION; \
0N/A c[ 3 ] = *channels[ 3 ] - SUBTRACTION; \
0N/A \
0N/A do \
0N/A { \
0N/A mlib_s32 q; \
0N/A mlib_u32 current_size = 1 << pass; \
0N/A \
0N/A q = ( ( c[ 0 ] >> pass ) & 1 ) | \
0N/A ( ( ( c[ 1 ] << 1 ) >> pass ) & 2 ) | \
0N/A ( ( ( c[ 2 ] << 2 ) >> pass ) & 4 ) | \
0N/A ( ( ( c[ 3 ] << 3 ) >> pass ) & 8 ); \
0N/A \
0N/A position[ 0 ] |= c[ 0 ] & current_size; \
0N/A position[ 1 ] |= c[ 1 ] & current_size; \
0N/A position[ 2 ] |= c[ 2 ] & current_size; \
0N/A position[ 3 ] |= c[ 3 ] & current_size; \
0N/A \
0N/A if( node->tag & ( 1 << q ) ) \
0N/A { \
0N/A /* \
0N/A Here is a cell with one color. We need to be sure it's \
0N/A the one that is the closest to our color \
0N/A */ \
0N/A mlib_s32 palindex = node->contents.index[ q ]; \
0N/A mlib_u32 palc[ 4 ]; \
0N/A mlib_s32 identical; \
0N/A \
0N/A palc[ 0 ] = p[ 0 ][ palindex ] - SUBTRACTION; \
0N/A palc[ 1 ] = p[ 1 ][ palindex ] - SUBTRACTION; \
0N/A palc[ 2 ] = p[ 2 ][ palindex ] - SUBTRACTION; \
0N/A palc[ 3 ] = p[ 3 ][ palindex ] - SUBTRACTION; \
0N/A \
0N/A identical = ( palc[ 0 ] - c[ 0 ] ) | ( palc[ 1 ] - c[ 1 ] ) | \
0N/A ( palc[ 2 ] - c[ 2 ] ) | ( palc[ 3 ] - c[ 3 ] ); \
0N/A \
0N/A if( !identical || BITS - pass == bits ) \
0N/A { \
0N/A /* Oh, here it is :) */ \
0N/A dst[ j ] = palindex + s->offset; \
0N/A we_found_it = 1; \
0N/A } \
0N/A else \
0N/A { \
0N/A mlib_u32 distance; \
0N/A /* First index is the channel, second is the number of the \
0N/A side */ \
0N/A mlib_s32 found_color; \
0N/A mlib_s32 continue_up; \
0N/A \
0N/A distance = FIND_DISTANCE_4( c[ 0 ], palc[ 0 ], \
0N/A c[ 1 ], palc[ 1 ], c[ 2 ], palc[ 2 ], c[ 3 ], palc[ 3 ], SHIFT ); \
0N/A found_color = palindex; \
0N/A \
0N/A do \
0N/A { \
0N/A mlib_s32 check_corner; \
0N/A mlib_s32 check_neibours[ 6 ]; \
0N/A mlib_s32 check_far_neibours[ 4 ]; \
0N/A \
0N/A /* \
0N/A Check neibours: quadrants that are different by 2 bits \
0N/A from the quadrant, that we are in: \
0N/A 3 - 0 \
0N/A 5 - 1 \
0N/A 6 - 2 \
0N/A 9 - 3 \
0N/A 10 - 4 \
0N/A 12 - 5 \
0N/A Far quadrants: different by 3 bits: \
0N/A 7 - 0 \
0N/A 11 - 1 \
0N/A 13 - 2 \
0N/A 14 - 3 \
0N/A */ \
0N/A \
0N/A check_neibours[ 0 ] = check_neibours[ 1 ] = \
0N/A check_neibours[ 2 ] = check_neibours[ 3 ] = \
0N/A check_neibours[ 4 ] = check_neibours[ 5 ] = 0; \
0N/A continue_up = 0; \
0N/A \
0N/A if( q & 1 ) \
0N/A { \
0N/A BINARY_TREE_EXPLORE_LEFT_4( 0, SOURCE_IMAGE, 0, 1, 3, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_EXPLORE_RIGHT_4( 0, COLOR_MAX, SOURCE_IMAGE, \
0N/A 0, 1, 3, SUBTRACTION, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 2 ) \
0N/A { \
0N/A BINARY_TREE_EXPLORE_LEFT_4( 1, SOURCE_IMAGE, 0, 2, 4, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_EXPLORE_RIGHT_4( 1, COLOR_MAX, SOURCE_IMAGE, \
0N/A 0, 2, 4, SUBTRACTION, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 4 ) \
0N/A { \
0N/A BINARY_TREE_EXPLORE_LEFT_4( 2, SOURCE_IMAGE, 1, 2, 5, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_EXPLORE_RIGHT_4( 2, COLOR_MAX, SOURCE_IMAGE, \
0N/A 1, 2, 5, SUBTRACTION, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 8 ) \
0N/A { \
0N/A BINARY_TREE_EXPLORE_LEFT_4( 3, SOURCE_IMAGE, 3, 4, 5, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_EXPLORE_RIGHT_4( 3, COLOR_MAX, SOURCE_IMAGE, \
0N/A 3, 4, 5, SUBTRACTION, SHIFT ); \
0N/A } \
0N/A \
0N/A check_far_neibours[ 0 ] = check_neibours[ 0 ] + \
0N/A check_neibours[ 1 ] + check_neibours[ 2 ]; \
0N/A check_far_neibours[ 1 ] = check_neibours[ 0 ] + \
0N/A check_neibours[ 3 ] + check_neibours[ 4 ]; \
0N/A check_far_neibours[ 2 ] = check_neibours[ 1 ] + \
0N/A check_neibours[ 3 ] + check_neibours[ 5 ]; \
0N/A check_far_neibours[ 3 ] = check_neibours[ 2 ] + \
0N/A check_neibours[ 4 ] + check_neibours[ 5 ]; \
0N/A \
0N/A check_corner = check_far_neibours[ 0 ] + \
0N/A check_far_neibours[ 1 ] + \
0N/A check_far_neibours[ 2 ] + \
0N/A check_far_neibours[ 3 ]; \
0N/A \
0N/A if( check_neibours[ 0 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 3; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 1 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 5; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 2 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 6; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 3 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 9; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 4 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 10; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 5 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 12; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_far_neibours[ 0 ] >= 3 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 7; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_far_neibours[ 1 ] >= 3 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 11; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_far_neibours[ 2 ] >= 3 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 13; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_far_neibours[ 3 ] >= 3 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 14; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_corner >= 4 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 15; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( q & 1 ) \
0N/A { \
0N/A BINARY_TREE_SEARCH_RIGHT( 0, COLOR_MAX, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_SEARCH_LEFT( 0, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 2 ) \
0N/A { \
0N/A BINARY_TREE_SEARCH_RIGHT( 1, COLOR_MAX, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_SEARCH_LEFT( 1, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 4 ) \
0N/A { \
0N/A BINARY_TREE_SEARCH_RIGHT( 2, COLOR_MAX, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_SEARCH_LEFT( 2, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 8 ) \
0N/A { \
0N/A BINARY_TREE_SEARCH_RIGHT( 3, COLOR_MAX, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_SEARCH_LEFT( 3, SHIFT ); \
0N/A } \
0N/A \
0N/A position[ 0 ] &= ~( c[ 0 ] & current_size ); \
0N/A position[ 1 ] &= ~( c[ 1 ] & current_size ); \
0N/A position[ 2 ] &= ~( c[ 2 ] & current_size ); \
0N/A position[ 3 ] &= ~( c[ 3 ] & current_size ); \
0N/A \
0N/A current_size <<= 1; \
0N/A \
0N/A pass++; \
0N/A \
0N/A stack_pointer--; \
0N/A q = stack[ stack_pointer ].q; \
0N/A node = stack[ stack_pointer ].node; \
0N/A } while( continue_up ); \
0N/A \
0N/A dst[ j ] = found_color + s->offset; \
0N/A we_found_it = 1; \
0N/A } \
0N/A } \
0N/A else if( node->contents.quadrants[ q ] ) \
0N/A { \
0N/A /* Descend one level */ \
0N/A stack[ stack_pointer ].node = node; \
0N/A stack[ stack_pointer++ ].q = q; \
0N/A node = node->contents.quadrants[ q ]; \
0N/A } \
0N/A else \
0N/A { \
0N/A /* Found the empty quadrant. Look around */ \
0N/A mlib_u32 distance = MLIB_U32_MAX; \
0N/A mlib_s32 found_color; \
0N/A mlib_s32 continue_up; \
0N/A \
0N/A /* \
0N/A As we had come to this level, it is warranted that there \
0N/A are other points on this level near the empty quadrant \
0N/A */ \
0N/A do \
0N/A { \
0N/A mlib_s32 check_corner; \
0N/A mlib_s32 check_neibours[ 6 ]; \
0N/A mlib_s32 check_far_neibours[ 4 ]; \
0N/A \
0N/A /* \
0N/A Check neibours: quadrants that are different by 2 bits \
0N/A from the quadrant, that we are in: \
0N/A 3 - 0 \
0N/A 5 - 1 \
0N/A 6 - 2 \
0N/A 9 - 3 \
0N/A 10 - 4 \
0N/A 12 - 5 \
0N/A Far quadrants: different by 3 bits: \
0N/A 7 - 0 \
0N/A 11 - 1 \
0N/A 13 - 2 \
0N/A 14 - 3 \
0N/A */ \
0N/A \
0N/A check_neibours[ 0 ] = check_neibours[ 1 ] = \
0N/A check_neibours[ 2 ] = check_neibours[ 3 ] = \
0N/A check_neibours[ 4 ] = check_neibours[ 5 ] = 0; \
0N/A continue_up = 0; \
0N/A \
0N/A if( q & 1 ) \
0N/A { \
0N/A BINARY_TREE_EXPLORE_LEFT_4( 0, SOURCE_IMAGE, 0, 1, 3, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_EXPLORE_RIGHT_4( 0, COLOR_MAX, SOURCE_IMAGE, \
0N/A 0, 1, 3, SUBTRACTION, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 2 ) \
0N/A { \
0N/A BINARY_TREE_EXPLORE_LEFT_4( 1, SOURCE_IMAGE, 0, 2, 4, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_EXPLORE_RIGHT_4( 1, COLOR_MAX, SOURCE_IMAGE, \
0N/A 0, 2, 4, SUBTRACTION, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 4 ) \
0N/A { \
0N/A BINARY_TREE_EXPLORE_LEFT_4( 2, SOURCE_IMAGE, 1, 2, 5, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_EXPLORE_RIGHT_4( 2, COLOR_MAX, SOURCE_IMAGE, \
0N/A 1, 2, 5, SUBTRACTION, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 8 ) \
0N/A { \
0N/A BINARY_TREE_EXPLORE_LEFT_4( 3, SOURCE_IMAGE, 3, 4, 5, \
0N/A SUBTRACTION, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_EXPLORE_RIGHT_4( 3, COLOR_MAX, SOURCE_IMAGE, \
0N/A 3, 4, 5, SUBTRACTION, SHIFT ); \
0N/A } \
0N/A \
0N/A check_far_neibours[ 0 ] = check_neibours[ 0 ] + \
0N/A check_neibours[ 1 ] + check_neibours[ 2 ]; \
0N/A check_far_neibours[ 1 ] = check_neibours[ 0 ] + \
0N/A check_neibours[ 3 ] + check_neibours[ 4 ]; \
0N/A check_far_neibours[ 2 ] = check_neibours[ 1 ] + \
0N/A check_neibours[ 3 ] + check_neibours[ 5 ]; \
0N/A check_far_neibours[ 3 ] = check_neibours[ 2 ] + \
0N/A check_neibours[ 4 ] + check_neibours[ 5 ]; \
0N/A \
0N/A check_corner = check_far_neibours[ 0 ] + \
0N/A check_far_neibours[ 1 ] + \
0N/A check_far_neibours[ 2 ] + \
0N/A check_far_neibours[ 3 ]; \
0N/A \
0N/A if( check_neibours[ 0 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 3; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 1 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 5; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 2 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 6; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 3 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 9; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 4 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 10; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_neibours[ 5 ] >= 2 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 12; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_far_neibours[ 0 ] >= 3 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 7; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_far_neibours[ 1 ] >= 3 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 11; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_far_neibours[ 2 ] >= 3 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 13; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_far_neibours[ 3 ] >= 3 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 14; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( check_corner >= 4 ) \
0N/A { \
0N/A mlib_s32 qq = q ^ 15; \
0N/A CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq ); \
0N/A } \
0N/A \
0N/A if( q & 1 ) \
0N/A { \
0N/A BINARY_TREE_SEARCH_RIGHT( 0, COLOR_MAX, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_SEARCH_LEFT( 0, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 2 ) \
0N/A { \
0N/A BINARY_TREE_SEARCH_RIGHT( 1, COLOR_MAX, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_SEARCH_LEFT( 1, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 4 ) \
0N/A { \
0N/A BINARY_TREE_SEARCH_RIGHT( 2, COLOR_MAX, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_SEARCH_LEFT( 2, SHIFT ); \
0N/A } \
0N/A \
0N/A if( q & 8 ) \
0N/A { \
0N/A BINARY_TREE_SEARCH_RIGHT( 3, COLOR_MAX, SHIFT ); \
0N/A } \
0N/A else \
0N/A { \
0N/A BINARY_TREE_SEARCH_LEFT( 3, SHIFT ); \
0N/A } \
0N/A \
0N/A position[ 0 ] &= ~( c[ 0 ] & current_size ); \
0N/A position[ 1 ] &= ~( c[ 1 ] & current_size ); \
0N/A position[ 2 ] &= ~( c[ 2 ] & current_size ); \
0N/A position[ 3 ] &= ~( c[ 3 ] & current_size ); \
0N/A \
0N/A current_size <<= 1; \
0N/A \
0N/A pass++; \
0N/A \
0N/A stack_pointer--; \
0N/A q = stack[ stack_pointer ].q; \
0N/A node = stack[ stack_pointer ].node; \
0N/A } while( continue_up ); \
0N/A \
0N/A dst[ j ] = found_color + s->offset; \
0N/A we_found_it = 1; \
0N/A } \
0N/A \
0N/A pass--; \
0N/A \
0N/A } while( !we_found_it ); \
0N/A \
0N/A channels[ 0 ] += 4; \
0N/A channels[ 1 ] += 4; \
0N/A channels[ 2 ] += 4; \
0N/A channels[ 3 ] += 4; \
0N/A } \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define FIND_NEAREST_U8_3_C( SHIFT, STEP ) \
0N/A mlib_s32 i, k, k_min, min_dist, diff, mask; \
0N/A mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1; \
0N/A mlib_s32 entries = s -> lutlength; \
0N/A mlib_d64 *double_lut = mlib_ImageGetLutDoubleData( s ); \
0N/A mlib_d64 col0, col1, col2; \
0N/A mlib_d64 dist, len0, len1, len2; \
0N/A \
0N/A for ( i = 0; i < length; i++ ) { \
0N/A col0 = src[ STEP * i + SHIFT ]; \
0N/A col1 = src[ STEP * i + 1 + SHIFT ]; \
0N/A col2 = src[ STEP * i + 2 + SHIFT ]; \
0N/A min_dist = MLIB_S32_MAX; \
0N/A k_min = 1; \
0N/A len0 = double_lut[ 0 ] - col0; \
0N/A len1 = double_lut[ 1 ] - col1; \
0N/A len2 = double_lut[ 2 ] - col2; \
0N/A \
0N/A for ( k = 1; k <= entries; k++ ) { \
0N/A dist = len0 * len0; \
0N/A len0 = double_lut[ 3 * k ] - col0; \
0N/A dist += len1 * len1; \
0N/A len1 = double_lut[ 3 * k + 1 ] - col1; \
0N/A dist += len2 * len2; \
0N/A len2 = double_lut[ 3 * k + 2 ] - col2; \
0N/A diff = ( mlib_s32 )dist - min_dist; \
0N/A mask = diff >> 31; \
0N/A min_dist += diff & mask; \
0N/A k_min += ( k - k_min ) & mask; \
0N/A } \
0N/A \
0N/A dst[ i ] = k_min + offset; \
0N/A }
0N/A
0N/A/***************************************************************/
0N/A#define FIND_NEAREST_U8_4_C \
0N/A mlib_s32 i, k, k_min, min_dist, diff, mask; \
0N/A mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1; \
0N/A mlib_s32 entries = s -> lutlength; \
0N/A mlib_d64 *double_lut = mlib_ImageGetLutDoubleData( s ); \
0N/A mlib_d64 col0, col1, col2, col3; \
0N/A mlib_d64 dist, len0, len1, len2, len3; \
0N/A \
0N/A for ( i = 0; i < length; i++ ) { \
0N/A col0 = src[ 4 * i ]; \
0N/A col1 = src[ 4 * i + 1 ]; \
0N/A col2 = src[ 4 * i + 2 ]; \
0N/A col3 = src[ 4 * i + 3 ]; \
0N/A min_dist = MLIB_S32_MAX; \
0N/A k_min = 1; \
0N/A len0 = double_lut[ 0 ] - col0; \
0N/A len1 = double_lut[ 1 ] - col1; \
0N/A len2 = double_lut[ 2 ] - col2; \
0N/A len3 = double_lut[ 3 ] - col3; \
0N/A \
0N/A for ( k = 1; k <= entries; k++ ) { \
0N/A dist = len0 * len0; \
0N/A len0 = double_lut[ 4 * k ] - col0; \
0N/A dist += len1 * len1; \
0N/A len1 = double_lut[ 4 * k + 1 ] - col1; \
0N/A dist += len2 * len2; \
0N/A len2 = double_lut[ 4 * k + 2 ] - col2; \
0N/A dist += len3 * len3; \
0N/A len3 = double_lut[ 4 * k + 3 ] - col3; \
0N/A diff = ( mlib_s32 )dist - min_dist; \
0N/A mask = diff >> 31; \
0N/A min_dist += diff & mask; \
0N/A k_min += ( k - k_min ) & mask; \
0N/A } \
0N/A \
0N/A dst[ i ] = k_min + offset; \
0N/A }
0N/A
0N/A/***************************************************************/
0N/A#define FSQR_S16_HI(dsrc) \
0N/A vis_fpadd32( vis_fmuld8ulx16( vis_read_hi( dsrc ), vis_read_hi( dsrc ) ), \
0N/A vis_fmuld8sux16( vis_read_hi( dsrc ), vis_read_hi( dsrc ) ) )
0N/A
0N/A/***************************************************************/
0N/A#define FSQR_S16_LO(dsrc) \
0N/A vis_fpadd32( vis_fmuld8ulx16( vis_read_lo( dsrc ), vis_read_lo( dsrc) ), \
0N/A vis_fmuld8sux16( vis_read_lo( dsrc ), vis_read_lo( dsrc ) ) )
0N/A
0N/A/***************************************************************/
0N/A#define FIND_NEAREST_U8_3 \
0N/A{ \
0N/A mlib_d64 *dpsrc, dsrc, dsrc1, ddist, ddist1, ddist2, ddist3; \
0N/A mlib_d64 dcolor, dind, dres, dres1, dpind[1], dpmin[1]; \
0N/A mlib_d64 done = vis_to_double_dup( 1 ), \
0N/A dmax = vis_to_double_dup( MLIB_S32_MAX ); \
0N/A mlib_f32 *lut = ( mlib_f32 * )mlib_ImageGetLutNormalTable( s ); \
0N/A mlib_f32 fone = vis_to_float( 0x100 ); \
0N/A mlib_s32 i, k, mask; \
0N/A mlib_s32 gsr[1]; \
0N/A mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1; \
0N/A mlib_s32 entries = s->lutlength; \
0N/A \
0N/A gsr[0] = vis_read_gsr(); \
0N/A for( i = 0; i <= ( length-2 ); i += 2 ) \
0N/A { \
0N/A dpsrc = VIS_ALIGNADDR( src, -1 ); \
0N/A src += 6; \
0N/A dsrc = dpsrc[ 0 ]; \
0N/A dsrc1 = dpsrc[ 1 ]; \
0N/A dsrc1 = vis_faligndata( dsrc, dsrc1 ); \
0N/A dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone ); \
0N/A VIS_ALIGNADDR( dpsrc, 3 ); \
0N/A dsrc1 = vis_faligndata( dsrc1, dsrc1 ); \
0N/A dsrc1 = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone ); \
0N/A dpind[ 0 ] = dind = done; \
0N/A dpmin[ 0 ] = dmax; \
0N/A dcolor = vis_fmul8x16al( lut[ 0 ], fone ); \
0N/A for( k = 1; k <= entries; k++ ) \
0N/A { \
0N/A ddist1 = vis_fpsub16( dcolor, dsrc ); \
0N/A ddist = FSQR_S16_HI( ddist1 ); \
0N/A ddist1 = FSQR_S16_LO( ddist1 ); \
0N/A dres = vis_fpadd32( ddist, ddist1 ); \
0N/A ddist3 = vis_fpsub16( dcolor, dsrc1 ); \
0N/A ddist2 = FSQR_S16_HI( ddist3 ); \
0N/A ddist3 = FSQR_S16_LO( ddist3 ); \
0N/A dres1 = vis_fpadd32( ddist2, ddist3 ); \
0N/A dcolor = vis_fmul8x16al( lut[ k ], fone ); \
0N/A dres = vis_freg_pair( \
0N/A vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ), \
0N/A vis_fpadd32s( vis_read_hi( dres1 ), vis_read_lo( dres1 ) ) ); \
0N/A mask = vis_fcmplt32( dres, dpmin[ 0 ] ); \
0N/A vis_pst_32( dind, ( void * )dpind, mask ); \
0N/A dind = vis_fpadd32( dind, done ); \
0N/A vis_pst_32( dres, ( void * )dpmin, mask ); \
0N/A } \
0N/A dst[ i ] = ( ( mlib_s32 * )dpind )[ 0 ] + offset; \
0N/A dst[ i + 1 ] = ( ( mlib_s32 * )dpind)[ 1 ] + offset; \
0N/A } \
0N/A if( i < length ) \
0N/A { \
0N/A dpsrc = VIS_ALIGNADDR( src, -1 ); \
0N/A dsrc = dpsrc[ 0 ]; \
0N/A dsrc1 = dpsrc[ 1 ]; \
0N/A dsrc1 = vis_faligndata( dsrc, dsrc1 ); \
0N/A dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone ); \
0N/A dpind[ 0 ] = dind = done; \
0N/A dpmin[ 0 ] = dmax; \
0N/A for( k = 0; k < entries; k++ ) \
0N/A { \
0N/A dcolor = vis_fmul8x16al( lut[ k ], fone ); \
0N/A ddist1 = vis_fpsub16( dcolor, dsrc ); \
0N/A ddist = FSQR_S16_HI( ddist1 ); \
0N/A ddist1 = FSQR_S16_LO( ddist1 ); \
0N/A dres = vis_fpadd32( ddist, ddist1 ); \
0N/A dres = vis_write_lo( dres, \
0N/A vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ) ); \
0N/A mask = vis_fcmplt32( dres, dpmin[ 0 ] ); \
0N/A vis_pst_32( dind, ( void * )dpind, mask ); \
0N/A dind = vis_fpadd32( dind, done ); \
0N/A vis_pst_32( dres, ( void * )dpmin, mask ); \
0N/A } \
0N/A dst[ i ] = ( ( mlib_s32 * )dpind)[ 1 ] + offset; \
0N/A } \
0N/A vis_write_gsr(gsr[0]); \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define FIND_NEAREST_U8_3_IN4 \
0N/A{ \
0N/A mlib_d64 *dpsrc, dsrc, dsrc1, ddist, ddist1, ddist2, ddist3; \
0N/A mlib_d64 dcolor, dind, dres, dres1, dpind[1], dpmin[1]; \
0N/A mlib_d64 done = vis_to_double_dup( 1 ), \
0N/A dmax = vis_to_double_dup( MLIB_S32_MAX ); \
0N/A mlib_f32 *lut = ( mlib_f32 * )mlib_ImageGetLutNormalTable( s ); \
0N/A mlib_f32 fone = vis_to_float( 0x100 ); \
0N/A mlib_s32 i, k, mask, gsr[1]; \
0N/A mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1; \
0N/A mlib_s32 entries = s->lutlength; \
0N/A \
0N/A gsr[0] = vis_read_gsr(); \
0N/A dpsrc = VIS_ALIGNADDR( src, 0 ); \
0N/A for( i = 0; i <= ( length-2 ); i += 2 ) \
0N/A { \
0N/A dsrc = dpsrc[ 0 ]; \
0N/A dsrc1 = dpsrc[ 1 ]; \
0N/A dsrc1 = vis_faligndata( dsrc, dsrc1 ); \
0N/A dpsrc++; \
0N/A dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone ); \
0N/A dsrc1 = vis_fmul8x16al( vis_read_lo( dsrc1 ), fone ); \
0N/A dpind[ 0 ] = dind = done; \
0N/A dpmin[ 0 ] = dmax; \
0N/A dcolor = vis_fmul8x16al( lut[ 0 ], fone ); \
0N/A for( k = 1; k <= entries; k++ ) \
0N/A { \
0N/A ddist1 = vis_fpsub16( dcolor, dsrc ); \
0N/A ddist = FSQR_S16_HI( ddist1 ); \
0N/A ddist1 = FSQR_S16_LO( ddist1 ); \
0N/A dres = vis_fpadd32( ddist, ddist1 ); \
0N/A ddist3 = vis_fpsub16( dcolor, dsrc1 ); \
0N/A ddist2 = FSQR_S16_HI( ddist3 ); \
0N/A ddist3 = FSQR_S16_LO( ddist3 ); \
0N/A dres1 = vis_fpadd32( ddist2, ddist3 ); \
0N/A dcolor = vis_fmul8x16al( lut[ k ], fone ); \
0N/A dres = vis_freg_pair( \
0N/A vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ), \
0N/A vis_fpadd32s( vis_read_hi( dres1 ), vis_read_lo( dres1 ) ) ); \
0N/A mask = vis_fcmplt32( dres, dpmin[ 0 ] ); \
0N/A vis_pst_32( dind, ( void * )dpind, mask ); \
0N/A dind = vis_fpadd32( dind, done ); \
0N/A vis_pst_32( dres, ( void * )dpmin, mask ); \
0N/A } \
0N/A dst[ i ] = ( ( mlib_s32 * )dpind )[ 0 ] + offset; \
0N/A dst[ i + 1 ] = ( ( mlib_s32 * )dpind)[ 1 ] + offset; \
0N/A } \
0N/A if( i < length ) \
0N/A { \
0N/A dsrc = dpsrc[ 0 ]; \
0N/A dsrc1 = dpsrc[ 1 ]; \
0N/A dsrc1 = vis_faligndata( dsrc, dsrc1 ); \
0N/A dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone ); \
0N/A dpind[ 0 ] = dind = done; \
0N/A dpmin[ 0 ] = dmax; \
0N/A for( k = 0; k < entries; k++ ) \
0N/A { \
0N/A dcolor = vis_fmul8x16al( lut[ k ], fone ); \
0N/A ddist1 = vis_fpsub16( dcolor, dsrc ); \
0N/A ddist = FSQR_S16_HI( ddist1 ); \
0N/A ddist1 = FSQR_S16_LO( ddist1 ); \
0N/A dres = vis_fpadd32( ddist, ddist1 ); \
0N/A dres = vis_write_lo( dres, \
0N/A vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ) ); \
0N/A mask = vis_fcmplt32( dres, dpmin[ 0 ] ); \
0N/A vis_pst_32( dind, ( void * )dpind, mask ); \
0N/A dind = vis_fpadd32( dind, done ); \
0N/A vis_pst_32( dres, ( void * )dpmin, mask ); \
0N/A } \
0N/A dst[ i ] = ( ( mlib_s32 * )dpind)[ 1 ] + offset; \
0N/A } \
0N/A vis_write_gsr(gsr[0]); \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define FIND_NEAREST_U8_4 \
0N/A{ \
0N/A mlib_d64 *dpsrc, dsrc, dsrc1, ddist, ddist1, ddist2, ddist3; \
0N/A mlib_d64 dcolor, dind, dres, dres1, dpind[ 1 ], dpmin[ 1 ]; \
0N/A mlib_d64 done = vis_to_double_dup( 1 ), \
0N/A dmax = vis_to_double_dup( MLIB_S32_MAX ); \
0N/A mlib_f32 *lut = ( mlib_f32 * )mlib_ImageGetLutNormalTable( s ); \
0N/A mlib_f32 fone = vis_to_float( 0x100 ); \
0N/A mlib_s32 i, k, mask, gsr[1]; \
0N/A mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1; \
0N/A mlib_s32 entries = s->lutlength; \
0N/A \
0N/A gsr[0] = vis_read_gsr(); \
0N/A dpsrc = VIS_ALIGNADDR( src, 0 ); \
0N/A for( i = 0; i <= ( length-2 ); i += 2 ) \
0N/A { \
0N/A dsrc = dpsrc[ 0 ]; \
0N/A dsrc1 = dpsrc[ 1 ]; \
0N/A dsrc1 = vis_faligndata( dsrc, dsrc1 ); \
0N/A dpsrc++; \
0N/A dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone ); \
0N/A dsrc1 = vis_fmul8x16al( vis_read_lo( dsrc1 ), fone ); \
0N/A dpind[ 0 ] = dind = done; \
0N/A dpmin[ 0 ] = dmax; \
0N/A dcolor = vis_fmul8x16al(lut[0], fone); \
0N/A for( k = 1; k <= entries; k++ ) \
0N/A { \
0N/A ddist1 = vis_fpsub16( dcolor, dsrc ); \
0N/A ddist = FSQR_S16_HI( ddist1 ); \
0N/A ddist1 = FSQR_S16_LO( ddist1 ); \
0N/A dres = vis_fpadd32( ddist, ddist1 ); \
0N/A ddist3 = vis_fpsub16( dcolor, dsrc1 ); \
0N/A ddist2 = FSQR_S16_HI( ddist3 ); \
0N/A ddist3 = FSQR_S16_LO( ddist3 ); \
0N/A dres1 = vis_fpadd32( ddist2, ddist3 ); \
0N/A dcolor = vis_fmul8x16al( lut[ k ], fone ); \
0N/A dres = vis_freg_pair( \
0N/A vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ), \
0N/A vis_fpadd32s( vis_read_hi( dres1 ), vis_read_lo( dres1 ) ) ); \
0N/A mask = vis_fcmplt32( dres, dpmin[ 0 ] ); \
0N/A vis_pst_32( dind, ( void * )dpind, mask ); \
0N/A dind = vis_fpadd32( dind, done ); \
0N/A vis_pst_32( dres, ( void * )dpmin, mask ); \
0N/A } \
0N/A dst[ i ] = ( ( mlib_s32 * )dpind )[ 0 ] + offset; \
0N/A dst[ i + 1 ] = ( ( mlib_s32 * )dpind )[ 1 ] + offset; \
0N/A } \
0N/A if( i < length ) \
0N/A { \
0N/A dsrc = dpsrc[ 0 ]; \
0N/A dsrc1 = dpsrc[ 1 ]; \
0N/A dsrc1 = vis_faligndata( dsrc, dsrc1 ); \
0N/A dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone ); \
0N/A dpind[ 0 ] = dind = done; \
0N/A dpmin[ 0 ] = dmax; \
0N/A for( k = 0; k < entries; k++ ) \
0N/A { \
0N/A dcolor = vis_fmul8x16al( lut[ k ], fone ); \
0N/A ddist1 = vis_fpsub16( dcolor, dsrc ); \
0N/A ddist = FSQR_S16_HI( ddist1 ); \
0N/A ddist1 = FSQR_S16_LO( ddist1 ); \
0N/A dres = vis_fpadd32( ddist, ddist1 ); \
0N/A dres = vis_write_lo( dres, \
0N/A vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ) ); \
0N/A mask = vis_fcmplt32( dres, dpmin[ 0 ] ); \
0N/A vis_pst_32( dind, ( void * )dpind, mask ); \
0N/A dind = vis_fpadd32( dind, done ); \
0N/A vis_pst_32( dres, ( void * )dpmin, mask ); \
0N/A } \
0N/A dst[ i ] = ( ( mlib_s32 * )dpind )[ 1 ] + offset; \
0N/A } \
0N/A vis_write_gsr(gsr[0]); \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A#define FIND_NEAREST_S16_3( SHIFT, STEP ) \
0N/A mlib_s32 i, k, k_min, min_dist, diff, mask; \
0N/A mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1; \
0N/A mlib_s32 entries = s->lutlength; \
0N/A mlib_d64 *double_lut = mlib_ImageGetLutDoubleData( s ); \
0N/A mlib_d64 col0, col1, col2; \
0N/A mlib_d64 dist, len0, len1, len2; \
0N/A \
0N/A for( i = 0; i < length; i++ ) \
0N/A { \
0N/A col0 = src[ STEP * i + SHIFT ]; \
0N/A col1 = src[ STEP * i + 1 + SHIFT ]; \
0N/A col2 = src[ STEP * i + 2 + SHIFT ]; \
0N/A min_dist = MLIB_S32_MAX; \
0N/A k_min = 1; \
0N/A len0 = double_lut[ 0 ] - col0; \
0N/A len1 = double_lut[ 1 ] - col1; \
0N/A len2 = double_lut[ 2 ] - col2; \
0N/A for( k = 1; k <= entries; k++ ) \
0N/A { \
0N/A dist = len0 * len0; \
0N/A len0 = double_lut[ 3 * k ] - col0; \
0N/A dist += len1 * len1; \
0N/A len1 = double_lut[ 3 * k + 1 ] - col1; \
0N/A dist += len2 * len2; \
0N/A len2 = double_lut[ 3 * k + 2 ] - col2; \
0N/A diff = ( mlib_s32 )( dist * 0.125 ) - min_dist; \
0N/A mask = diff >> 31; \
0N/A min_dist += diff & mask; \
0N/A k_min += ( k - k_min ) & mask; \
0N/A } \
0N/A dst[ i ] = k_min + offset; \
0N/A }
0N/A
0N/A/***************************************************************/
0N/A#define FIND_NEAREST_S16_4 \
0N/A mlib_s32 i, k, k_min, min_dist, diff, mask; \
0N/A mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1; \
0N/A mlib_s32 entries = s->lutlength; \
0N/A mlib_d64 *double_lut = mlib_ImageGetLutDoubleData( s ); \
0N/A mlib_d64 col0, col1, col2, col3; \
0N/A mlib_d64 dist, len0, len1, len2, len3; \
0N/A \
0N/A for( i = 0; i < length; i++ ) \
0N/A { \
0N/A col0 = src[ 4 * i ]; \
0N/A col1 = src[ 4 * i + 1 ]; \
0N/A col2 = src[ 4 * i + 2 ]; \
0N/A col3 = src[ 4 * i + 3 ]; \
0N/A min_dist = MLIB_S32_MAX; \
0N/A k_min = 1; \
0N/A len0 = double_lut[ 0 ] - col0; \
0N/A len1 = double_lut[ 1 ] - col1; \
0N/A len2 = double_lut[ 2 ] - col2; \
0N/A len3 = double_lut[ 3 ] - col3; \
0N/A for( k = 1; k <= entries; k++ ) \
0N/A { \
0N/A dist = len0 * len0; \
0N/A len0 = double_lut[ 4 * k ] - col0; \
0N/A dist += len1 * len1; \
0N/A len1 = double_lut[ 4 * k + 1 ] - col1; \
0N/A dist += len2 * len2; \
0N/A len2 = double_lut[ 4 * k + 2 ] - col2; \
0N/A dist += len3 * len3; \
0N/A len3 = double_lut[ 4 * k + 3 ] - col3; \
0N/A diff = ( mlib_s32 )( dist * 0.125 ) - min_dist; \
0N/A mask = diff >> 31; \
0N/A min_dist += diff & mask; \
0N/A k_min += ( k - k_min ) & mask; \
0N/A } \
0N/A dst[ i ] = k_min + offset; \
0N/A }
0N/A
0N/A/***************************************************************/
0N/Amlib_status mlib_ImageColorTrue2Index(mlib_image *dst,
0N/A const mlib_image *src,
0N/A const void *colormap)
0N/A{
0N/A mlib_s32 y, width, height, sstride, dstride, schann;
0N/A mlib_colormap *s = (mlib_colormap *)colormap;
0N/A mlib_s32 channels;
0N/A mlib_type stype, dtype;
0N/A
0N/A MLIB_IMAGE_CHECK(src);
0N/A MLIB_IMAGE_CHECK(dst);
0N/A MLIB_IMAGE_SIZE_EQUAL(src, dst);
0N/A MLIB_IMAGE_HAVE_CHAN(dst, 1);
0N/A
0N/A if (!colormap)
0N/A return MLIB_NULLPOINTER;
0N/A
0N/A channels = s->channels;
0N/A stype = mlib_ImageGetType(src);
0N/A dtype = mlib_ImageGetType(dst);
0N/A width = mlib_ImageGetWidth(src);
0N/A height = mlib_ImageGetHeight(src);
0N/A sstride = mlib_ImageGetStride(src);
0N/A dstride = mlib_ImageGetStride(dst);
0N/A schann = mlib_ImageGetChannels(src);
0N/A
0N/A if (stype != s->intype || dtype != s->outtype)
0N/A return MLIB_FAILURE;
0N/A
0N/A if (channels != schann)
0N/A return MLIB_FAILURE;
0N/A
0N/A switch (stype) {
0N/A case MLIB_BYTE:
0N/A {
0N/A mlib_u8 *sdata = mlib_ImageGetData(src);
0N/A
0N/A switch (dtype) {
0N/A case MLIB_BYTE:
0N/A {
0N/A mlib_u8 *ddata = mlib_ImageGetData(dst);
0N/A
0N/A switch (channels) {
0N/A case 3:
0N/A {
0N/A MAIN_COLORTRUE2INDEX_LOOP(U8, U8, 3);
0N/A return MLIB_SUCCESS;
0N/A }
0N/A
0N/A case 4:
0N/A {
0N/A MAIN_COLORTRUE2INDEX_LOOP(U8, U8, 4);
0N/A return MLIB_SUCCESS;
0N/A }
0N/A
0N/A default:
0N/A return MLIB_FAILURE;
0N/A }
0N/A }
0N/A
0N/A case MLIB_SHORT:
0N/A {
0N/A mlib_s16 *ddata = mlib_ImageGetData(dst);
0N/A
0N/A dstride /= 2;
0N/A switch (channels) {
0N/A case 3:
0N/A {
0N/A MAIN_COLORTRUE2INDEX_LOOP(U8, S16, 3);
0N/A return MLIB_SUCCESS;
0N/A }
0N/A
0N/A case 4:
0N/A {
0N/A MAIN_COLORTRUE2INDEX_LOOP(U8, S16, 4);
0N/A return MLIB_SUCCESS;
0N/A }
0N/A
0N/A default:
0N/A return MLIB_FAILURE;
0N/A }
0N/A }
3813N/A default:
3813N/A /* Unsupported type of destination image */
3813N/A return MLIB_FAILURE;
0N/A }
0N/A }
0N/A
0N/A case MLIB_SHORT:
0N/A {
0N/A mlib_s16 *sdata = mlib_ImageGetData(src);
0N/A
0N/A sstride /= 2;
0N/A switch (dtype) {
0N/A case MLIB_BYTE:
0N/A {
0N/A mlib_u8 *ddata = mlib_ImageGetData(dst);
0N/A
0N/A switch (channels) {
0N/A case 3:
0N/A {
0N/A MAIN_COLORTRUE2INDEX_LOOP(S16, U8, 3);
0N/A return MLIB_SUCCESS;
0N/A }
0N/A
0N/A case 4:
0N/A {
0N/A MAIN_COLORTRUE2INDEX_LOOP(S16, U8, 4);
0N/A return MLIB_SUCCESS;
0N/A }
0N/A
0N/A default:
0N/A return MLIB_FAILURE;
0N/A }
0N/A }
0N/A
0N/A case MLIB_SHORT:
0N/A {
0N/A mlib_s16 *ddata = mlib_ImageGetData(dst);
0N/A
0N/A dstride /= 2;
0N/A switch (channels) {
0N/A case 3:
0N/A {
0N/A MAIN_COLORTRUE2INDEX_LOOP(S16, S16, 3);
0N/A return MLIB_SUCCESS;
0N/A }
0N/A
0N/A case 4:
0N/A {
0N/A MAIN_COLORTRUE2INDEX_LOOP(S16, S16, 4);
0N/A return MLIB_SUCCESS;
0N/A }
0N/A
0N/A default:
0N/A return MLIB_FAILURE;
0N/A }
0N/A }
3813N/A default:
3813N/A /* Unsupported type of destination image */
3813N/A return MLIB_FAILURE;
0N/A }
0N/A }
0N/A
0N/A default:
0N/A return MLIB_FAILURE;
0N/A }
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_u32 mlib_search_quadrant_U8_3(struct lut_node_3 *node,
0N/A mlib_u32 distance,
0N/A mlib_s32 *found_color,
0N/A mlib_u32 c0,
0N/A mlib_u32 c1,
0N/A mlib_u32 c2,
0N/A const mlib_u8 **base)
0N/A{
0N/A mlib_s32 i;
0N/A
0N/A for (i = 0; i < 8; i++) {
0N/A
0N/A if (node->tag & (1 << i)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[i];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex];
0N/A newpalc1 = base[1][newindex];
0N/A newpalc2 = base[2][newindex];
0N/A newdistance = FIND_DISTANCE_3(c0, newpalc0, c1, newpalc1, c2, newpalc2, 0);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[i])
0N/A distance =
0N/A mlib_search_quadrant_U8_3(node->contents.quadrants[i], distance,
0N/A found_color, c0, c1, c2, base);
0N/A }
0N/A
0N/A return distance;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_u32 mlib_search_quadrant_part_to_left_U8_3(struct lut_node_3 *node,
0N/A mlib_u32 distance,
0N/A mlib_s32 *found_color,
0N/A const mlib_u32 *c,
0N/A const mlib_u8 **base,
0N/A mlib_u32 position,
0N/A mlib_s32 pass,
0N/A mlib_s32 dir_bit)
0N/A{
0N/A mlib_u32 current_size = 1 << pass;
0N/A mlib_s32 i;
0N/A static mlib_s32 opposite_quadrants[3][4] = {
0N/A {0, 2, 4, 6},
0N/A {0, 1, 4, 5},
0N/A {0, 1, 2, 3}
0N/A };
0N/A
0N/A/* Search only quadrant's half untill it is necessary to check the
0N/A whole quadrant */
0N/A
0N/A if (distance < (position + current_size - c[dir_bit]) * (position + current_size - c[dir_bit])) { /* Search half of quadrant */
0N/A for (i = 0; i < 4; i++) {
0N/A mlib_s32 qq = opposite_quadrants[dir_bit][i];
0N/A
0N/A if (node->tag & (1 << qq)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[qq];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex];
0N/A newpalc1 = base[1][newindex];
0N/A newpalc2 = base[2][newindex];
0N/A newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 0);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[qq])
0N/A distance =
0N/A mlib_search_quadrant_part_to_left_U8_3(node->contents.quadrants[qq],
0N/A distance, found_color, c, base,
0N/A position, pass - 1, dir_bit);
0N/A }
0N/A }
0N/A else { /* Search whole quadrant */
0N/A
0N/A mlib_s32 mask = 1 << dir_bit;
0N/A
0N/A for (i = 0; i < 8; i++) {
0N/A
0N/A if (node->tag & (1 << i)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[i];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex];
0N/A newpalc1 = base[1][newindex];
0N/A newpalc2 = base[2][newindex];
0N/A newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 0);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[i]) {
0N/A
0N/A if (i & mask)
0N/A /* This quadrant may require partial checking */
0N/A distance =
0N/A mlib_search_quadrant_part_to_left_U8_3(node->contents.quadrants[i],
0N/A distance, found_color, c,
0N/A base,
0N/A position + current_size,
0N/A pass - 1, dir_bit);
0N/A else
0N/A /* Here we should check all */
0N/A distance =
0N/A mlib_search_quadrant_U8_3(node->contents.quadrants[i], distance,
0N/A found_color, c[0], c[1], c[2], base);
0N/A }
0N/A }
0N/A }
0N/A
0N/A return distance;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_u32 mlib_search_quadrant_part_to_right_U8_3(struct lut_node_3 *node,
0N/A mlib_u32 distance,
0N/A mlib_s32 *found_color,
0N/A const mlib_u32 *c,
0N/A const mlib_u8 **base,
0N/A mlib_u32 position,
0N/A mlib_s32 pass,
0N/A mlib_s32 dir_bit)
0N/A{
0N/A mlib_u32 current_size = 1 << pass;
0N/A mlib_s32 i;
0N/A static mlib_s32 opposite_quadrants[3][4] = {
0N/A {1, 3, 5, 7},
0N/A {2, 3, 6, 7},
0N/A {4, 5, 6, 7}
0N/A };
0N/A
0N/A/* Search only quadrant's half untill it is necessary to check the
0N/A whole quadrant */
0N/A
0N/A if (distance <= (c[dir_bit] - position - current_size) * (c[dir_bit] - position - current_size)) { /* Search half of quadrant */
0N/A for (i = 0; i < 4; i++) {
0N/A mlib_s32 qq = opposite_quadrants[dir_bit][i];
0N/A
0N/A if (node->tag & (1 << qq)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[qq];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex];
0N/A newpalc1 = base[1][newindex];
0N/A newpalc2 = base[2][newindex];
0N/A newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 0);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[qq])
0N/A distance =
0N/A mlib_search_quadrant_part_to_right_U8_3(node->contents.quadrants[qq],
0N/A distance, found_color, c,
0N/A base, position + current_size,
0N/A pass - 1, dir_bit);
0N/A }
0N/A }
0N/A else { /* Search whole quadrant */
0N/A
0N/A mlib_s32 mask = 1 << dir_bit;
0N/A
0N/A for (i = 0; i < 8; i++) {
0N/A
0N/A if (node->tag & (1 << i)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[i];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex];
0N/A newpalc1 = base[1][newindex];
0N/A newpalc2 = base[2][newindex];
0N/A newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 0);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[i]) {
0N/A
0N/A if (i & mask)
0N/A /* Here we should check all */
0N/A distance =
0N/A mlib_search_quadrant_U8_3(node->contents.quadrants[i], distance,
0N/A found_color, c[0], c[1], c[2], base);
0N/A else
0N/A /* This quadrant may require partial checking */
0N/A distance =
0N/A mlib_search_quadrant_part_to_right_U8_3(node->contents.quadrants[i],
0N/A distance, found_color, c,
0N/A base, position, pass - 1, dir_bit);
0N/A }
0N/A }
0N/A }
0N/A
0N/A return distance;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_u32 mlib_search_quadrant_S16_3(struct lut_node_3 *node,
0N/A mlib_u32 distance,
0N/A mlib_s32 *found_color,
0N/A mlib_u32 c0,
0N/A mlib_u32 c1,
0N/A mlib_u32 c2,
0N/A const mlib_s16 **base)
0N/A{
0N/A mlib_s32 i;
0N/A
0N/A for (i = 0; i < 8; i++) {
0N/A
0N/A if (node->tag & (1 << i)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[i];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex] - MLIB_S16_MIN;
0N/A newpalc1 = base[1][newindex] - MLIB_S16_MIN;
0N/A newpalc2 = base[2][newindex] - MLIB_S16_MIN;
0N/A newdistance = FIND_DISTANCE_3(c0, newpalc0, c1, newpalc1, c2, newpalc2, 2);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[i])
0N/A distance =
0N/A mlib_search_quadrant_S16_3(node->contents.quadrants[i], distance,
0N/A found_color, c0, c1, c2, base);
0N/A }
0N/A
0N/A return distance;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_u32 mlib_search_quadrant_part_to_left_S16_3(struct lut_node_3 *node,
0N/A mlib_u32 distance,
0N/A mlib_s32 *found_color,
0N/A const mlib_u32 *c,
0N/A const mlib_s16 **base,
0N/A mlib_u32 position,
0N/A mlib_s32 pass,
0N/A mlib_s32 dir_bit)
0N/A{
0N/A mlib_u32 current_size = 1 << pass;
0N/A mlib_s32 i;
0N/A static mlib_s32 opposite_quadrants[3][4] = {
0N/A {0, 2, 4, 6},
0N/A {0, 1, 4, 5},
0N/A {0, 1, 2, 3}
0N/A };
0N/A
0N/A/* Search only quadrant's half untill it is necessary to check the
0N/A whole quadrant */
0N/A
0N/A if (distance < (((position + current_size - c[dir_bit]) * (position + current_size - c[dir_bit])) >> 2)) { /* Search half of quadrant */
0N/A for (i = 0; i < 4; i++) {
0N/A mlib_s32 qq = opposite_quadrants[dir_bit][i];
0N/A
0N/A if (node->tag & (1 << qq)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[qq];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex] - MLIB_S16_MIN;
0N/A newpalc1 = base[1][newindex] - MLIB_S16_MIN;
0N/A newpalc2 = base[2][newindex] - MLIB_S16_MIN;
0N/A newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 2);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[qq])
0N/A distance =
0N/A mlib_search_quadrant_part_to_left_S16_3(node->contents.quadrants[qq],
0N/A distance, found_color, c,
0N/A base, position, pass - 1, dir_bit);
0N/A }
0N/A }
0N/A else { /* Search whole quadrant */
0N/A
0N/A mlib_s32 mask = 1 << dir_bit;
0N/A
0N/A for (i = 0; i < 8; i++) {
0N/A
0N/A if (node->tag & (1 << i)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[i];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex] - MLIB_S16_MIN;
0N/A newpalc1 = base[1][newindex] - MLIB_S16_MIN;
0N/A newpalc2 = base[2][newindex] - MLIB_S16_MIN;
0N/A newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 2);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[i]) {
0N/A
0N/A if (i & mask)
0N/A /* This quadrant may require partial checking */
0N/A distance =
0N/A mlib_search_quadrant_part_to_left_S16_3(node->contents.quadrants[i],
0N/A distance, found_color, c,
0N/A base,
0N/A position + current_size,
0N/A pass - 1, dir_bit);
0N/A else
0N/A /* Here we should check all */
0N/A distance =
0N/A mlib_search_quadrant_S16_3(node->contents.quadrants[i], distance,
0N/A found_color, c[0], c[1], c[2], base);
0N/A }
0N/A }
0N/A }
0N/A
0N/A return distance;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_u32 mlib_search_quadrant_part_to_right_S16_3(struct lut_node_3 *node,
0N/A mlib_u32 distance,
0N/A mlib_s32 *found_color,
0N/A const mlib_u32 *c,
0N/A const mlib_s16 **base,
0N/A mlib_u32 position,
0N/A mlib_s32 pass,
0N/A mlib_s32 dir_bit)
0N/A{
0N/A mlib_u32 current_size = 1 << pass;
0N/A mlib_s32 i;
0N/A static mlib_s32 opposite_quadrants[3][4] = {
0N/A {1, 3, 5, 7},
0N/A {2, 3, 6, 7},
0N/A {4, 5, 6, 7}
0N/A };
0N/A
0N/A/* Search only quadrant's half untill it is necessary to check the
0N/A whole quadrant */
0N/A
0N/A if (distance <= (((c[dir_bit] - position - current_size) * (c[dir_bit] - position - current_size)) >> 2)) { /* Search half of quadrant */
0N/A for (i = 0; i < 4; i++) {
0N/A mlib_s32 qq = opposite_quadrants[dir_bit][i];
0N/A
0N/A if (node->tag & (1 << qq)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[qq];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex] - MLIB_S16_MIN;
0N/A newpalc1 = base[1][newindex] - MLIB_S16_MIN;
0N/A newpalc2 = base[2][newindex] - MLIB_S16_MIN;
0N/A newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 2);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[qq])
0N/A distance =
0N/A mlib_search_quadrant_part_to_right_S16_3(node->contents.quadrants[qq],
0N/A distance, found_color, c,
0N/A base,
0N/A position + current_size,
0N/A pass - 1, dir_bit);
0N/A }
0N/A }
0N/A else { /* Search whole quadrant */
0N/A
0N/A mlib_s32 mask = 1 << dir_bit;
0N/A
0N/A for (i = 0; i < 8; i++) {
0N/A
0N/A if (node->tag & (1 << i)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[i];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex] - MLIB_S16_MIN;
0N/A newpalc1 = base[1][newindex] - MLIB_S16_MIN;
0N/A newpalc2 = base[2][newindex] - MLIB_S16_MIN;
0N/A newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 2);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[i]) {
0N/A
0N/A if (i & mask)
0N/A /* Here we should check all */
0N/A distance =
0N/A mlib_search_quadrant_S16_3(node->contents.quadrants[i], distance,
0N/A found_color, c[0], c[1], c[2], base);
0N/A else
0N/A /* This quadrant may require partial checking */
0N/A distance =
0N/A mlib_search_quadrant_part_to_right_S16_3(node->contents.
0N/A quadrants[i], distance,
0N/A found_color, c, base,
0N/A position, pass - 1, dir_bit);
0N/A }
0N/A }
0N/A }
0N/A
0N/A return distance;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_u32 mlib_search_quadrant_U8_4(struct lut_node_4 *node,
0N/A mlib_u32 distance,
0N/A mlib_s32 *found_color,
0N/A mlib_u32 c0,
0N/A mlib_u32 c1,
0N/A mlib_u32 c2,
0N/A mlib_u32 c3,
0N/A const mlib_u8 **base)
0N/A{
0N/A mlib_s32 i;
0N/A
0N/A for (i = 0; i < 16; i++) {
0N/A
0N/A if (node->tag & (1 << i)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[i];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex];
0N/A newpalc1 = base[1][newindex];
0N/A newpalc2 = base[2][newindex];
0N/A newpalc3 = base[3][newindex];
0N/A newdistance = FIND_DISTANCE_4(c0, newpalc0,
0N/A c1, newpalc1, c2, newpalc2, c3, newpalc3, 0);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[i])
0N/A distance =
0N/A mlib_search_quadrant_U8_4(node->contents.quadrants[i], distance,
0N/A found_color, c0, c1, c2, c3, base);
0N/A }
0N/A
0N/A return distance;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_u32 mlib_search_quadrant_part_to_left_U8_4(struct lut_node_4 *node,
0N/A mlib_u32 distance,
0N/A mlib_s32 *found_color,
0N/A const mlib_u32 *c,
0N/A const mlib_u8 **base,
0N/A mlib_u32 position,
0N/A mlib_s32 pass,
0N/A mlib_s32 dir_bit)
0N/A{
0N/A mlib_u32 current_size = 1 << pass;
0N/A mlib_s32 i;
0N/A static mlib_s32 opposite_quadrants[4][8] = {
0N/A {0, 2, 4, 6, 8, 10, 12, 14},
0N/A {0, 1, 4, 5, 8, 9, 12, 13},
0N/A {0, 1, 2, 3, 8, 9, 10, 11},
0N/A {0, 1, 2, 3, 4, 5, 6, 7}
0N/A };
0N/A
0N/A/* Search only quadrant's half untill it is necessary to check the
0N/A whole quadrant */
0N/A
0N/A if (distance < (position + current_size - c[dir_bit]) * (position + current_size - c[dir_bit])) { /* Search half of quadrant */
0N/A for (i = 0; i < 8; i++) {
0N/A mlib_s32 qq = opposite_quadrants[dir_bit][i];
0N/A
0N/A if (node->tag & (1 << qq)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[qq];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex];
0N/A newpalc1 = base[1][newindex];
0N/A newpalc2 = base[2][newindex];
0N/A newpalc3 = base[3][newindex];
0N/A newdistance = FIND_DISTANCE_4(c[0], newpalc0,
0N/A c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 0);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[qq])
0N/A distance =
0N/A mlib_search_quadrant_part_to_left_U8_4(node->contents.quadrants[qq],
0N/A distance, found_color, c, base,
0N/A position, pass - 1, dir_bit);
0N/A }
0N/A }
0N/A else { /* Search whole quadrant */
0N/A
0N/A mlib_s32 mask = 1 << dir_bit;
0N/A
0N/A for (i = 0; i < 16; i++) {
0N/A
0N/A if (node->tag & (1 << i)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[i];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex];
0N/A newpalc1 = base[1][newindex];
0N/A newpalc2 = base[2][newindex];
0N/A newpalc3 = base[3][newindex];
0N/A newdistance = FIND_DISTANCE_4(c[0], newpalc0,
0N/A c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 0);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[i]) {
0N/A
0N/A if (i & mask)
0N/A /* This quadrant may require partial checking */
0N/A distance =
0N/A mlib_search_quadrant_part_to_left_U8_4(node->contents.quadrants[i],
0N/A distance, found_color, c,
0N/A base,
0N/A position + current_size,
0N/A pass - 1, dir_bit);
0N/A else
0N/A /* Here we should check all */
0N/A distance =
0N/A mlib_search_quadrant_U8_4(node->contents.quadrants[i], distance,
0N/A found_color, c[0], c[1], c[2], c[3], base);
0N/A }
0N/A }
0N/A }
0N/A
0N/A return distance;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_u32 mlib_search_quadrant_part_to_right_U8_4(struct lut_node_4 *node,
0N/A mlib_u32 distance,
0N/A mlib_s32 *found_color,
0N/A const mlib_u32 *c,
0N/A const mlib_u8 **base,
0N/A mlib_u32 position,
0N/A mlib_s32 pass,
0N/A mlib_s32 dir_bit)
0N/A{
0N/A mlib_u32 current_size = 1 << pass;
0N/A mlib_s32 i;
0N/A static mlib_s32 opposite_quadrants[4][8] = {
0N/A {1, 3, 5, 7, 9, 11, 13, 15},
0N/A {2, 3, 6, 7, 10, 11, 14, 15},
0N/A {4, 5, 6, 7, 12, 13, 14, 15},
0N/A {8, 9, 10, 11, 12, 13, 14, 15}
0N/A };
0N/A
0N/A/* Search only quadrant's half untill it is necessary to check the
0N/A whole quadrant */
0N/A
0N/A if (distance <= (c[dir_bit] - position - current_size) * (c[dir_bit] - position - current_size)) { /* Search half of quadrant */
0N/A for (i = 0; i < 8; i++) {
0N/A mlib_s32 qq = opposite_quadrants[dir_bit][i];
0N/A
0N/A if (node->tag & (1 << qq)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[qq];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex];
0N/A newpalc1 = base[1][newindex];
0N/A newpalc2 = base[2][newindex];
0N/A newpalc3 = base[3][newindex];
0N/A newdistance = FIND_DISTANCE_4(c[0], newpalc0,
0N/A c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 0);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[qq])
0N/A distance =
0N/A mlib_search_quadrant_part_to_right_U8_4(node->contents.quadrants[qq],
0N/A distance, found_color, c,
0N/A base, position + current_size,
0N/A pass - 1, dir_bit);
0N/A }
0N/A }
0N/A else { /* Search whole quadrant */
0N/A
0N/A mlib_s32 mask = 1 << dir_bit;
0N/A
0N/A for (i = 0; i < 16; i++) {
0N/A
0N/A if (node->tag & (1 << i)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[i];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex];
0N/A newpalc1 = base[1][newindex];
0N/A newpalc2 = base[2][newindex];
0N/A newpalc3 = base[3][newindex];
0N/A newdistance = FIND_DISTANCE_4(c[0], newpalc0,
0N/A c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 0);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[i]) {
0N/A
0N/A if (i & mask)
0N/A /* Here we should check all */
0N/A distance =
0N/A mlib_search_quadrant_U8_4(node->contents.quadrants[i], distance,
0N/A found_color, c[0], c[1], c[2], c[3], base);
0N/A else
0N/A /* This quadrant may require partial checking */
0N/A distance =
0N/A mlib_search_quadrant_part_to_right_U8_4(node->contents.quadrants[i],
0N/A distance, found_color, c,
0N/A base, position, pass - 1, dir_bit);
0N/A }
0N/A }
0N/A }
0N/A
0N/A return distance;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_u32 mlib_search_quadrant_S16_4(struct lut_node_4 *node,
0N/A mlib_u32 distance,
0N/A mlib_s32 *found_color,
0N/A mlib_u32 c0,
0N/A mlib_u32 c1,
0N/A mlib_u32 c2,
0N/A mlib_u32 c3,
0N/A const mlib_s16 **base)
0N/A{
0N/A mlib_s32 i;
0N/A
0N/A for (i = 0; i < 16; i++) {
0N/A
0N/A if (node->tag & (1 << i)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[i];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex] - MLIB_S16_MIN;
0N/A newpalc1 = base[1][newindex] - MLIB_S16_MIN;
0N/A newpalc2 = base[2][newindex] - MLIB_S16_MIN;
0N/A newpalc3 = base[3][newindex] - MLIB_S16_MIN;
0N/A newdistance = FIND_DISTANCE_4(c0, newpalc0,
0N/A c1, newpalc1, c2, newpalc2, c3, newpalc3, 2);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[i])
0N/A distance =
0N/A mlib_search_quadrant_S16_4(node->contents.quadrants[i], distance,
0N/A found_color, c0, c1, c2, c3, base);
0N/A }
0N/A
0N/A return distance;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_u32 mlib_search_quadrant_part_to_left_S16_4(struct lut_node_4 *node,
0N/A mlib_u32 distance,
0N/A mlib_s32 *found_color,
0N/A const mlib_u32 *c,
0N/A const mlib_s16 **base,
0N/A mlib_u32 position,
0N/A mlib_s32 pass,
0N/A mlib_s32 dir_bit)
0N/A{
0N/A mlib_u32 current_size = 1 << pass;
0N/A mlib_s32 i;
0N/A static mlib_s32 opposite_quadrants[4][8] = {
0N/A {0, 2, 4, 6, 8, 10, 12, 14},
0N/A {0, 1, 4, 5, 8, 9, 12, 13},
0N/A {0, 1, 2, 3, 8, 9, 10, 11},
0N/A {0, 1, 2, 3, 4, 5, 6, 7}
0N/A };
0N/A
0N/A/* Search only quadrant's half untill it is necessary to check the
0N/A whole quadrant */
0N/A
0N/A if (distance < (((position + current_size - c[dir_bit]) * (position + current_size - c[dir_bit])) >> 2)) { /* Search half of quadrant */
0N/A for (i = 0; i < 8; i++) {
0N/A mlib_s32 qq = opposite_quadrants[dir_bit][i];
0N/A
0N/A if (node->tag & (1 << qq)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[qq];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex] - MLIB_S16_MIN;
0N/A newpalc1 = base[1][newindex] - MLIB_S16_MIN;
0N/A newpalc2 = base[2][newindex] - MLIB_S16_MIN;
0N/A newpalc3 = base[3][newindex] - MLIB_S16_MIN;
0N/A newdistance = FIND_DISTANCE_4(c[0], newpalc0,
0N/A c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 2);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[qq])
0N/A distance =
0N/A mlib_search_quadrant_part_to_left_S16_4(node->contents.quadrants[qq],
0N/A distance, found_color, c,
0N/A base, position, pass - 1, dir_bit);
0N/A }
0N/A }
0N/A else { /* Search whole quadrant */
0N/A
0N/A mlib_s32 mask = 1 << dir_bit;
0N/A
0N/A for (i = 0; i < 16; i++) {
0N/A
0N/A if (node->tag & (1 << i)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[i];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex] - MLIB_S16_MIN;
0N/A newpalc1 = base[1][newindex] - MLIB_S16_MIN;
0N/A newpalc2 = base[2][newindex] - MLIB_S16_MIN;
0N/A newpalc3 = base[3][newindex] - MLIB_S16_MIN;
0N/A newdistance = FIND_DISTANCE_4(c[0], newpalc0,
0N/A c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 2);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[i]) {
0N/A
0N/A if (i & mask)
0N/A /* This quadrant may require partial checking */
0N/A distance =
0N/A mlib_search_quadrant_part_to_left_S16_4(node->contents.quadrants[i],
0N/A distance, found_color, c,
0N/A base,
0N/A position + current_size,
0N/A pass - 1, dir_bit);
0N/A else
0N/A /* Here we should check all */
0N/A distance =
0N/A mlib_search_quadrant_S16_4(node->contents.quadrants[i], distance,
0N/A found_color, c[0], c[1], c[2], c[3], base);
0N/A }
0N/A }
0N/A }
0N/A
0N/A return distance;
0N/A}
0N/A
0N/A/***************************************************************/
0N/Amlib_u32 mlib_search_quadrant_part_to_right_S16_4(struct lut_node_4 *node,
0N/A mlib_u32 distance,
0N/A mlib_s32 *found_color,
0N/A const mlib_u32 *c,
0N/A const mlib_s16 **base,
0N/A mlib_u32 position,
0N/A mlib_s32 pass,
0N/A mlib_s32 dir_bit)
0N/A{
0N/A mlib_u32 current_size = 1 << pass;
0N/A mlib_s32 i;
0N/A static mlib_s32 opposite_quadrants[4][8] = {
0N/A {1, 3, 5, 7, 9, 11, 13, 15},
0N/A {2, 3, 6, 7, 10, 11, 14, 15},
0N/A {4, 5, 6, 7, 12, 13, 14, 15},
0N/A {8, 9, 10, 11, 12, 13, 14, 15}
0N/A };
0N/A
0N/A/* Search only quadrant's half untill it is necessary to check the
0N/A whole quadrant */
0N/A
0N/A if (distance <= (((c[dir_bit] - position - current_size) * (c[dir_bit] - position - current_size)) >> 2)) { /* Search half of quadrant */
0N/A for (i = 0; i < 8; i++) {
0N/A mlib_s32 qq = opposite_quadrants[dir_bit][i];
0N/A
0N/A if (node->tag & (1 << qq)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[qq];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex] - MLIB_S16_MIN;
0N/A newpalc1 = base[1][newindex] - MLIB_S16_MIN;
0N/A newpalc2 = base[2][newindex] - MLIB_S16_MIN;
0N/A newpalc3 = base[3][newindex] - MLIB_S16_MIN;
0N/A newdistance = FIND_DISTANCE_4(c[0], newpalc0,
0N/A c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 2);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[qq])
0N/A distance =
0N/A mlib_search_quadrant_part_to_right_S16_4(node->contents.quadrants[qq],
0N/A distance, found_color, c,
0N/A base,
0N/A position + current_size,
0N/A pass - 1, dir_bit);
0N/A }
0N/A }
0N/A else { /* Search whole quadrant */
0N/A
0N/A mlib_s32 mask = 1 << dir_bit;
0N/A
0N/A for (i = 0; i < 16; i++) {
0N/A
0N/A if (node->tag & (1 << i)) {
0N/A /* Here is alone color cell. Check the distance */
0N/A mlib_s32 newindex = node->contents.index[i];
0N/A mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
0N/A mlib_u32 newdistance;
0N/A
0N/A newpalc0 = base[0][newindex] - MLIB_S16_MIN;
0N/A newpalc1 = base[1][newindex] - MLIB_S16_MIN;
0N/A newpalc2 = base[2][newindex] - MLIB_S16_MIN;
0N/A newpalc3 = base[3][newindex] - MLIB_S16_MIN;
0N/A newdistance = FIND_DISTANCE_4(c[0], newpalc0,
0N/A c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 2);
0N/A
0N/A if (distance > newdistance) {
0N/A *found_color = newindex;
0N/A distance = newdistance;
0N/A }
0N/A }
0N/A else if (node->contents.quadrants[i]) {
0N/A
0N/A if (i & mask)
0N/A /* Here we should check all */
0N/A distance =
0N/A mlib_search_quadrant_S16_4(node->contents.quadrants[i], distance,
0N/A found_color, c[0], c[1], c[2], c[3], base);
0N/A else
0N/A /* This quadrant may require partial checking */
0N/A distance =
0N/A mlib_search_quadrant_part_to_right_S16_4(node->contents.
0N/A quadrants[i], distance,
0N/A found_color, c, base,
0N/A position, pass - 1, dir_bit);
0N/A }
0N/A }
0N/A }
0N/A
0N/A return distance;
0N/A}
0N/A
0N/A/***************************************************************/
0N/A
0N/A#define TAB_SIZE_mlib_u8 256
0N/A#define TAB_SIZE_mlib_s16 1024
0N/A
0N/A#define SRC_mlib_u8(i) src[i]
0N/A#define SRC_mlib_s16(i) (((mlib_u16*)src)[i] >> 6)
0N/A
0N/A/***************************************************************/
0N/A
0N/A#define DIMENSIONS_SEARCH_3(STYPE, DTYPE, STEP) \
0N/A{ \
0N/A DTYPE *tab0 = ((mlib_colormap *)state)->table; \
0N/A DTYPE *tab1 = tab0 + TAB_SIZE_##STYPE; \
0N/A DTYPE *tab2 = tab1 + TAB_SIZE_##STYPE; \
0N/A mlib_s32 i; \
0N/A \
0N/A for (i = 0; i < length; i++) { \
0N/A dst[i] = tab0[SRC_##STYPE(0)] + tab1[SRC_##STYPE(1)] + \
0N/A tab2[SRC_##STYPE(2)]; \
0N/A src += STEP; \
0N/A } \
0N/A}
0N/A
0N/A/***************************************************************/
0N/A
0N/A#define DIMENSIONS_SEARCH_4(STYPE, DTYPE) \
0N/A{ \
0N/A DTYPE *tab0 = ((mlib_colormap *)state)->table; \
0N/A DTYPE *tab1 = tab0 + TAB_SIZE_##STYPE; \
0N/A DTYPE *tab2 = tab1 + TAB_SIZE_##STYPE; \
0N/A DTYPE *tab3 = tab2 + TAB_SIZE_##STYPE; \
0N/A mlib_s32 i; \
0N/A \
0N/A for (i = 0; i < length; i++) { \
0N/A dst[i] = tab0[SRC_##STYPE(0)] + tab1[SRC_##STYPE(1)] + \
0N/A tab2[SRC_##STYPE(2)] + tab3[SRC_##STYPE(3)]; \
0N/A src += 4; \
0N/A } \
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid mlib_ImageColorTrue2IndexLine_U8_U8_3(const mlib_u8 *src,
0N/A mlib_u8 *dst,
0N/A mlib_s32 length,
0N/A const void *state)
0N/A{
0N/A mlib_colormap *s = (mlib_colormap *)state;
0N/A
0N/A switch (s->method) {
0N/A#if LUT_BYTE_COLORS_3CHANNELS <= 256
0N/A case LUT_BINARY_TREE_SEARCH:
0N/A {
0N/A mlib_s32 bits = s->bits;
0N/A BINARY_TREE_SEARCH_3(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 0, 3, 0);
0N/A }
0N/A break;
0N/A
0N/A#endif /* LUT_BYTE_COLORS_3CHANNELS <= 256 */
0N/A case LUT_COLOR_CUBE_SEARCH:
0N/A {
0N/A COLOR_CUBE_U8_3_SEARCH(mlib_u8, 0, 3);
0N/A }
0N/A break;
0N/A
0N/A case LUT_STUPID_SEARCH:
0N/A {
0N/A#ifdef USE_VIS_CODE
0N/A FIND_NEAREST_U8_3;
0N/A#else
0N/A FIND_NEAREST_U8_3_C(0, 3);
0N/A#endif
0N/A }
0N/A break;
0N/A
0N/A case LUT_COLOR_DIMENSIONS:
0N/A DIMENSIONS_SEARCH_3(mlib_u8, mlib_u8, 3)
0N/A break;
0N/A }
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid mlib_ImageColorTrue2IndexLine_U8_U8_3_in_4(const mlib_u8 *src,
0N/A mlib_u8 *dst,
0N/A mlib_s32 length,
0N/A const void *state)
0N/A{
0N/A mlib_colormap *s = (mlib_colormap *)state;
0N/A
0N/A switch (s->method) {
0N/A#if LUT_BYTE_COLORS_3CHANNELS <= 256
0N/A case LUT_BINARY_TREE_SEARCH:
0N/A {
0N/A mlib_s32 bits = s->bits;
0N/A BINARY_TREE_SEARCH_3(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 1, 4, 0);
0N/A break;
0N/A }
0N/A
0N/A#endif /* LUT_BYTE_COLORS_3CHANNELS <= 256 */
0N/A case LUT_COLOR_CUBE_SEARCH:
0N/A {
0N/A COLOR_CUBE_U8_3_SEARCH(mlib_u8, 1, 4);
0N/A break;
0N/A }
0N/A
0N/A case LUT_STUPID_SEARCH:
0N/A {
0N/A#ifdef USE_VIS_CODE
0N/A FIND_NEAREST_U8_3_IN4;
0N/A#else
0N/A FIND_NEAREST_U8_3_C(1, 4);
0N/A#endif
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_DIMENSIONS:
0N/A src++;
0N/A DIMENSIONS_SEARCH_3(mlib_u8, mlib_u8, 4)
0N/A break;
0N/A }
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid mlib_ImageColorTrue2IndexLine_U8_U8_4(const mlib_u8 *src,
0N/A mlib_u8 *dst,
0N/A mlib_s32 length,
0N/A const void *state)
0N/A{
0N/A mlib_colormap *s = (mlib_colormap *)state;
0N/A
0N/A switch (s->method) {
0N/A#if LUT_BYTE_COLORS_4CHANNELS <= 256
0N/A case LUT_BINARY_TREE_SEARCH:
0N/A {
0N/A mlib_s32 bits = s->bits;
0N/A BINARY_TREE_SEARCH_4(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 0);
0N/A break;
0N/A }
0N/A
0N/A#endif /* LUT_BYTE_COLORS_4CHANNELS <= 256 */
0N/A case LUT_COLOR_CUBE_SEARCH:
0N/A {
0N/A COLOR_CUBE_U8_4_SEARCH(mlib_u8);
0N/A break;
0N/A }
0N/A
0N/A case LUT_STUPID_SEARCH:
0N/A {
0N/A#ifdef USE_VIS_CODE
0N/A FIND_NEAREST_U8_4;
0N/A#else
0N/A FIND_NEAREST_U8_4_C;
0N/A#endif
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_DIMENSIONS:
0N/A DIMENSIONS_SEARCH_4(mlib_u8, mlib_u8)
0N/A break;
0N/A }
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid mlib_ImageColorTrue2IndexLine_U8_S16_3(const mlib_u8 *src,
0N/A mlib_s16 *dst,
0N/A mlib_s32 length,
0N/A const void *state)
0N/A{
0N/A mlib_colormap *s = (mlib_colormap *)state;
0N/A mlib_s32 bits = s->bits;
0N/A
0N/A switch (s->method) {
0N/A case LUT_BINARY_TREE_SEARCH:
0N/A {
0N/A BINARY_TREE_SEARCH_3(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 0, 3, 0);
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_CUBE_SEARCH:
0N/A {
0N/A switch (s->indexsize) {
0N/A case 1:
0N/A {
0N/A COLOR_CUBE_U8_3_SEARCH(mlib_u8, 0, 3);
0N/A break;
0N/A }
0N/A
0N/A case 2:
0N/A {
0N/A COLOR_CUBE_U8_3_SEARCH(mlib_s16, 0, 3);
0N/A break;
0N/A }
0N/A }
0N/A
0N/A break;
0N/A }
0N/A
0N/A case LUT_STUPID_SEARCH:
0N/A {
0N/A#ifdef USE_VIS_CODE
0N/A FIND_NEAREST_U8_3;
0N/A#else
0N/A FIND_NEAREST_U8_3_C(0, 3);
0N/A#endif
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_DIMENSIONS:
0N/A DIMENSIONS_SEARCH_3(mlib_u8, mlib_s16, 3)
0N/A break;
0N/A }
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid mlib_ImageColorTrue2IndexLine_U8_S16_3_in_4(const mlib_u8 *src,
0N/A mlib_s16 *dst,
0N/A mlib_s32 length,
0N/A const void *state)
0N/A{
0N/A mlib_colormap *s = (mlib_colormap *)state;
0N/A mlib_s32 bits = s->bits;
0N/A
0N/A switch (s->method) {
0N/A case LUT_BINARY_TREE_SEARCH:
0N/A {
0N/A BINARY_TREE_SEARCH_3(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 1, 4, 0);
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_CUBE_SEARCH:
0N/A {
0N/A switch (s->indexsize) {
0N/A case 1:
0N/A {
0N/A COLOR_CUBE_U8_3_SEARCH(mlib_u8, 1, 4);
0N/A break;
0N/A }
0N/A
0N/A case 2:
0N/A {
0N/A COLOR_CUBE_U8_3_SEARCH(mlib_s16, 1, 4);
0N/A break;
0N/A }
0N/A }
0N/A
0N/A break;
0N/A }
0N/A
0N/A case LUT_STUPID_SEARCH:
0N/A {
0N/A#ifdef USE_VIS_CODE
0N/A FIND_NEAREST_U8_3_IN4;
0N/A#else
0N/A FIND_NEAREST_U8_3_C(1, 4);
0N/A#endif
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_DIMENSIONS:
0N/A src++;
0N/A DIMENSIONS_SEARCH_3(mlib_u8, mlib_s16, 4)
0N/A break;
0N/A }
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid mlib_ImageColorTrue2IndexLine_U8_S16_4(const mlib_u8 *src,
0N/A mlib_s16 *dst,
0N/A mlib_s32 length,
0N/A const void *state)
0N/A{
0N/A mlib_colormap *s = (mlib_colormap *)state;
0N/A mlib_s32 bits = s->bits;
0N/A
0N/A switch (s->method) {
0N/A case LUT_BINARY_TREE_SEARCH:
0N/A {
0N/A BINARY_TREE_SEARCH_4(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 0);
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_CUBE_SEARCH:
0N/A {
0N/A switch (s->indexsize) {
0N/A case 1:
0N/A {
0N/A COLOR_CUBE_U8_4_SEARCH(mlib_u8);
0N/A break;
0N/A }
0N/A
0N/A case 2:
0N/A {
0N/A COLOR_CUBE_U8_4_SEARCH(mlib_s16);
0N/A break;
0N/A }
0N/A }
0N/A
0N/A break;
0N/A }
0N/A
0N/A case LUT_STUPID_SEARCH:
0N/A {
0N/A#ifdef USE_VIS_CODE
0N/A FIND_NEAREST_U8_4;
0N/A#else
0N/A FIND_NEAREST_U8_4_C;
0N/A#endif
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_DIMENSIONS:
0N/A DIMENSIONS_SEARCH_4(mlib_u8, mlib_s16)
0N/A break;
0N/A }
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid mlib_ImageColorTrue2IndexLine_S16_S16_3(const mlib_s16 *src,
0N/A mlib_s16 *dst,
0N/A mlib_s32 length,
0N/A const void *state)
0N/A{
0N/A mlib_colormap *s = (mlib_colormap *)state;
0N/A mlib_s32 bits = s->bits;
0N/A
0N/A switch (s->method) {
0N/A case LUT_BINARY_TREE_SEARCH:
0N/A {
0N/A BINARY_TREE_SEARCH_3(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
0N/A MLIB_S16_MIN, 0, 3, 2);
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_CUBE_SEARCH:
0N/A {
0N/A switch (s->indexsize) {
0N/A case 1:
0N/A {
0N/A COLOR_CUBE_S16_3_SEARCH(mlib_u8, 0, 3);
0N/A break;
0N/A }
0N/A
0N/A case 2:
0N/A {
0N/A COLOR_CUBE_S16_3_SEARCH(mlib_s16, 0, 3);
0N/A break;
0N/A }
0N/A }
0N/A
0N/A break;
0N/A }
0N/A
0N/A case LUT_STUPID_SEARCH:
0N/A {
0N/A FIND_NEAREST_S16_3(0, 3);
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_DIMENSIONS:
0N/A DIMENSIONS_SEARCH_3(mlib_s16, mlib_s16, 3)
0N/A break;
0N/A }
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid mlib_ImageColorTrue2IndexLine_S16_S16_3_in_4(const mlib_s16 *src,
0N/A mlib_s16 *dst,
0N/A mlib_s32 length,
0N/A const void *state)
0N/A{
0N/A mlib_colormap *s = (mlib_colormap *)state;
0N/A mlib_s32 bits = s->bits;
0N/A
0N/A switch (s->method) {
0N/A case LUT_BINARY_TREE_SEARCH:
0N/A {
0N/A BINARY_TREE_SEARCH_3(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
0N/A MLIB_S16_MIN, 1, 4, 2);
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_CUBE_SEARCH:
0N/A {
0N/A switch (s->indexsize) {
0N/A case 1:
0N/A {
0N/A COLOR_CUBE_S16_3_SEARCH(mlib_u8, 1, 4);
0N/A break;
0N/A }
0N/A
0N/A case 2:
0N/A {
0N/A COLOR_CUBE_S16_3_SEARCH(mlib_s16, 1, 4);
0N/A break;
0N/A }
0N/A }
0N/A
0N/A break;
0N/A }
0N/A
0N/A case LUT_STUPID_SEARCH:
0N/A {
0N/A FIND_NEAREST_S16_3(1, 4);
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_DIMENSIONS:
0N/A src++;
0N/A DIMENSIONS_SEARCH_3(mlib_s16, mlib_s16, 4)
0N/A break;
0N/A }
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid mlib_ImageColorTrue2IndexLine_S16_S16_4(const mlib_s16 *src,
0N/A mlib_s16 *dst,
0N/A mlib_s32 length,
0N/A const void *state)
0N/A{
0N/A mlib_colormap *s = (mlib_colormap *)state;
0N/A mlib_s32 bits = s->bits;
0N/A
0N/A switch (s->method) {
0N/A case LUT_BINARY_TREE_SEARCH:
0N/A {
0N/A BINARY_TREE_SEARCH_4(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
0N/A MLIB_S16_MIN, 2);
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_CUBE_SEARCH:
0N/A {
0N/A switch (s->indexsize) {
0N/A case 1:
0N/A {
0N/A COLOR_CUBE_S16_4_SEARCH(mlib_u8);
0N/A break;
0N/A }
0N/A
0N/A case 2:
0N/A {
0N/A COLOR_CUBE_S16_4_SEARCH(mlib_s16);
0N/A break;
0N/A }
0N/A }
0N/A
0N/A break;
0N/A }
0N/A
0N/A case LUT_STUPID_SEARCH:
0N/A {
0N/A FIND_NEAREST_S16_4;
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_DIMENSIONS:
0N/A DIMENSIONS_SEARCH_4(mlib_s16, mlib_s16)
0N/A break;
0N/A }
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid mlib_ImageColorTrue2IndexLine_S16_U8_3(const mlib_s16 *src,
0N/A mlib_u8 *dst,
0N/A mlib_s32 length,
0N/A const void *state)
0N/A{
0N/A mlib_colormap *s = (mlib_colormap *)state;
0N/A
0N/A switch (s->method) {
0N/A#if LUT_SHORT_COLORS_3CHANNELS <= 256
0N/A case LUT_BINARY_TREE_SEARCH:
0N/A {
0N/A mlib_s32 bits = s->bits;
0N/A BINARY_TREE_SEARCH_3(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
0N/A MLIB_S16_MIN, 0, 3, 2);
0N/A break;
0N/A }
0N/A
0N/A#endif /* LUT_SHORT_COLORS_3CHANNELS <= 256 */
0N/A case LUT_COLOR_CUBE_SEARCH:
0N/A {
0N/A COLOR_CUBE_S16_3_SEARCH(mlib_u8, 0, 3);
0N/A break;
0N/A }
0N/A
0N/A case LUT_STUPID_SEARCH:
0N/A {
0N/A FIND_NEAREST_S16_3(0, 3);
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_DIMENSIONS:
0N/A DIMENSIONS_SEARCH_3(mlib_s16, mlib_u8, 3)
0N/A break;
0N/A }
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid mlib_ImageColorTrue2IndexLine_S16_U8_3_in_4(const mlib_s16 *src,
0N/A mlib_u8 *dst,
0N/A mlib_s32 length,
0N/A const void *state)
0N/A{
0N/A mlib_colormap *s = (mlib_colormap *)state;
0N/A
0N/A switch (s->method) {
0N/A#if LUT_SHORT_COLORS_3CHANNELS <= 256
0N/A case LUT_BINARY_TREE_SEARCH:
0N/A {
0N/A mlib_s32 bits = s->bits;
0N/A BINARY_TREE_SEARCH_3(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
0N/A MLIB_S16_MIN, 1, 4, 2);
0N/A break;
0N/A }
0N/A
0N/A#endif /* LUT_SHORT_COLORS_3CHANNELS <= 256 */
0N/A case LUT_COLOR_CUBE_SEARCH:
0N/A {
0N/A COLOR_CUBE_S16_3_SEARCH(mlib_u8, 1, 4);
0N/A break;
0N/A }
0N/A
0N/A case LUT_STUPID_SEARCH:
0N/A {
0N/A FIND_NEAREST_S16_3(1, 4);
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_DIMENSIONS:
0N/A src++;
0N/A DIMENSIONS_SEARCH_3(mlib_s16, mlib_u8, 4)
0N/A break;
0N/A }
0N/A}
0N/A
0N/A/***************************************************************/
0N/Avoid mlib_ImageColorTrue2IndexLine_S16_U8_4(const mlib_s16 *src,
0N/A mlib_u8 *dst,
0N/A mlib_s32 length,
0N/A const void *state)
0N/A{
0N/A mlib_colormap *s = (mlib_colormap *)state;
0N/A
0N/A switch (s->method) {
0N/A#if LUT_SHORT_COLORS_4CHANNELS <= 256
0N/A case LUT_BINARY_TREE_SEARCH:
0N/A {
0N/A mlib_s32 bits = s->bits;
0N/A BINARY_TREE_SEARCH_4(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
0N/A MLIB_S16_MIN, 2);
0N/A break;
0N/A }
0N/A
0N/A#endif /* LUT_SHORT_COLORS_4CHANNELS <= 256 */
0N/A case LUT_COLOR_CUBE_SEARCH:
0N/A {
0N/A COLOR_CUBE_S16_4_SEARCH(mlib_u8);
0N/A break;
0N/A }
0N/A
0N/A case LUT_STUPID_SEARCH:
0N/A {
0N/A FIND_NEAREST_S16_4;
0N/A break;
0N/A }
0N/A
0N/A case LUT_COLOR_DIMENSIONS:
0N/A DIMENSIONS_SEARCH_4(mlib_s16, mlib_u8)
0N/A break;
0N/A }
0N/A}
0N/A
0N/A/***************************************************************/
0N/A
0N/A#ifndef VIS
0N/A
0N/Avoid mlib_c_ImageThresh1_U81_1B(void *psrc,
0N/A void *pdst,
0N/A mlib_s32 src_stride,
0N/A mlib_s32 dst_stride,
0N/A mlib_s32 width,
0N/A mlib_s32 height,
0N/A void *thresh,
0N/A void *ghigh,
0N/A void *glow,
0N/A mlib_s32 dbit_off);
0N/A
0N/A/***************************************************************/
0N/A
0N/Avoid mlib_ImageColorTrue2IndexLine_U8_BIT_1(const mlib_u8 *src,
0N/A mlib_u8 *dst,
0N/A mlib_s32 bit_offset,
0N/A mlib_s32 length,
0N/A const void *state)
0N/A{
0N/A mlib_u8 *lut = ((mlib_colormap *)state)->table;
0N/A mlib_s32 thresh[1];
0N/A mlib_s32 ghigh[1];
0N/A mlib_s32 glow[1];
0N/A
0N/A thresh[0] = lut[2];
0N/A
0N/A glow[0] = lut[0] - lut[1];
0N/A ghigh[0] = lut[1] - lut[0];
0N/A
0N/A mlib_c_ImageThresh1_U81_1B((void*)src, dst, 0, 0, length, 1,
0N/A thresh, ghigh, glow, bit_offset);
0N/A}
0N/A
0N/A#else
0N/A
0N/A/***************************************************************/
0N/A
0N/Avoid mlib_v_ImageThresh1B_U8_1(const mlib_u8 *src,
0N/A mlib_s32 slb,
0N/A mlib_u8 *dst,
0N/A mlib_s32 dlb,
0N/A mlib_s32 xsize,
0N/A mlib_s32 ysize,
0N/A mlib_s32 dbit_off,
0N/A const mlib_s32 *th,
0N/A mlib_s32 hc,
0N/A mlib_s32 lc);
0N/A
0N/A/***************************************************************/
0N/A
0N/Avoid mlib_ImageColorTrue2IndexLine_U8_BIT_1(const mlib_u8 *src,
0N/A mlib_u8 *dst,
0N/A mlib_s32 bit_offset,
0N/A mlib_s32 length,
0N/A const void *state)
0N/A{
0N/A mlib_u8 *lut = ((mlib_colormap *)state)->table;
0N/A mlib_s32 thresh[4];
0N/A mlib_s32 ghigh[1];
0N/A mlib_s32 glow[1];
0N/A
0N/A thresh[0] = thresh[1] = thresh[2] = thresh[3] = lut[2];
0N/A
0N/A glow[0] = (lut[1] < lut[0]) ? 0xFF : 0;
0N/A ghigh[0] = (lut[1] < lut[0]) ? 0 : 0xFF;
0N/A
0N/A mlib_v_ImageThresh1B_U8_1((void*)src, 0, dst, 0, length, 1,
0N/A bit_offset, thresh, ghigh[0], glow[0]);
0N/A}
0N/A
0N/A/***************************************************************/
0N/A
0N/A#endif