alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (mlib_ImageColorTrue2Index.c)

This example Java source code file (mlib_ImageColorTrue2Index.c) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

check_quadrant_, color_max, find_distance_3, find_distance_4, first_neibour, image_type, mlib_s16_min, position, second_neibour, shift, source_image, step, substraction, subtraction

The mlib_ImageColorTrue2Index.c Java example source code

/*
 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * FUNCTION
 *      mlib_ImageColorTrue2Index - convert a true color image to an indexed
 *                                  color image
 *
 * SYNOPSIS
 *      mlib_status mlib_ImageColorTrue2Index(mlib_image       *dst,
 *                                            const mlib_image *src,
 *                                            const void       *colormap)
 *
 * ARGUMENTS
 *      colormap  Internal data structure for inverse color mapping.
 *      dst       Pointer to destination image.
 *      src       Pointer to source image.
 *
 * DESCRIPTION
 *      Convert a true color image to a pseudo color image with the method
 *      of finding the nearest matched lut entry for each pixel.
 *
 *      The src can be an MLIB_BYTE or MLIB_SHORT image with 3 or 4 channels.
 *      The dst must be a 1-channel MLIB_BYTE or MLIB_SHORT image.
 *
 *      The lut might have either 3 or 4 channels. The type of the lut can be
 *      one of the following:
 *              MLIB_BYTE in, MLIB_BYTE out (i.e., BYTE-to-BYTE)
 *              MLIB_BYTE in, MLIB_SHORT out (i.e., BYTE-to-SHORT)
 *              MLIB_SHORT in, MLIB_SHORT out (i.e., SHORT-to-SHORT)
 *              MLIB_SHORT in, MLIB_BYTE out (i.e., SHORT-to-BYTE)
 *
 *      The src image and the lut must have same number of channels.
 */

#include "mlib_image.h"
#include "mlib_ImageColormap.h"
#include "mlib_ImageCheck.h"

/***************************************************************/

/*#define USE_VIS_CODE*/

#ifdef USE_VIS_CODE
#include "vis_proto.h"
#define VIS_ALIGNADDR(X, Y)  vis_alignaddr((void *)(X), (Y))
#endif

/***************************************************************/

#define LUT_BYTE_COLORS_3CHANNELS  1000
#define LUT_BYTE_COLORS_4CHANNELS  3000
#define LUT_SHORT_COLORS_3CHANNELS 1000
#define LUT_SHORT_COLORS_4CHANNELS 1000

/***************************************************************/

#define MAIN_COLORTRUE2INDEX_LOOP( FROM_TYPE, TO_TYPE, NCHANNELS )       \
  for( y = 0; y < height; y++ )                                          \
  {                                                                      \
    mlib_ImageColorTrue2IndexLine_##FROM_TYPE##_##TO_TYPE##_##NCHANNELS( \
      sdata, ddata, width, colormap );                                   \
                                                                         \
    sdata += sstride;                                                    \
    ddata += dstride;                                                    \
  }

/***************************************************************/

#define COLOR_CUBE_U8_3_SEARCH( TABLE_POINTER_TYPE, SHIFT, STEP ) \
{                                                                 \
  const mlib_u8 *c0, *c1, *c2;                                    \
  TABLE_POINTER_TYPE *table = s->table;                           \
  mlib_s32 bits = s->bits;                                        \
  mlib_s32 nbits = 8 - bits;                                      \
  mlib_s32 mask = ~( ( 1 << nbits ) - 1 );                        \
  mlib_s32 j;                                                     \
                                                                  \
  c0 = src + SHIFT;                                               \
  c1 = src + 1 + SHIFT;                                           \
  c2 = src + 2 + SHIFT;                                           \
                                                                  \
  switch( bits )                                                  \
  {                                                               \
    case 1:                                                       \
    case 2:                                                       \
    {                                                             \
      mlib_s32 bits0 = 8 - bits;                                  \
      mlib_s32 bits1 = bits0 - bits;                              \
      mlib_s32 bits2 = bits1 - bits;                              \
                                                                  \
      for( j = 0; j < length; j++ )                               \
      {                                                           \
        dst[ j ] = table[ ( ( *c0 & mask ) >> bits2 ) |           \
          ( ( *c1 & mask ) >> bits1 ) |                           \
          ( ( *c2 & mask ) >> bits0 ) ];                          \
                                                                  \
        c0 += STEP;                                               \
        c1 += STEP;                                               \
        c2 += STEP;                                               \
      }                                                           \
      break;                                                      \
    }                                                             \
    case 3:                                                       \
    {                                                             \
      for( j = 0; j < length; j++ )                               \
      {                                                           \
        dst[ j ] = table[ ( ( *c0 & mask ) << 1 ) |               \
          ( ( *c1 & mask ) >> 2 ) |                               \
          ( ( *c2 & mask ) >> 5 ) ];                              \
                                                                  \
        c0 += STEP;                                               \
        c1 += STEP;                                               \
        c2 += STEP;                                               \
      }                                                           \
      break;                                                      \
    }                                                             \
    case 4:                                                       \
    {                                                             \
      for( j = 0; j < length; j++ )                               \
      {                                                           \
        dst[ j ] = table[ ( ( *c0 & mask ) << 4 ) |               \
          ( *c1 & mask ) |                                        \
          ( ( *c2 & mask ) >> 4 ) ];                              \
                                                                  \
        c0 += STEP;                                               \
        c1 += STEP;                                               \
        c2 += STEP;                                               \
      }                                                           \
      break;                                                      \
    }                                                             \
    case 5:                                                       \
    case 6:                                                       \
    case 7:                                                       \
    {                                                             \
      mlib_s32 bits0 = 8 - bits;                                  \
      mlib_s32 bits1 = bits * 2 - 8;                              \
      mlib_s32 bits2 = bits1 + bits;                              \
                                                                  \
      for( j = 0; j < length; j++ )                               \
      {                                                           \
        dst[ j ] = table[ ( ( *c0 & mask ) << bits2 ) |           \
          ( ( *c1 & mask ) << bits1 ) |                           \
          ( ( *c2 & mask ) >> bits0 ) ];                          \
                                                                  \
        c0 += STEP;                                               \
        c1 += STEP;                                               \
        c2 += STEP;                                               \
      }                                                           \
      break;                                                      \
    }                                                             \
    case 8:                                                       \
    {                                                             \
      for( j = 0; j < length; j++ )                               \
      {                                                           \
        dst[ j ] = table[ ( ( *c0 & mask ) << 16 ) |              \
          ( ( *c1 & mask ) << 8 ) |                               \
          ( *c2 & mask ) ];                                       \
                                                                  \
        c0 += STEP;                                               \
        c1 += STEP;                                               \
        c2 += STEP;                                               \
      }                                                           \
      break;                                                      \
    }                                                             \
  }                                                               \
}

/***************************************************************/
#define COLOR_CUBE_U8_4_SEARCH( TABLE_TYPE )                    \
{                                                               \
  const mlib_u8 *c0, *c1, *c2, *c3;                             \
  TABLE_TYPE *table = s->table;                                 \
  mlib_s32 bits = s->bits;                                      \
  mlib_s32 nbits = 8 - bits;                                    \
  mlib_s32 mask = ~( ( 1 << nbits ) - 1 );                      \
  mlib_s32 j;                                                   \
                                                                \
  c0 = src;                                                     \
  c1 = src + 1;                                                 \
  c2 = src + 2;                                                 \
  c3 = src + 3;                                                 \
                                                                \
  switch( bits )                                                \
  {                                                             \
    case 1:                                                     \
    {                                                           \
      for( j = 0; j < length; j++ )                             \
      {                                                         \
        dst[ j ] = table[ ( ( *c0 & mask ) >> 4 ) |             \
          ( ( *c1 & mask ) >> 5 ) |                             \
          ( ( *c2 & mask ) >> 6 ) |                             \
          ( ( *c3 & mask ) >> 7 ) ];                            \
                                                                \
        c0 += 4;                                                \
        c1 += 4;                                                \
        c2 += 4;                                                \
        c3 += 4;                                                \
      }                                                         \
      break;                                                    \
    }                                                           \
    case 2:                                                     \
    {                                                           \
      for( j = 0; j < length; j++ )                             \
      {                                                         \
        dst[ j ] = table[ ( *c0 & mask ) |                      \
          ( ( *c1 & mask ) >> 2 ) |                             \
          ( ( *c2 & mask ) >> 4 ) |                             \
          ( ( *c3 & mask ) >> 6 ) ];                            \
                                                                \
        c0 += 4;                                                \
        c1 += 4;                                                \
        c2 += 4;                                                \
        c3 += 4;                                                \
          }                                                     \
      break;                                                    \
    }                                                           \
    case 3:                                                     \
    {                                                           \
      for( j = 0; j < length; j++ )                             \
      {                                                         \
        dst[ j ] = table[ ( ( *c0 & mask ) << 4 ) |             \
          ( ( *c1 & mask ) << 1 ) |                             \
          ( ( *c2 & mask ) >> 2 ) |                             \
          ( ( *c3 & mask ) >> 5 ) ];                            \
                                                                \
        c0 += 4;                                                \
        c1 += 4;                                                \
        c2 += 4;                                                \
        c3 += 4;                                                \
      }                                                         \
      break;                                                    \
    }                                                           \
    case 4:                                                     \
    {                                                           \
      for( j = 0; j < length; j++ )                             \
      {                                                         \
        dst[ j ] = table[ ( ( *c0 & mask ) << 8 ) |             \
          ( ( *c1 & mask ) << 4 ) |                             \
          ( *c2 & mask ) |                                      \
          ( ( *c3 & mask ) >> 4 ) ];                            \
                                                                \
        c0 += 4;                                                \
        c1 += 4;                                                \
        c2 += 4;                                                \
        c3 += 4;                                                \
      }                                                         \
      break;                                                    \
    }                                                           \
    case 5:                                                     \
    case 6:                                                     \
    {                                                           \
      mlib_s32 bits3 = bits * 4 - 8;                            \
      mlib_s32 bits2 = bits3 - bits;                            \
      mlib_s32 bits1 = bits2 - bits;                            \
      mlib_s32 bits0 = 8 - bits;                                \
                                                                \
      for( j = 0; j < length; j++ )                             \
      {                                                         \
        dst[ j ] = table[ ( ( *c0 & mask ) << bits3 ) |         \
          ( ( *c1 & mask ) << bits2 ) |                         \
          ( ( *c2 & mask ) << bits1 ) |                         \
          ( ( *c3 & mask ) >> bits0 ) ];                        \
                                                                \
        c0 += 4;                                                \
        c1 += 4;                                                \
        c2 += 4;                                                \
        c3 += 4;                                                \
      }                                                         \
      break;                                                    \
    }                                                           \
    case 7:                                                     \
    {                                                           \
      for( j = 0; j < length; j++ )                             \
      {                                                         \
        dst[ j ] = table[ ( ( *c0 & mask ) << 20 ) |            \
          ( ( *c1 & mask ) << 13 ) |                            \
          ( ( *c2 & mask ) << 6 ) |                             \
          ( ( *c3 & mask ) >> 1 ) ];                            \
                                                                \
        c0 += 4;                                                \
        c1 += 4;                                                \
        c2 += 4;                                                \
        c3 += 4;                                                \
      }                                                         \
      break;                                                    \
    }                                                           \
    case 8: /* will never be called */                          \
    {                                                           \
      for( j = 0; j < length; j++ )                             \
      {                                                         \
        dst[ j ] = table[ ( ( *c0 & mask ) << 24 ) |            \
          ( ( *c1 & mask ) << 16 ) |                            \
          ( ( *c2 & mask ) << 8 ) |                             \
          ( *c3 & mask ) ];                                     \
                                                                \
        c0 += 4;                                                \
        c1 += 4;                                                \
        c2 += 4;                                                \
        c3 += 4;                                                \
      }                                                         \
      break;                                                    \
    }                                                           \
  }                                                             \
}

/***************************************************************/
#define COLOR_CUBE_S16_3_SEARCH( TABLE_TYPE, SHIFT, STEP )                 \
{                                                                          \
  const mlib_s16 *c0, *c1, *c2;                                            \
  mlib_s32 bits = s->bits;                                                 \
  mlib_s32 nbits = 16 - bits;                                              \
  mlib_s32 mask = ~( ( 1 << nbits ) - 1 );                                 \
  TABLE_TYPE *table = s->table;                                            \
  mlib_s32 j;                                                              \
                                                                           \
  c0 = src + SHIFT;                                                        \
  c1 = src + 1 + SHIFT;                                                    \
  c2 = src + 2 + SHIFT;                                                    \
                                                                           \
  switch( bits )                                                           \
  {                                                                        \
    case 1:                                                                \
    case 2:                                                                \
    case 3:                                                                \
    case 4:                                                                \
    case 5:                                                                \
    {                                                                      \
      mlib_s32 bits0 = 16 - bits;                                          \
      mlib_s32 bits1 = bits0 - bits;                                       \
      mlib_s32 bits2 = bits1 - bits;                                       \
                                                                           \
      for( j = 0; j < length; j++ )                                        \
      {                                                                    \
        dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) >> bits2 ) | \
          ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> bits1 ) |                 \
          ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits0 ) ];                \
                                                                           \
        c0 += STEP;                                                        \
        c1 += STEP;                                                        \
        c2 += STEP;                                                        \
      }                                                                    \
      break;                                                               \
    }                                                                      \
    case 6:                                                                \
    case 7:                                                                \
    {                                                                      \
      mlib_s32 bits0 = 16 - bits;                                          \
      mlib_s32 bits1 = bits0 - bits;                                       \
      mlib_s32 bits2 = bits * 3 - 16;                                      \
                                                                           \
      for( j = 0; j < length; j++ )                                        \
      {                                                                    \
        dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << bits2 ) | \
          ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> bits1 ) |                 \
          ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits0 ) ];                \
                                                                           \
        c0 += STEP;                                                        \
        c1 += STEP;                                                        \
        c2 += STEP;                                                        \
      }                                                                    \
      break;                                                               \
    }                                                                      \
    case 8:                                                                \
    {                                                                      \
      for( j = 0; j < length; j++ )                                        \
      {                                                                    \
        dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << 8 ) |     \
          ( ( *c1 - MLIB_S16_MIN ) & mask ) |                              \
          ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> 8 ) ];                    \
                                                                           \
        c0 += STEP;                                                        \
        c1 += STEP;                                                        \
        c2 += STEP;                                                        \
      }                                                                    \
      break;                                                               \
    }                                                                      \
    case 9:                                                                \
    case 10:                                                               \
    {                                                                      \
      mlib_s32 bits0 = 16 - bits;                                          \
      mlib_s32 bits1 = 2 * bits - 16;                                      \
      mlib_s32 bits2 = bits1 + bits;                                       \
                                                                           \
      for( j = 0; j < length; j++ )                                        \
      {                                                                    \
        dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << bits2 ) | \
          ( ( ( *c1 - MLIB_S16_MIN ) & mask ) << bits1 ) |                 \
          ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits0 ) ];                \
                                                                           \
        c0 += STEP;                                                        \
        c1 += STEP;                                                        \
        c2 += STEP;                                                        \
      }                                                                    \
      break;                                                               \
    }                                                                      \
    /* Other cases may not be considered as the table size will be more    \
       than 2^32 */                                                        \
  }                                                                        \
}

