X-Git-Url: http://git.imager.perl.org/imager.git/blobdiff_plain/7ac6a2e94b36fac75cf949ea96c0b0dabac88528..53a6bbd48b0530c5e3f013ddd242db8960b79b80:/quant.c diff --git a/quant.c b/quant.c index 2a23b107..dc74bebd 100644 --- a/quant.c +++ b/quant.c @@ -2,7 +2,7 @@ currently only used by gif.c, but maybe we'll support producing 8-bit (or bigger indexed) png files at some point */ -#include "image.h" +#include "imager.h" static void makemap_addi(i_quantize *, i_img **imgs, int count); static void makemap_mediancut(i_quantize *, i_img **imgs, int count); @@ -26,8 +26,20 @@ setcol(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char handle multiple colour maps. */ +/* +=item i_quant_makemap(quant, imgs, count) + +=category Image quantization + +Analyzes the I images in I according to the rules in +I to build a color map (optimal or not depending on +quant->make_colors). + +=cut +*/ + void -quant_makemap(i_quantize *quant, i_img **imgs, int count) { +i_quant_makemap(i_quantize *quant, i_img **imgs, int count) { if (quant->translate == pt_giflib) { /* giflib does it's own color table generation */ @@ -66,19 +78,34 @@ quant_makemap(i_quantize *quant, i_img **imgs, int count) { } } -#ifdef HAVE_LIBGIF -static void translate_giflib(i_quantize *, i_img *, i_palidx *); -#endif static void translate_closest(i_quantize *, i_img *, i_palidx *); static void translate_errdiff(i_quantize *, i_img *, i_palidx *); static void translate_addi(i_quantize *, i_img *, i_palidx *); -/* Quantize the image given the palette in quant. +/* +=item i_quant_translate(quant, img) + +=category Image quantization + +Quantize the image given the palette in quant. - The giflib quantizer ignores the palette. +On success returns a pointer to a memory block of img->xsize * +img->ysize i_palidx entries. + +On failure returns NULL. + +You should call myfree() on the returned block when you're done with +it. + +This function will fail if the supplied palette contains no colors. + +=cut */ -i_palidx *quant_translate(i_quantize *quant, i_img *img) { +i_palidx * +i_quant_translate(i_quantize *quant, i_img *img) { i_palidx *result; + int bytes; + mm_log((1, "quant_translate(quant %p, img %p)\n", quant, img)); /* there must be at least one color in the paletted (though even that @@ -88,7 +115,12 @@ i_palidx *quant_translate(i_quantize *quant, i_img *img) { return NULL; } - result = mymalloc(img->xsize * img->ysize); + bytes = img->xsize * img->ysize; + if (bytes / img->ysize != img->xsize) { + i_push_error(0, "integer overflow calculating memory allocation"); + return NULL; + } + result = mymalloc(bytes); switch (quant->translate) { case pt_closest: @@ -109,162 +141,6 @@ i_palidx *quant_translate(i_quantize *quant, i_img *img) { return result; } -#ifdef HAVE_LIBGIF_THIS_NOT_USED - -#include "gif_lib.h" - -#define GET_RGB(im, x, y, ri, gi, bi, col) \ - i_gpix((im),(x),(y),&(col)); (ri)=(col).rgb.r; \ - if((im)->channels==3) { (bi)=(col).rgb.b; (gi)=(col).rgb.g; } - -static int -quant_replicate(i_img *im, i_palidx *output, i_quantize *quant); - - -/* Use the gif_lib quantization functions to quantize the image */ -static void translate_giflib(i_quantize *quant, i_img *img, i_palidx *out) { - int x,y,ColorMapSize,colours_in; - unsigned long Size; - int i; - - GifByteType *RedBuffer = NULL, *GreenBuffer = NULL, *BlueBuffer = NULL; - GifByteType *RedP, *GreenP, *BlueP; - ColorMapObject *OutputColorMap = NULL; - - i_color col; - - mm_log((1,"translate_giflib(quant %p, img %p, out %p)\n", quant, img, out)); - - /*if (!(im->channels==1 || im->channels==3)) { fprintf(stderr,"Unable to write gif, improper colorspace.\n"); exit(3); }*/ - - ColorMapSize = quant->mc_size; - - Size = ((long) img->xsize) * img->ysize * sizeof(GifByteType); - - - if ((OutputColorMap = MakeMapObject(ColorMapSize, NULL)) == NULL) - m_fatal(0,"Failed to allocate memory for Output colormap."); - /* if ((OutputBuffer = (GifByteType *) mymalloc(im->xsize * im->ysize * sizeof(GifByteType))) == NULL) - m_fatal(0,"Failed to allocate memory for output buffer.");*/ - - /* ******************************************************* */ - /* count the number of colours in the image */ - colours_in=i_count_colors(img, OutputColorMap->ColorCount); - - if(colours_in != -1) { /* less then the number wanted */ - /* so we copy them over as-is */ - mm_log((2,"image has %d colours, which fits in %d. Copying\n", - colours_in,ColorMapSize)); - quant_replicate(img, out, quant); - /* saves the colors, so don't fall through */ - return; - } else { - - mm_log((2,"image has %d colours, more then %d. Quantizing\n",colours_in,ColorMapSize)); - - if (img->channels >= 3) { - if ((RedBuffer = (GifByteType *) mymalloc((unsigned int) Size)) == NULL) { - m_fatal(0,"Failed to allocate memory required, aborted."); - return; - } - if ((GreenBuffer = (GifByteType *) mymalloc((unsigned int) Size)) == NULL) { - m_fatal(0,"Failed to allocate memory required, aborted."); - myfree(RedBuffer); - return; - } - - if ((BlueBuffer = (GifByteType *) mymalloc((unsigned int) Size)) == NULL) { - m_fatal(0,"Failed to allocate memory required, aborted."); - myfree(RedBuffer); - myfree(GreenBuffer); - return; - } - - RedP = RedBuffer; - GreenP = GreenBuffer; - BlueP = BlueBuffer; - - for (y=0; y< img->ysize; y++) for (x=0; x < img->xsize; x++) { - i_gpix(img,x,y,&col); - *RedP++ = col.rgb.r; - *GreenP++ = col.rgb.g; - *BlueP++ = col.rgb.b; - } - - } else { - - if ((RedBuffer = (GifByteType *) mymalloc((unsigned int) Size))==NULL) { - m_fatal(0,"Failed to allocate memory required, aborted."); - return; - } - - GreenBuffer=BlueBuffer=RedBuffer; - RedP = RedBuffer; - for (y=0; y< img->ysize; y++) for (x=0; x < img->xsize; x++) { - i_gpix(img,x,y,&col); - *RedP++ = col.rgb.r; - } - } - - if (QuantizeBuffer(img->xsize, img->ysize, &ColorMapSize, RedBuffer, GreenBuffer, BlueBuffer, - out, OutputColorMap->Colors) == GIF_ERROR) { - mm_log((1,"Error in QuantizeBuffer, unable to write image.\n")); - } - } - - myfree(RedBuffer); - if (img->channels == 3) { myfree(GreenBuffer); myfree(BlueBuffer); } - - /* copy over the color map */ - for (i = 0; i < ColorMapSize; ++i) { - quant->mc_colors[i].rgb.r = OutputColorMap->Colors[i].Red; - quant->mc_colors[i].rgb.g = OutputColorMap->Colors[i].Green; - quant->mc_colors[i].rgb.b = OutputColorMap->Colors[i].Blue; - } - quant->mc_count = ColorMapSize; -} - -static -int -quant_replicate(i_img *im, GifByteType *output, i_quantize *quant) { - int x, y, alloced, r, g=0, b=0, idx ; - i_color col; - - alloced=0; - for(y=0; yysize; y++) { - for(x=0; xxsize; x++) { - - GET_RGB(im, x,y, r,g,b, col); - - for(idx=0; idxmc_colors[idx].rgb.r==r && - quant->mc_colors[idx].rgb.g==g && - quant->mc_colors[idx].rgb.b==b) { - break; - } - } - - if(idx >= alloced) { /* if we haven't already, we */ - idx=alloced++; /* add the colour to the map */ - if(quant->mc_size < alloced) { - mm_log((1,"Tried to allocate more then %d colours.\n", - quant->mc_size)); - return 0; - } - quant->mc_colors[idx].rgb.r=r; - quant->mc_colors[idx].rgb.g=g; - quant->mc_colors[idx].rgb.b=b; - } - *output=idx; /* fill output buffer */ - output++; /* with colour indexes */ - } - } - quant->mc_count = alloced; - return 1; -} - -#endif - static void translate_closest(i_quantize *quant, i_img *img, i_palidx *out) { quant->perturb = 0; translate_addi(quant, img, out); @@ -328,9 +204,11 @@ frand(void) { return rand()/(RAND_MAX+1.0); } +#ifdef NOTEF static int eucl_d(cvec* cv,i_color *cl) { return PWR2(cv->r-cl->channel[0])+PWR2(cv->g-cl->channel[1])+PWR2(cv->b-cl->channel[2]); } +#endif static int @@ -896,7 +774,7 @@ static int distcomp(void const *a, void const *b) { welcome. */ static void hbsetup(i_quantize *quant, hashbox *hb) { - long *dists, mind, maxd, cd; + long *dists, mind, maxd; int cr, cb, cg, hbnum, i; i_color cenc; #ifdef HB_SORT @@ -1306,8 +1184,6 @@ translate_errdiff(i_quantize *quant, i_img *img, i_palidx *out) { int errw; int difftotal; int x, y, dx, dy; - int minr, maxr, ming, maxg, minb, maxb, cr, cg, cb; - i_color find; int bst_idx; CF_VARS; @@ -1590,7 +1466,21 @@ static void transparent_threshold(i_quantize *, i_palidx *, i_img *, i_palidx); static void transparent_errdiff(i_quantize *, i_palidx *, i_img *, i_palidx); static void transparent_ordered(i_quantize *, i_palidx *, i_img *, i_palidx); -void quant_transparent(i_quantize *quant, i_palidx *data, i_img *img, +/* +=item i_quant_transparent(quant, data, img, trans_index) + +=category Image quantization + +Dither the alpha channel on I into the palette indexes in +I. Pixels to be transparent are replaced with I. + +The method used depends on the tr_* members of quant. + +=cut +*/ + +void +i_quant_transparent(i_quantize *quant, i_palidx *data, i_img *img, i_palidx trans_index) { switch (quant->transp) {