File indexing completed on 2025-03-09 04:09:53
0001 /* Palette-manipulation functions functions for xcftools 0002 * 0003 * This file was written by Henning Makholm <henning@makholm.net> 0004 * It is hereby in the public domain. 0005 * 0006 * In jurisdictions that do not recognise grants of copyright to the 0007 * public domain: I, the author and (presumably, in those jurisdictions) 0008 * copyright holder, hereby permit anyone to distribute and use this code, 0009 * in source code or binary form, with or without modifications. This 0010 * permission is world-wide and irrevocable. 0011 * 0012 * Of course, I will not be liable for any errors or shortcomings in the 0013 * code, since I give it away without asking any compenstations. 0014 * 0015 * If you use or distribute this code, I would appreciate receiving 0016 * credit for writing it, in whichever way you find proper and customary. 0017 */ 0018 0019 #include "palette.h" 0020 #include <assert.h> 0021 0022 #define HASH_SIZE 1711 0023 /* If I remember correctly, this size hash will be able to handle 0024 * either of 0025 * a) the Netscape cube with intensities 0x00, 0x33, 0x66, 0x99, 0xCC, xFF 0026 * b) the EGA cube with intensities 0x00, 0x55, 0xAA, 0xFF 0027 * c) the "CGA cube" with intensites 0x00, 0x80, 0xFF 0028 * d) a full 256-step grayscale 0029 * without collisions. It will also have a minimal number of collisions 0030 * (4) on a full 16-to-a-side cube with intensities 0031 * 0x00, 0x11, 0x22, ..., 0xDD, 0xEE, 0xFF. 0032 */ 0033 0034 unsigned paletteSize ; 0035 rgba palette[MAX_PALETTE] ; 0036 static int masterhash[HASH_SIZE]; 0037 static int bucketlinks[MAX_PALETTE]; 0038 0039 void 0040 init_palette_hash(void) 0041 { 0042 unsigned i ; 0043 for( i=0; i<HASH_SIZE; i++ ) 0044 masterhash[i] = -1 ; 0045 for( i=0; i<MAX_PALETTE; i++ ) 0046 bucketlinks[i] = -1 ; 0047 paletteSize = 0 ; 0048 } 0049 0050 inline int 0051 lookup_or_intern(rgba color) { 0052 int *target = &masterhash[color % HASH_SIZE]; 0053 while( *target >= 0 ) { 0054 if( palette[*target] == color ) 0055 return *target ; 0056 target = &bucketlinks[*target] ; 0057 } 0058 #if 0 0059 fprintf(stderr,"Palette[%u] = %08x (%u --> %d)\n",paletteSize,color, 0060 color % HASH_SIZE, *target); 0061 #endif 0062 if( paletteSize >= MAX_PALETTE ) 0063 return -1 ; 0064 *target = paletteSize ; 0065 palette[paletteSize] = color ; 0066 return paletteSize++ ; 0067 } 0068 0069 static inline void 0070 unpalettify_row(rgba *row,unsigned ncols) 0071 { 0072 index_t *newrow = (index_t*) row ; 0073 unsigned i ; 0074 for( i=ncols; i--; ) { 0075 row[i] = palette[newrow[i]] ; 0076 } 0077 } 0078 0079 int 0080 palettify_row(rgba *row,unsigned ncols) 0081 { 0082 index_t *newrow = (index_t*)row ; 0083 assert(sizeof(index_t) <= sizeof(rgba)); 0084 unsigned i ; 0085 for( i=0; i<ncols; i++ ) { 0086 int j = lookup_or_intern(row[i]) ; 0087 if( j < 0 ) { 0088 unpalettify_row(row,i); 0089 return 0 ; 0090 } 0091 newrow[i] = j ; 0092 } 0093 return 1 ; 0094 } 0095 0096 int 0097 palettify_rows (rgba *rows[],unsigned ncols,unsigned nlines) 0098 { 0099 unsigned i ; 0100 for( i=0; i<nlines; i++ ) { 0101 if( !palettify_row(rows[i],ncols) ) { 0102 while( i-- ) 0103 unpalettify_row(rows[i],ncols); 0104 return 0 ; 0105 } 0106 } 0107 return 1 ; 0108 } 0109 0110