/***************************************************************/
#define COLOR_CUBE_S16_4_SEARCH( TABLE_TYPE )                              \
{                                                                          \
  const mlib_s16 *c0, *c1, *c2, *c3;                                       \
  TABLE_TYPE *table = s->table;                                            \
  mlib_s32 bits = s->bits;                                                 \
  mlib_s32 nbits = 16 - bits;                                              \
  mlib_s32 mask = ~( ( 1 << nbits ) - 1 );                                 \
  mlib_s32 j;                                                              \
                                                                           \
  c0 = src;                                                                \
  c1 = src + 1;                                                            \
  c2 = src + 2;                                                            \
  c3 = src + 3;                                                            \
                                                                           \
  switch( bits )                                                           \
  {                                                                        \
    case 1:                                                                \
    case 2:                                                                \
    case 3:                                                                \
    {                                                                      \
      mlib_s32 bits0 = 16 - bits;                                          \
      mlib_s32 bits1 = bits0 - bits;                                       \
      mlib_s32 bits2 = bits1 - bits;                                       \
      mlib_s32 bits3 = bits2 - bits;                                       \
                                                                           \
      for( j = 0; j < length; j++ )                                        \
      {                                                                    \
        dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) >> bits3 ) | \
          ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> bits2 ) |                 \
          ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits1 ) |                 \
          ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> bits0 ) ];                \
                                                                           \
        c0 += 4;                                                           \
        c1 += 4;                                                           \
        c2 += 4;                                                           \
        c3 += 4;                                                           \
      }                                                                    \
      break;                                                               \
    }                                                                      \
    case 4:                                                                \
    {                                                                      \
      for( j = 0; j < length; j++ )                                        \
      {                                                                    \
        dst[ j ] = table[ ( ( *c0 - MLIB_S16_MIN ) & mask ) |              \
          ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> 4 ) |                     \
          ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> 8 ) |                     \
          ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> 12 ) ];                   \
                                                                           \
        c0 += 4;                                                           \
        c1 += 4;                                                           \
        c2 += 4;                                                           \
        c3 += 4;                                                           \
      }                                                                    \
      break;                                                               \
    }                                                                      \
    case 5:                                                                \
    {                                                                      \
      for( j = 0; j < length; j++ )                                        \
      {                                                                    \
        dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << 4 ) |     \
          ( ( ( *c1 - MLIB_S16_MIN ) & mask ) >> 1 ) |                     \
          ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> 6 ) |                     \
          ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> 11 ) ];                   \
                                                                           \
        c0 += 4;                                                           \
        c1 += 4;                                                           \
        c2 += 4;                                                           \
        c3 += 4;                                                           \
      }                                                                    \
      break;                                                               \
    }                                                                      \
    case 6:                                                                \
    case 7:                                                                \
    {                                                                      \
      mlib_s32 bits0 = 16 - bits;                                          \
      mlib_s32 bits1 = bits0 - bits;                                       \
      mlib_s32 bits3 = bits * 4 - 16;                                      \
      mlib_s32 bits2 = bits3 - bits;                                       \
                                                                           \
      for( j = 0; j < length; j++ )                                        \
      {                                                                    \
        dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << bits3 ) | \
          ( ( ( *c1 - MLIB_S16_MIN ) & mask ) << bits2 ) |                 \
          ( ( ( *c2 - MLIB_S16_MIN ) & mask ) >> bits1 ) |                 \
          ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> bits0 ) ];                \
                                                                           \
        c0 += 4;                                                           \
        c1 += 4;                                                           \
        c2 += 4;                                                           \
        c3 += 4;                                                           \
      }                                                                    \
      break;                                                               \
    }                                                                      \
    case 8:                                                                \
    {                                                                      \
      for( j = 0; j < length; j++ )                                        \
      {                                                                    \
        dst[ j ] = table[ ( ( ( *c0 - MLIB_S16_MIN ) & mask ) << 16 ) |    \
          ( ( ( *c1 - MLIB_S16_MIN ) & mask ) << 8 ) |                     \
          ( ( *c2 - MLIB_S16_MIN ) & mask ) |                              \
          ( ( ( *c3 - MLIB_S16_MIN ) & mask ) >> 8 ) ];                    \
                                                                           \
        c0 += 4;                                                           \
        c1 += 4;                                                           \
        c2 += 4;                                                           \
        c3 += 4;                                                           \
      }                                                                    \
      break;                                                               \
    }                                                                      \
    /* Other cases may not be considered as the table size will be more    \
       than 2^32 */                                                        \
  }                                                                        \
}

/***************************************************************/
#define BINARY_TREE_SEARCH_RIGHT( POSITION, COLOR_MAX, SHIFT )  \
{                                                               \
  if( ( distance >= ( ( ( position[ POSITION ] + current_size - \
    c[ POSITION ] ) * ( position[ POSITION ] + current_size -   \
    c[ POSITION ] ) ) >> SHIFT ) ) &&                           \
    ( position[ POSITION ] + current_size != COLOR_MAX ) )      \
    continue_up = 1;                                            \
}

/***************************************************************/
#define BINARY_TREE_EXPLORE_RIGHT_3( POSITION, COLOR_MAX, IMAGE_TYPE,    \
  FIRST_NEIBOUR, SECOND_NEIBOUR, SUBSTRACTION, SHIFT )                   \
{                                                                        \
  if( distance >= ( ( ( position[ POSITION ] + current_size -            \
    c[ POSITION ] ) * ( position[ POSITION ] +                           \
      current_size - c[ POSITION ] ) ) >> SHIFT ) )                      \
  {                                                                      \
    if( distance < ( ( ( COLOR_MAX - c[ POSITION ] ) *                   \
      ( COLOR_MAX - c[ POSITION ] ) ) >> SHIFT ) )                       \
    {                                                                    \
      if( distance < ( ( ( position[ POSITION ] +                        \
        current_size * 2 - c[ POSITION ] ) *                             \
        ( position[ POSITION ] + current_size * 2 -                      \
          c[ POSITION ] ) ) >> SHIFT ) )                                 \
      {                                                                  \
        /* Check only a part of quadrant */                              \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 1;                            \
        check_neibours[ SECOND_NEIBOUR ] += 1;                           \
        check_corner += 1;                                               \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Only a part of quadrant needs checking */                   \
          distance =                                                     \
            mlib_search_quadrant_part_to_left_##IMAGE_TYPE##_3(          \
              node->contents.quadrants[ qq ],                            \
              distance, &found_color, c, p,                              \
              position[ POSITION ] + current_size, pass - 1, POSITION ); \
      }                                                                  \
      else /* Check whole quadrant */                                    \
      {                                                                  \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 2;                            \
        check_neibours[ SECOND_NEIBOUR ] += 2;                           \
        check_corner += 2;                                               \
        continue_up = 1;                                                 \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Here is a full node. Just explore it */                     \
          distance = mlib_search_quadrant_##IMAGE_TYPE##_3(              \
            node->contents.quadrants[ qq ],                              \
            distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], p );         \
      }                                                                  \
    }                                                                    \
    else /* Cell is on the edge of the space */                          \
    {                                                                    \
      if( position[ POSITION ] + current_size * 2 ==                     \
        COLOR_MAX )                                                      \
      {                                                                  \
        /* Check only a part of quadrant */                              \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 1;                            \
        check_neibours[ SECOND_NEIBOUR ] += 1;                           \
        check_corner += 1;                                               \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Only a part of quadrant needs checking */                   \
          distance =                                                     \
            mlib_search_quadrant_part_to_left_##IMAGE_TYPE##_3(          \
              node->contents.quadrants[ qq ],                            \
              distance, &found_color, c, p,                              \
              position[ POSITION ] + current_size,                       \
              pass - 1, POSITION );                                      \
      }                                                                  \
      else /* Check whole quadrant */                                    \
      {                                                                  \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 2;                            \
        check_neibours[ SECOND_NEIBOUR ] += 2;                           \
        check_corner += 2;                                               \
        continue_up = 1;                                                 \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Here is a full node. Just explore it */                     \
          distance = mlib_search_quadrant_##IMAGE_TYPE##_3(              \
            node->contents.quadrants[ qq ],                              \
            distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], p );         \
      }                                                                  \
    }                                                                    \
  }                                                                      \
}

/***************************************************************/
#define BINARY_TREE_EXPLORE_RIGHT_4( POSITION, COLOR_MAX, IMAGE_TYPE,    \
  FIRST_NEIBOUR, SECOND_NEIBOUR, THIRD_NEIBOUR, SUBSTRACTION, SHIFT )    \
{                                                                        \
  if( distance >= ( ( ( position[ POSITION ] + current_size -            \
    c[ POSITION ] ) * ( position[ POSITION ] +                           \
      current_size - c[ POSITION ] ) ) >> SHIFT ) )                      \
  {                                                                      \
    if( distance < ( ( ( COLOR_MAX - c[ POSITION ] ) *                   \
      ( COLOR_MAX - c[ POSITION ] ) ) >> SHIFT ) )                       \
    {                                                                    \
      if( distance < ( ( ( position[ POSITION ] +                        \
        current_size * 2 - c[ POSITION ] ) *                             \
        ( position[ POSITION ] + current_size * 2 -                      \
          c[ POSITION ] ) ) >> SHIFT ) )                                 \
      {                                                                  \
        /* Check only a part of quadrant */                              \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 1;                            \
        check_neibours[ SECOND_NEIBOUR ] += 1;                           \
        check_neibours[ THIRD_NEIBOUR ] += 1;                            \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
            p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Only a part of quadrant needs checking */                   \
          distance =                                                     \
            mlib_search_quadrant_part_to_left_##IMAGE_TYPE##_4(          \
              node->contents.quadrants[ qq ],                            \
              distance, &found_color, c, p,                              \
              position[ POSITION ] + current_size, pass - 1, POSITION ); \
      }                                                                  \
      else /* Check whole quadrant */                                    \
      {                                                                  \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 2;                            \
        check_neibours[ SECOND_NEIBOUR ] += 2;                           \
        check_neibours[ THIRD_NEIBOUR ] += 2;                            \
        continue_up = 1;                                                 \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
            p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Here is a full node. Just explore it */                     \
          distance = mlib_search_quadrant_##IMAGE_TYPE##_4(              \
            node->contents.quadrants[ qq ],                              \
            distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p ); \
      }                                                                  \
    }                                                                    \
    else /* Cell is on the edge of the space */                          \
    {                                                                    \
      if( position[ POSITION ] + current_size * 2 ==                     \
        COLOR_MAX )                                                      \
      {                                                                  \
        /* Check only a part of quadrant */                              \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 1;                            \
        check_neibours[ SECOND_NEIBOUR ] += 1;                           \
        check_neibours[ THIRD_NEIBOUR ] += 1;                            \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
            p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Only a part of quadrant needs checking */                   \
          distance =                                                     \
            mlib_search_quadrant_part_to_left_##IMAGE_TYPE##_4(          \
              node->contents.quadrants[ qq ],                            \
              distance, &found_color, c, p,                              \
              position[ POSITION ] + current_size,                       \
              pass - 1, POSITION );                                      \
      }                                                                  \
      else /* Check whole quadrant */                                    \
      {                                                                  \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 2;                            \
        check_neibours[ SECOND_NEIBOUR ] += 2;                           \
        check_neibours[ THIRD_NEIBOUR ] += 2;                            \
        continue_up = 1;                                                 \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
            p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Here is a full node. Just explore it */                     \
          distance = mlib_search_quadrant_##IMAGE_TYPE##_4(              \
            node->contents.quadrants[ qq ],                              \
            distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p ); \
      }                                                                  \
    }                                                                    \
  }                                                                      \
}

/***************************************************************/
#define BINARY_TREE_SEARCH_LEFT( POSITION, SHIFT )                \
{                                                                 \
  if( ( distance > ( ( ( position[ POSITION ] - c[ POSITION ] ) * \
    ( position[ POSITION ] - c[ POSITION ] ) ) >> SHIFT ) )  &&   \
    position[ POSITION ] )                                        \
    continue_up = 1;                                              \
}

/***************************************************************/
#define BINARY_TREE_EXPLORE_LEFT_3( POSITION, IMAGE_TYPE,                \
  FIRST_NEIBOUR, SECOND_NEIBOUR, SUBSTRACTION, SHIFT )                   \
{                                                                        \
  if( distance >                                                         \
    ( ( ( c[ POSITION ] - position[ POSITION ] ) *                       \
    ( c[ POSITION ] - position[ POSITION ] ) ) >> SHIFT ) )              \
  {                                                                      \
    if( distance <= ( ( c[ POSITION ] * c[ POSITION ] ) >> SHIFT ) )     \
    {                                                                    \
      if( distance <= ( ( ( c[ POSITION ] + current_size -               \
        position[ POSITION ] ) *                                         \
        ( c[ POSITION ] + current_size -                                 \
          position[ POSITION ] ) ) >> SHIFT ) )                          \
      {                                                                  \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 1;                            \
        check_neibours[ SECOND_NEIBOUR ] += 1;                           \
        check_corner += 1;                                               \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Only a part of quadrant needs checking */                   \
          distance =                                                     \
            mlib_search_quadrant_part_to_right_##IMAGE_TYPE##_3(         \
              node->contents.quadrants[ qq ],                            \
              distance, &found_color, c, p,                              \
              position[ POSITION ] - current_size, pass - 1, POSITION ); \
      }                                                                  \
      else /* Check whole quadrant */                                    \
      {                                                                  \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 2;                            \
        check_neibours[ SECOND_NEIBOUR ] += 2;                           \
        check_corner += 2;                                               \
        continue_up = 1;                                                 \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Here is a full node. Just explore it */                     \
          distance = mlib_search_quadrant_##IMAGE_TYPE##_3(              \
            node->contents.quadrants[ qq ],                              \
            distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], p );         \
      }                                                                  \
    }                                                                    \
    else                                                                 \
    {                                                                    \
      if( !( position[ POSITION ] - current_size ) )                     \
      {                                                                  \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 1;                            \
        check_neibours[ SECOND_NEIBOUR ] += 1;                           \
        check_corner += 1;                                               \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Only a part of quadrant needs checking */                   \
          distance =                                                     \
            mlib_search_quadrant_part_to_right_##IMAGE_TYPE##_3(         \
              node->contents.quadrants[ qq ],                            \
              distance, &found_color, c, p,                              \
              position[ POSITION ] - current_size, pass - 1, POSITION ); \
      }                                                                  \
      else                                                               \
      {                                                                  \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 2;                            \
        check_neibours[ SECOND_NEIBOUR ] += 2;                           \
        check_corner += 2;                                               \
        continue_up = 1;                                                 \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Here is a full node. Just explore it */                     \
          distance = mlib_search_quadrant_##IMAGE_TYPE##_3(              \
            node->contents.quadrants[ qq ],                              \
            distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], p );         \
      }                                                                  \
    }                                                                    \
  }                                                                      \
}

/***************************************************************/
#define BINARY_TREE_EXPLORE_LEFT_4( POSITION, IMAGE_TYPE,                \
  FIRST_NEIBOUR, SECOND_NEIBOUR, THIRD_NEIBOUR, SUBSTRACTION, SHIFT )    \
{                                                                        \
  if( distance >                                                         \
    ( ( ( c[ POSITION ] - position[ POSITION ] ) *                       \
    ( c[ POSITION ] - position[ POSITION ] ) ) >> SHIFT ) )              \
  {                                                                      \
    if( distance <= ( ( c[ POSITION ] * c[ POSITION ] ) >> SHIFT ) )     \
    {                                                                    \
      if( distance <= ( ( ( c[ POSITION ] + current_size -               \
        position[ POSITION ] ) *                                         \
        ( c[ POSITION ] + current_size -                                 \
          position[ POSITION ] ) ) >> SHIFT ) )                          \
      {                                                                  \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 1;                            \
        check_neibours[ SECOND_NEIBOUR ] += 1;                           \
        check_neibours[ THIRD_NEIBOUR ] += 1;                            \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
            p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Only a part of quadrant needs checking */                   \
          distance =                                                     \
            mlib_search_quadrant_part_to_right_##IMAGE_TYPE##_4(         \
              node->contents.quadrants[ qq ],                            \
              distance, &found_color, c, p,                              \
              position[ POSITION ] - current_size, pass - 1, POSITION ); \
      }                                                                  \
      else /* Check whole quadrant */                                    \
      {                                                                  \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 2;                            \
        check_neibours[ SECOND_NEIBOUR ] += 2;                           \
        check_neibours[ THIRD_NEIBOUR ] += 2;                            \
        continue_up = 1;                                                 \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
            p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Here is a full node. Just explore it */                     \
          distance = mlib_search_quadrant_##IMAGE_TYPE##_4(              \
            node->contents.quadrants[ qq ],                              \
            distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p ); \
      }                                                                  \
    }                                                                    \
    else                                                                 \
    {                                                                    \
      if( !( position[ POSITION ] - current_size ) )                     \
      {                                                                  \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 1;                            \
        check_neibours[ SECOND_NEIBOUR ] += 1;                           \
        check_neibours[ THIRD_NEIBOUR ] += 1;                            \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
            p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Only a part of quadrant needs checking */                   \
          distance =                                                     \
            mlib_search_quadrant_part_to_right_##IMAGE_TYPE##_4(         \
              node->contents.quadrants[ qq ],                            \
              distance, &found_color, c, p,                              \
              position[ POSITION ] - current_size, pass - 1, POSITION ); \
      }                                                                  \
      else                                                               \
      {                                                                  \
        mlib_s32 qq = q ^ ( 1 << POSITION );                             \
                                                                         \
        check_neibours[ FIRST_NEIBOUR ] += 2;                            \
        check_neibours[ SECOND_NEIBOUR ] += 2;                           \
        check_neibours[ THIRD_NEIBOUR ] += 2;                            \
        continue_up = 1;                                                 \
        if( node->tag & ( 1 << qq ) )                                    \
        {                                                                \
          /* Here is another color cell.                                 \
             Check the distance */                                       \
          mlib_s32 new_found_color =                                     \
            node->contents.index[ qq ];                                  \
          mlib_u32 newdistance = FIND_DISTANCE_4( c[ 0 ],                \
            p[ 0 ][ new_found_color ] - SUBSTRACTION, c[ 1 ],            \
            p[ 1 ][ new_found_color ] - SUBSTRACTION, c[ 2 ],            \
            p[ 2 ][ new_found_color ] - SUBSTRACTION, c[ 3 ],            \
            p[ 3 ][ new_found_color ] - SUBSTRACTION, SHIFT );           \
                                                                         \
          if( newdistance < distance )                                   \
          {                                                              \
            found_color = new_found_color;                               \
            distance = newdistance;                                      \
          }                                                              \
        }                                                                \
        else if( node->contents.quadrants[ qq ] )                        \
          /* Here is a full node. Just explore it */                     \
          distance = mlib_search_quadrant_##IMAGE_TYPE##_4(              \
            node->contents.quadrants[ qq ],                              \
            distance, &found_color, c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], p ); \
      }                                                                  \
    }                                                                    \
  }                                                                      \
}

