static acolorhist_vector pam_computeacolorhist(rgbaPixel **apixels, int cols, int rows, int maxacolors, int* acolorsP) { acolorhash_table acht; acolorhist_vector achv; acht = pam_computeacolorhash( apixels, cols, rows, maxacolors, acolorsP ); if ( acht == (acolorhash_table) 0 ) return (acolorhist_vector) 0; achv = pam_acolorhashtoacolorhist( acht, maxacolors ); pam_freeacolorhash( acht ); return achv; }
static acolorhash_table pam_computeacolorhash(rgbaPixel** apixels, int cols, int rows, int maxacolors, int* acolorsP) { acolorhash_table acht; register rgbaPixel* pP; acolorhist_list achl; int col, row, hash; acht = pam_allocacolorhash( ); *acolorsP = 0; /* Go through the entire image, building a hash table of colors. */ for ( row = 0; row < rows; ++row ) for ( col = 0, pP = apixels[row]; col < cols; ++col, ++pP ) { hash = pam_hashapixel( *pP ); for ( achl = acht[hash]; achl != (acolorhist_list) 0; achl = achl->next ) if ( PAM_EQUAL( achl->ch.acolor, *pP ) ) break; if ( achl != (acolorhist_list) 0 ) ++(achl->ch.value); else { if ( ++(*acolorsP) > maxacolors ) { pam_freeacolorhash( acht ); return (acolorhash_table) 0; } achl = (acolorhist_list) malloc( sizeof(struct acolorhist_list_item) ); if ( achl == 0 ) { #ifdef _DEBUG_PNG8 printf( stderr, " out of memory computing hash table\n" ); #endif exit(7); } achl->ch.acolor = *pP; achl->ch.value = 1; achl->next = acht[hash]; acht[hash] = achl; } } return acht; }
int msClassifyRasterBuffer(rasterBufferObj *rb, rasterBufferObj *qrb) { register int ind; unsigned char *outrow,*pQ; register rgbaPixel *pP; acolorhash_table acht; int usehash, row, col; /* ** Step 4: map the colors in the image to their closest match in the ** new colormap, and write 'em out. */ acht = pam_allocacolorhash( ); usehash = 1; for ( row = 0; row < qrb->height; ++row ) { outrow = &(qrb->data.palette.pixels[row*qrb->width]); col = 0; pP = (rgbaPixel*)(&(rb->data.rgba.pixels[row * rb->data.rgba.row_step]));; pQ = outrow; do { /* Check hash table to see if we have already matched this color. */ ind = pam_lookupacolor( acht, pP ); if ( ind == -1 ) { /* No; search acolormap for closest match. */ register int i, r1, g1, b1, a1, r2, g2, b2, a2; register long dist, newdist; r1 = PAM_GETR( *pP ); g1 = PAM_GETG( *pP ); b1 = PAM_GETB( *pP ); a1 = PAM_GETA( *pP ); dist = 2000000000; for ( i = 0; i < qrb->data.palette.num_entries; ++i ) { r2 = PAM_GETR( qrb->data.palette.palette[i] ); g2 = PAM_GETG( qrb->data.palette.palette[i] ); b2 = PAM_GETB( qrb->data.palette.palette[i] ); a2 = PAM_GETA( qrb->data.palette.palette[i] ); /* GRR POSSIBLE BUG */ newdist = ( r1 - r2 ) * ( r1 - r2 ) + /* may overflow? */ ( g1 - g2 ) * ( g1 - g2 ) + ( b1 - b2 ) * ( b1 - b2 ) + ( a1 - a2 ) * ( a1 - a2 ); if ( newdist < dist ) { ind = i; dist = newdist; } } if ( usehash ) { if ( pam_addtoacolorhash( acht, pP, ind ) < 0 ) { usehash = 0; } } } /* *pP = acolormap[ind].acolor; */ *pQ = (unsigned char)ind; ++col; ++pP; ++pQ; } while ( col != rb->width ); } pam_freeacolorhash(acht); return MS_SUCCESS; }