X-Git-Url: http://git.imager.perl.org/imager.git/blobdiff_plain/5715f7c346843625ebcd21c2d2d57edd6473cce0..a87997b2f901c06ea67e73d89558aa376f64019b:/image.c diff --git a/image.c b/image.c index dfd6f1cf..03dc6e2c 100644 --- a/image.c +++ b/image.c @@ -1,3 +1,5 @@ +#define IMAGER_NO_CONTEXT + #include "imager.h" #include "imageri.h" @@ -12,7 +14,7 @@ image.c - implements most of the basic functions of Imager and much of the rest i_color *c; c = i_color_new(red, green, blue, alpha); ICL_DESTROY(c); - i = i_img_new(); + i = i_img_8_new(); i_img_destroy(i); // and much more @@ -30,6 +32,8 @@ Some of these functions are internal. =cut */ +im_context_t (*im_get_context)(void) = NULL; + #define XAXIS 0 #define YAXIS 1 #define XYAXIS 2 @@ -37,22 +41,14 @@ Some of these functions are internal. #define minmax(a,b,i) ( ((a>=i)?a: ( (b<=i)?b:i )) ) /* Hack around an obscure linker bug on solaris - probably due to builtin gcc thingies */ -static void fake(void) { ceil(1); } - -static int i_ppix_d(i_img *im, int x, int y, const i_color *val); -static int i_gpix_d(i_img *im, int x, int y, i_color *val); -static int i_glin_d(i_img *im, int l, int r, int y, i_color *vals); -static int i_plin_d(i_img *im, int l, int r, int y, const i_color *vals); -static int i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val); -static int i_gpixf_d(i_img *im, int x, int y, i_fcolor *val); -static int i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals); -static int i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals); -static int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, const int *chans, int chan_count); -static int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, const int *chans, int chan_count); +void i_linker_bug_fake(void) { ceil(1); } /* -=item i_img_alloc() +=item im_img_alloc(aIMCTX) +XX =category Image Implementation +=synopsis i_img *im = im_img_alloc(aIMCTX); +=synopsis i_img *im = i_img_alloc(); Allocates a new i_img structure. @@ -81,25 +77,29 @@ object. */ i_img * -i_img_alloc(void) { +im_img_alloc(pIMCTX) { return mymalloc(sizeof(i_img)); } /* -=item i_img_init(C) +=item im_img_init(aIMCTX, image) +XX =category Image Implementation +=synopsis im_img_init(aIMCTX, im); +=synopsis i_img_init(im); Imager internal initialization of images. -Currently this does very little, in the future it may be used to -support threads, or color profiles. +See L for more information. =cut */ void -i_img_init(i_img *img) { +im_img_init(pIMCTX, i_img *img) { img->im_data = NULL; + img->context = aIMCTX; + im_context_refinc(aIMCTX, "img_init"); } /* @@ -118,15 +118,16 @@ Return a new color object with values passed to it. i_color * ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a) { i_color *cl = NULL; + dIMCTX; - mm_log((1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a)); + im_log((aIMCTX,1,"ICL_new_internal(r %d,g %d,b %d,a %d)\n", r, g, b, a)); - if ( (cl=mymalloc(sizeof(i_color))) == NULL) i_fatal(2,"malloc() error\n"); + if ( (cl=mymalloc(sizeof(i_color))) == NULL) im_fatal(aIMCTX, 2,"malloc() error\n"); cl->rgba.r = r; cl->rgba.g = g; cl->rgba.b = b; cl->rgba.a = a; - mm_log((1,"(%p) <- ICL_new_internal\n",cl)); + im_log((aIMCTX,1,"(%p) <- ICL_new_internal\n",cl)); return cl; } @@ -147,15 +148,16 @@ ICL_new_internal(unsigned char r,unsigned char g,unsigned char b,unsigned char a i_color * ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a) { - mm_log((1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a)); + dIMCTX; + im_log((aIMCTX,1,"ICL_set_internal(cl* %p,r %d,g %d,b %d,a %d)\n",cl,r,g,b,a)); if (cl == NULL) if ( (cl=mymalloc(sizeof(i_color))) == NULL) - i_fatal(2,"malloc() error\n"); + im_fatal(aIMCTX, 2,"malloc() error\n"); cl->rgba.r=r; cl->rgba.g=g; cl->rgba.b=b; cl->rgba.a=a; - mm_log((1,"(%p) <- ICL_set_internal\n",cl)); + im_log((aIMCTX,1,"(%p) <- ICL_set_internal\n",cl)); return cl; } @@ -193,8 +195,9 @@ Dump color information to log - strictly for debugging. void ICL_info(i_color const *cl) { - mm_log((1,"i_color_info(cl* %p)\n",cl)); - mm_log((1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a)); + dIMCTX; + im_log((aIMCTX, 1,"i_color_info(cl* %p)\n",cl)); + im_log((aIMCTX, 1,"i_color_info: (%d,%d,%d,%d)\n",cl->rgba.r,cl->rgba.g,cl->rgba.b,cl->rgba.a)); } /* @@ -209,7 +212,8 @@ Destroy ancillary data for Color object. void ICL_DESTROY(i_color *cl) { - mm_log((1,"ICL_DESTROY(cl* %p)\n",cl)); + dIMCTX; + im_log((aIMCTX, 1,"ICL_DESTROY(cl* %p)\n",cl)); myfree(cl); } @@ -220,15 +224,16 @@ ICL_DESTROY(i_color *cl) { */ i_fcolor *i_fcolor_new(double r, double g, double b, double a) { i_fcolor *cl = NULL; + dIMCTX; - mm_log((1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a)); + im_log((aIMCTX, 1,"i_fcolor_new(r %g,g %g,b %g,a %g)\n", r, g, b, a)); - if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) i_fatal(2,"malloc() error\n"); + if ( (cl=mymalloc(sizeof(i_fcolor))) == NULL) im_fatal(aIMCTX, 2,"malloc() error\n"); cl->rgba.r = r; cl->rgba.g = g; cl->rgba.b = b; cl->rgba.a = a; - mm_log((1,"(%p) <- i_fcolor_new\n",cl)); + im_log((aIMCTX, 1,"(%p) <- i_fcolor_new\n",cl)); return cl; } @@ -242,213 +247,6 @@ void i_fcolor_destroy(i_fcolor *cl) { myfree(cl); } -/* -=item IIM_base_8bit_direct (static) - -A static i_img object used to initialize direct 8-bit per sample images. - -=cut -*/ -static i_img IIM_base_8bit_direct = -{ - 0, /* channels set */ - 0, 0, 0, /* xsize, ysize, bytes */ - ~0U, /* ch_mask */ - i_8_bits, /* bits */ - i_direct_type, /* type */ - 0, /* virtual */ - NULL, /* idata */ - { 0, 0, NULL }, /* tags */ - NULL, /* ext_data */ - - i_ppix_d, /* i_f_ppix */ - i_ppixf_d, /* i_f_ppixf */ - i_plin_d, /* i_f_plin */ - i_plinf_d, /* i_f_plinf */ - i_gpix_d, /* i_f_gpix */ - i_gpixf_d, /* i_f_gpixf */ - i_glin_d, /* i_f_glin */ - i_glinf_d, /* i_f_glinf */ - i_gsamp_d, /* i_f_gsamp */ - i_gsampf_d, /* i_f_gsampf */ - - NULL, /* i_f_gpal */ - NULL, /* i_f_ppal */ - NULL, /* i_f_addcolors */ - NULL, /* i_f_getcolors */ - NULL, /* i_f_colorcount */ - NULL, /* i_f_maxcolors */ - NULL, /* i_f_findcolor */ - NULL, /* i_f_setcolors */ - - NULL, /* i_f_destroy */ - - i_gsamp_bits_fb, - NULL, /* i_f_psamp_bits */ -}; - -/*static void set_8bit_direct(i_img *im) { - im->i_f_ppix = i_ppix_d; - im->i_f_ppixf = i_ppixf_d; - im->i_f_plin = i_plin_d; - im->i_f_plinf = i_plinf_d; - im->i_f_gpix = i_gpix_d; - im->i_f_gpixf = i_gpixf_d; - im->i_f_glin = i_glin_d; - im->i_f_glinf = i_glinf_d; - im->i_f_gpal = NULL; - im->i_f_ppal = NULL; - im->i_f_addcolor = NULL; - im->i_f_getcolor = NULL; - im->i_f_colorcount = NULL; - im->i_f_findcolor = NULL; - }*/ - -/* -=item IIM_new(x, y, ch) - -=item i_img_8_new(x, y, ch) - -=category Image creation/destruction - -=synopsis i_img *img = i_img_8_new(width, height, channels); - -Creates a new image object I pixels wide, and I pixels high with -I channels. - -=cut -*/ - - -i_img * -IIM_new(int x,int y,int ch) { - i_img *im; - mm_log((1,"IIM_new(x %d,y %d,ch %d)\n",x,y,ch)); - - im=i_img_empty_ch(NULL,x,y,ch); - - mm_log((1,"(%p) <- IIM_new\n",im)); - return im; -} - - -void -IIM_DESTROY(i_img *im) { - mm_log((1,"IIM_DESTROY(im* %p)\n",im)); - i_img_destroy(im); - /* myfree(cl); */ -} - -/* -=item i_img_new() - -Create new image reference - notice that this isn't an object yet and -this should be fixed asap. - -=cut -*/ - - -i_img * -i_img_new() { - i_img *im; - - mm_log((1,"i_img_struct()\n")); - - im = i_img_alloc(); - - *im = IIM_base_8bit_direct; - im->xsize=0; - im->ysize=0; - im->channels=3; - im->ch_mask=MAXINT; - im->bytes=0; - im->idata=NULL; - - i_img_init(im); - - mm_log((1,"(%p) <- i_img_struct\n",im)); - return im; -} - -/* -=item i_img_empty(im, x, y) - -Re-new image reference (assumes 3 channels) - - im - Image pointer - x - xsize of destination image - y - ysize of destination image - -**FIXME** what happens if a live image is passed in here? - -Should this just call i_img_empty_ch()? - -=cut -*/ - -i_img * -i_img_empty(i_img *im,int x,int y) { - mm_log((1,"i_img_empty(*im %p, x %d, y %d)\n",im, x, y)); - return i_img_empty_ch(im, x, y, 3); -} - -/* -=item i_img_empty_ch(im, x, y, ch) - -Re-new image reference - - im - Image pointer - x - xsize of destination image - y - ysize of destination image - ch - number of channels - -=cut -*/ - -i_img * -i_img_empty_ch(i_img *im,int x,int y,int ch) { - int bytes; - - mm_log((1,"i_img_empty_ch(*im %p, x %d, y %d, ch %d)\n", im, x, y, ch)); - - if (x < 1 || y < 1) { - i_push_error(0, "Image sizes must be positive"); - return NULL; - } - if (ch < 1 || ch > MAXCHANNELS) { - i_push_errorf(0, "channels must be between 1 and %d", MAXCHANNELS); - return NULL; - } - /* check this multiplication doesn't overflow */ - bytes = x*y*ch; - if (bytes / y / ch != x) { - i_push_errorf(0, "integer overflow calculating image allocation"); - return NULL; - } - - if (im == NULL) - im = i_img_alloc(); - - memcpy(im, &IIM_base_8bit_direct, sizeof(i_img)); - i_tags_new(&im->tags); - im->xsize = x; - im->ysize = y; - im->channels = ch; - im->ch_mask = MAXINT; - im->bytes=bytes; - if ( (im->idata=mymalloc(im->bytes)) == NULL) - i_fatal(2,"malloc() error\n"); - memset(im->idata,0,(size_t)im->bytes); - - im->ext_data = NULL; - - i_img_init(im); - - mm_log((1,"(%p) <- i_img_empty_ch\n",im)); - return im; -} - /* =item i_img_exorcise(im) @@ -461,7 +259,8 @@ Free image data. void i_img_exorcise(i_img *im) { - mm_log((1,"i_img_exorcise(im* 0x%x)\n",im)); + dIMCTXim(im); + im_log((aIMCTX,1,"i_img_exorcise(im* %p)\n",im)); i_tags_destroy(&im->tags); if (im->i_f_destroy) (im->i_f_destroy)(im); @@ -471,10 +270,6 @@ i_img_exorcise(i_img *im) { im->ysize = 0; im->channels = 0; - im->i_f_ppix=i_ppix_d; - im->i_f_gpix=i_gpix_d; - im->i_f_plin=i_plin_d; - im->i_f_glin=i_glin_d; im->ext_data=NULL; } @@ -491,9 +286,11 @@ Destroy an image object void i_img_destroy(i_img *im) { - mm_log((1,"i_img_destroy(im %p)\n",im)); + dIMCTXim(im); + im_log((aIMCTX, 1,"i_img_destroy(im %p)\n",im)); i_img_exorcise(im); if (im) { myfree(im); } + im_context_refdec(aIMCTX, "img_destroy"); } /* @@ -518,11 +315,14 @@ info is an array of 4 integers with the following values: void -i_img_info(i_img *im,int *info) { - mm_log((1,"i_img_info(im 0x%x)\n",im)); +i_img_info(i_img *im, i_img_dim *info) { + dIMCTXim(im); + im_log((aIMCTX,1,"i_img_info(im %p)\n",im)); if (im != NULL) { - mm_log((1,"i_img_info: xsize=%d ysize=%d channels=%d mask=%ud\n",im->xsize,im->ysize,im->channels,im->ch_mask)); - mm_log((1,"i_img_info: idata=0x%d\n",im->idata)); + im_log((aIMCTX,1,"i_img_info: xsize=%" i_DF " ysize=%" i_DF " channels=%d " + "mask=%ud\n", + i_DFc(im->xsize), i_DFc(im->ysize), im->channels,im->ch_mask)); + im_log((aIMCTX,1,"i_img_info: idata=%p\n",im->idata)); info[0] = im->xsize; info[1] = im->ysize; info[2] = im->channels; @@ -538,7 +338,7 @@ i_img_info(i_img *im,int *info) { /* =item i_img_setmask(C, C) =category Image Information -=synopsis // only channel 0 writeable +=synopsis // only channel 0 writable =synopsis i_img_setmask(img, 0x01); Set the image channel mask for C to C. @@ -617,12 +417,15 @@ the target image. pass NULL in C for non transparent i_colors. */ void -i_copyto_trans(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,const i_color *trans) { +i_copyto_trans(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty,const i_color *trans) { i_color pv; - int x,y,t,ttx,tty,tt,ch; + i_img_dim x,y,t,ttx,tty,tt; + int ch; + dIMCTXim(im); - mm_log((1,"i_copyto_trans(im* %p,src 0x%x, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d, trans* 0x%x)\n", - im, src, x1, y1, x2, y2, tx, ty, trans)); + im_log((aIMCTX, 1,"i_copyto_trans(im* %p,src %p, p1(" i_DFp "), p2(" i_DFp "), " + "to(" i_DFp "), trans* %p)\n", + im, src, i_DFcp(x1, y1), i_DFcp(x2, y2), i_DFcp(tx, ty), trans)); if (x2xsize, src->ysize); - mm_log((1,"i_copy(src %p)\n", src)); + im_log((aIMCTX,1,"i_copy(src %p)\n", src)); if (!im) return NULL; @@ -708,10 +512,11 @@ i_copy(i_img *src) { return im; } +/* +http://en.wikipedia.org/wiki/Lanczos_resampling - - +*/ static float @@ -737,23 +542,26 @@ wither the x-axis (I == 0) or the y-axis (I == 1). */ i_img* -i_scaleaxis(i_img *im, float Value, int Axis) { - int hsize, vsize, i, j, k, l, lMax, iEnd, jEnd; - int LanczosWidthFactor; - float *l0, *l1, OldLocation; - int T; - float t; +i_scaleaxis(i_img *im, double Value, int Axis) { + i_img_dim hsize, vsize, i, j, k, l, lMax, iEnd, jEnd; + i_img_dim LanczosWidthFactor; + float *l0, *l1; + double OldLocation; + i_img_dim T; + double t; float F, PictureValue[MAXCHANNELS]; short psave; i_color val,val1,val2; i_img *new_img; + int has_alpha = i_img_has_alpha(im); + int color_chans = i_img_color_channels(im); + dIMCTXim(im); i_clear_error(); - mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis)); - + im_log((aIMCTX, 1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis)); if (Axis == XAXIS) { - hsize = (int)(0.5 + im->xsize * Value); + hsize = (i_img_dim)(0.5 + im->xsize * Value); if (hsize < 1) { hsize = 1; Value = 1.0 / im->xsize; @@ -764,7 +572,7 @@ i_scaleaxis(i_img *im, float Value, int Axis) { iEnd = vsize; } else { hsize = im->xsize; - vsize = (int)(0.5 + im->ysize * Value); + vsize = (i_img_dim)(0.5 + im->ysize * Value); if (vsize < 1) { vsize = 1; @@ -775,23 +583,23 @@ i_scaleaxis(i_img *im, float Value, int Axis) { iEnd = hsize; } - new_img = i_img_empty_ch(NULL, hsize, vsize, im->channels); + new_img = i_img_8_new(hsize, vsize, im->channels); if (!new_img) { i_push_error(0, "cannot create output image"); return NULL; } /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */ - LanczosWidthFactor = (Value >= 1) ? 1 : (int) (1.4/Value); + LanczosWidthFactor = (Value >= 1) ? 1 : (i_img_dim) (1.4/Value); lMax = LanczosWidthFactor << 1; l0 = mymalloc(lMax * sizeof(float)); l1 = mymalloc(lMax * sizeof(float)); for (j=0; jchannels; k++) PictureValue[k] = 0.0; for (l=0; l= im->xsize) ? im->xsize-1 : Mx; i_gpix(im, Mx, i, &val1); i_gpix(im, mx, i, &val2); - - for (k=0; kchannels; k++) { - PictureValue[k] += l1[l] * val1.channel[k]; - PictureValue[k] += l0[lMax-l-1] * val2.channel[k]; + + if (has_alpha) { + i_sample_t alpha1 = val1.channel[color_chans]; + i_sample_t alpha2 = val2.channel[color_chans]; + for (k=0; k < color_chans; k++) { + PictureValue[k] += l1[l] * val1.channel[k] * alpha1 / 255; + PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255; + } + PictureValue[color_chans] += l1[l] * val1.channel[color_chans]; + PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans]; + } + else { + for (k=0; kchannels; k++) { + PictureValue[k] += l1[l] * val1.channel[k]; + PictureValue[k] += l0[lMax-l-1] * val2.channel[k]; + } } } - for(k=0;kchannels;k++) { - psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor)); - val.channel[k]=minmax(0,255,psave); + + if (has_alpha) { + float fa = PictureValue[color_chans] / LanczosWidthFactor; + int alpha = minmax(0, 255, fa+0.5); + if (alpha) { + for (k = 0; k < color_chans; ++k) { + psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa)); + val.channel[k]=minmax(0,255,psave); + } + val.channel[color_chans] = alpha; + } + else { + /* zero alpha, so the pixel has no color */ + for (k = 0; k < im->channels; ++k) + val.channel[k] = 0; + } + } + else { + for(k=0;kchannels;k++) { + psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor)); + val.channel[k]=minmax(0,255,psave); + } } i_ppix(new_img, j, i, &val); } @@ -841,21 +680,50 @@ i_scaleaxis(i_img *im, float Value, int Axis) { for (i=0; ichannels; k++) PictureValue[k] = 0.0; for (l=0; l < lMax; l++) { - int mx = T-lMax+l+1; - int Mx = T+l+1; + i_img_dim mx = T-lMax+l+1; + i_img_dim Mx = T+l+1; mx = (mx < 0) ? 0 : mx; Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx; i_gpix(im, i, Mx, &val1); i_gpix(im, i, mx, &val2); - for (k=0; kchannels; k++) { - PictureValue[k] += l1[l] * val1.channel[k]; - PictureValue[k] += l0[lMax-l-1] * val2.channel[k]; + if (has_alpha) { + i_sample_t alpha1 = val1.channel[color_chans]; + i_sample_t alpha2 = val2.channel[color_chans]; + for (k=0; k < color_chans; k++) { + PictureValue[k] += l1[l] * val1.channel[k] * alpha1 / 255; + PictureValue[k] += l0[lMax-l-1] * val2.channel[k] * alpha2 / 255; + } + PictureValue[color_chans] += l1[l] * val1.channel[color_chans]; + PictureValue[color_chans] += l0[lMax-l-1] * val2.channel[color_chans]; + } + else { + for (k=0; kchannels; k++) { + PictureValue[k] += l1[l] * val1.channel[k]; + PictureValue[k] += l0[lMax-l-1] * val2.channel[k]; + } } } - for (k=0; kchannels; k++) { - psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor)); - val.channel[k] = minmax(0, 255, psave); + if (has_alpha) { + float fa = PictureValue[color_chans] / LanczosWidthFactor; + int alpha = minmax(0, 255, fa+0.5); + if (alpha) { + for (k = 0; k < color_chans; ++k) { + psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor * 255 / fa)); + val.channel[k]=minmax(0,255,psave); + } + val.channel[color_chans] = alpha; + } + else { + for (k = 0; k < im->channels; ++k) + val.channel[k] = 0; + } + } + else { + for(k=0;kchannels;k++) { + psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor)); + val.channel[k]=minmax(0,255,psave); + } } i_ppix(new_img, i, j, &val); } @@ -865,7 +733,7 @@ i_scaleaxis(i_img *im, float Value, int Axis) { myfree(l0); myfree(l1); - mm_log((1,"(%p) <- i_scaleaxis\n", new_img)); + im_log((aIMCTX, 1,"(%p) <- i_scaleaxis\n", new_img)); return new_img; } @@ -883,20 +751,21 @@ nothing is gained by doing it in two steps i_img* -i_scale_nn(i_img *im, float scx, float scy) { +i_scale_nn(i_img *im, double scx, double scy) { - int nxsize,nysize,nx,ny; + i_img_dim nxsize,nysize,nx,ny; i_img *new_img; i_color val; + dIMCTXim(im); - mm_log((1,"i_scale_nn(im 0x%x,scx %.2f,scy %.2f)\n",im,scx,scy)); + im_log((aIMCTX, 1,"i_scale_nn(im %p,scx %.2f,scy %.2f)\n",im,scx,scy)); - nxsize = (int) ((float) im->xsize * scx); + nxsize = (i_img_dim) ((double) im->xsize * scx); if (nxsize < 1) { nxsize = 1; scx = 1.0 / im->xsize; } - nysize = (int) ((float) im->ysize * scy); + nysize = (i_img_dim) ((double) im->ysize * scy); if (nysize < 1) { nysize = 1; scy = 1.0 / im->ysize; @@ -906,11 +775,11 @@ i_scale_nn(i_img *im, float scx, float scy) { new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels); for(ny=0;nytype == i_direct_type) { if (src->bits == 8) { return i_img_empty_ch(NULL, xsize, ysize, src->channels); @@ -971,7 +843,10 @@ For paletted images the equivalent direct type is returned. =cut */ -i_img *i_sametype_chans(i_img *src, int xsize, int ysize, int channels) { +i_img * +i_sametype_chans(i_img *src, i_img_dim xsize, i_img_dim ysize, int channels) { + dIMCTXim(src); + if (src->bits == 8) { return i_img_empty_ch(NULL, xsize, ysize, channels); } @@ -1009,11 +884,12 @@ The operators for this function are defined in L. i_img* i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) { double rx,ry; - int nxsize,nysize,nx,ny; + i_img_dim nxsize,nysize,nx,ny; i_img *new_img; i_color val; + dIMCTXim(im); - mm_log((1,"i_transform(im 0x%x, opx 0x%x, opxl %d, opy 0x%x, opyl %d, parm 0x%x, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen)); + im_log((aIMCTX, 1,"i_transform(im %p, opx %p, opxl %d, opy %p, opyl %d, parm %p, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen)); nxsize = im->xsize; nysize = im->ysize ; @@ -1035,7 +911,7 @@ i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int par i_ppix(new_img,nx,ny,&val); } - mm_log((1,"(0x%x) <- i_transform\n",new_img)); + im_log((aIMCTX, 1,"(%p) <- i_transform\n",new_img)); return new_img; } @@ -1054,17 +930,20 @@ can return zero. float i_img_diff(i_img *im1,i_img *im2) { - int x,y,ch,xb,yb,chb; + i_img_dim x, y, xb, yb; + int ch, chb; float tdiff; i_color val1,val2; + dIMCTXim(im1); - mm_log((1,"i_img_diff(im1 0x%x,im2 0x%x)\n",im1,im2)); + im_log((aIMCTX, 1,"i_img_diff(im1 %p,im2 %p)\n",im1,im2)); xb=(im1->xsizexsize)?im1->xsize:im2->xsize; yb=(im1->ysizeysize)?im1->ysize:im2->ysize; chb=(im1->channelschannels)?im1->channels:im2->channels; - mm_log((1,"i_img_diff: xb=%d xy=%d chb=%d\n",xb,yb,chb)); + im_log((aIMCTX, 1,"i_img_diff: b=(" i_DFp ") chb=%d\n", + i_DFcp(xb,yb), chb)); tdiff=0; for(y=0;yxsizexsize)?im1->xsize:im2->xsize; yb=(im1->ysizeysize)?im1->ysize:im2->ysize; chb=(im1->channelschannels)?im1->channels:im2->channels; - mm_log((1,"i_img_diff: xb=%d xy=%d chb=%d\n",xb,yb,chb)); + im_log((aIMCTX, 1,"i_img_diffd: b(" i_DFp ") chb=%d\n", + i_DFcp(xb, yb), chb)); tdiff=0; for(y=0;yxsizexsize)?im1->xsize:im2->xsize; + yb=(im1->ysizeysize)?im1->ysize:im2->ysize; + chb=(im1->channelschannels)?im1->channels:im2->channels; + + im_log((aIMCTX, 1,"i_img_samef: b(" i_DFp ") chb=%d\n", + i_DFcp(xb, yb), chb)); + + for(y = 0; y < yb; y++) { + for(x = 0; x < xb; x++) { + i_gpixf(im1, x, y, &val1); + i_gpixf(im2, x, y, &val2); + + for(ch = 0; ch < chb; ch++) { + double sdiff = val1.channel[ch] - val2.channel[ch]; + if (fabs(sdiff) > epsilon) { + im_log((aIMCTX, 1,"i_img_samef <- different %g @(" i_DFp ")\n", + sdiff, i_DFcp(x, y))); + return 0; + } + } + } + } + im_log((aIMCTX, 1,"i_img_samef <- same\n")); + + return 1; +} + /* just a tiny demo of haar wavelets */ i_img* i_haar(i_img *im) { - int mx,my; - int fx,fy; - int x,y; - int ch,c; + i_img_dim mx,my; + i_img_dim fx,fy; + i_img_dim x,y; + int ch; i_img *new_img,*new_img2; i_color val1,val2,dval1,dval2; + dIMCTXim(im); mx=im->xsize; my=im->ysize; @@ -1143,7 +1065,6 @@ i_haar(i_img *im) { new_img=i_img_empty_ch(NULL,fx*2,fy*2,im->channels); new_img2=i_img_empty_ch(NULL,fx*2,fy*2,im->channels); - c=0; for(y=0;yxsize; - int ysize = im->ysize; + i_img_dim xsize = im->xsize; + i_img_dim ysize = im->ysize; int samp_cnt = 3 * xsize; if (im->channels >= 3) { @@ -1272,15 +1193,15 @@ hpsort(unsigned int n, unsigned *ra) { int i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) { struct octt *ct; - int x,y; + i_img_dim x,y; int colorcnt; unsigned int *col_usage_it; i_sample_t * samp; int channels[3]; int *samp_chans; - int xsize = im->xsize; - int ysize = im->ysize; + i_img_dim xsize = im->xsize; + i_img_dim ysize = im->ysize; int samp_cnt = 3 * xsize; ct = octt_new(); @@ -1318,388 +1239,6 @@ i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) { /* =back -=head2 8-bit per sample image internal functions - -These are the functions installed in an 8-bit per sample image. - -=over - -=item i_ppix_d(im, x, y, col) - -Internal function. - -This is the function kept in the i_f_ppix member of an i_img object. -It does a normal store of a pixel into the image with range checking. - -Returns 0 if the pixel could be set, -1 otherwise. - -=cut -*/ -static -int -i_ppix_d(i_img *im, int x, int y, const i_color *val) { - int ch; - - if ( x>-1 && xxsize && y>-1 && yysize ) { - for(ch=0;chchannels;ch++) - if (im->ch_mask&(1<idata[(x+y*im->xsize)*im->channels+ch]=val->channel[ch]; - return 0; - } - return -1; /* error was clipped */ -} - -/* -=item i_gpix_d(im, x, y, &col) - -Internal function. - -This is the function kept in the i_f_gpix member of an i_img object. -It does normal retrieval of a pixel from the image with range checking. - -Returns 0 if the pixel could be set, -1 otherwise. - -=cut -*/ -static -int -i_gpix_d(i_img *im, int x, int y, i_color *val) { - int ch; - if (x>-1 && xxsize && y>-1 && yysize) { - for(ch=0;chchannels;ch++) - val->channel[ch]=im->idata[(x+y*im->xsize)*im->channels+ch]; - return 0; - } - for(ch=0;chchannels;ch++) val->channel[ch] = 0; - return -1; /* error was cliped */ -} - -/* -=item i_glin_d(im, l, r, y, vals) - -Reads a line of data from the image, storing the pixels at vals. - -The line runs from (l,y) inclusive to (r,y) non-inclusive - -vals should point at space for (r-l) pixels. - -l should never be less than zero (to avoid confusion about where to -put the pixels in vals). - -Returns the number of pixels copied (eg. if r, l or y is out of range) - -=cut -*/ -static -int -i_glin_d(i_img *im, int l, int r, int y, i_color *vals) { - int ch, count, i; - unsigned char *data; - if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { - if (r > im->xsize) - r = im->xsize; - data = im->idata + (l+y*im->xsize) * im->channels; - count = r - l; - for (i = 0; i < count; ++i) { - for (ch = 0; ch < im->channels; ++ch) - vals[i].channel[ch] = *data++; - } - return count; - } - else { - return 0; - } -} - -/* -=item i_plin_d(im, l, r, y, vals) - -Writes a line of data into the image, using the pixels at vals. - -The line runs from (l,y) inclusive to (r,y) non-inclusive - -vals should point at (r-l) pixels. - -l should never be less than zero (to avoid confusion about where to -get the pixels in vals). - -Returns the number of pixels copied (eg. if r, l or y is out of range) - -=cut -*/ -static -int -i_plin_d(i_img *im, int l, int r, int y, const i_color *vals) { - int ch, count, i; - unsigned char *data; - if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { - if (r > im->xsize) - r = im->xsize; - data = im->idata + (l+y*im->xsize) * im->channels; - count = r - l; - for (i = 0; i < count; ++i) { - for (ch = 0; ch < im->channels; ++ch) { - if (im->ch_mask & (1 << ch)) - *data = vals[i].channel[ch]; - ++data; - } - } - return count; - } - else { - return 0; - } -} - -/* -=item i_ppixf_d(im, x, y, val) - -=cut -*/ -static -int -i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val) { - int ch; - - if ( x>-1 && xxsize && y>-1 && yysize ) { - for(ch=0;chchannels;ch++) - if (im->ch_mask&(1<idata[(x+y*im->xsize)*im->channels+ch] = - SampleFTo8(val->channel[ch]); - } - return 0; - } - return -1; /* error was clipped */ -} - -/* -=item i_gpixf_d(im, x, y, val) - -=cut -*/ -static -int -i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) { - int ch; - if (x>-1 && xxsize && y>-1 && yysize) { - for(ch=0;chchannels;ch++) { - val->channel[ch] = - Sample8ToF(im->idata[(x+y*im->xsize)*im->channels+ch]); - } - return 0; - } - return -1; /* error was cliped */ -} - -/* -=item i_glinf_d(im, l, r, y, vals) - -Reads a line of data from the image, storing the pixels at vals. - -The line runs from (l,y) inclusive to (r,y) non-inclusive - -vals should point at space for (r-l) pixels. - -l should never be less than zero (to avoid confusion about where to -put the pixels in vals). - -Returns the number of pixels copied (eg. if r, l or y is out of range) - -=cut -*/ -static -int -i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) { - int ch, count, i; - unsigned char *data; - if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { - if (r > im->xsize) - r = im->xsize; - data = im->idata + (l+y*im->xsize) * im->channels; - count = r - l; - for (i = 0; i < count; ++i) { - for (ch = 0; ch < im->channels; ++ch) - vals[i].channel[ch] = Sample8ToF(*data++); - } - return count; - } - else { - return 0; - } -} - -/* -=item i_plinf_d(im, l, r, y, vals) - -Writes a line of data into the image, using the pixels at vals. - -The line runs from (l,y) inclusive to (r,y) non-inclusive - -vals should point at (r-l) pixels. - -l should never be less than zero (to avoid confusion about where to -get the pixels in vals). - -Returns the number of pixels copied (eg. if r, l or y is out of range) - -=cut -*/ -static -int -i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals) { - int ch, count, i; - unsigned char *data; - if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { - if (r > im->xsize) - r = im->xsize; - data = im->idata + (l+y*im->xsize) * im->channels; - count = r - l; - for (i = 0; i < count; ++i) { - for (ch = 0; ch < im->channels; ++ch) { - if (im->ch_mask & (1 << ch)) - *data = SampleFTo8(vals[i].channel[ch]); - ++data; - } - } - return count; - } - else { - return 0; - } -} - -/* -=item i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count) - -Reads sample values from im for the horizontal line (l, y) to (r-1,y) -for the channels specified by chans, an array of int with chan_count -elements. - -Returns the number of samples read (which should be (r-l) * bits_set(chan_mask) - -=cut -*/ -static -int -i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, - const int *chans, int chan_count) { - int ch, count, i, w; - unsigned char *data; - - if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { - if (r > im->xsize) - r = im->xsize; - data = im->idata + (l+y*im->xsize) * im->channels; - w = r - l; - count = 0; - - if (chans) { - /* make sure we have good channel numbers */ - for (ch = 0; ch < chan_count; ++ch) { - if (chans[ch] < 0 || chans[ch] >= im->channels) { - i_push_errorf(0, "No channel %d in this image", chans[ch]); - return 0; - } - } - for (i = 0; i < w; ++i) { - for (ch = 0; ch < chan_count; ++ch) { - *samps++ = data[chans[ch]]; - ++count; - } - data += im->channels; - } - } - else { - if (chan_count <= 0 || chan_count > im->channels) { - i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels", - chan_count); - return 0; - } - for (i = 0; i < w; ++i) { - for (ch = 0; ch < chan_count; ++ch) { - *samps++ = data[ch]; - ++count; - } - data += im->channels; - } - } - - return count; - } - else { - return 0; - } -} - -/* -=item i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count) - -Reads sample values from im for the horizontal line (l, y) to (r-1,y) -for the channels specified by chan_mask, where bit 0 is the first -channel. - -Returns the number of samples read (which should be (r-l) * bits_set(chan_mask) - -=cut -*/ -static -int -i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, - const int *chans, int chan_count) { - int ch, count, i, w; - unsigned char *data; - for (ch = 0; ch < chan_count; ++ch) { - if (chans[ch] < 0 || chans[ch] >= im->channels) { - i_push_errorf(0, "No channel %d in this image", chans[ch]); - } - } - if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { - if (r > im->xsize) - r = im->xsize; - data = im->idata + (l+y*im->xsize) * im->channels; - w = r - l; - count = 0; - - if (chans) { - /* make sure we have good channel numbers */ - for (ch = 0; ch < chan_count; ++ch) { - if (chans[ch] < 0 || chans[ch] >= im->channels) { - i_push_errorf(0, "No channel %d in this image", chans[ch]); - return 0; - } - } - for (i = 0; i < w; ++i) { - for (ch = 0; ch < chan_count; ++ch) { - *samps++ = Sample8ToF(data[chans[ch]]); - ++count; - } - data += im->channels; - } - } - else { - if (chan_count <= 0 || chan_count > im->channels) { - i_push_errorf(0, "chan_count %d out of range, must be >0, <= channels", - chan_count); - return 0; - } - for (i = 0; i < w; ++i) { - for (ch = 0; ch < chan_count; ++ch) { - *samps++ = Sample8ToF(data[ch]); - ++count; - } - data += im->channels; - } - } - return count; - } - else { - return 0; - } -} - -/* -=back - =head2 Image method wrappers These functions provide i_fsample_t functions in terms of their @@ -1707,12 +1246,12 @@ i_sample_t versions. =over -=item i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix) +=item i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) =cut */ -int i_ppixf_fp(i_img *im, int x, int y, const i_fcolor *pix) { +int i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix) { i_color temp; int ch; @@ -1723,15 +1262,15 @@ int i_ppixf_fp(i_img *im, int x, int y, const i_fcolor *pix) { } /* -=item i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) +=item i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) =cut */ -int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) { +int i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) { i_color temp; int ch; - if (i_gpix(im, x, y, &temp)) { + if (i_gpix(im, x, y, &temp) == 0) { for (ch = 0; ch < im->channels; ++ch) pix->channel[ch] = Sample8ToF(temp.channel[ch]); return 0; @@ -1741,19 +1280,21 @@ int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) { } /* -=item i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) +=item i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix) =cut */ -int i_plinf_fp(i_img *im, int l, int r, int y, const i_fcolor *pix) { +i_img_dim +i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *pix) { i_color *work; if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; if (r > l) { - int ret; - int i, ch; + i_img_dim ret; + i_img_dim i; + int ch; work = mymalloc(sizeof(i_color) * (r-l)); for (i = 0; i < r-l; ++i) { for (ch = 0; ch < im->channels; ++ch) @@ -1774,19 +1315,21 @@ int i_plinf_fp(i_img *im, int l, int r, int y, const i_fcolor *pix) { } /* -=item i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) +=item i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix) =cut */ -int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) { +i_img_dim +i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix) { i_color *work; if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; if (r > l) { - int ret; - int i, ch; + i_img_dim ret; + i_img_dim i; + int ch; work = mymalloc(sizeof(i_color) * (r-l)); ret = i_plin(im, l, r, y, work); for (i = 0; i < r-l; ++i) { @@ -1807,11 +1350,13 @@ int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) { } /* -=item i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, int *chans, int chan_count) +=item i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, int *chans, int chan_count) =cut */ -int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, + +i_img_dim +i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, int const *chans, int chan_count) { i_sample_t *work; @@ -1819,8 +1364,8 @@ int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, if (r > im->xsize) r = im->xsize; if (r > l) { - int ret; - int i; + i_img_dim ret; + i_img_dim i; work = mymalloc(sizeof(i_sample_t) * (r-l)); ret = i_gsamp(im, l, r, y, work, chans, chan_count); for (i = 0; i < ret; ++i) { @@ -1915,9 +1460,11 @@ int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) { =cut */ -int -i_gsamp_bits_fb(i_img *im, int l, int r, int y, unsigned *samps, +i_img_dim +i_gsamp_bits_fb(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps, const int *chans, int chan_count, int bits) { + dIMCTXim(im); + if (bits < 1 || bits > 32) { i_push_error(0, "Invalid bits, must be 1..32"); return -1; @@ -1925,7 +1472,8 @@ i_gsamp_bits_fb(i_img *im, int l, int r, int y, unsigned *samps, if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { double scale; - int ch, count, i, w; + int ch; + i_img_dim count, i, w; if (bits == 32) scale = 4294967295.0; @@ -1941,7 +1489,7 @@ i_gsamp_bits_fb(i_img *im, int l, int r, int y, unsigned *samps, /* make sure we have good channel numbers */ for (ch = 0; ch < chan_count; ++ch) { if (chans[ch] < 0 || chans[ch] >= im->channels) { - i_push_errorf(0, "No channel %d in this image", chans[ch]); + im_push_errorf(aIMCTX, 0, "No channel %d in this image", chans[ch]); return -1; } } @@ -1977,194 +1525,6 @@ i_gsamp_bits_fb(i_img *im, int l, int r, int y, unsigned *samps, } } -/* -=back - -=head2 Stream reading and writing wrapper functions - -=over - -=item i_gen_reader(i_gen_read_data *info, char *buf, int length) - -Performs general read buffering for file readers that permit reading -to be done through a callback. - -The final callback gets two parameters, a I value, and a I -value, where I is the amount of data that the file library needs -to read, and I is the amount of space available in the buffer -maintained by these functions. - -This means if you need to read from a stream that you don't know the -length of, you can return I bytes, taking the performance hit of -possibly expensive callbacks (eg. back to perl code), or if you are -reading from a stream where it doesn't matter if some data is lost, or -if the total length of the stream is known, you can return I -bytes. - -=cut -*/ - -int -i_gen_reader(i_gen_read_data *gci, char *buf, int length) { - int total; - - if (length < gci->length - gci->cpos) { - /* simplest case */ - memcpy(buf, gci->buffer+gci->cpos, length); - gci->cpos += length; - return length; - } - - total = 0; - memcpy(buf, gci->buffer+gci->cpos, gci->length-gci->cpos); - total += gci->length - gci->cpos; - length -= gci->length - gci->cpos; - buf += gci->length - gci->cpos; - if (length < (int)sizeof(gci->buffer)) { - int did_read; - int copy_size; - while (length - && (did_read = (gci->cb)(gci->userdata, gci->buffer, length, - sizeof(gci->buffer))) > 0) { - gci->cpos = 0; - gci->length = did_read; - - copy_size = i_min(length, gci->length); - memcpy(buf, gci->buffer, copy_size); - gci->cpos += copy_size; - buf += copy_size; - total += copy_size; - length -= copy_size; - } - } - else { - /* just read the rest - too big for our buffer*/ - int did_read; - while ((did_read = (gci->cb)(gci->userdata, buf, length, length)) > 0) { - length -= did_read; - total += did_read; - buf += did_read; - } - } - return total; -} - -/* -=item i_gen_read_data_new(i_read_callback_t cb, char *userdata) - -For use by callback file readers to initialize the reader buffer. - -Allocates, initializes and returns the reader buffer. - -See also L and L. - -=cut -*/ -i_gen_read_data * -i_gen_read_data_new(i_read_callback_t cb, char *userdata) { - i_gen_read_data *self = mymalloc(sizeof(i_gen_read_data)); - self->cb = cb; - self->userdata = userdata; - self->length = 0; - self->cpos = 0; - - return self; -} - -/* -=item i_free_gen_read_data(i_gen_read_data *) - -Cleans up. - -=cut -*/ -void i_free_gen_read_data(i_gen_read_data *self) { - myfree(self); -} - -/* -=item i_gen_writer(i_gen_write_data *info, char const *data, int size) - -Performs write buffering for a callback based file writer. - -Failures are considered fatal, if a write fails then data will be -dropped. - -=cut -*/ -int -i_gen_writer( -i_gen_write_data *self, -char const *data, -int size) -{ - if (self->filledto && self->filledto+size > self->maxlength) { - if (self->cb(self->userdata, self->buffer, self->filledto)) { - self->filledto = 0; - } - else { - self->filledto = 0; - return 0; - } - } - if (self->filledto+size <= self->maxlength) { - /* just save it */ - memcpy(self->buffer+self->filledto, data, size); - self->filledto += size; - return 1; - } - /* doesn't fit - hand it off */ - return self->cb(self->userdata, data, size); -} - -/* -=item i_gen_write_data_new(i_write_callback_t cb, char *userdata, int max_length) - -Allocates and initializes the data structure used by i_gen_writer. - -This should be released with L - -=cut -*/ -i_gen_write_data *i_gen_write_data_new(i_write_callback_t cb, - char *userdata, int max_length) -{ - i_gen_write_data *self = mymalloc(sizeof(i_gen_write_data)); - self->cb = cb; - self->userdata = userdata; - self->maxlength = i_min(max_length, sizeof(self->buffer)); - if (self->maxlength < 0) - self->maxlength = sizeof(self->buffer); - self->filledto = 0; - - return self; -} - -/* -=item i_free_gen_write_data(i_gen_write_data *info, int flush) - -Cleans up the write buffer. - -Will flush any left-over data if I is non-zero. - -Returns non-zero if flush is zero or if info->cb() returns non-zero. - -Return zero only if flush is non-zero and info->cb() returns zero. -ie. if it fails. - -=cut -*/ - -int i_free_gen_write_data(i_gen_write_data *info, int flush) -{ - int result = !flush || - info->filledto == 0 || - info->cb(info->userdata, info->buffer, info->filledto); - myfree(info); - - return result; -} - struct magic_entry { unsigned char *magic; size_t magic_size; @@ -2267,6 +1627,14 @@ i_test_format_probe(io_glue *data, int length) { /* bzip2 compressed */ FORMAT_ENTRY("BZh", "bzip2"), + + /* WEBP + http://code.google.com/speed/webp/docs/riff_container.html */ + FORMAT_ENTRY2("RIFF WEBP", "webp", "xxxx xxxx"), + + /* JPEG 2000 + This might match a little loosely */ + FORMAT_ENTRY("\x00\x00\x00\x0CjP \x0D\x0A\x87\x0A", "jp2"), }; static const struct magic_entry more_formats[] = { /* these were originally both listed as ico, but cur files can @@ -2281,10 +1649,17 @@ i_test_format_probe(io_glue *data, int length) { unsigned char head[18]; ssize_t rc; - io_glue_commit_types(data); - rc = data->readcb(data, head, 18); + rc = i_io_peekn(data, head, 18); if (rc == -1) return NULL; - data->seekcb(data, -rc, SEEK_CUR); +#if 0 + { + int i; + fprintf(stderr, "%d bytes -", (int)rc); + for (i = 0; i < rc; ++i) + fprintf(stderr, " %02x", head[i]); + fprintf(stderr, "\n"); + } +#endif for(i=0; i for +C. For performance of encoders we require monochrome images: @@ -2325,12 +1703,12 @@ be paletted =item * -have a palette of two colors, containing only (0,0,0) and -(255,255,255) in either order. +have a palette of two colors, containing only C<(0,0,0)> and +C<(255,255,255)> in either order. =back -zero_is_white is set to non-zero iff the first palette entry is white. +C is set to non-zero if the first palette entry is white. =cut */ @@ -2382,45 +1760,57 @@ i_img_is_monochrome(i_img *im, int *zero_is_white) { /* =item i_get_file_background(im, &bg) +=category Files + Retrieve the file write background color tag from the image. -If not present, returns black. +If not present, C is set to black. + +Returns 1 if the C tag was found and valid. =cut */ -void +int i_get_file_background(i_img *im, i_color *bg) { - if (!i_tags_get_color(&im->tags, "i_background", 0, bg)) { + int result = i_tags_get_color(&im->tags, "i_background", 0, bg); + if (!result) { /* black default */ bg->channel[0] = bg->channel[1] = bg->channel[2] = 0; } /* always full alpha */ bg->channel[3] = 255; + + return result; } /* =item i_get_file_backgroundf(im, &bg) +=category Files + Retrieve the file write background color tag from the image as a floating point color. Implemented in terms of i_get_file_background(). -If not present, returns black. +If not present, C is set to black. + +Returns 1 if the C tag was found and valid. =cut */ -void +int i_get_file_backgroundf(i_img *im, i_fcolor *fbg) { i_color bg; - - i_get_file_background(im, &bg); + int result = i_get_file_background(im, &bg); fbg->rgba.r = Sample8ToF(bg.rgba.r); fbg->rgba.g = Sample8ToF(bg.rgba.g); fbg->rgba.b = Sample8ToF(bg.rgba.b); fbg->rgba.a = 1.0; + + return result; } /* @@ -2430,7 +1820,7 @@ i_get_file_backgroundf(i_img *im, i_fcolor *fbg) { Arnar M. Hrafnkelsson -Tony Cook +Tony Cook =head1 SEE ALSO