/***************************************************************/
#define CHECK_QUADRANT_U8_3( qq )                               \
{                                                               \
  if( node->tag & ( 1 << qq ) )                                 \
  {                                                             \
    /* Here is another color cell. Check the distance */        \
    mlib_s32 new_found_color = node->contents.index[ qq ];      \
    mlib_u32 newdistance = FIND_DISTANCE_3( c[ 0 ],             \
      p[ 0 ][ new_found_color ], c[ 1 ],                        \
      p[ 1 ][ new_found_color ], c[ 2 ],                        \
      p[ 2 ][ new_found_color ], 0 );                           \
                                                                \
    if( newdistance < distance )                                \
    {                                                           \
      found_color = new_found_color;                            \
      distance = newdistance;                                   \
    }                                                           \
  }                                                             \
  else if( node->contents.quadrants[ qq ] )                     \
    /* Here is a full node. Just explore it all */              \
    distance = mlib_search_quadrant_U8_3(                       \
      node->contents.quadrants[ qq ], distance, &found_color,   \
      c[ 0 ], c[ 1 ], c[ 2 ], p );                              \
/* Else there is just an empty cell */                          \
}

/***************************************************************/
#define CHECK_QUADRANT_S16_3( qq )                              \
{                                                               \
  if( node->tag & ( 1 << qq ) )                                 \
  {                                                             \
    /* Here is another color cell. Check the distance */        \
    mlib_s32 new_found_color = node->contents.index[ qq ];      \
    mlib_u32 palc0, palc1, palc2, newdistance;                  \
                                                                \
    palc0 = p[ 0 ][ new_found_color ] - MLIB_S16_MIN;           \
    palc1 = p[ 1 ][ new_found_color ] - MLIB_S16_MIN;           \
    palc2 = p[ 2 ][ new_found_color ] - MLIB_S16_MIN;           \
                                                                \
    newdistance = FIND_DISTANCE_3( c[ 0 ], palc0,               \
      c[ 1 ], palc1,                                            \
      c[ 2 ], palc2, 2 );                                       \
                                                                \
    if( newdistance < distance )                                \
    {                                                           \
      found_color = new_found_color;                            \
      distance = newdistance;                                   \
    }                                                           \
  }                                                             \
  else if( node->contents.quadrants[ qq ] )                     \
    /* Here is a full node. Just explore it all */              \
    distance = mlib_search_quadrant_S16_3(                      \
      node->contents.quadrants[ qq ], distance, &found_color,   \
      c[ 0 ], c[ 1 ], c[ 2 ], p );                              \
/* Else there is just an empty cell */                          \
}

