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