ascmap.c

Go to the documentation of this file.
00001 /* This file contains code colormapping of the image                */
00002 /********************************************************************/
00003 /* Copyright (c) 2001 Sasha Vasko <sasha at aftercode.net>           */
00004 /********************************************************************/
00005 /*
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #undef LOCAL_DEBUG
00023 #undef DO_CLOCKING
00024 
00025 #ifdef _WIN32
00026 #include "win32/config.h"
00027 #else
00028 #include "config.h"
00029 #endif
00030 
00031 #include <string.h>
00032 #if TIME_WITH_SYS_TIME
00033 # include <sys/time.h>
00034 # include <time.h>
00035 #else
00036 # if HAVE_SYS_TIME_H
00037 #  include <sys/time.h>
00038 # else
00039 #  include <time.h>
00040 # endif
00041 #endif
00042 #ifdef HAVE_UNISTD_H
00043 #include <unistd.h>
00044 #endif
00045 #ifdef HAVE_STDLIB_H
00046 #include <stdlib.h>
00047 #endif
00048 #ifdef HAVE_STDARG_H
00049 #include <stdarg.h>
00050 #endif
00051 #include <ctype.h>
00052 
00053 #ifdef _WIN32
00054 # include "win32/afterbase.h"
00055 #else
00056 # include "afterbase.h"
00057 #endif
00058 
00059 #include "asimage.h"
00060 #include "import.h"
00061 #include "export.h"
00062 #include "imencdec.h"
00063 #include "ascmap.h"
00064 
00065 /***********************************************************************************/
00066 /* reduced colormap building code :                                                */
00067 /***********************************************************************************/
00068 static inline ASMappedColor *new_mapped_color( CARD32 red, CARD32 green, CARD32 blue, CARD32 indexed )
00069 {
00070         register ASMappedColor *pnew = malloc( sizeof( ASMappedColor ));
00071         if( pnew != NULL )
00072         {
00073                 pnew->red   = INDEX_UNSHIFT_RED  (red) ;
00074                 pnew->green = INDEX_UNSHIFT_GREEN(green) ;
00075                 pnew->blue  = INDEX_UNSHIFT_BLUE (blue) ;
00076                 pnew->indexed = indexed ;
00077                 pnew->count = 1 ;
00078                 pnew->cmap_idx = -1 ;
00079                 pnew->next = NULL ;
00080 /*LOCAL_DEBUG_OUT( "indexed color added: 0x%X(%d): #%2.2X%2.2X%2.2X", indexed, indexed, red, green, blue );*/
00081         }
00082         return pnew;
00083 }
00084 
00085 void
00086 add_index_color( ASSortedColorHash *index, CARD32 indexed, unsigned int slot, CARD32 red, CARD32 green, CARD32 blue )
00087 {
00088         ASSortedColorBucket *stack ;
00089         ASMappedColor **pnext ;
00090 
00091         stack = &(index->buckets[slot]);
00092         pnext = &(stack->head);
00093 
00094         ++(stack->count);
00095 
00096         if( stack->tail )
00097         {
00098                 if( indexed == stack->tail->indexed )
00099                 {
00100                         ++(stack->tail->count);
00101                         return;
00102                 }else if( indexed > stack->tail->indexed )
00103                         pnext = &(stack->tail);
00104         }
00105         while( *pnext )
00106         {
00107                 register ASMappedColor *pelem = *pnext ;/* to avoid double redirection */
00108                 if( pelem->indexed == indexed )
00109                 {
00110                         ++(pelem->count);
00111                         return ;
00112                 }else if( pelem->indexed > indexed )
00113                 {
00114                         register ASMappedColor *pnew = new_mapped_color( red, green, blue, indexed );
00115                         if( pnew )
00116                         {
00117                                 ++(index->count_unique);
00118                                 pnew->next = pelem ;
00119                                 *pnext = pnew ;
00120                                 return;
00121                         }
00122                 }
00123                 pnext = &(pelem->next);
00124         }
00125         /* we want to avoid memory overflow : */
00126         if( (*pnext = new_mapped_color( red, green, blue, indexed )) != NULL )
00127         {
00128                 stack->tail = (*pnext);
00129                 ++(index->count_unique);
00130         }
00131 }
00132 
00133 void destroy_colorhash( ASSortedColorHash *index, Bool reusable )
00134 {
00135         if( index )
00136         {
00137                 int i ;
00138                 for( i = 0 ; i < index->buckets_num ; i++ )
00139                         while( index->buckets[i].head )
00140                         {
00141                                 ASMappedColor *to_free = index->buckets[i].head;
00142                                 index->buckets[i].head = to_free->next ;
00143                                 free( to_free );
00144                         }
00145                 if( !reusable )
00146                 {
00147                         free( index->buckets );
00148                         free( index );
00149                 }
00150         }
00151 }
00152 
00153 #ifdef LOCAL_DEBUG
00154 void
00155 check_colorindex_counts( ASSortedColorHash *index )
00156 {
00157         int i ;
00158         int count_unique = 0;
00159 
00160         for( i = 0 ; i < index->buckets_num ; i++ )
00161         {
00162                 register ASMappedColor *pelem = index->buckets[i].head ;
00163                 int row_count = 0 ;
00164                 while( pelem != NULL )
00165                 {
00166                         count_unique++ ;
00167                         if( pelem->cmap_idx < 0 )
00168                                 row_count += pelem->count ;
00169                         pelem = pelem->next ;
00170                 }
00171                 if( row_count != index->buckets[i].count )
00172                         fprintf( stderr, "bucket %d counts-> %d : %d\n", i, row_count, index->buckets[i].count );
00173         }
00174         fprintf( stderr, "total unique-> %d : %d\n", count_unique, index->count_unique );
00175 
00176 }
00177 #endif
00178 
00179 void
00180 fix_colorindex_shortcuts( ASSortedColorHash *index )
00181 {
00182         int i ;
00183         int last_good = -1, next_good = -1;
00184 
00185         index->last_found = -1 ;
00186 
00187         for( i = 0 ; i < index->buckets_num ; i++ )
00188         {
00189                 register ASMappedColor **pelem = &(index->buckets[i].head) ;
00190                 register ASMappedColor **tail = &(index->buckets[i].tail) ;
00191                 while( *pelem != NULL )
00192                 {
00193                         if( (*pelem)->cmap_idx < 0 )
00194                         {
00195                                 ASMappedColor *to_free = *pelem ;
00196                                 *pelem = (*pelem)->next ;
00197                                 free( to_free );
00198                         }else
00199                         {
00200                                 *tail = *pelem ;
00201                                 pelem = &((*pelem)->next);
00202                         }
00203                 }
00204         }
00205         for( i = 0 ; i < index->buckets_num ; i++ )
00206         {
00207                 if( next_good < 0 )
00208                 {
00209                         for( next_good = i ; next_good < index->buckets_num ; next_good++ )
00210                                 if( index->buckets[next_good].head )
00211                                         break;
00212                         if( next_good >= index->buckets_num )
00213                                 next_good = last_good ;
00214                 }
00215                 if( index->buckets[i].head )
00216                 {
00217                         last_good = i;
00218                         next_good = -1;
00219                 }else
00220                 {
00221                         if( last_good < 0 || ( i-last_good >= next_good-i && i < next_good ) )
00222                                 index->buckets[i].good_offset = next_good-i ;
00223                         else
00224                                 index->buckets[i].good_offset = last_good-i ;
00225                 }
00226         }
00227 }
00228 
00229 
00230 
00231 static inline void
00232 add_colormap_item( register ASColormapEntry *pentry, ASMappedColor *pelem, int cmap_idx )
00233 {
00234         pentry->red   = pelem->red ;
00235         pentry->green = pelem->green ;
00236         pentry->blue  = pelem->blue ;
00237         pelem->cmap_idx = cmap_idx ;
00238 LOCAL_DEBUG_OUT( "colormap entry added: %d: #%2.2X%2.2X%2.2X",cmap_idx, pelem->red, pelem->green, pelem->blue );
00239 }
00240 
00241 unsigned int
00242 add_colormap_items( ASSortedColorHash *index, unsigned int start, unsigned int stop, unsigned int quota, unsigned int base, ASColormapEntry *entries )
00243 {
00244         int cmap_idx = 0 ;
00245         unsigned int i ;
00246         if( quota >= index->count_unique )
00247         {
00248                 for( i = start ; i < stop ; i++ )
00249                 {
00250                         register ASMappedColor *pelem = index->buckets[i].head ;
00251                         while ( pelem != NULL )
00252                         {
00253                                 add_colormap_item( &(entries[cmap_idx]), pelem, base++ );
00254                                 index->buckets[i].count -= pelem->count ;
00255                                 ++cmap_idx ;
00256                                 pelem = pelem->next ;
00257                         }
00258                 }
00259         }else
00260         {
00261                 int total = 0 ;
00262                 int subcount = 0 ;
00263                 ASMappedColor *best = NULL ;
00264                 int best_slot = start;
00265                 for( i = start ; i <= stop ; i++ )
00266                         total += index->buckets[i].count ;
00267 
00268                 for( i = start ; i <= stop ; i++ )
00269                 {
00270                         register ASMappedColor *pelem = index->buckets[i].head ;
00271                         while ( pelem != NULL /*&& cmap_idx < quota*/ )
00272                         {
00273                                 if( pelem->cmap_idx < 0 )
00274                                 {
00275                                         if( best == NULL )
00276                                         {
00277                                                 best = pelem ;
00278                                                 best_slot = i ;
00279                                         }else if( best->count < pelem->count )
00280                                         {
00281                                                 best = pelem ;
00282                                                 best_slot = i ;
00283                                         }
00284                                         else if( best->count == pelem->count &&
00285                                                      subcount >= (total>>2) && subcount <= (total>>1)*3 )
00286                                         {
00287                                                 best = pelem ;
00288                                                 best_slot = i ;
00289                                         }
00290                                         subcount += pelem->count*quota ;
00291 LOCAL_DEBUG_OUT( "count = %d subtotal = %d, quota = %d, idx = %d, i = %d, total = %d", pelem->count, subcount, quota, cmap_idx, i, total );
00292                                         if( subcount >= total )
00293                                         {
00294                                                 add_colormap_item( &(entries[cmap_idx]), best, base++ );
00295                                                 index->buckets[best_slot].count -= best->count ;
00296                                                 ++cmap_idx ;
00297                                                 subcount -= total ;
00298                                                 best = NULL ;
00299                                         }
00300                                 }
00301                                 pelem = pelem->next ;
00302                         }
00303                 }
00304         }
00305         return cmap_idx ;
00306 }
00307 
00308 ASColormap *
00309 color_hash2colormap( ASColormap *cmap, unsigned int max_colors )
00310 {
00311         unsigned int cmap_idx = 0 ;
00312         int i ;
00313         ASSortedColorHash *index = NULL ;
00314 
00315         if( cmap == NULL || cmap->hash == NULL )
00316                 return NULL;
00317 
00318         index = cmap->hash ;
00319         cmap->count = MIN(max_colors,index->count_unique);
00320         cmap->entries = safemalloc( cmap->count*sizeof( ASColormapEntry) );
00321         /* now lets go ahead and populate colormap : */
00322         if( index->count_unique <= max_colors )
00323         {
00324                 add_colormap_items( index, 0, index->buckets_num, index->count_unique, 0, cmap->entries);
00325         }else
00326         while( cmap_idx < max_colors )
00327         {
00328                 long total = 0 ;
00329                 long subcount = 0 ;
00330                 int start_slot = 0 ;
00331                 int quota = max_colors-cmap_idx ;
00332 
00333                 for( i = 0 ; i < index->buckets_num ; i++ )
00334                         total += index->buckets[i].count ;
00335 
00336                 for( i = 0 ; i < index->buckets_num ; i++ )
00337                 {
00338                         subcount += index->buckets[i].count*quota ;
00339 LOCAL_DEBUG_OUT( "count = %d, subtotal = %ld, to_add = %ld, idx = %d, i = %d, total = %ld", index->buckets[i].count, subcount, subcount/total, cmap_idx, i, total );
00340                         if( subcount >= total )
00341                         {       /* we need to add subcount/index->count items */
00342                                 int to_add = subcount/total ;
00343                                 if( i == index->buckets_num-1 && to_add < (int)max_colors-(int)cmap_idx )
00344                                         to_add = max_colors-cmap_idx;
00345                                 cmap_idx += add_colormap_items( index, start_slot, i, to_add, cmap_idx, &(cmap->entries[cmap_idx]));
00346                                 subcount %= total;
00347                                 start_slot = i+1;
00348                         }
00349                 }
00350                 if( quota == (int)max_colors-(int)cmap_idx )
00351                         break;
00352         }
00353         fix_colorindex_shortcuts( index );
00354         return cmap;
00355 }
00356 
00357 void destroy_colormap( ASColormap *cmap, Bool reusable )
00358 {
00359         if( cmap )
00360         {
00361                 if( cmap->entries )
00362                         free( cmap->entries );
00363                 if( cmap->hash )
00364                         destroy_colorhash( cmap->hash, False );
00365                 if( !reusable )
00366                         free( cmap );
00367         }
00368 }
00369 
00370 int
00371 get_color_index( ASSortedColorHash *index, CARD32 indexed, unsigned int slot )
00372 {
00373         ASSortedColorBucket *stack ;
00374         ASMappedColor *pnext, *lesser ;
00375         int offset ;
00376 
00377         if( index->last_found == indexed )
00378                 return index->last_idx;
00379         index->last_found = indexed ;
00380 
00381 LOCAL_DEBUG_OUT( "index = %lX(%ld), slot = %d, offset = %d", indexed, indexed, slot, index->buckets[slot].good_offset );
00382         if( (offset = index->buckets[slot].good_offset) != 0 )
00383                 slot += offset ;
00384         stack = &(index->buckets[slot]);
00385 LOCAL_DEBUG_OUT( "first_good = %lX(%ld), last_good = %lX(%ld)", stack->head->indexed, stack->head->indexed, stack->tail->indexed, stack->tail->indexed );
00386         if( offset < 0 || stack->tail->indexed <= indexed )
00387                 return (index->last_idx=stack->tail->cmap_idx);
00388         if( offset > 0 || stack->head->indexed >= indexed )
00389                 return (index->last_idx=stack->head->cmap_idx);
00390 
00391         lesser = stack->head ;
00392         for( pnext = lesser; pnext != NULL ; pnext = pnext->next )
00393         {
00394 LOCAL_DEBUG_OUT( "lesser = %lX(%ld), pnext = %lX(%ld)", lesser->indexed, lesser->indexed, pnext->indexed, pnext->indexed );
00395                         if( pnext->indexed >= indexed )
00396                         {
00397                                 index->last_idx = ( pnext->indexed-indexed > indexed-lesser->indexed )?
00398                                                 lesser->cmap_idx : pnext->cmap_idx ;
00399                                 return index->last_idx;
00400                         }
00401                         lesser = pnext ;
00402         }
00403         return stack->tail->cmap_idx;
00404 }
00405 
00406 int *
00407 colormap_asimage( ASImage *im, ASColormap *cmap, unsigned int max_colors, unsigned int dither, int opaque_threshold )
00408 {
00409         int *mapped_im = NULL;
00410         int buckets_num  = MAX_COLOR_BUCKETS;
00411         ASImageDecoder *imdec ;
00412         CARD32 *a, *r, *g, *b ;
00413         START_TIME(started);
00414 
00415         int *dst ;
00416         unsigned int y ;
00417         register int x ;
00418 
00419         if( im == NULL || cmap == NULL || im->width == 0 )
00420                 return NULL;
00421 
00422         if((imdec = start_image_decoding( NULL /* default visual */ , im,
00423                                               SCL_DO_ALL, 0, 0, im->width, 0, NULL)) == NULL )
00424         {
00425                 LOCAL_DEBUG_OUT( "failed to start image decoding%s", "");
00426                 return NULL;
00427         }
00428 
00429 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
00430 print_asimage( im, ASFLAGS_EVERYTHING, __FUNCTION__, __LINE__ );
00431 #endif
00432 
00433     if( max_colors == 0 )
00434                 max_colors = 256 ;
00435         if( dither == -1 )
00436                 dither = 4 ;
00437         else if( dither >= 8 )
00438                 dither = 7 ;
00439         switch( dither )
00440         {
00441                 case 0 :
00442                 case 1 :
00443                 case 2 : buckets_num = 4096 ;
00444                     break ;
00445                 case 3 :
00446                 case 4 : buckets_num = 1024 ;
00447                     break ;
00448                 case 5 :
00449                 case 6 : buckets_num = 64 ;
00450                     break ;
00451                 case 7 : buckets_num = 8 ;
00452                     break ;
00453         }
00454 
00455         dst = mapped_im = safemalloc( im->width*im->height*sizeof(int));
00456         memset(cmap, 0x00, sizeof(ASColormap));
00457         cmap->hash = safecalloc( 1, sizeof(ASSortedColorHash) );
00458         cmap->hash->buckets = safecalloc( buckets_num, sizeof( ASSortedColorBucket ) );
00459         cmap->hash->buckets_num = buckets_num ;
00460 
00461         a = imdec->buffer.alpha ;
00462         r = imdec->buffer.red ;
00463         g = imdec->buffer.green ;
00464         b = imdec->buffer.blue ;
00465 
00466         for( y = 0 ; y < im->height ; y++ )
00467         {
00468                 int red = 0, green = 0, blue = 0;
00469                 int im_width = im->width ;
00470                 imdec->decode_image_scanline( imdec );
00471                 if( opaque_threshold > 0 && !cmap->has_opaque)
00472                 {
00473                         x = im->width ;
00474                         while( --x >= 0  )
00475                                 if( a[x] != 0x00FF )
00476                                 {
00477                                         cmap->has_opaque = True;
00478                                         break;
00479                                 }
00480                 }
00481                 switch( dither )
00482                 {
00483                         case 0 :
00484                                 for( x = 0; x < im_width ; x++ )
00485                                 {
00486                                         if( (int)a[x] < opaque_threshold )      dst[x] = -1 ;
00487                                         else
00488                                         {
00489                                                 red   = INDEX_SHIFT_RED(r[x]);
00490                                                 green = INDEX_SHIFT_GREEN(g[x]);
00491                                                 blue  = INDEX_SHIFT_BLUE(b[x]);
00492                                                 dst[x] = MAKE_INDEXED_COLOR24(red,green,blue);
00493                                                 add_index_color( cmap->hash, dst[x], ((dst[x]>>12)&0x0FFF), red, green, blue);
00494                                         }
00495                                 }
00496                             break ;
00497                         case 1 :
00498                                 for( x = 0; x < im_width ; x++ )
00499                                 {
00500                                         if( (int)a[x] < opaque_threshold )      dst[x] = -1 ;
00501                                         else
00502                                         {
00503                                                 red   = INDEX_SHIFT_RED(r[x]);
00504                                                 green = INDEX_SHIFT_GREEN(g[x]);
00505                                                 blue  = INDEX_SHIFT_BLUE(b[x]);
00506                                                 dst[x] = MAKE_INDEXED_COLOR21(red,green,blue);
00507                                                 add_index_color( cmap->hash, dst[x], ((dst[x]>>12)&0x0FFF), red, green, blue);
00508                                         }
00509                                 }
00510                             break ;
00511                         case 2 :                           /* 666 */
00512                                 {
00513                                         for( x = 0 ; x < im_width ; ++x )
00514                                         {
00515                                                 red   = INDEX_SHIFT_RED  ((red  +r[x]>255)?255:red+r[x]);
00516                                                 green = INDEX_SHIFT_GREEN((green+g[x]>255)?255:green+g[x]);
00517                                                 blue  = INDEX_SHIFT_BLUE ((blue +b[x]>255)?255:blue+b[x]);
00518                                                 if( (int)a[x] < opaque_threshold )
00519                                                         dst[x] = -1 ;
00520                                                 else
00521                                                 {
00522                                                         dst[x] = MAKE_INDEXED_COLOR18(red,green,blue);
00523                                                         add_index_color( cmap->hash, dst[x], ((dst[x]>>12)&0x0FFF), red, green, blue);
00524                                                 }
00525                                                 red   = INDEX_UNESHIFT_RED(red,1)&0x01 ;
00526                                                 green = INDEX_UNESHIFT_GREEN(green,1)&0x01 ;
00527                                                 blue  = INDEX_UNESHIFT_BLUE(blue,1)  &0x01 ;
00528                                         }
00529                                 }
00530                             break ;
00531                         case 3 :                           /* 555 */
00532                                 {
00533                                         for( x = 0 ; x < im_width ; ++x )
00534                                         {
00535                                                 red   = INDEX_SHIFT_RED  ((red  +r[x]>255)?255:red+r[x]);
00536                                                 green = INDEX_SHIFT_GREEN((green+g[x]>255)?255:green+g[x]);
00537                                                 blue  = INDEX_SHIFT_BLUE ((blue +b[x]>255)?255:blue+b[x]);
00538                         LOCAL_DEBUG_OUT( "alpha(%d,%d) = %ld, threshold = %d", x, y, a[x], opaque_threshold );
00539                                                 if( (int)a[x] < opaque_threshold )
00540                                                         dst[x] = -1 ;
00541                                                 else
00542                                                 {
00543                                                         dst[x] = MAKE_INDEXED_COLOR15(red,green,blue);
00544                                                         add_index_color( cmap->hash, dst[x], ((dst[x]>>14)&0x03FF), red, green, blue);
00545                                                 }
00546                                                 red   = INDEX_UNESHIFT_RED(red,1)    &0x03 ;
00547                                                 green = INDEX_UNESHIFT_GREEN(green,1)&0x03 ;
00548                                                 blue  = INDEX_UNESHIFT_BLUE(blue,1)  &0x03 ;
00549                                         }
00550                                 }
00551                             break ;
00552                         case 4 :                           /* 444 */
00553                                 {
00554                                         for( x = 0 ; x < im_width ; ++x )
00555                                         {
00556                                                 red   = INDEX_SHIFT_RED  ((red  +r[x]>255)?255:red+r[x]);
00557                                                 green = INDEX_SHIFT_GREEN((green+g[x]>255)?255:green+g[x]);
00558                                                 blue  = INDEX_SHIFT_BLUE ((blue +b[x]>255)?255:blue+b[x]);
00559                                                 if( (int)a[x] < opaque_threshold )
00560                                                         dst[x] = -1 ;
00561                                                 else
00562                                                 {
00563                                                         dst[x] = MAKE_INDEXED_COLOR12(red,green,blue);
00564                                                         add_index_color( cmap->hash, dst[x], ((dst[x]>>14)&0x3FF), red, green, blue);
00565                                                 }
00566                                                 red   = INDEX_UNESHIFT_RED(red,1)    &0x07 ;
00567                                                 green = INDEX_UNESHIFT_GREEN(green,1)&0x07 ;
00568                                                 blue  = INDEX_UNESHIFT_BLUE(blue,1)  &0x07 ;
00569                                         }
00570                                 }
00571                             break ;
00572                         case 5 :                           /* 333 */
00573                                 {
00574                                         for( x = 0 ; x < im_width ; ++x )
00575                                         {
00576                                                 red   = INDEX_SHIFT_RED  ((red  +r[x]>255)?255:red+r[x]);
00577                                                 green = INDEX_SHIFT_GREEN((green+g[x]>255)?255:green+g[x]);
00578                                                 blue  = INDEX_SHIFT_BLUE ((blue +b[x]>255)?255:blue+b[x]);
00579                                                 if( (int)a[x] < opaque_threshold )
00580                                                         dst[x] = -1 ;
00581                                                 else
00582                                                 {
00583                                                         dst[x] = MAKE_INDEXED_COLOR9(red,green,blue);
00584                                                         add_index_color( cmap->hash, dst[x], ((dst[x]>>18)&0x03F), red, green, blue);
00585                                                 }
00586                                                 red   = INDEX_UNESHIFT_RED(red,1)&0x0F ;
00587                                                 green = INDEX_UNESHIFT_GREEN(green,1)&0x0F ;
00588                                                 blue  = INDEX_UNESHIFT_BLUE(blue,1)  &0x0F ;
00589                                         }
00590                                 }
00591                             break ;
00592                         case 6 :                           /* 222 */
00593                                 {
00594                                         for( x = 0 ; x < im_width ; ++x )
00595                                         {
00596                                                 red   = INDEX_SHIFT_RED  ((red  +r[x]>255)?255:red+r[x]);
00597                                                 green = INDEX_SHIFT_GREEN((green+g[x]>255)?255:green+g[x]);
00598                                                 blue  = INDEX_SHIFT_BLUE ((blue +b[x]>255)?255:blue+b[x]);
00599                                                 if( (int)a[x] < opaque_threshold )
00600                                                         dst[x] = -1 ;
00601                                                 else
00602                                                 {
00603                                                         dst[x] = MAKE_INDEXED_COLOR6(red,green,blue);
00604                                                         add_index_color( cmap->hash, dst[x], ((dst[x]>>18)&0x03F), red, green, blue);
00605                                                 }
00606                                                 red   = INDEX_UNESHIFT_RED(red,1)&0x01F ;
00607                                                 green = INDEX_UNESHIFT_GREEN(green,1)&0x01F ;
00608                                                 blue  = INDEX_UNESHIFT_BLUE(blue,1)  &0x01F ;
00609                                         }
00610                                 }
00611                             break ;
00612                         case 7 :                           /* 111 */
00613                                 {
00614                                         for( x = 0 ; x < im_width ; ++x )
00615                                         {
00616                                                 red   = INDEX_SHIFT_RED  ((red  +r[x]>255)?255:red+r[x]);
00617                                                 green = INDEX_SHIFT_GREEN((green+g[x]>255)?255:green+g[x]);
00618                                                 blue  = INDEX_SHIFT_BLUE ((blue +b[x]>255)?255:blue+b[x]);
00619                                                 if( (int)a[x] < opaque_threshold )
00620                                                         dst[x] = -1 ;
00621                                                 else
00622                                                 {
00623                                                         dst[x] = MAKE_INDEXED_COLOR3(red,green,blue);
00624                                                         add_index_color( cmap->hash, dst[x], ((dst[x]>>21)&0x07), red, green, blue);
00625                                                 }
00626                                                 red   = INDEX_UNESHIFT_RED(red,1)&0x03F ;
00627                                                 green = INDEX_UNESHIFT_GREEN(green,1)&0x03F ;
00628                                                 blue  = INDEX_UNESHIFT_BLUE(blue,1)  &0x03F ;
00629                                         }
00630                                 }
00631                             break ;
00632                 }
00633                 dst += im_width ;
00634         }
00635         stop_image_decoding( &imdec );
00636         SHOW_TIME("color indexing",started);
00637 
00638 #ifdef LOCAL_DEBUG
00639 check_colorindex_counts( cmap->hash );
00640 #endif
00641 
00642         LOCAL_DEBUG_OUT("building colormap%s","");
00643         color_hash2colormap( cmap, max_colors );
00644         SHOW_TIME("colormap calculation",started);
00645 
00646 #ifdef LOCAL_DEBUG
00647 check_colorindex_counts( cmap->hash );
00648 #endif
00649 
00650         dst = mapped_im ;
00651         for( y = 0 ; y < im->height ; ++y )
00652         {
00653                 switch( dither )
00654                 {
00655                         case 0 :
00656                         case 1 :
00657                         case 2 :
00658                                 for( x = 0 ; x < (int)im->width ; ++x )
00659                 {
00660                     LOCAL_DEBUG_OUT( "Mapping color at (%dx%d) indexed = %X", x, y, dst[x] );
00661                                         if( dst[x] >= 0 )
00662                                                 dst[x] = get_color_index( cmap->hash, dst[x], ((dst[x]>>12)&0x0FFF));
00663                                         else
00664                                                 dst[x] = cmap->count ;
00665                 }
00666                                 break;
00667                         case 3 :
00668                         case 4 :
00669                                 for( x = 0 ; x < (int)im->width ; ++x )
00670                                 {
00671                     LOCAL_DEBUG_OUT( "Mapping color at (%dx%d) indexed = %X", x, y, dst[x] );
00672                     if( dst[x] >= 0 )
00673                                                 dst[x] = get_color_index( cmap->hash, dst[x], ((dst[x]>>14)&0x03FF));
00674                                         else
00675                                                 dst[x] = cmap->count ;
00676                                 }
00677                                 break;
00678                         case 5 :
00679                         case 6 :
00680                                 for( x = 0 ; x < (int)im->width ; ++x )
00681                                         if( dst[x] >= 0 )
00682                                                 dst[x] = get_color_index( cmap->hash, dst[x], ((dst[x]>>18)&0x03F));
00683                                         else
00684                                                 dst[x] = cmap->count ;
00685                             break ;
00686                         case 7 :
00687                                 for( x = 0 ; x < (int)im->width ; ++x )
00688                                         if( dst[x] >= 0 )
00689                                                 dst[x] = get_color_index( cmap->hash, dst[x], ((dst[x]>>21)&0x007));
00690                                         else
00691                                                 dst[x] = cmap->count ;
00692                             break ;
00693                 }
00694                 dst += im->width ;
00695         }
00696 
00697         return mapped_im ;
00698 }
00699 

Generated on Tue Jul 5 14:13:25 2011 for ROOT_528-00b_version by  doxygen 1.5.1