/***************************************************************/
#define BINARY_TREE_SEARCH_3( SOURCE_IMAGE, POINTER_TYPE, BITS,              \
  COLOR_MAX, SUBTRACTION, POINTER_SHIFT, STEP, SHIFT )                       \
{                                                                            \
  const POINTER_TYPE *channels[ 3 ], *p[ 3 ];                                \
  mlib_u32 c[ 3 ];                                                           \
  mlib_s32 j;                                                                \
                                                                             \
  p[ 0 ] = s->lut[ 0 ];                                                      \
  p[ 1 ] = s->lut[ 1 ];                                                      \
  p[ 2 ] = s->lut[ 2 ];                                                      \
  channels[ 0 ] = src + POINTER_SHIFT;                                       \
  channels[ 1 ] = src + 1 + POINTER_SHIFT;                                   \
  channels[ 2 ] = src + 2 + POINTER_SHIFT;                                   \
                                                                             \
  for( j = 0; j < length; j++ )                                              \
  {                                                                          \
    mlib_s32 pass = BITS - 1;                                                \
    mlib_u32 position[ 3 ] = { 0, 0, 0 };                                    \
    mlib_s32 we_found_it = 0;                                                \
    struct lut_node_3 *node = s->table;                                      \
    /* Stack pointer pointers to the first free element of stack. */         \
    /* The node we are in is in the `node' */                                \
    struct                                                                   \
    {                                                                        \
      struct lut_node_3 *node;                                               \
      mlib_s32 q;                                                            \
    } stack[ BITS ];                                                         \
    mlib_s32 stack_pointer = 0;                                              \
                                                                             \
    c[ 0 ] = *channels[ 0 ] - SUBTRACTION;                                   \
    c[ 1 ] = *channels[ 1 ] - SUBTRACTION;                                   \
    c[ 2 ] = *channels[ 2 ] - SUBTRACTION;                                   \
                                                                             \
    do                                                                       \
    {                                                                        \
      mlib_s32 q;                                                            \
      mlib_u32 current_size = 1 << pass;                                     \
                                                                             \
      q = ( ( c[ 0 ] >> pass ) & 1 ) |                                       \
        ( ( ( c[ 1 ] << 1 ) >> pass ) & 2 ) |                                \
        ( ( ( c[ 2 ] << 2 ) >> pass ) & 4 );                                 \
                                                                             \
      position[ 0 ] |= c[ 0 ] & current_size;                                \
      position[ 1 ] |= c[ 1 ] & current_size;                                \
      position[ 2 ] |= c[ 2 ] & current_size;                                \
                                                                             \
      if( node->tag & ( 1 << q ) )                                           \
      {                                                                      \
        /*                                                                   \
          Here is a cell with one color. We need to be sure it's             \
          the one that is the closest to our color                           \
        */                                                                   \
        mlib_s32 palindex = node->contents.index[ q ];                       \
        mlib_u32 palc[ 3 ];                                                  \
        mlib_s32 identical;                                                  \
                                                                             \
        palc[ 0 ] = p[ 0 ][ palindex ] - SUBTRACTION;                        \
        palc[ 1 ] = p[ 1 ][ palindex ] - SUBTRACTION;                        \
        palc[ 2 ] = p[ 2 ][ palindex ] - SUBTRACTION;                        \
                                                                             \
        identical = ( palc[ 0 ] - c[ 0 ] ) | ( palc[ 1 ] - c[ 1 ] ) |        \
          ( palc[ 2 ] - c[ 2 ] );                                            \
                                                                             \
        if( !identical || BITS - pass == bits )                              \
        {                                                                    \
          /* Oh, here it is :) */                                            \
          dst[ j ] = palindex + s->offset;                                   \
          we_found_it = 1;                                                   \
        }                                                                    \
        else                                                                 \
        {                                                                    \
          mlib_u32 distance;                                                 \
          /* First index is the channel, second is the number of the         \
             side */                                                         \
          mlib_s32 found_color;                                              \
          mlib_s32 continue_up;                                              \
                                                                             \
          distance = FIND_DISTANCE_3( c[ 0 ], palc[ 0 ],                     \
            c[ 1 ], palc[ 1 ], c[ 2 ], palc[ 2 ], SHIFT );                   \
          found_color = palindex;                                            \
                                                                             \
          do                                                                 \
          {                                                                  \
            mlib_s32 check_corner;                                           \
                                                                             \
            /*                                                               \
              Neibours are enumerated in a cicle:                            \
              0 - between quadrants 0 and 1,                                 \
              1 - between quadrants 1 and 2 and                              \
              2 - between quadrants 2 and 0                                  \
            */                                                               \
            mlib_s32 check_neibours[ 3 ];                                    \
                                                                             \
            /*                                                               \
              Others are three two neibour quadrants                         \
                                                                             \
              Side number is [ <number of the coordinate >][  pass ) & 1 ) |                                        \
        ( ( ( c[ 1 ] << 1 ) >> pass ) & 2 ) |                                 \
        ( ( ( c[ 2 ] << 2 ) >> pass ) & 4 ) |                                 \
        ( ( ( c[ 3 ] << 3 ) >> pass ) & 8 );                                  \
                                                                              \
      position[ 0 ] |= c[ 0 ] & current_size;                                 \
      position[ 1 ] |= c[ 1 ] & current_size;                                 \
      position[ 2 ] |= c[ 2 ] & current_size;                                 \
      position[ 3 ] |= c[ 3 ] & current_size;                                 \
                                                                              \
      if( node->tag & ( 1 << q ) )                                            \
      {                                                                       \
        /*                                                                    \
          Here is a cell with one color. We need to be sure it's              \
          the one that is the closest to our color                            \
        */                                                                    \
        mlib_s32 palindex = node->contents.index[ q ];                        \
        mlib_u32 palc[ 4 ];                                                   \
        mlib_s32 identical;                                                   \
                                                                              \
        palc[ 0 ] = p[ 0 ][ palindex ] - SUBTRACTION;                         \
        palc[ 1 ] = p[ 1 ][ palindex ] - SUBTRACTION;                         \
        palc[ 2 ] = p[ 2 ][ palindex ] - SUBTRACTION;                         \
        palc[ 3 ] = p[ 3 ][ palindex ] - SUBTRACTION;                         \
                                                                              \
        identical = ( palc[ 0 ] - c[ 0 ] ) | ( palc[ 1 ] - c[ 1 ] ) |         \
          ( palc[ 2 ] - c[ 2 ] ) | ( palc[ 3 ] - c[ 3 ] );                    \
                                                                              \
        if( !identical || BITS - pass == bits )                               \
        {                                                                     \
          /* Oh, here it is :) */                                             \
          dst[ j ] = palindex + s->offset;                                    \
          we_found_it = 1;                                                    \
        }                                                                     \
        else                                                                  \
        {                                                                     \
          mlib_u32 distance;                                                  \
          /* First index is the channel, second is the number of the          \
             side */                                                          \
          mlib_s32 found_color;                                               \
          mlib_s32 continue_up;                                               \
                                                                              \
          distance = FIND_DISTANCE_4( c[ 0 ], palc[ 0 ],                      \
            c[ 1 ], palc[ 1 ], c[ 2 ], palc[ 2 ], c[ 3 ], palc[ 3 ], SHIFT ); \
          found_color = palindex;                                             \
                                                                              \
          do                                                                  \
          {                                                                   \
            mlib_s32 check_corner;                                            \
            mlib_s32 check_neibours[ 6 ];                                     \
            mlib_s32 check_far_neibours[ 4 ];                                 \
                                                                              \
            /*                                                                \
              Check neibours: quadrants that are different by 2 bits          \
              from the quadrant, that we are in:                              \
              3 -  0                                                          \
              5 -  1                                                          \
              6 -  2                                                          \
              9 -  3                                                          \
              10 - 4                                                          \
              12 - 5                                                          \
              Far quadrants: different by 3 bits:                             \
              7  - 0                                                          \
              11 - 1                                                          \
              13 - 2                                                          \
              14 - 3                                                          \
            */                                                                \
                                                                              \
            check_neibours[ 0 ] = check_neibours[ 1 ] =                       \
              check_neibours[ 2 ] = check_neibours[ 3 ] =                     \
              check_neibours[ 4 ] = check_neibours[ 5 ] = 0;                  \
            continue_up = 0;                                                  \
                                                                              \
            if( q & 1 )                                                       \
            {                                                                 \
              BINARY_TREE_EXPLORE_LEFT_4( 0, SOURCE_IMAGE, 0, 1, 3,           \
                SUBTRACTION, SHIFT );                                         \
            }                                                                 \
            else                                                              \
            {                                                                 \
              BINARY_TREE_EXPLORE_RIGHT_4( 0, COLOR_MAX, SOURCE_IMAGE,        \
                0, 1, 3, SUBTRACTION, SHIFT );                                \
            }                                                                 \
                                                                              \
            if( q & 2 )                                                       \
            {                                                                 \
              BINARY_TREE_EXPLORE_LEFT_4( 1, SOURCE_IMAGE, 0, 2, 4,           \
                SUBTRACTION, SHIFT );                                         \
            }                                                                 \
            else                                                              \
            {                                                                 \
              BINARY_TREE_EXPLORE_RIGHT_4( 1, COLOR_MAX, SOURCE_IMAGE,        \
                0, 2, 4, SUBTRACTION, SHIFT );                                \
            }                                                                 \
                                                                              \
            if( q & 4 )                                                       \
            {                                                                 \
              BINARY_TREE_EXPLORE_LEFT_4( 2, SOURCE_IMAGE, 1, 2, 5,           \
                SUBTRACTION, SHIFT );                                         \
            }                                                                 \
            else                                                              \
            {                                                                 \
              BINARY_TREE_EXPLORE_RIGHT_4( 2, COLOR_MAX, SOURCE_IMAGE,        \
                1, 2, 5, SUBTRACTION, SHIFT );                                \
            }                                                                 \
                                                                              \
            if( q & 8 )                                                       \
            {                                                                 \
              BINARY_TREE_EXPLORE_LEFT_4( 3, SOURCE_IMAGE, 3, 4, 5,           \
                SUBTRACTION, SHIFT );                                         \
            }                                                                 \
            else                                                              \
            {                                                                 \
              BINARY_TREE_EXPLORE_RIGHT_4( 3, COLOR_MAX, SOURCE_IMAGE,        \
                3, 4, 5, SUBTRACTION, SHIFT );                                \
            }                                                                 \
                                                                              \
            check_far_neibours[ 0 ] = check_neibours[ 0 ] +                   \
              check_neibours[ 1 ] + check_neibours[ 2 ];                      \
            check_far_neibours[ 1 ] = check_neibours[ 0 ] +                   \
              check_neibours[ 3 ] + check_neibours[ 4 ];                      \
            check_far_neibours[ 2 ] = check_neibours[ 1 ] +                   \
              check_neibours[ 3 ] + check_neibours[ 5 ];                      \
            check_far_neibours[ 3 ] = check_neibours[ 2 ] +                   \
              check_neibours[ 4 ] + check_neibours[ 5 ];                      \
                                                                              \
            check_corner = check_far_neibours[ 0 ] +                          \
              check_far_neibours[ 1 ] +                                       \
              check_far_neibours[ 2 ] +                                       \
              check_far_neibours[ 3 ];                                        \
                                                                              \
            if( check_neibours[ 0 ] >= 2 )                                    \
            {                                                                 \
              mlib_s32 qq = q ^ 3;                                            \
              CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
            }                                                                 \
                                                                              \
            if( check_neibours[ 1 ] >= 2 )                                    \
            {                                                                 \
              mlib_s32 qq = q ^ 5;                                            \
              CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
            }                                                                 \
                                                                              \
            if( check_neibours[ 2 ] >= 2 )                                    \
            {                                                                 \
              mlib_s32 qq = q ^ 6;                                            \
              CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
            }                                                                 \
                                                                              \
            if( check_neibours[ 3 ] >= 2 )                                    \
            {                                                                 \
              mlib_s32 qq = q ^ 9;                                            \
              CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
            }                                                                 \
                                                                              \
            if( check_neibours[ 4 ] >= 2 )                                    \
            {                                                                 \
              mlib_s32 qq = q ^ 10;                                           \
              CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
            }                                                                 \
                                                                              \
            if( check_neibours[ 5 ] >= 2 )                                    \
            {                                                                 \
              mlib_s32 qq = q ^ 12;                                           \
              CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
            }                                                                 \
                                                                              \
            if( check_far_neibours[ 0 ] >= 3 )                                \
            {                                                                 \
              mlib_s32 qq = q ^ 7;                                            \
              CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
            }                                                                 \
                                                                              \
            if( check_far_neibours[ 1 ] >= 3 )                                \
            {                                                                 \
              mlib_s32 qq = q ^ 11;                                           \
              CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
            }                                                                 \
                                                                              \
            if( check_far_neibours[ 2 ] >= 3 )                                \
            {                                                                 \
              mlib_s32 qq = q ^ 13;                                           \
              CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
            }                                                                 \
                                                                              \
            if( check_far_neibours[ 3 ] >= 3 )                                \
            {                                                                 \
              mlib_s32 qq = q ^ 14;                                           \
              CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
            }                                                                 \
                                                                              \
            if( check_corner >= 4 )                                           \
            {                                                                 \
              mlib_s32 qq = q ^ 15;                                           \
              CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                        \
            }                                                                 \
                                                                              \
            if( q & 1 )                                                       \
            {                                                                 \
              BINARY_TREE_SEARCH_RIGHT( 0, COLOR_MAX, SHIFT );                \
            }                                                                 \
            else                                                              \
            {                                                                 \
              BINARY_TREE_SEARCH_LEFT( 0, SHIFT );                            \
            }                                                                 \
                                                                              \
            if( q & 2 )                                                       \
            {                                                                 \
              BINARY_TREE_SEARCH_RIGHT( 1, COLOR_MAX, SHIFT );                \
            }                                                                 \
            else                                                              \
            {                                                                 \
              BINARY_TREE_SEARCH_LEFT( 1, SHIFT );                            \
            }                                                                 \
                                                                              \
            if( q & 4 )                                                       \
            {                                                                 \
              BINARY_TREE_SEARCH_RIGHT( 2, COLOR_MAX, SHIFT );                \
            }                                                                 \
            else                                                              \
            {                                                                 \
              BINARY_TREE_SEARCH_LEFT( 2, SHIFT );                            \
            }                                                                 \
                                                                              \
            if( q & 8 )                                                       \
            {                                                                 \
              BINARY_TREE_SEARCH_RIGHT( 3, COLOR_MAX, SHIFT );                \
            }                                                                 \
            else                                                              \
            {                                                                 \
              BINARY_TREE_SEARCH_LEFT( 3, SHIFT );                            \
            }                                                                 \
                                                                              \
            position[ 0 ] &= ~( c[ 0 ] & current_size );                      \
            position[ 1 ] &= ~( c[ 1 ] & current_size );                      \
            position[ 2 ] &= ~( c[ 2 ] & current_size );                      \
            position[ 3 ] &= ~( c[ 3 ] & current_size );                      \
                                                                              \
            current_size <<= 1;                                               \
                                                                              \
            pass++;                                                           \
                                                                              \
            stack_pointer--;                                                  \
            q = stack[ stack_pointer ].q;                                     \
            node = stack[ stack_pointer ].node;                               \
          } while( continue_up );                                             \
                                                                              \
          dst[ j ] = found_color + s->offset;                                 \
          we_found_it = 1;                                                    \
        }                                                                     \
      }                                                                       \
      else if( node->contents.quadrants[ q ] )                                \
      {                                                                       \
        /* Descend one level */                                               \
        stack[ stack_pointer ].node = node;                                   \
        stack[ stack_pointer++ ].q = q;                                       \
        node = node->contents.quadrants[ q ];                                 \
      }                                                                       \
      else                                                                    \
      {                                                                       \
        /* Found the empty quadrant. Look around */                           \
        mlib_u32 distance = MLIB_U32_MAX;                                     \
        mlib_s32 found_color;                                                 \
        mlib_s32 continue_up;                                                 \
                                                                              \
        /*                                                                    \
          As we had come to this level, it is warranted that there            \
          are other points on this level near the empty quadrant              \
        */                                                                    \
        do                                                                    \
        {                                                                     \
          mlib_s32 check_corner;                                              \
          mlib_s32 check_neibours[ 6 ];                                       \
          mlib_s32 check_far_neibours[ 4 ];                                   \
                                                                              \
          /*                                                                  \
            Check neibours: quadrants that are different by 2 bits            \
            from the quadrant, that we are in:                                \
            3 -  0                                                            \
            5 -  1                                                            \
            6 -  2                                                            \
            9 -  3                                                            \
            10 - 4                                                            \
            12 - 5                                                            \
            Far quadrants: different by 3 bits:                               \
            7  - 0                                                            \
            11 - 1                                                            \
            13 - 2                                                            \
            14 - 3                                                            \
          */                                                                  \
                                                                              \
          check_neibours[ 0 ] = check_neibours[ 1 ] =                         \
            check_neibours[ 2 ] = check_neibours[ 3 ] =                       \
            check_neibours[ 4 ] = check_neibours[ 5 ] = 0;                    \
          continue_up = 0;                                                    \
                                                                              \
          if( q & 1 )                                                         \
          {                                                                   \
            BINARY_TREE_EXPLORE_LEFT_4( 0, SOURCE_IMAGE, 0, 1, 3,             \
              SUBTRACTION, SHIFT );                                           \
          }                                                                   \
          else                                                                \
          {                                                                   \
            BINARY_TREE_EXPLORE_RIGHT_4( 0, COLOR_MAX, SOURCE_IMAGE,          \
              0, 1, 3, SUBTRACTION, SHIFT );                                  \
          }                                                                   \
                                                                              \
          if( q & 2 )                                                         \
          {                                                                   \
            BINARY_TREE_EXPLORE_LEFT_4( 1, SOURCE_IMAGE, 0, 2, 4,             \
              SUBTRACTION, SHIFT );                                           \
          }                                                                   \
          else                                                                \
          {                                                                   \
            BINARY_TREE_EXPLORE_RIGHT_4( 1, COLOR_MAX, SOURCE_IMAGE,          \
              0, 2, 4, SUBTRACTION, SHIFT );                                  \
          }                                                                   \
                                                                              \
          if( q & 4 )                                                         \
          {                                                                   \
            BINARY_TREE_EXPLORE_LEFT_4( 2, SOURCE_IMAGE, 1, 2, 5,             \
              SUBTRACTION, SHIFT );                                           \
          }                                                                   \
          else                                                                \
          {                                                                   \
            BINARY_TREE_EXPLORE_RIGHT_4( 2, COLOR_MAX, SOURCE_IMAGE,          \
              1, 2, 5, SUBTRACTION, SHIFT );                                  \
          }                                                                   \
                                                                              \
          if( q & 8 )                                                         \
          {                                                                   \
            BINARY_TREE_EXPLORE_LEFT_4( 3, SOURCE_IMAGE, 3, 4, 5,             \
              SUBTRACTION, SHIFT );                                           \
          }                                                                   \
          else                                                                \
          {                                                                   \
            BINARY_TREE_EXPLORE_RIGHT_4( 3, COLOR_MAX, SOURCE_IMAGE,          \
              3, 4, 5, SUBTRACTION, SHIFT );                                  \
          }                                                                   \
                                                                              \
          check_far_neibours[ 0 ] = check_neibours[ 0 ] +                     \
            check_neibours[ 1 ] + check_neibours[ 2 ];                        \
          check_far_neibours[ 1 ] = check_neibours[ 0 ] +                     \
            check_neibours[ 3 ] + check_neibours[ 4 ];                        \
          check_far_neibours[ 2 ] = check_neibours[ 1 ] +                     \
            check_neibours[ 3 ] + check_neibours[ 5 ];                        \
          check_far_neibours[ 3 ] = check_neibours[ 2 ] +                     \
            check_neibours[ 4 ] + check_neibours[ 5 ];                        \
                                                                              \
          check_corner = check_far_neibours[ 0 ] +                            \
            check_far_neibours[ 1 ] +                                         \
            check_far_neibours[ 2 ] +                                         \
            check_far_neibours[ 3 ];                                          \
                                                                              \
          if( check_neibours[ 0 ] >= 2 )                                      \
          {                                                                   \
            mlib_s32 qq = q ^ 3;                                              \
            CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
          }                                                                   \
                                                                              \
          if( check_neibours[ 1 ] >= 2 )                                      \
          {                                                                   \
            mlib_s32 qq = q ^ 5;                                              \
            CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
          }                                                                   \
                                                                              \
          if( check_neibours[ 2 ] >= 2 )                                      \
          {                                                                   \
            mlib_s32 qq = q ^ 6;                                              \
            CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
          }                                                                   \
                                                                              \
          if( check_neibours[ 3 ] >= 2 )                                      \
          {                                                                   \
            mlib_s32 qq = q ^ 9;                                              \
            CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
          }                                                                   \
                                                                              \
          if( check_neibours[ 4 ] >= 2 )                                      \
          {                                                                   \
            mlib_s32 qq = q ^ 10;                                             \
            CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
          }                                                                   \
                                                                              \
          if( check_neibours[ 5 ] >= 2 )                                      \
          {                                                                   \
            mlib_s32 qq = q ^ 12;                                             \
            CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
          }                                                                   \
                                                                              \
          if( check_far_neibours[ 0 ] >= 3 )                                  \
          {                                                                   \
            mlib_s32 qq = q ^ 7;                                              \
            CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
          }                                                                   \
                                                                              \
          if( check_far_neibours[ 1 ] >= 3 )                                  \
          {                                                                   \
            mlib_s32 qq = q ^ 11;                                             \
            CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
          }                                                                   \
                                                                              \
          if( check_far_neibours[ 2 ] >= 3 )                                  \
          {                                                                   \
            mlib_s32 qq = q ^ 13;                                             \
            CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
          }                                                                   \
                                                                              \
          if( check_far_neibours[ 3 ] >= 3 )                                  \
          {                                                                   \
            mlib_s32 qq = q ^ 14;                                             \
            CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
          }                                                                   \
                                                                              \
          if( check_corner >= 4 )                                             \
          {                                                                   \
            mlib_s32 qq = q ^ 15;                                             \
            CHECK_QUADRANT_##SOURCE_IMAGE##_4( qq );                          \
          }                                                                   \
                                                                              \
          if( q & 1 )                                                         \
          {                                                                   \
            BINARY_TREE_SEARCH_RIGHT( 0, COLOR_MAX, SHIFT );                  \
          }                                                                   \
          else                                                                \
          {                                                                   \
            BINARY_TREE_SEARCH_LEFT( 0, SHIFT );                              \
          }                                                                   \
                                                                              \
          if( q & 2 )                                                         \
          {                                                                   \
            BINARY_TREE_SEARCH_RIGHT( 1, COLOR_MAX, SHIFT );                  \
          }                                                                   \
          else                                                                \
          {                                                                   \
            BINARY_TREE_SEARCH_LEFT( 1, SHIFT );                              \
          }                                                                   \
                                                                              \
          if( q & 4 )                                                         \
          {                                                                   \
            BINARY_TREE_SEARCH_RIGHT( 2, COLOR_MAX, SHIFT );                  \
          }                                                                   \
          else                                                                \
          {                                                                   \
            BINARY_TREE_SEARCH_LEFT( 2, SHIFT );                              \
          }                                                                   \
                                                                              \
          if( q & 8 )                                                         \
          {                                                                   \
            BINARY_TREE_SEARCH_RIGHT( 3, COLOR_MAX, SHIFT );                  \
          }                                                                   \
          else                                                                \
          {                                                                   \
            BINARY_TREE_SEARCH_LEFT( 3, SHIFT );                              \
          }                                                                   \
                                                                              \
          position[ 0 ] &= ~( c[ 0 ] & current_size );                        \
          position[ 1 ] &= ~( c[ 1 ] & current_size );                        \
          position[ 2 ] &= ~( c[ 2 ] & current_size );                        \
          position[ 3 ] &= ~( c[ 3 ] & current_size );                        \
                                                                              \
          current_size <<= 1;                                                 \
                                                                              \
          pass++;                                                             \
                                                                              \
          stack_pointer--;                                                    \
          q = stack[ stack_pointer ].q;                                       \
          node = stack[ stack_pointer ].node;                                 \
        } while( continue_up );                                               \
                                                                              \
        dst[ j ] = found_color + s->offset;                                   \
        we_found_it = 1;                                                      \
      }                                                                       \
                                                                              \
      pass--;                                                                 \
                                                                              \
    } while( !we_found_it );                                                  \
                                                                              \
    channels[ 0 ] += 4;                                                       \
    channels[ 1 ] += 4;                                                       \
    channels[ 2 ] += 4;                                                       \
    channels[ 3 ] += 4;                                                       \
  }                                                                           \
}

/***************************************************************/
#define FIND_NEAREST_U8_3_C( SHIFT, STEP )                      \
  mlib_s32 i, k, k_min, min_dist, diff, mask;                   \
  mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1;            \
  mlib_s32 entries = s -> lutlength;                            \
  mlib_d64 *double_lut = mlib_ImageGetLutDoubleData( s );       \
  mlib_d64 col0, col1, col2;                                    \
  mlib_d64 dist, len0, len1, len2;                              \
                                                                \
  for ( i = 0; i < length; i++ ) {                              \
    col0 = src[ STEP * i + SHIFT ];                             \
    col1 = src[ STEP * i + 1 + SHIFT ];                         \
    col2 = src[ STEP * i + 2 + SHIFT ];                         \
    min_dist = MLIB_S32_MAX;                                    \
    k_min = 1;                                                  \
    len0 = double_lut[ 0 ] - col0;                              \
    len1 = double_lut[ 1 ] - col1;                              \
    len2 = double_lut[ 2 ] - col2;                              \
                                                                \
    for ( k = 1; k <= entries; k++ ) {                          \
      dist = len0 * len0;                                       \
      len0 = double_lut[ 3 * k ] - col0;                        \
      dist += len1 * len1;                                      \
      len1 = double_lut[ 3 * k + 1 ] - col1;                    \
      dist += len2 * len2;                                      \
      len2 = double_lut[ 3 * k + 2 ] - col2;                    \
      diff = ( mlib_s32 )dist - min_dist;                       \
      mask = diff >> 31;                                        \
      min_dist += diff & mask;                                  \
      k_min += ( k - k_min ) & mask;                            \
    }                                                           \
                                                                \
    dst[ i ] = k_min + offset;                                  \
  }

/***************************************************************/
#define FIND_NEAREST_U8_4_C                                     \
  mlib_s32 i, k, k_min, min_dist, diff, mask;                   \
  mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1;            \
  mlib_s32 entries = s -> lutlength;                            \
  mlib_d64 *double_lut = mlib_ImageGetLutDoubleData( s );       \
  mlib_d64 col0, col1, col2, col3;                              \
  mlib_d64 dist, len0, len1, len2, len3;                        \
                                                                \
  for ( i = 0; i < length; i++ ) {                              \
    col0 = src[ 4 * i ];                                        \
    col1 = src[ 4 * i + 1 ];                                    \
    col2 = src[ 4 * i + 2 ];                                    \
    col3 = src[ 4 * i + 3 ];                                    \
    min_dist = MLIB_S32_MAX;                                    \
    k_min = 1;                                                  \
    len0 = double_lut[ 0 ] - col0;                              \
    len1 = double_lut[ 1 ] - col1;                              \
    len2 = double_lut[ 2 ] - col2;                              \
    len3 = double_lut[ 3 ] - col3;                              \
                                                                \
    for ( k = 1; k <= entries; k++ ) {                          \
      dist = len0 * len0;                                       \
      len0 =  double_lut[ 4 * k ] - col0;                       \
      dist += len1 * len1;                                      \
      len1 = double_lut[ 4 * k + 1 ] - col1;                    \
      dist += len2 * len2;                                      \
      len2 =  double_lut[ 4 * k + 2 ] - col2;                   \
      dist += len3 * len3;                                      \
      len3 =  double_lut[ 4 * k + 3 ] - col3;                   \
      diff = ( mlib_s32 )dist - min_dist;                       \
      mask = diff >> 31;                                        \
      min_dist += diff & mask;                                  \
      k_min += ( k - k_min ) & mask;                            \
    }                                                           \
                                                                \
    dst[ i ] = k_min + offset;                                  \
  }

/***************************************************************/
#define FSQR_S16_HI(dsrc)                                                   \
  vis_fpadd32( vis_fmuld8ulx16( vis_read_hi( dsrc ), vis_read_hi( dsrc ) ), \
    vis_fmuld8sux16( vis_read_hi( dsrc ), vis_read_hi( dsrc ) ) )

/***************************************************************/
#define FSQR_S16_LO(dsrc)                                                  \
  vis_fpadd32( vis_fmuld8ulx16( vis_read_lo( dsrc ), vis_read_lo( dsrc) ), \
    vis_fmuld8sux16( vis_read_lo( dsrc ), vis_read_lo( dsrc ) ) )

/***************************************************************/
#define FIND_NEAREST_U8_3                                             \
{                                                                     \
  mlib_d64 *dpsrc, dsrc, dsrc1, ddist, ddist1, ddist2, ddist3;        \
  mlib_d64 dcolor, dind, dres, dres1, dpind[1], dpmin[1];             \
  mlib_d64 done = vis_to_double_dup( 1 ),                             \
           dmax = vis_to_double_dup( MLIB_S32_MAX );                  \
  mlib_f32 *lut = ( mlib_f32 * )mlib_ImageGetLutNormalTable( s );     \
  mlib_f32 fone = vis_to_float( 0x100 );                              \
  mlib_s32 i, k, mask;                                                \
  mlib_s32 gsr[1];                                                    \
  mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1;                  \
  mlib_s32 entries = s->lutlength;                                    \
                                                                      \
  gsr[0] = vis_read_gsr();                                            \
  for( i = 0; i <= ( length-2 ); i += 2 )                             \
  {                                                                   \
    dpsrc = VIS_ALIGNADDR( src, -1 );                                 \
    src += 6;                                                         \
    dsrc = dpsrc[ 0 ];                                                \
    dsrc1 = dpsrc[ 1 ];                                               \
    dsrc1 = vis_faligndata( dsrc, dsrc1 );                            \
    dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone );              \
    VIS_ALIGNADDR( dpsrc, 3 );                                        \
    dsrc1 = vis_faligndata( dsrc1, dsrc1 );                           \
    dsrc1 = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone );             \
    dpind[ 0 ] = dind = done;                                         \
    dpmin[ 0 ] = dmax;                                                \
    dcolor = vis_fmul8x16al( lut[ 0 ], fone );                        \
    for( k = 1; k <= entries; k++ )                                   \
    {                                                                 \
      ddist1 = vis_fpsub16( dcolor, dsrc );                           \
      ddist = FSQR_S16_HI( ddist1 );                                  \
      ddist1 = FSQR_S16_LO( ddist1 );                                 \
      dres = vis_fpadd32( ddist, ddist1 );                            \
      ddist3 = vis_fpsub16( dcolor, dsrc1 );                          \
      ddist2 = FSQR_S16_HI( ddist3 );                                 \
      ddist3 = FSQR_S16_LO( ddist3 );                                 \
      dres1 = vis_fpadd32( ddist2, ddist3 );                          \
      dcolor = vis_fmul8x16al( lut[ k ], fone );                      \
      dres = vis_freg_pair(                                           \
        vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ),     \
        vis_fpadd32s( vis_read_hi( dres1 ), vis_read_lo( dres1 ) ) ); \
      mask = vis_fcmplt32( dres, dpmin[ 0 ] );                        \
      vis_pst_32( dind, ( void * )dpind, mask );                      \
      dind = vis_fpadd32( dind, done );                               \
      vis_pst_32( dres, ( void * )dpmin, mask );                      \
    }                                                                 \
    dst[ i ] = ( ( mlib_s32 * )dpind )[ 0 ] + offset;                 \
    dst[ i + 1 ] = ( ( mlib_s32 * )dpind)[ 1 ] + offset;              \
  }                                                                   \
  if( i < length )                                                    \
  {                                                                   \
    dpsrc = VIS_ALIGNADDR( src, -1 );                                 \
    dsrc = dpsrc[ 0 ];                                                \
    dsrc1 = dpsrc[ 1 ];                                               \
    dsrc1 = vis_faligndata( dsrc, dsrc1 );                            \
    dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone );              \
    dpind[ 0 ] = dind = done;                                         \
    dpmin[ 0 ] = dmax;                                                \
    for( k = 0; k < entries; k++ )                                    \
    {                                                                 \
      dcolor = vis_fmul8x16al( lut[ k ], fone );                      \
      ddist1 = vis_fpsub16( dcolor, dsrc );                           \
      ddist = FSQR_S16_HI( ddist1 );                                  \
      ddist1 = FSQR_S16_LO( ddist1 );                                 \
      dres = vis_fpadd32( ddist, ddist1 );                            \
      dres = vis_write_lo( dres,                                      \
        vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ) );   \
      mask = vis_fcmplt32( dres, dpmin[ 0 ] );                        \
      vis_pst_32( dind, ( void * )dpind, mask );                      \
      dind = vis_fpadd32( dind, done );                               \
      vis_pst_32( dres, ( void * )dpmin, mask );                      \
    }                                                                 \
    dst[ i ] = ( ( mlib_s32 * )dpind)[ 1 ] + offset;                  \
  }                                                                   \
  vis_write_gsr(gsr[0]);                                              \
}

