X-Git-Url: http://git.imager.perl.org/imager.git/blobdiff_plain/44d86483e53c24a85195af04197b1c37c4a944e1..e1c0692925:/image.c diff --git a/image.c b/image.c index 5c602d75..bd634ee1 100644 --- a/image.c +++ b/image.c @@ -14,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 @@ -44,8 +44,11 @@ im_context_t (*im_get_context)(void) = NULL; 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. @@ -79,13 +82,15 @@ im_img_alloc(pIMCTX) { } /* -=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 */ @@ -94,6 +99,7 @@ void im_img_init(pIMCTX, i_img *img) { img->im_data = NULL; img->context = aIMCTX; + im_context_refinc(aIMCTX, "img_init"); } /* @@ -112,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; } @@ -141,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; } @@ -187,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)); } /* @@ -203,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); } @@ -214,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; } @@ -248,7 +259,8 @@ Free image data. void i_img_exorcise(i_img *im) { - mm_log((1,"i_img_exorcise(im* %p)\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); @@ -274,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"); } /* @@ -302,22 +316,17 @@ info is an array of 4 integers with the following values: void i_img_info(i_img *im, i_img_dim *info) { - mm_log((1,"i_img_info(im %p)\n",im)); - if (im != NULL) { - mm_log((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)); - mm_log((1,"i_img_info: idata=%p\n",im->idata)); - info[0] = im->xsize; - info[1] = im->ysize; - info[2] = im->channels; - info[3] = im->ch_mask; - } else { - info[0] = 0; - info[1] = 0; - info[2] = 0; - info[3] = 0; - } + dIMCTXim(im); + im_log((aIMCTX,1,"i_img_info(im %p)\n",im)); + + 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; + info[3] = im->ch_mask; } /* @@ -389,6 +398,85 @@ i_img_get_height(i_img *im) { return im->ysize; } +/* +=item i_img_color_model(im) +=category Image Information +=synopsis i_color_model_t cm = i_img_color_model(im); + +Returns the color model for the image. + +A future version of Imager will allow for images with extra channels +beyond gray/rgb and alpha. + +=cut +*/ +i_color_model_t +i_img_color_model(i_img *im) { + return (i_color_model_t)im->channels; +} + +/* +=item i_img_alpha_channel(im, &channel) +=category Image Information +=synopsis int alpha_channel; +=synopsis int has_alpha = i_img_alpha_channel(im, &alpha_channel); + +Work out the alpha channel for an image. + +If the image has an alpha channel, sets C<*channel> to the alpha +channel index and returns non-zero. + +If the image has no alpha channel, returns zero and C<*channel> is not +modified. + +C may be C. + +=cut +*/ + +int +i_img_alpha_channel(i_img *im, int *channel) { + i_color_model_t model = i_img_color_model(im); + switch (model) { + case icm_gray_alpha: + case icm_rgb_alpha: + if (channel) *channel = (int)model - 1; + return 1; + + default: + return 0; + } +} + +/* +=item i_img_color_channels(im) +=category Image Information +=synopsis int color_channels = i_img_color_channels(im); + +Returns the number of color channels in the image. For now this is +always 1 (for grayscale) or 3 (for RGB) but may be 0 in some special +cases in a future release of Imager. + +=cut +*/ + +int +i_img_color_channels(i_img *im) { + i_color_model_t model = i_img_color_model(im); + switch (model) { + case icm_gray_alpha: + case icm_rgb_alpha: + return (int)model - 1; + + case icm_gray: + case icm_rgb: + return (int)model; + + default: + return 0; + } +} + /* =item i_copyto_trans(C, C, C, C, C, C, C, C, C) @@ -406,8 +494,9 @@ i_copyto_trans(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img i_color pv; i_img_dim x,y,t,ttx,tty,tt; int ch; + dIMCTXim(im); - mm_log((1,"i_copyto_trans(im* %p,src %p, p1(" i_DFp "), p2(" i_DFp "), " + 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)); @@ -450,9 +539,10 @@ Returns: i_img * i_img * i_copy(i_img *src) { i_img_dim y, y1, x1; + dIMCTXim(src); i_img *im = i_sametype(src, src->xsize, 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; @@ -541,7 +631,7 @@ i_scaleaxis(i_img *im, double Value, int Axis) { 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 = (i_img_dim)(0.5 + im->xsize * Value); @@ -566,7 +656,7 @@ i_scaleaxis(i_img *im, double 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; @@ -716,7 +806,7 @@ i_scaleaxis(i_img *im, double 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; } @@ -741,7 +831,7 @@ i_scale_nn(i_img *im, double scx, double scy) { i_color val; dIMCTXim(im); - mm_log((1,"i_scale_nn(im %p,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 = (i_img_dim) ((double) im->xsize * scx); if (nxsize < 1) { @@ -762,7 +852,7 @@ i_scale_nn(i_img *im, double scx, double scy) { i_ppix(new_img,nx,ny,&val); } - mm_log((1,"(%p) <- i_scale_nn\n",new_img)); + im_log((aIMCTX, 1,"(%p) <- i_scale_nn\n",new_img)); return new_img; } @@ -872,7 +962,7 @@ i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int par i_color val; dIMCTXim(im); - mm_log((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)); + 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 ; @@ -894,7 +984,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,"(%p) <- i_transform\n",new_img)); + im_log((aIMCTX, 1,"(%p) <- i_transform\n",new_img)); return new_img; } @@ -919,13 +1009,13 @@ i_img_diff(i_img *im1,i_img *im2) { i_color val1,val2; dIMCTXim(im1); - mm_log((1,"i_img_diff(im1 %p,im2 %p)\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: b=(" i_DFp ") chb=%d\n", + im_log((aIMCTX, 1,"i_img_diff: b=(" i_DFp ") chb=%d\n", i_DFcp(xb,yb), chb)); tdiff=0; @@ -935,7 +1025,7 @@ i_img_diff(i_img *im1,i_img *im2) { for(ch=0;chxsizexsize)?im1->xsize:im2->xsize; yb=(im1->ysizeysize)?im1->ysize:im2->ysize; chb=(im1->channelschannels)?im1->channels:im2->channels; - mm_log((1,"i_img_diffd: b(" i_DFp ") chb=%d\n", + im_log((aIMCTX, 1,"i_img_diffd: b(" i_DFp ") chb=%d\n", i_DFcp(xb, yb), chb)); tdiff=0; @@ -980,7 +1071,7 @@ i_img_diffd(i_img *im1,i_img *im2) { tdiff += sdiff * sdiff; } } - mm_log((1,"i_img_diffd <- (%.2f)\n",tdiff)); + im_log((aIMCTX, 1,"i_img_diffd <- (%.2f)\n",tdiff)); return tdiff; } @@ -990,17 +1081,18 @@ i_img_samef(i_img *im1,i_img *im2, double epsilon, char const *what) { i_img_dim x,y,xb,yb; int ch, chb; i_fcolor val1,val2; + dIMCTXim(im1); if (what == NULL) what = "(null)"; - mm_log((1,"i_img_samef(im1 %p,im2 %p, epsilon %g, what '%s')\n", im1, im2, epsilon, what)); + im_log((aIMCTX,1,"i_img_samef(im1 %p,im2 %p, epsilon %g, what '%s')\n", im1, im2, epsilon, what)); 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_samef: b(" i_DFp ") chb=%d\n", + im_log((aIMCTX, 1,"i_img_samef: b(" i_DFp ") chb=%d\n", i_DFcp(xb, yb), chb)); for(y = 0; y < yb; y++) { @@ -1011,14 +1103,14 @@ i_img_samef(i_img *im1,i_img *im2, double epsilon, char const *what) { for(ch = 0; ch < chb; ch++) { double sdiff = val1.channel[ch] - val2.channel[ch]; if (fabs(sdiff) > epsilon) { - mm_log((1,"i_img_samef <- different %g @(" i_DFp ")\n", + im_log((aIMCTX, 1,"i_img_samef <- different %g @(" i_DFp ")\n", sdiff, i_DFcp(x, y))); return 0; } } } } - mm_log((1,"i_img_samef <- same\n")); + im_log((aIMCTX, 1,"i_img_samef <- same\n")); return 1; } @@ -1030,7 +1122,7 @@ i_haar(i_img *im) { i_img_dim mx,my; i_img_dim fx,fy; i_img_dim x,y; - int ch,c; + int ch; i_img *new_img,*new_img2; i_color val1,val2,dval1,dval2; dIMCTXim(im); @@ -1046,7 +1138,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;y maxc) { + if (colorcnt > maxc) { + myfree(samp); octt_delete(ct); return -1; } @@ -1204,7 +1296,8 @@ i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) { colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]); x += 3; if (colorcnt > maxc) { - octt_delete(ct); + octt_delete(ct); + myfree(samp); return -1; } } @@ -1471,7 +1564,7 @@ i_gsamp_bits_fb(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samp /* 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; } } @@ -1617,6 +1710,9 @@ i_test_format_probe(io_glue *data, int length) { /* JPEG 2000 This might match a little loosely */ FORMAT_ENTRY("\x00\x00\x00\x0CjP \x0D\x0A\x87\x0A", "jp2"), + + /* FLIF - Free Lossless Image Format - https://flif.info/spec.html */ + FORMAT_ENTRY("FLIF", "flif") }; static const struct magic_entry more_formats[] = { /* these were originally both listed as ico, but cur files can @@ -1700,7 +1796,8 @@ i_img_is_monochrome(i_img *im, int *zero_is_white) { if (im->type == i_palette_type && i_colorcount(im) == 2) { i_color colors[2]; - i_getcolors(im, 0, colors, 2); + if (!i_getcolors(im, 0, colors, 2)) + return 0; if (im->channels == 3) { if (colors[0].rgb.r == 255 && colors[0].rgb.g == 255 &&