/***************************************************************/
#define FIND_NEAREST_U8_3_IN4                                         \
{                                                                     \
  mlib_d64 *dpsrc, dsrc, dsrc1, ddist, ddist1, ddist2, ddist3;        \
  mlib_d64 dcolor, dind, dres, dres1, dpind[1], dpmin[1];             \
  mlib_d64 done = vis_to_double_dup( 1 ),                             \
           dmax = vis_to_double_dup( MLIB_S32_MAX );                  \
  mlib_f32 *lut = ( mlib_f32 * )mlib_ImageGetLutNormalTable( s );     \
  mlib_f32 fone = vis_to_float( 0x100 );                              \
  mlib_s32 i, k, mask, gsr[1];                                        \
  mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1;                  \
  mlib_s32 entries = s->lutlength;                                    \
                                                                      \
  gsr[0] = vis_read_gsr();                                            \
  dpsrc = VIS_ALIGNADDR( src, 0 );                                    \
  for( i = 0; i <= ( length-2 ); i += 2 )                             \
  {                                                                   \
    dsrc = dpsrc[ 0 ];                                                \
    dsrc1 = dpsrc[ 1 ];                                               \
    dsrc1 = vis_faligndata( dsrc, dsrc1 );                            \
    dpsrc++;                                                          \
    dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone );              \
    dsrc1 = vis_fmul8x16al( vis_read_lo( dsrc1 ), fone );             \
    dpind[ 0 ] = dind = done;                                         \
    dpmin[ 0 ] = dmax;                                                \
    dcolor = vis_fmul8x16al( lut[ 0 ], fone );                        \
    for( k = 1; k <= entries; k++ )                                   \
    {                                                                 \
      ddist1 = vis_fpsub16( dcolor, dsrc );                           \
      ddist = FSQR_S16_HI( ddist1 );                                  \
      ddist1 = FSQR_S16_LO( ddist1 );                                 \
      dres = vis_fpadd32( ddist, ddist1 );                            \
      ddist3 = vis_fpsub16( dcolor, dsrc1 );                          \
      ddist2 = FSQR_S16_HI( ddist3 );                                 \
      ddist3 = FSQR_S16_LO( ddist3 );                                 \
      dres1 = vis_fpadd32( ddist2, ddist3 );                          \
      dcolor = vis_fmul8x16al( lut[ k ], fone );                      \
      dres = vis_freg_pair(                                           \
        vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ),     \
        vis_fpadd32s( vis_read_hi( dres1 ), vis_read_lo( dres1 ) ) ); \
      mask = vis_fcmplt32( dres, dpmin[ 0 ] );                        \
      vis_pst_32( dind, ( void * )dpind, mask );                      \
      dind = vis_fpadd32( dind, done );                               \
      vis_pst_32( dres, ( void * )dpmin, mask );                      \
    }                                                                 \
    dst[ i ] = ( ( mlib_s32 * )dpind )[ 0 ] + offset;                 \
    dst[ i + 1 ] = ( ( mlib_s32 * )dpind)[ 1 ] + offset;              \
  }                                                                   \
  if( i < length )                                                    \
  {                                                                   \
    dsrc = dpsrc[ 0 ];                                                \
    dsrc1 = dpsrc[ 1 ];                                               \
    dsrc1 = vis_faligndata( dsrc, dsrc1 );                            \
    dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone );              \
    dpind[ 0 ] = dind = done;                                         \
    dpmin[ 0 ] = dmax;                                                \
    for( k = 0; k < entries; k++ )                                    \
    {                                                                 \
      dcolor = vis_fmul8x16al( lut[ k ], fone );                      \
      ddist1 = vis_fpsub16( dcolor, dsrc );                           \
      ddist = FSQR_S16_HI( ddist1 );                                  \
      ddist1 = FSQR_S16_LO( ddist1 );                                 \
      dres = vis_fpadd32( ddist, ddist1 );                            \
      dres = vis_write_lo( dres,                                      \
        vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ) );   \
      mask = vis_fcmplt32( dres, dpmin[ 0 ] );                        \
      vis_pst_32( dind, ( void * )dpind, mask );                      \
      dind = vis_fpadd32( dind, done );                               \
      vis_pst_32( dres, ( void * )dpmin, mask );                      \
    }                                                                 \
    dst[ i ] = ( ( mlib_s32 * )dpind)[ 1 ] + offset;                  \
  }                                                                   \
  vis_write_gsr(gsr[0]);                                              \
}

/***************************************************************/
#define FIND_NEAREST_U8_4                                             \
{                                                                     \
  mlib_d64 *dpsrc, dsrc, dsrc1, ddist, ddist1, ddist2, ddist3;        \
  mlib_d64 dcolor, dind, dres, dres1, dpind[ 1 ], dpmin[ 1 ];         \
  mlib_d64 done = vis_to_double_dup( 1 ),                             \
           dmax = vis_to_double_dup( MLIB_S32_MAX );                  \
  mlib_f32 *lut = ( mlib_f32 * )mlib_ImageGetLutNormalTable( s );     \
  mlib_f32 fone = vis_to_float( 0x100 );                              \
  mlib_s32 i, k, mask, gsr[1];                                        \
  mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1;                  \
  mlib_s32 entries = s->lutlength;                                    \
                                                                      \
  gsr[0] = vis_read_gsr();                                            \
  dpsrc = VIS_ALIGNADDR( src, 0 );                                    \
  for( i = 0; i <= ( length-2 ); i += 2 )                             \
  {                                                                   \
    dsrc = dpsrc[ 0 ];                                                \
    dsrc1 = dpsrc[ 1 ];                                               \
    dsrc1 = vis_faligndata( dsrc, dsrc1 );                            \
    dpsrc++;                                                          \
    dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone );              \
    dsrc1 = vis_fmul8x16al( vis_read_lo( dsrc1 ), fone );             \
    dpind[ 0 ] = dind = done;                                         \
    dpmin[ 0 ] = dmax;                                                \
    dcolor = vis_fmul8x16al(lut[0], fone);                            \
    for( k = 1; k <= entries; k++ )                                   \
    {                                                                 \
      ddist1 = vis_fpsub16( dcolor, dsrc );                           \
      ddist = FSQR_S16_HI( ddist1 );                                  \
      ddist1 = FSQR_S16_LO( ddist1 );                                 \
      dres = vis_fpadd32( ddist, ddist1 );                            \
      ddist3 = vis_fpsub16( dcolor, dsrc1 );                          \
      ddist2 = FSQR_S16_HI( ddist3 );                                 \
      ddist3 = FSQR_S16_LO( ddist3 );                                 \
      dres1 = vis_fpadd32( ddist2, ddist3 );                          \
      dcolor = vis_fmul8x16al( lut[ k ], fone );                      \
      dres = vis_freg_pair(                                           \
        vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ),     \
        vis_fpadd32s( vis_read_hi( dres1 ), vis_read_lo( dres1 ) ) ); \
      mask = vis_fcmplt32( dres, dpmin[ 0 ] );                        \
      vis_pst_32( dind, ( void * )dpind, mask );                      \
      dind = vis_fpadd32( dind, done );                               \
      vis_pst_32( dres, ( void * )dpmin, mask );                      \
    }                                                                 \
    dst[ i ] = ( ( mlib_s32 * )dpind )[ 0 ] + offset;                 \
    dst[ i + 1 ] = ( ( mlib_s32 * )dpind )[ 1 ] + offset;             \
  }                                                                   \
  if( i < length )                                                    \
  {                                                                   \
    dsrc = dpsrc[ 0 ];                                                \
    dsrc1 = dpsrc[ 1 ];                                               \
    dsrc1 = vis_faligndata( dsrc, dsrc1 );                            \
    dsrc = vis_fmul8x16al( vis_read_hi( dsrc1 ), fone );              \
    dpind[ 0 ] = dind = done;                                         \
    dpmin[ 0 ] = dmax;                                                \
    for( k = 0; k < entries; k++ )                                    \
    {                                                                 \
      dcolor = vis_fmul8x16al( lut[ k ], fone );                      \
      ddist1 = vis_fpsub16( dcolor, dsrc );                           \
      ddist = FSQR_S16_HI( ddist1 );                                  \
      ddist1 = FSQR_S16_LO( ddist1 );                                 \
      dres = vis_fpadd32( ddist, ddist1 );                            \
      dres = vis_write_lo( dres,                                      \
        vis_fpadd32s( vis_read_hi( dres ), vis_read_lo( dres ) ) );   \
      mask = vis_fcmplt32( dres, dpmin[ 0 ] );                        \
      vis_pst_32( dind, ( void * )dpind, mask );                      \
      dind = vis_fpadd32( dind, done );                               \
      vis_pst_32( dres, ( void * )dpmin, mask );                      \
    }                                                                 \
    dst[ i ] = ( ( mlib_s32 * )dpind )[ 1 ] + offset;                 \
  }                                                                   \
  vis_write_gsr(gsr[0]);                                              \
}

/***************************************************************/
#define FIND_NEAREST_S16_3( SHIFT, STEP )                       \
  mlib_s32 i, k, k_min, min_dist, diff, mask;                   \
  mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1;            \
  mlib_s32 entries = s->lutlength;                              \
  mlib_d64 *double_lut = mlib_ImageGetLutDoubleData( s );       \
  mlib_d64 col0, col1, col2;                                    \
  mlib_d64 dist, len0, len1, len2;                              \
                                                                \
  for( i = 0; i < length; i++ )                                 \
  {                                                             \
    col0 = src[ STEP * i + SHIFT ];                             \
    col1 = src[ STEP * i + 1 + SHIFT ];                         \
    col2 = src[ STEP * i + 2 + SHIFT ];                         \
    min_dist = MLIB_S32_MAX;                                    \
    k_min = 1;                                                  \
    len0 = double_lut[ 0 ] - col0;                              \
    len1 = double_lut[ 1 ] - col1;                              \
    len2 = double_lut[ 2 ] - col2;                              \
    for( k = 1; k <= entries; k++ )                             \
    {                                                           \
      dist = len0 * len0;                                       \
      len0 = double_lut[ 3 * k ] - col0;                        \
      dist += len1 * len1;                                      \
      len1 = double_lut[ 3 * k + 1 ] - col1;                    \
      dist += len2 * len2;                                      \
      len2 = double_lut[ 3 * k + 2 ] - col2;                    \
      diff = ( mlib_s32 )( dist * 0.125 ) - min_dist;           \
      mask = diff >> 31;                                        \
      min_dist += diff & mask;                                  \
      k_min += ( k - k_min ) & mask;                            \
    }                                                           \
    dst[ i ] = k_min + offset;                                  \
  }

/***************************************************************/
#define FIND_NEAREST_S16_4                                      \
  mlib_s32 i, k, k_min, min_dist, diff, mask;                   \
  mlib_s32 offset = mlib_ImageGetLutOffset( s ) - 1;            \
  mlib_s32 entries = s->lutlength;                              \
  mlib_d64 *double_lut = mlib_ImageGetLutDoubleData( s );       \
  mlib_d64 col0, col1, col2, col3;                              \
  mlib_d64 dist, len0, len1, len2, len3;                        \
                                                                \
  for( i = 0; i < length; i++ )                                 \
  {                                                             \
    col0 = src[ 4 * i ];                                        \
    col1 = src[ 4 * i + 1 ];                                    \
    col2 = src[ 4 * i + 2 ];                                    \
    col3 = src[ 4 * i + 3 ];                                    \
    min_dist = MLIB_S32_MAX;                                    \
    k_min = 1;                                                  \
    len0 = double_lut[ 0 ] - col0;                              \
    len1 = double_lut[ 1 ] - col1;                              \
    len2 = double_lut[ 2 ] - col2;                              \
    len3 = double_lut[ 3 ] - col3;                              \
    for( k = 1; k <= entries; k++ )                             \
    {                                                           \
      dist = len0 * len0;                                       \
      len0 =  double_lut[ 4 * k ] - col0;                       \
      dist += len1 * len1;                                      \
      len1 = double_lut[ 4 * k + 1 ] - col1;                    \
      dist += len2 * len2;                                      \
      len2 =  double_lut[ 4 * k + 2 ] - col2;                   \
      dist += len3 * len3;                                      \
      len3 =  double_lut[ 4 * k + 3 ] - col3;                   \
      diff = ( mlib_s32 )( dist * 0.125 ) - min_dist;           \
      mask = diff >> 31;                                        \
      min_dist += diff & mask;                                  \
      k_min += ( k - k_min ) & mask;                            \
    }                                                           \
    dst[ i ] = k_min + offset;                                  \
  }

/***************************************************************/
mlib_status mlib_ImageColorTrue2Index(mlib_image       *dst,
                                      const mlib_image *src,
                                      const void       *colormap)
{
  mlib_s32 y, width, height, sstride, dstride, schann;
  mlib_colormap *s = (mlib_colormap *)colormap;
  mlib_s32 channels;
  mlib_type stype, dtype;

  MLIB_IMAGE_CHECK(src);
  MLIB_IMAGE_CHECK(dst);
  MLIB_IMAGE_SIZE_EQUAL(src, dst);
  MLIB_IMAGE_HAVE_CHAN(dst, 1);

  if (!colormap)
    return MLIB_NULLPOINTER;

  channels = s->channels;
  stype = mlib_ImageGetType(src);
  dtype = mlib_ImageGetType(dst);
  width = mlib_ImageGetWidth(src);
  height = mlib_ImageGetHeight(src);
  sstride = mlib_ImageGetStride(src);
  dstride = mlib_ImageGetStride(dst);
  schann = mlib_ImageGetChannels(src);

  if (stype != s->intype || dtype != s->outtype)
    return MLIB_FAILURE;

  if (channels != schann)
    return MLIB_FAILURE;

  switch (stype) {
    case MLIB_BYTE:
      {
        mlib_u8 *sdata = mlib_ImageGetData(src);

        switch (dtype) {
          case MLIB_BYTE:
            {
              mlib_u8 *ddata = mlib_ImageGetData(dst);

              switch (channels) {
                case 3:
                  {
                    MAIN_COLORTRUE2INDEX_LOOP(U8, U8, 3);
                    return MLIB_SUCCESS;
                  }

                case 4:
                  {
                    MAIN_COLORTRUE2INDEX_LOOP(U8, U8, 4);
                    return MLIB_SUCCESS;
                  }

                default:
                  return MLIB_FAILURE;
              }
            }

          case MLIB_SHORT:
            {
              mlib_s16 *ddata = mlib_ImageGetData(dst);

              dstride /= 2;
              switch (channels) {
                case 3:
                  {
                    MAIN_COLORTRUE2INDEX_LOOP(U8, S16, 3);
                    return MLIB_SUCCESS;
                  }

                case 4:
                  {
                    MAIN_COLORTRUE2INDEX_LOOP(U8, S16, 4);
                    return MLIB_SUCCESS;
                  }

                default:
                  return MLIB_FAILURE;
              }
            }
        default:
          /* Unsupported type of destination image */
          return MLIB_FAILURE;
        }
      }

    case MLIB_SHORT:
      {
        mlib_s16 *sdata = mlib_ImageGetData(src);

        sstride /= 2;
        switch (dtype) {
          case MLIB_BYTE:
            {
              mlib_u8 *ddata = mlib_ImageGetData(dst);

              switch (channels) {
                case 3:
                  {
                    MAIN_COLORTRUE2INDEX_LOOP(S16, U8, 3);
                    return MLIB_SUCCESS;
                  }

                case 4:
                  {
                    MAIN_COLORTRUE2INDEX_LOOP(S16, U8, 4);
                    return MLIB_SUCCESS;
                  }

                default:
                  return MLIB_FAILURE;
              }
            }

          case MLIB_SHORT:
            {
              mlib_s16 *ddata = mlib_ImageGetData(dst);

              dstride /= 2;
              switch (channels) {
                case 3:
                  {
                    MAIN_COLORTRUE2INDEX_LOOP(S16, S16, 3);
                    return MLIB_SUCCESS;
                  }

                case 4:
                  {
                    MAIN_COLORTRUE2INDEX_LOOP(S16, S16, 4);
                    return MLIB_SUCCESS;
                  }

                default:
                  return MLIB_FAILURE;
              }
            }
        default:
          /* Unsupported type of destination image */
          return MLIB_FAILURE;
        }
      }

    default:
      return MLIB_FAILURE;
  }
}

/***************************************************************/
mlib_u32 mlib_search_quadrant_U8_3(struct lut_node_3 *node,
                                   mlib_u32          distance,
                                    mlib_s32    *found_color,
                                   mlib_u32          c0,
                                   mlib_u32          c1,
                                   mlib_u32          c2,
                                   const mlib_u8     **base)
{
  mlib_s32 i;

  for (i = 0; i < 8; i++) {

    if (node->tag & (1 << i)) {
      /* Here is alone color cell. Check the distance */
      mlib_s32 newindex = node->contents.index[i];
      mlib_u32 newpalc0, newpalc1, newpalc2;
      mlib_u32 newdistance;

      newpalc0 = base[0][newindex];
      newpalc1 = base[1][newindex];
      newpalc2 = base[2][newindex];
      newdistance = FIND_DISTANCE_3(c0, newpalc0, c1, newpalc1, c2, newpalc2, 0);

      if (distance > newdistance) {
        *found_color = newindex;
        distance = newdistance;
      }
    }
    else if (node->contents.quadrants[i])
      distance =
        mlib_search_quadrant_U8_3(node->contents.quadrants[i], distance,
                                  found_color, c0, c1, c2, base);
  }

  return distance;
}

/***************************************************************/
mlib_u32 mlib_search_quadrant_part_to_left_U8_3(struct lut_node_3 *node,
                                                mlib_u32          distance,
                                                 mlib_s32    *found_color,
                                                const mlib_u32    *c,
                                                const mlib_u8     **base,
                                                mlib_u32          position,
                                                mlib_s32          pass,
                                                mlib_s32          dir_bit)
{
  mlib_u32 current_size = 1 << pass;
  mlib_s32 i;
  static mlib_s32 opposite_quadrants[3][4] = {
    {0, 2, 4, 6},
    {0, 1, 4, 5},
    {0, 1, 2, 3}
  };

/* Search only quadrant's half untill it is necessary to check the
  whole quadrant */

  if (distance < (position + current_size - c[dir_bit]) * (position + current_size - c[dir_bit])) { /* Search half of quadrant */
    for (i = 0; i < 4; i++) {
      mlib_s32 qq = opposite_quadrants[dir_bit][i];

      if (node->tag & (1 << qq)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[qq];
        mlib_u32 newpalc0, newpalc1, newpalc2;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex];
        newpalc1 = base[1][newindex];
        newpalc2 = base[2][newindex];
        newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 0);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[qq])
        distance =
          mlib_search_quadrant_part_to_left_U8_3(node->contents.quadrants[qq],
                                                 distance, found_color, c, base,
                                                 position, pass - 1, dir_bit);
    }
  }
  else {                                    /* Search whole quadrant */

    mlib_s32 mask = 1 << dir_bit;

    for (i = 0; i < 8; i++) {

      if (node->tag & (1 << i)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[i];
        mlib_u32 newpalc0, newpalc1, newpalc2;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex];
        newpalc1 = base[1][newindex];
        newpalc2 = base[2][newindex];
        newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 0);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[i]) {

        if (i & mask)
          /* This quadrant may require partial checking */
          distance =
            mlib_search_quadrant_part_to_left_U8_3(node->contents.quadrants[i],
                                                   distance, found_color, c,
                                                   base,
                                                   position + current_size,
                                                   pass - 1, dir_bit);
        else
          /* Here we should check all */
          distance =
            mlib_search_quadrant_U8_3(node->contents.quadrants[i], distance,
                                      found_color, c[0], c[1], c[2], base);
      }
    }
  }

  return distance;
}

/***************************************************************/
mlib_u32 mlib_search_quadrant_part_to_right_U8_3(struct lut_node_3 *node,
                                                 mlib_u32          distance,
                                                  mlib_s32    *found_color,
                                                 const mlib_u32    *c,
                                                 const mlib_u8     **base,
                                                 mlib_u32          position,
                                                 mlib_s32          pass,
                                                 mlib_s32          dir_bit)
{
  mlib_u32 current_size = 1 << pass;
  mlib_s32 i;
  static mlib_s32 opposite_quadrants[3][4] = {
    {1, 3, 5, 7},
    {2, 3, 6, 7},
    {4, 5, 6, 7}
  };

/* Search only quadrant's half untill it is necessary to check the
  whole quadrant */

  if (distance <= (c[dir_bit] - position - current_size) * (c[dir_bit] - position - current_size)) { /* Search half of quadrant */
    for (i = 0; i < 4; i++) {
      mlib_s32 qq = opposite_quadrants[dir_bit][i];

      if (node->tag & (1 << qq)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[qq];
        mlib_u32 newpalc0, newpalc1, newpalc2;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex];
        newpalc1 = base[1][newindex];
        newpalc2 = base[2][newindex];
        newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 0);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[qq])
        distance =
          mlib_search_quadrant_part_to_right_U8_3(node->contents.quadrants[qq],
                                                  distance, found_color, c,
                                                  base, position + current_size,
                                                  pass - 1, dir_bit);
    }
  }
  else {                                    /* Search whole quadrant */

    mlib_s32 mask = 1 << dir_bit;

    for (i = 0; i < 8; i++) {

      if (node->tag & (1 << i)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[i];
        mlib_u32 newpalc0, newpalc1, newpalc2;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex];
        newpalc1 = base[1][newindex];
        newpalc2 = base[2][newindex];
        newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 0);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[i]) {

        if (i & mask)
          /* Here we should check all */
          distance =
            mlib_search_quadrant_U8_3(node->contents.quadrants[i], distance,
                                      found_color, c[0], c[1], c[2], base);
        else
          /* This quadrant may require partial checking */
          distance =
            mlib_search_quadrant_part_to_right_U8_3(node->contents.quadrants[i],
                                                    distance, found_color, c,
                                                    base, position, pass - 1, dir_bit);
      }
    }
  }

  return distance;
}

/***************************************************************/
mlib_u32 mlib_search_quadrant_S16_3(struct lut_node_3 *node,
                                    mlib_u32          distance,
                                     mlib_s32    *found_color,
                                    mlib_u32          c0,
                                    mlib_u32          c1,
                                    mlib_u32          c2,
                                    const mlib_s16    **base)
{
  mlib_s32 i;

  for (i = 0; i < 8; i++) {

    if (node->tag & (1 << i)) {
      /* Here is alone color cell. Check the distance */
      mlib_s32 newindex = node->contents.index[i];
      mlib_u32 newpalc0, newpalc1, newpalc2;
      mlib_u32 newdistance;

      newpalc0 = base[0][newindex] - MLIB_S16_MIN;
      newpalc1 = base[1][newindex] - MLIB_S16_MIN;
      newpalc2 = base[2][newindex] - MLIB_S16_MIN;
      newdistance = FIND_DISTANCE_3(c0, newpalc0, c1, newpalc1, c2, newpalc2, 2);

      if (distance > newdistance) {
        *found_color = newindex;
        distance = newdistance;
      }
    }
    else if (node->contents.quadrants[i])
      distance =
        mlib_search_quadrant_S16_3(node->contents.quadrants[i], distance,
                                   found_color, c0, c1, c2, base);
  }

  return distance;
}

/***************************************************************/
mlib_u32 mlib_search_quadrant_part_to_left_S16_3(struct lut_node_3 *node,
                                                 mlib_u32          distance,
                                                  mlib_s32    *found_color,
                                                 const mlib_u32    *c,
                                                 const mlib_s16    **base,
                                                 mlib_u32          position,
                                                 mlib_s32          pass,
                                                 mlib_s32          dir_bit)
{
  mlib_u32 current_size = 1 << pass;
  mlib_s32 i;
  static mlib_s32 opposite_quadrants[3][4] = {
    {0, 2, 4, 6},
    {0, 1, 4, 5},
    {0, 1, 2, 3}
  };

/* Search only quadrant's half untill it is necessary to check the
  whole quadrant */

  if (distance < (((position + current_size - c[dir_bit]) * (position + current_size - c[dir_bit])) >> 2)) { /* Search half of quadrant */
    for (i = 0; i < 4; i++) {
      mlib_s32 qq = opposite_quadrants[dir_bit][i];

      if (node->tag & (1 << qq)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[qq];
        mlib_u32 newpalc0, newpalc1, newpalc2;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex] - MLIB_S16_MIN;
        newpalc1 = base[1][newindex] - MLIB_S16_MIN;
        newpalc2 = base[2][newindex] - MLIB_S16_MIN;
        newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 2);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[qq])
        distance =
          mlib_search_quadrant_part_to_left_S16_3(node->contents.quadrants[qq],
                                                  distance, found_color, c,
                                                  base, position, pass - 1, dir_bit);
    }
  }
  else {                                    /* Search whole quadrant */

    mlib_s32 mask = 1 << dir_bit;

    for (i = 0; i < 8; i++) {

      if (node->tag & (1 << i)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[i];
        mlib_u32 newpalc0, newpalc1, newpalc2;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex] - MLIB_S16_MIN;
        newpalc1 = base[1][newindex] - MLIB_S16_MIN;
        newpalc2 = base[2][newindex] - MLIB_S16_MIN;
        newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 2);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[i]) {

        if (i & mask)
          /* This quadrant may require partial checking */
          distance =
            mlib_search_quadrant_part_to_left_S16_3(node->contents.quadrants[i],
                                                    distance, found_color, c,
                                                    base,
                                                    position + current_size,
                                                    pass - 1, dir_bit);
        else
          /* Here we should check all */
          distance =
            mlib_search_quadrant_S16_3(node->contents.quadrants[i], distance,
                                       found_color, c[0], c[1], c[2], base);
      }
    }
  }

  return distance;
}

/***************************************************************/
mlib_u32 mlib_search_quadrant_part_to_right_S16_3(struct lut_node_3 *node,
                                                  mlib_u32          distance,
                                                   mlib_s32    *found_color,
                                                  const mlib_u32    *c,
                                                  const mlib_s16    **base,
                                                  mlib_u32          position,
                                                  mlib_s32          pass,
                                                  mlib_s32          dir_bit)
{
  mlib_u32 current_size = 1 << pass;
  mlib_s32 i;
  static mlib_s32 opposite_quadrants[3][4] = {
    {1, 3, 5, 7},
    {2, 3, 6, 7},
    {4, 5, 6, 7}
  };

/* Search only quadrant's half untill it is necessary to check the
  whole quadrant */

  if (distance <= (((c[dir_bit] - position - current_size) * (c[dir_bit] - position - current_size)) >> 2)) { /* Search half of quadrant */
    for (i = 0; i < 4; i++) {
      mlib_s32 qq = opposite_quadrants[dir_bit][i];

      if (node->tag & (1 << qq)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[qq];
        mlib_u32 newpalc0, newpalc1, newpalc2;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex] - MLIB_S16_MIN;
        newpalc1 = base[1][newindex] - MLIB_S16_MIN;
        newpalc2 = base[2][newindex] - MLIB_S16_MIN;
        newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 2);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[qq])
        distance =
          mlib_search_quadrant_part_to_right_S16_3(node->contents.quadrants[qq],
                                                   distance, found_color, c,
                                                   base,
                                                   position + current_size,
                                                   pass - 1, dir_bit);
    }
  }
  else {                                    /* Search whole quadrant */

    mlib_s32 mask = 1 << dir_bit;

    for (i = 0; i < 8; i++) {

      if (node->tag & (1 << i)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[i];
        mlib_u32 newpalc0, newpalc1, newpalc2;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex] - MLIB_S16_MIN;
        newpalc1 = base[1][newindex] - MLIB_S16_MIN;
        newpalc2 = base[2][newindex] - MLIB_S16_MIN;
        newdistance = FIND_DISTANCE_3(c[0], newpalc0, c[1], newpalc1, c[2], newpalc2, 2);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[i]) {

        if (i & mask)
          /* Here we should check all */
          distance =
            mlib_search_quadrant_S16_3(node->contents.quadrants[i], distance,
                                       found_color, c[0], c[1], c[2], base);
        else
          /* This quadrant may require partial checking */
          distance =
            mlib_search_quadrant_part_to_right_S16_3(node->contents.
                                                     quadrants[i], distance,
                                                     found_color, c, base,
                                                     position, pass - 1, dir_bit);
      }
    }
  }

  return distance;
}

/***************************************************************/
mlib_u32 mlib_search_quadrant_U8_4(struct lut_node_4 *node,
                                   mlib_u32          distance,
                                    mlib_s32    *found_color,
                                   mlib_u32          c0,
                                   mlib_u32          c1,
                                   mlib_u32          c2,
                                   mlib_u32          c3,
                                   const mlib_u8     **base)
{
  mlib_s32 i;

  for (i = 0; i < 16; i++) {

    if (node->tag & (1 << i)) {
      /* Here is alone color cell. Check the distance */
      mlib_s32 newindex = node->contents.index[i];
      mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
      mlib_u32 newdistance;

      newpalc0 = base[0][newindex];
      newpalc1 = base[1][newindex];
      newpalc2 = base[2][newindex];
      newpalc3 = base[3][newindex];
      newdistance = FIND_DISTANCE_4(c0, newpalc0,
                                    c1, newpalc1, c2, newpalc2, c3, newpalc3, 0);

      if (distance > newdistance) {
        *found_color = newindex;
        distance = newdistance;
      }
    }
    else if (node->contents.quadrants[i])
      distance =
        mlib_search_quadrant_U8_4(node->contents.quadrants[i], distance,
                                  found_color, c0, c1, c2, c3, base);
  }

  return distance;
}

/***************************************************************/
mlib_u32 mlib_search_quadrant_part_to_left_U8_4(struct lut_node_4 *node,
                                                mlib_u32          distance,
                                                 mlib_s32    *found_color,
                                                const mlib_u32    *c,
                                                const mlib_u8     **base,
                                                mlib_u32          position,
                                                mlib_s32          pass,
                                                mlib_s32          dir_bit)
{
  mlib_u32 current_size = 1 << pass;
  mlib_s32 i;
  static mlib_s32 opposite_quadrants[4][8] = {
    {0, 2, 4, 6, 8, 10, 12, 14},
    {0, 1, 4, 5, 8, 9, 12, 13},
    {0, 1, 2, 3, 8, 9, 10, 11},
    {0, 1, 2, 3, 4, 5, 6, 7}
  };

/* Search only quadrant's half untill it is necessary to check the
  whole quadrant */

  if (distance < (position + current_size - c[dir_bit]) * (position + current_size - c[dir_bit])) { /* Search half of quadrant */
    for (i = 0; i < 8; i++) {
      mlib_s32 qq = opposite_quadrants[dir_bit][i];

      if (node->tag & (1 << qq)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[qq];
        mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex];
        newpalc1 = base[1][newindex];
        newpalc2 = base[2][newindex];
        newpalc3 = base[3][newindex];
        newdistance = FIND_DISTANCE_4(c[0], newpalc0,
                                      c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 0);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[qq])
        distance =
          mlib_search_quadrant_part_to_left_U8_4(node->contents.quadrants[qq],
                                                 distance, found_color, c, base,
                                                 position, pass - 1, dir_bit);
    }
  }
  else {                                    /* Search whole quadrant */

    mlib_s32 mask = 1 << dir_bit;

    for (i = 0; i < 16; i++) {

      if (node->tag & (1 << i)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[i];
        mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex];
        newpalc1 = base[1][newindex];
        newpalc2 = base[2][newindex];
        newpalc3 = base[3][newindex];
        newdistance = FIND_DISTANCE_4(c[0], newpalc0,
                                      c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 0);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[i]) {

        if (i & mask)
          /* This quadrant may require partial checking */
          distance =
            mlib_search_quadrant_part_to_left_U8_4(node->contents.quadrants[i],
                                                   distance, found_color, c,
                                                   base,
                                                   position + current_size,
                                                   pass - 1, dir_bit);
        else
          /* Here we should check all */
          distance =
            mlib_search_quadrant_U8_4(node->contents.quadrants[i], distance,
                                      found_color, c[0], c[1], c[2], c[3], base);
      }
    }
  }

  return distance;
}

/***************************************************************/
mlib_u32 mlib_search_quadrant_part_to_right_U8_4(struct lut_node_4 *node,
                                                 mlib_u32          distance,
                                                  mlib_s32    *found_color,
                                                 const mlib_u32    *c,
                                                 const mlib_u8     **base,
                                                 mlib_u32          position,
                                                 mlib_s32          pass,
                                                 mlib_s32          dir_bit)
{
  mlib_u32 current_size = 1 << pass;
  mlib_s32 i;
  static mlib_s32 opposite_quadrants[4][8] = {
    {1, 3, 5, 7, 9, 11, 13, 15},
    {2, 3, 6, 7, 10, 11, 14, 15},
    {4, 5, 6, 7, 12, 13, 14, 15},
    {8, 9, 10, 11, 12, 13, 14, 15}
  };

/* Search only quadrant's half untill it is necessary to check the
  whole quadrant */

  if (distance <= (c[dir_bit] - position - current_size) * (c[dir_bit] - position - current_size)) { /* Search half of quadrant */
    for (i = 0; i < 8; i++) {
      mlib_s32 qq = opposite_quadrants[dir_bit][i];

      if (node->tag & (1 << qq)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[qq];
        mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex];
        newpalc1 = base[1][newindex];
        newpalc2 = base[2][newindex];
        newpalc3 = base[3][newindex];
        newdistance = FIND_DISTANCE_4(c[0], newpalc0,
                                      c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 0);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[qq])
        distance =
          mlib_search_quadrant_part_to_right_U8_4(node->contents.quadrants[qq],
                                                  distance, found_color, c,
                                                  base, position + current_size,
                                                  pass - 1, dir_bit);
    }
  }
  else {                                    /* Search whole quadrant */

    mlib_s32 mask = 1 << dir_bit;

    for (i = 0; i < 16; i++) {

      if (node->tag & (1 << i)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[i];
        mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex];
        newpalc1 = base[1][newindex];
        newpalc2 = base[2][newindex];
        newpalc3 = base[3][newindex];
        newdistance = FIND_DISTANCE_4(c[0], newpalc0,
                                      c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 0);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[i]) {

        if (i & mask)
          /* Here we should check all */
          distance =
            mlib_search_quadrant_U8_4(node->contents.quadrants[i], distance,
                                      found_color, c[0], c[1], c[2], c[3], base);
        else
          /* This quadrant may require partial checking */
          distance =
            mlib_search_quadrant_part_to_right_U8_4(node->contents.quadrants[i],
                                                    distance, found_color, c,
                                                    base, position, pass - 1, dir_bit);
      }
    }
  }

  return distance;
}

/***************************************************************/
mlib_u32 mlib_search_quadrant_S16_4(struct lut_node_4 *node,
                                    mlib_u32          distance,
                                     mlib_s32    *found_color,
                                    mlib_u32          c0,
                                    mlib_u32          c1,
                                    mlib_u32          c2,
                                    mlib_u32          c3,
                                    const mlib_s16    **base)
{
  mlib_s32 i;

  for (i = 0; i < 16; i++) {

    if (node->tag & (1 << i)) {
      /* Here is alone color cell. Check the distance */
      mlib_s32 newindex = node->contents.index[i];
      mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
      mlib_u32 newdistance;

      newpalc0 = base[0][newindex] - MLIB_S16_MIN;
      newpalc1 = base[1][newindex] - MLIB_S16_MIN;
      newpalc2 = base[2][newindex] - MLIB_S16_MIN;
      newpalc3 = base[3][newindex] - MLIB_S16_MIN;
      newdistance = FIND_DISTANCE_4(c0, newpalc0,
                                    c1, newpalc1, c2, newpalc2, c3, newpalc3, 2);

      if (distance > newdistance) {
        *found_color = newindex;
        distance = newdistance;
      }
    }
    else if (node->contents.quadrants[i])
      distance =
        mlib_search_quadrant_S16_4(node->contents.quadrants[i], distance,
                                   found_color, c0, c1, c2, c3, base);
  }

  return distance;
}

/***************************************************************/
mlib_u32 mlib_search_quadrant_part_to_left_S16_4(struct lut_node_4 *node,
                                                 mlib_u32          distance,
                                                  mlib_s32    *found_color,
                                                 const mlib_u32    *c,
                                                 const mlib_s16    **base,
                                                 mlib_u32          position,
                                                 mlib_s32          pass,
                                                 mlib_s32          dir_bit)
{
  mlib_u32 current_size = 1 << pass;
  mlib_s32 i;
  static mlib_s32 opposite_quadrants[4][8] = {
    {0, 2, 4, 6, 8, 10, 12, 14},
    {0, 1, 4, 5, 8, 9, 12, 13},
    {0, 1, 2, 3, 8, 9, 10, 11},
    {0, 1, 2, 3, 4, 5, 6, 7}
  };

/* Search only quadrant's half untill it is necessary to check the
  whole quadrant */

  if (distance < (((position + current_size - c[dir_bit]) * (position + current_size - c[dir_bit])) >> 2)) { /* Search half of quadrant */
    for (i = 0; i < 8; i++) {
      mlib_s32 qq = opposite_quadrants[dir_bit][i];

      if (node->tag & (1 << qq)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[qq];
        mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex] - MLIB_S16_MIN;
        newpalc1 = base[1][newindex] - MLIB_S16_MIN;
        newpalc2 = base[2][newindex] - MLIB_S16_MIN;
        newpalc3 = base[3][newindex] - MLIB_S16_MIN;
        newdistance = FIND_DISTANCE_4(c[0], newpalc0,
                                      c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 2);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[qq])
        distance =
          mlib_search_quadrant_part_to_left_S16_4(node->contents.quadrants[qq],
                                                  distance, found_color, c,
                                                  base, position, pass - 1, dir_bit);
    }
  }
  else {                                    /* Search whole quadrant */

    mlib_s32 mask = 1 << dir_bit;

    for (i = 0; i < 16; i++) {

      if (node->tag & (1 << i)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[i];
        mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex] - MLIB_S16_MIN;
        newpalc1 = base[1][newindex] - MLIB_S16_MIN;
        newpalc2 = base[2][newindex] - MLIB_S16_MIN;
        newpalc3 = base[3][newindex] - MLIB_S16_MIN;
        newdistance = FIND_DISTANCE_4(c[0], newpalc0,
                                      c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 2);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[i]) {

        if (i & mask)
          /* This quadrant may require partial checking */
          distance =
            mlib_search_quadrant_part_to_left_S16_4(node->contents.quadrants[i],
                                                    distance, found_color, c,
                                                    base,
                                                    position + current_size,
                                                    pass - 1, dir_bit);
        else
          /* Here we should check all */
          distance =
            mlib_search_quadrant_S16_4(node->contents.quadrants[i], distance,
                                       found_color, c[0], c[1], c[2], c[3], base);
      }
    }
  }

  return distance;
}

/***************************************************************/
mlib_u32 mlib_search_quadrant_part_to_right_S16_4(struct lut_node_4 *node,
                                                  mlib_u32          distance,
                                                   mlib_s32    *found_color,
                                                  const mlib_u32    *c,
                                                  const mlib_s16    **base,
                                                  mlib_u32          position,
                                                  mlib_s32          pass,
                                                  mlib_s32          dir_bit)
{
  mlib_u32 current_size = 1 << pass;
  mlib_s32 i;
  static mlib_s32 opposite_quadrants[4][8] = {
    {1, 3, 5, 7, 9, 11, 13, 15},
    {2, 3, 6, 7, 10, 11, 14, 15},
    {4, 5, 6, 7, 12, 13, 14, 15},
    {8, 9, 10, 11, 12, 13, 14, 15}
  };

/* Search only quadrant's half untill it is necessary to check the
  whole quadrant */

  if (distance <= (((c[dir_bit] - position - current_size) * (c[dir_bit] - position - current_size)) >> 2)) { /* Search half of quadrant */
    for (i = 0; i < 8; i++) {
      mlib_s32 qq = opposite_quadrants[dir_bit][i];

      if (node->tag & (1 << qq)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[qq];
        mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex] - MLIB_S16_MIN;
        newpalc1 = base[1][newindex] - MLIB_S16_MIN;
        newpalc2 = base[2][newindex] - MLIB_S16_MIN;
        newpalc3 = base[3][newindex] - MLIB_S16_MIN;
        newdistance = FIND_DISTANCE_4(c[0], newpalc0,
                                      c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 2);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[qq])
        distance =
          mlib_search_quadrant_part_to_right_S16_4(node->contents.quadrants[qq],
                                                   distance, found_color, c,
                                                   base,
                                                   position + current_size,
                                                   pass - 1, dir_bit);
    }
  }
  else {                                    /* Search whole quadrant */

    mlib_s32 mask = 1 << dir_bit;

    for (i = 0; i < 16; i++) {

      if (node->tag & (1 << i)) {
        /* Here is alone color cell. Check the distance */
        mlib_s32 newindex = node->contents.index[i];
        mlib_u32 newpalc0, newpalc1, newpalc2, newpalc3;
        mlib_u32 newdistance;

        newpalc0 = base[0][newindex] - MLIB_S16_MIN;
        newpalc1 = base[1][newindex] - MLIB_S16_MIN;
        newpalc2 = base[2][newindex] - MLIB_S16_MIN;
        newpalc3 = base[3][newindex] - MLIB_S16_MIN;
        newdistance = FIND_DISTANCE_4(c[0], newpalc0,
                                      c[1], newpalc1, c[2], newpalc2, c[3], newpalc3, 2);

        if (distance > newdistance) {
          *found_color = newindex;
          distance = newdistance;
        }
      }
      else if (node->contents.quadrants[i]) {

        if (i & mask)
          /* Here we should check all */
          distance =
            mlib_search_quadrant_S16_4(node->contents.quadrants[i], distance,
                                       found_color, c[0], c[1], c[2], c[3], base);
        else
          /* This quadrant may require partial checking */
          distance =
            mlib_search_quadrant_part_to_right_S16_4(node->contents.
                                                     quadrants[i], distance,
                                                     found_color, c, base,
                                                     position, pass - 1, dir_bit);
      }
    }
  }

  return distance;
}

/***************************************************************/

#define TAB_SIZE_mlib_u8   256
#define TAB_SIZE_mlib_s16 1024

#define SRC_mlib_u8(i)    src[i]
#define SRC_mlib_s16(i)   (((mlib_u16*)src)[i] >> 6)

/***************************************************************/

#define DIMENSIONS_SEARCH_3(STYPE, DTYPE, STEP)                 \
{                                                               \
  DTYPE  *tab0 = ((mlib_colormap *)state)->table;               \
  DTYPE  *tab1 = tab0 + TAB_SIZE_##STYPE;                       \
  DTYPE  *tab2 = tab1 + TAB_SIZE_##STYPE;                       \
  mlib_s32 i;                                                   \
                                                                \
  for (i = 0; i < length; i++) {                                \
    dst[i] = tab0[SRC_##STYPE(0)] + tab1[SRC_##STYPE(1)] +      \
             tab2[SRC_##STYPE(2)];                              \
    src += STEP;                                                \
  }                                                             \
}

/***************************************************************/

#define DIMENSIONS_SEARCH_4(STYPE, DTYPE)                       \
{                                                               \
  DTYPE  *tab0 = ((mlib_colormap *)state)->table;               \
  DTYPE  *tab1 = tab0 + TAB_SIZE_##STYPE;                       \
  DTYPE  *tab2 = tab1 + TAB_SIZE_##STYPE;                       \
  DTYPE  *tab3 = tab2 + TAB_SIZE_##STYPE;                       \
  mlib_s32 i;                                                   \
                                                                \
  for (i = 0; i < length; i++) {                                \
    dst[i] = tab0[SRC_##STYPE(0)] + tab1[SRC_##STYPE(1)] +      \
             tab2[SRC_##STYPE(2)] + tab3[SRC_##STYPE(3)];       \
    src += 4;                                                   \
  }                                                             \
}

/***************************************************************/
void mlib_ImageColorTrue2IndexLine_U8_U8_3(const mlib_u8 *src,
                                           mlib_u8       *dst,
                                           mlib_s32      length,
                                           const void    *state)
{
  mlib_colormap *s = (mlib_colormap *)state;

  switch (s->method) {
#if LUT_BYTE_COLORS_3CHANNELS <= 256
    case LUT_BINARY_TREE_SEARCH:
      {
        mlib_s32 bits = s->bits;
        BINARY_TREE_SEARCH_3(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 0, 3, 0);
      }
      break;

#endif /* LUT_BYTE_COLORS_3CHANNELS <= 256 */
    case LUT_COLOR_CUBE_SEARCH:
      {
        COLOR_CUBE_U8_3_SEARCH(mlib_u8, 0, 3);
      }
      break;

    case LUT_STUPID_SEARCH:
      {
#ifdef USE_VIS_CODE
        FIND_NEAREST_U8_3;
#else
        FIND_NEAREST_U8_3_C(0, 3);
#endif
      }
      break;

    case LUT_COLOR_DIMENSIONS:
      DIMENSIONS_SEARCH_3(mlib_u8, mlib_u8, 3)
      break;
  }
}

/***************************************************************/
void mlib_ImageColorTrue2IndexLine_U8_U8_3_in_4(const mlib_u8 *src,
                                                mlib_u8       *dst,
                                                mlib_s32      length,
                                                const void    *state)
{
  mlib_colormap *s = (mlib_colormap *)state;

  switch (s->method) {
#if LUT_BYTE_COLORS_3CHANNELS <= 256
    case LUT_BINARY_TREE_SEARCH:
      {
        mlib_s32 bits = s->bits;
        BINARY_TREE_SEARCH_3(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 1, 4, 0);
        break;
      }

#endif /* LUT_BYTE_COLORS_3CHANNELS <= 256 */
    case LUT_COLOR_CUBE_SEARCH:
      {
        COLOR_CUBE_U8_3_SEARCH(mlib_u8, 1, 4);
        break;
      }

    case LUT_STUPID_SEARCH:
      {
#ifdef USE_VIS_CODE
        FIND_NEAREST_U8_3_IN4;
#else
        FIND_NEAREST_U8_3_C(1, 4);
#endif
        break;
      }

    case LUT_COLOR_DIMENSIONS:
      src++;
      DIMENSIONS_SEARCH_3(mlib_u8, mlib_u8, 4)
      break;
  }
}

/***************************************************************/
void mlib_ImageColorTrue2IndexLine_U8_U8_4(const mlib_u8 *src,
                                           mlib_u8       *dst,
                                           mlib_s32      length,
                                           const void    *state)
{
  mlib_colormap *s = (mlib_colormap *)state;

  switch (s->method) {
#if LUT_BYTE_COLORS_4CHANNELS <= 256
    case LUT_BINARY_TREE_SEARCH:
      {
        mlib_s32 bits = s->bits;
        BINARY_TREE_SEARCH_4(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 0);
        break;
      }

#endif /* LUT_BYTE_COLORS_4CHANNELS <= 256 */
    case LUT_COLOR_CUBE_SEARCH:
      {
        COLOR_CUBE_U8_4_SEARCH(mlib_u8);
        break;
      }

    case LUT_STUPID_SEARCH:
      {
#ifdef USE_VIS_CODE
        FIND_NEAREST_U8_4;
#else
        FIND_NEAREST_U8_4_C;
#endif
        break;
      }

    case LUT_COLOR_DIMENSIONS:
      DIMENSIONS_SEARCH_4(mlib_u8, mlib_u8)
      break;
  }
}

/***************************************************************/
void mlib_ImageColorTrue2IndexLine_U8_S16_3(const mlib_u8 *src,
                                            mlib_s16      *dst,
                                            mlib_s32      length,
                                            const void    *state)
{
  mlib_colormap *s = (mlib_colormap *)state;
  mlib_s32 bits = s->bits;

  switch (s->method) {
    case LUT_BINARY_TREE_SEARCH:
      {
        BINARY_TREE_SEARCH_3(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 0, 3, 0);
        break;
      }

    case LUT_COLOR_CUBE_SEARCH:
      {
        switch (s->indexsize) {
          case 1:
            {
              COLOR_CUBE_U8_3_SEARCH(mlib_u8, 0, 3);
              break;
            }

          case 2:
            {
              COLOR_CUBE_U8_3_SEARCH(mlib_s16, 0, 3);
              break;
            }
        }

        break;
      }

    case LUT_STUPID_SEARCH:
      {
#ifdef USE_VIS_CODE
        FIND_NEAREST_U8_3;
#else
        FIND_NEAREST_U8_3_C(0, 3);
#endif
        break;
      }

    case LUT_COLOR_DIMENSIONS:
      DIMENSIONS_SEARCH_3(mlib_u8, mlib_s16, 3)
      break;
  }
}

/***************************************************************/
void mlib_ImageColorTrue2IndexLine_U8_S16_3_in_4(const mlib_u8 *src,
                                                 mlib_s16      *dst,
                                                 mlib_s32      length,
                                                 const void    *state)
{
  mlib_colormap *s = (mlib_colormap *)state;
  mlib_s32 bits = s->bits;

  switch (s->method) {
    case LUT_BINARY_TREE_SEARCH:
      {
        BINARY_TREE_SEARCH_3(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 1, 4, 0);
        break;
      }

    case LUT_COLOR_CUBE_SEARCH:
      {
        switch (s->indexsize) {
          case 1:
            {
              COLOR_CUBE_U8_3_SEARCH(mlib_u8, 1, 4);
              break;
            }

          case 2:
            {
              COLOR_CUBE_U8_3_SEARCH(mlib_s16, 1, 4);
              break;
            }
        }

        break;
      }

    case LUT_STUPID_SEARCH:
      {
#ifdef USE_VIS_CODE
        FIND_NEAREST_U8_3_IN4;
#else
        FIND_NEAREST_U8_3_C(1, 4);
#endif
        break;
      }

    case LUT_COLOR_DIMENSIONS:
      src++;
      DIMENSIONS_SEARCH_3(mlib_u8, mlib_s16, 4)
      break;
  }
}

/***************************************************************/
void mlib_ImageColorTrue2IndexLine_U8_S16_4(const mlib_u8 *src,
                                            mlib_s16      *dst,
                                            mlib_s32      length,
                                            const void    *state)
{
  mlib_colormap *s = (mlib_colormap *)state;
  mlib_s32 bits = s->bits;

  switch (s->method) {
    case LUT_BINARY_TREE_SEARCH:
      {
        BINARY_TREE_SEARCH_4(U8, mlib_u8, 8, (MLIB_U8_MAX + 1), 0, 0);
        break;
      }

    case LUT_COLOR_CUBE_SEARCH:
      {
        switch (s->indexsize) {
          case 1:
            {
              COLOR_CUBE_U8_4_SEARCH(mlib_u8);
              break;
            }

          case 2:
            {
              COLOR_CUBE_U8_4_SEARCH(mlib_s16);
              break;
            }
        }

        break;
      }

    case LUT_STUPID_SEARCH:
      {
#ifdef USE_VIS_CODE
        FIND_NEAREST_U8_4;
#else
        FIND_NEAREST_U8_4_C;
#endif
        break;
      }

    case LUT_COLOR_DIMENSIONS:
      DIMENSIONS_SEARCH_4(mlib_u8, mlib_s16)
      break;
  }
}

/***************************************************************/
void mlib_ImageColorTrue2IndexLine_S16_S16_3(const mlib_s16 *src,
                                             mlib_s16       *dst,
                                             mlib_s32       length,
                                             const void     *state)
{
  mlib_colormap *s = (mlib_colormap *)state;
  mlib_s32 bits = s->bits;

  switch (s->method) {
    case LUT_BINARY_TREE_SEARCH:
      {
        BINARY_TREE_SEARCH_3(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
                             MLIB_S16_MIN, 0, 3, 2);
        break;
      }

    case LUT_COLOR_CUBE_SEARCH:
      {
        switch (s->indexsize) {
          case 1:
            {
              COLOR_CUBE_S16_3_SEARCH(mlib_u8, 0, 3);
              break;
            }

          case 2:
            {
              COLOR_CUBE_S16_3_SEARCH(mlib_s16, 0, 3);
              break;
            }
        }

        break;
      }

    case LUT_STUPID_SEARCH:
      {
        FIND_NEAREST_S16_3(0, 3);
        break;
      }

    case LUT_COLOR_DIMENSIONS:
      DIMENSIONS_SEARCH_3(mlib_s16, mlib_s16, 3)
      break;
  }
}

/***************************************************************/
void mlib_ImageColorTrue2IndexLine_S16_S16_3_in_4(const mlib_s16 *src,
                                                  mlib_s16       *dst,
                                                  mlib_s32       length,
                                                  const void     *state)
{
  mlib_colormap *s = (mlib_colormap *)state;
  mlib_s32 bits = s->bits;

  switch (s->method) {
    case LUT_BINARY_TREE_SEARCH:
      {
        BINARY_TREE_SEARCH_3(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
                             MLIB_S16_MIN, 1, 4, 2);
        break;
      }

    case LUT_COLOR_CUBE_SEARCH:
      {
        switch (s->indexsize) {
          case 1:
            {
              COLOR_CUBE_S16_3_SEARCH(mlib_u8, 1, 4);
              break;
            }

          case 2:
            {
              COLOR_CUBE_S16_3_SEARCH(mlib_s16, 1, 4);
              break;
            }
        }

        break;
      }

    case LUT_STUPID_SEARCH:
      {
        FIND_NEAREST_S16_3(1, 4);
        break;
      }

    case LUT_COLOR_DIMENSIONS:
      src++;
      DIMENSIONS_SEARCH_3(mlib_s16, mlib_s16, 4)
      break;
  }
}

/***************************************************************/
void mlib_ImageColorTrue2IndexLine_S16_S16_4(const mlib_s16 *src,
                                             mlib_s16       *dst,
                                             mlib_s32       length,
                                             const void     *state)
{
  mlib_colormap *s = (mlib_colormap *)state;
  mlib_s32 bits = s->bits;

  switch (s->method) {
    case LUT_BINARY_TREE_SEARCH:
      {
        BINARY_TREE_SEARCH_4(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
                             MLIB_S16_MIN, 2);
        break;
      }

    case LUT_COLOR_CUBE_SEARCH:
      {
        switch (s->indexsize) {
          case 1:
            {
              COLOR_CUBE_S16_4_SEARCH(mlib_u8);
              break;
            }

          case 2:
            {
              COLOR_CUBE_S16_4_SEARCH(mlib_s16);
              break;
            }
        }

        break;
      }

    case LUT_STUPID_SEARCH:
      {
        FIND_NEAREST_S16_4;
        break;
      }

    case LUT_COLOR_DIMENSIONS:
      DIMENSIONS_SEARCH_4(mlib_s16, mlib_s16)
      break;
  }
}

/***************************************************************/
void mlib_ImageColorTrue2IndexLine_S16_U8_3(const mlib_s16 *src,
                                            mlib_u8        *dst,
                                            mlib_s32       length,
                                            const void     *state)
{
  mlib_colormap *s = (mlib_colormap *)state;

  switch (s->method) {
#if LUT_SHORT_COLORS_3CHANNELS <= 256
    case LUT_BINARY_TREE_SEARCH:
      {
        mlib_s32 bits = s->bits;
        BINARY_TREE_SEARCH_3(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
                             MLIB_S16_MIN, 0, 3, 2);
        break;
      }

#endif /* LUT_SHORT_COLORS_3CHANNELS <= 256 */
    case LUT_COLOR_CUBE_SEARCH:
      {
        COLOR_CUBE_S16_3_SEARCH(mlib_u8, 0, 3);
        break;
      }

    case LUT_STUPID_SEARCH:
      {
        FIND_NEAREST_S16_3(0, 3);
        break;
      }

    case LUT_COLOR_DIMENSIONS:
      DIMENSIONS_SEARCH_3(mlib_s16, mlib_u8, 3)
      break;
  }
}

/***************************************************************/
void mlib_ImageColorTrue2IndexLine_S16_U8_3_in_4(const mlib_s16 *src,
                                                 mlib_u8        *dst,
                                                 mlib_s32       length,
                                                 const void     *state)
{
  mlib_colormap *s = (mlib_colormap *)state;

  switch (s->method) {
#if LUT_SHORT_COLORS_3CHANNELS <= 256
    case LUT_BINARY_TREE_SEARCH:
      {
        mlib_s32 bits = s->bits;
        BINARY_TREE_SEARCH_3(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
                             MLIB_S16_MIN, 1, 4, 2);
        break;
      }

#endif /* LUT_SHORT_COLORS_3CHANNELS <= 256 */
    case LUT_COLOR_CUBE_SEARCH:
      {
        COLOR_CUBE_S16_3_SEARCH(mlib_u8, 1, 4);
        break;
      }

    case LUT_STUPID_SEARCH:
      {
        FIND_NEAREST_S16_3(1, 4);
        break;
      }

    case LUT_COLOR_DIMENSIONS:
      src++;
      DIMENSIONS_SEARCH_3(mlib_s16, mlib_u8, 4)
      break;
  }
}

/***************************************************************/
void mlib_ImageColorTrue2IndexLine_S16_U8_4(const mlib_s16 *src,
                                            mlib_u8        *dst,
                                            mlib_s32       length,
                                            const void     *state)
{
  mlib_colormap *s = (mlib_colormap *)state;

  switch (s->method) {
#if LUT_SHORT_COLORS_4CHANNELS <= 256
    case LUT_BINARY_TREE_SEARCH:
      {
        mlib_s32 bits = s->bits;
        BINARY_TREE_SEARCH_4(S16, mlib_s16, 16, ((MLIB_S16_MAX + 1) * 2),
                             MLIB_S16_MIN, 2);
        break;
      }

#endif /* LUT_SHORT_COLORS_4CHANNELS <= 256 */
    case LUT_COLOR_CUBE_SEARCH:
      {
        COLOR_CUBE_S16_4_SEARCH(mlib_u8);
        break;
      }

    case LUT_STUPID_SEARCH:
      {
        FIND_NEAREST_S16_4;
        break;
      }

    case LUT_COLOR_DIMENSIONS:
      DIMENSIONS_SEARCH_4(mlib_s16, mlib_u8)
      break;
  }
}

/***************************************************************/

#ifndef VIS

void mlib_c_ImageThresh1_U81_1B(void     *psrc,
                                void     *pdst,
                                mlib_s32 src_stride,
                                mlib_s32 dst_stride,
                                mlib_s32 width,
                                mlib_s32 height,
                                void     *thresh,
                                void     *ghigh,
                                void     *glow,
                                mlib_s32 dbit_off);

/***************************************************************/

void mlib_ImageColorTrue2IndexLine_U8_BIT_1(const mlib_u8 *src,
                                            mlib_u8       *dst,
                                            mlib_s32      bit_offset,
                                            mlib_s32      length,
                                            const void    *state)
{
  mlib_u8  *lut = ((mlib_colormap *)state)->table;
  mlib_s32 thresh[1];
  mlib_s32 ghigh[1];
  mlib_s32 glow[1];

  thresh[0] = lut[2];

  glow[0]  = lut[0] - lut[1];
  ghigh[0] = lut[1] - lut[0];

  mlib_c_ImageThresh1_U81_1B((void*)src, dst, 0, 0, length, 1,
                             thresh, ghigh, glow, bit_offset);
}

#else

/***************************************************************/

void mlib_v_ImageThresh1B_U8_1(const mlib_u8  *src,
                               mlib_s32       slb,
                               mlib_u8        *dst,
                               mlib_s32       dlb,
                               mlib_s32       xsize,
                               mlib_s32       ysize,
                               mlib_s32       dbit_off,
                               const mlib_s32 *th,
                               mlib_s32       hc,
                               mlib_s32       lc);

/***************************************************************/

void mlib_ImageColorTrue2IndexLine_U8_BIT_1(const mlib_u8 *src,
                                            mlib_u8       *dst,
                                            mlib_s32      bit_offset,
                                            mlib_s32      length,
                                            const void    *state)
{
  mlib_u8  *lut = ((mlib_colormap *)state)->table;
  mlib_s32 thresh[4];
  mlib_s32 ghigh[1];
  mlib_s32 glow[1];

  thresh[0] = thresh[1] = thresh[2] = thresh[3] = lut[2];

  glow[0]  = (lut[1] < lut[0]) ? 0xFF : 0;
  ghigh[0] = (lut[1] < lut[0]) ? 0 : 0xFF;

  mlib_v_ImageThresh1B_U8_1((void*)src, 0, dst, 0, length, 1,
                            bit_offset, thresh, ghigh[0], glow[0]);
}

/***************************************************************/

#endif

Other Java examples (source code examples)

Here is a short list of links related to this Java mlib_ImageColorTrue2Index.c source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.