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);
-/*static int i_psamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count);
- static int i_psampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count);*/
+
+/*
+=item i_img_alloc()
+=category Image Implementation
+
+Allocates a new i_img structure.
+
+When implementing a new image type perform the following steps in your
+image object creation function:
+
+=over
+
+=item 1.
+
+allocate the image with i_img_alloc().
+
+=item 2.
+
+initialize any function pointers or other data as needed, you can
+overwrite the whole block if you need to.
+
+=item 3.
+
+initialize Imager's internal data by calling i_img_init() on the image
+object.
+
+=back
+
+=cut
+*/
+
+i_img *
+i_img_alloc(void) {
+ return mymalloc(sizeof(i_img));
+}
+
+/*
+=item i_img_init(img)
+=category Image Implementation
+
+Imager interal initialization of images.
+
+Currently this does very little, in the future it may be used to
+support threads, or color profiles.
+
+=cut
+*/
+
+void
+i_img_init(i_img *img) {
+ img->im_data = NULL;
+}
/*
=item ICL_new_internal(r, g, b, a)
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) {
=item i_img_8_new(x, y, ch)
-=category Image creation
+=category Image creation/destruction
+
+=synopsis i_img *img = i_img_8_new(width, height, channels);
Creates a new image object I<x> pixels wide, and I<y> pixels high with
I<ch> channels.
i_img *im;
mm_log((1,"i_img_struct()\n"));
- if ( (im=mymalloc(sizeof(i_img))) == NULL)
- i_fatal(2,"malloc() error\n");
+
+ im = i_img_alloc();
*im = IIM_base_8bit_direct;
im->xsize=0;
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;
}
if (im == NULL)
- if ( (im=mymalloc(sizeof(i_img))) == NULL)
- i_fatal(2,"malloc() error\n");
+ im = i_img_alloc();
memcpy(im, &IIM_base_8bit_direct, sizeof(i_img));
i_tags_new(&im->tags);
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_destroy(im)
+=item i_img_destroy(img)
-=category Image
-
-Destroy image and free data via exorcise.
+=category Image creation/destruction
+=synopsis i_img_destroy(img)
- im - Image pointer
+Destroy an image object
=cut
*/
}
}
-/*
-=item i_copyto(dest, src, x1, y1, x2, y2, tx, ty)
-
-=category Image
-
-Copies image data from the area (x1,y1)-[x2,y2] in the source image to
-a rectangle the same size with it's top-left corner at (tx,ty) in the
-destination image.
-
-If x1 > x2 or y1 > y2 then the corresponding co-ordinates are swapped.
-
-=cut
-*/
-
-void
-i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty) {
- int x, y, t, ttx, tty;
-
- if (x2<x1) { t=x1; x1=x2; x2=t; }
- if (y2<y1) { t=y1; y1=y2; y2=t; }
- if (tx < 0) {
- /* adjust everything equally */
- x1 += -tx;
- x2 += -tx;
- tx = 0;
- }
- if (ty < 0) {
- y1 += -ty;
- y2 += -ty;
- ty = 0;
- }
- if (x1 >= src->xsize || y1 >= src->ysize)
- return; /* nothing to do */
- if (x2 > src->xsize)
- x2 = src->xsize;
- if (y2 > src->ysize)
- y2 = src->ysize;
- if (x1 == x2 || y1 == y2)
- return; /* nothing to do */
-
- mm_log((1,"i_copyto(im* %p, src %p, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d)\n",
- im, src, x1, y1, x2, y2, tx, ty));
-
- if (im->bits == i_8_bits) {
- i_color *row = mymalloc(sizeof(i_color) * (x2-x1));
- tty = ty;
- for(y=y1; y<y2; y++) {
- ttx = tx;
- i_glin(src, x1, x2, y, row);
- i_plin(im, tx, tx+x2-x1, tty, row);
- tty++;
- }
- myfree(row);
- }
- else {
- i_fcolor pv;
- tty = ty;
- for(y=y1; y<y2; y++) {
- ttx = tx;
- for(x=x1; x<x2; x++) {
- i_gpixf(src, x, y, &pv);
- i_ppixf(im, ttx, tty, &pv);
- ttx++;
- }
- tty++;
- }
- }
-}
-
/*
=item i_copy(src)
}
}
else {
- i_color temp;
- int index;
- int count;
i_palidx *vals;
- /* paletted image */
- i_img_pal_new_low(im, x1, y1, src->channels, i_maxcolors(src));
- /* copy across the palette */
- count = i_colorcount(src);
- for (index = 0; index < count; ++index) {
- i_getcolors(src, index, &temp, 1);
- i_addcolors(im, &temp, 1);
- }
-
vals = mymalloc(sizeof(i_palidx) * x1);
for (y = 0; y < y1; ++y) {
i_gpal(src, 0, x1, y, vals);
i_color val,val1,val2;
i_img *new_img;
+ i_clear_error();
mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
}
new_img = i_img_empty_ch(NULL, 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);
/*
=item i_sametype(i_img *im, int xsize, int ysize)
-=category Image creation
+=category Image creation/destruction
+=synopsis i_img *img = i_sametype(src, width, height);
Returns an image of the same type (sample size, channels, paletted/direct).
/*
=item i_sametype_chans(i_img *im, int xsize, int ysize, int channels)
-=category Image creation
+=category Image creation/destruction
+=synopsis i_img *img = i_sametype_chans(src, width, height, channels);
Returns an image of the same type (sample size).
int channels[3];
int *samp_chans;
i_sample_t * samp;
-
int xsize = im->xsize;
int ysize = im->ysize;
+ int samp_cnt = 3 * xsize;
+
if (im->channels >= 3) {
samp_chans = NULL;
}
channels[0] = channels[1] = channels[2] = 0;
samp_chans = channels;
}
- int samp_cnt = 3 * xsize;
+
ct = octt_new();
samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
* (adapted from the Numerical Recipes)
*/
/* Needed by get_anonymous_color_histo */
-void hpsort(unsigned int n, int *ra) {
+static void
+hpsort(unsigned int n, unsigned *ra) {
unsigned int i,
ir,
j,
* the maxc ;-) and you might want to change the name... */
/* Uses octt_histo */
int
-get_anonymous_color_histo(i_img *im, unsigned int **col_usage) {
- struct octt *ct;
- int x,y,i;
- int colorcnt;
- int maxc = 10000000;
- unsigned int *col_usage_it;
- i_sample_t * samp;
-
- int xsize = im->xsize;
- int ysize = im->ysize;
- int samp_cnt = 3 * xsize;
- ct = octt_new();
-
- samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
-
- colorcnt = 0;
- for(y = 0; y < ysize; ) {
- i_gsamp(im, 0, xsize, y++, samp, NULL, 3);
- for(x = 0; x < samp_cnt; ) {
- colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
- x += 3;
- if (colorcnt > maxc) {
- octt_delete(ct);
- return -1;
- }
- }
+i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) {
+ struct octt *ct;
+ int 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;
+ int samp_cnt = 3 * xsize;
+ ct = octt_new();
+
+ samp = (i_sample_t *) mymalloc( xsize * 3 * sizeof(i_sample_t));
+
+ if (im->channels >= 3) {
+ samp_chans = NULL;
+ }
+ else {
+ channels[0] = channels[1] = channels[2] = 0;
+ samp_chans = channels;
+ }
+
+ colorcnt = 0;
+ for(y = 0; y < ysize; ) {
+ i_gsamp(im, 0, xsize, y++, samp, samp_chans, 3);
+ for(x = 0; x < samp_cnt; ) {
+ colorcnt += octt_add(ct, samp[x], samp[x+1], samp[x+2]);
+ x += 3;
+ if (colorcnt > maxc) {
+ octt_delete(ct);
+ return -1;
+ }
}
- myfree(samp);
- /* Now that we know the number of colours... */
- col_usage_it = *col_usage = (unsigned int *) mymalloc(colorcnt * 2 * sizeof(unsigned int));
- octt_histo(ct, &col_usage_it);
- hpsort(colorcnt, *col_usage);
- octt_delete(ct);
- return colorcnt;
+ }
+ myfree(samp);
+ /* Now that we know the number of colours... */
+ col_usage_it = *col_usage = (unsigned int *) mymalloc(colorcnt * sizeof(unsigned int));
+ octt_histo(ct, &col_usage_it);
+ hpsort(colorcnt, *col_usage);
+ octt_delete(ct);
+ return colorcnt;
}
-
-
/*
=back
}
}
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];
}
}
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]);
/*
=back
+=head2 Fallback handler
+
+=over
+
+=item i_gsamp_bits_fb
+
+=cut
+*/
+
+int
+i_gsamp_bits_fb(i_img *im, int l, int r, int y, unsigned *samps,
+ const int *chans, int chan_count, int bits) {
+ if (bits < 1 || bits > 32) {
+ i_push_error(0, "Invalid bits, must be 1..32");
+ return -1;
+ }
+
+ if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
+ double scale;
+ int ch, count, i, w;
+
+ if (bits == 32)
+ scale = 4294967295.0;
+ else
+ scale = (double)(1 << bits) - 1;
+
+ if (r > im->xsize)
+ r = im->xsize;
+ 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 -1;
+ }
+ }
+ for (i = 0; i < w; ++i) {
+ i_fcolor c;
+ i_gpixf(im, l+i, y, &c);
+ for (ch = 0; ch < chan_count; ++ch) {
+ *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
+ ++count;
+ }
+ }
+ }
+ else {
+ if (chan_count <= 0 || chan_count > im->channels) {
+ i_push_error(0, "Invalid channel count");
+ return -1;
+ }
+ for (i = 0; i < w; ++i) {
+ i_fcolor c;
+ i_gpixf(im, l+i, y, &c);
+ for (ch = 0; ch < chan_count; ++ch) {
+ *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
+ ++count;
+ }
+ }
+ }
+
+ return count;
+ }
+ else {
+ i_push_error(0, "Image position outside of image");
+ return -1;
+ }
+}
+
+/*
+=back
+
=head2 Stream reading and writing wrapper functions
=over
colors[1].rgb.r == 0 &&
colors[1].rgb.g == 0 &&
colors[1].rgb.b == 0) {
- *zero_is_white = 0;
+ *zero_is_white = 1;
return 1;
}
else if (colors[0].rgb.r == 0 &&
colors[1].rgb.r == 255 &&
colors[1].rgb.g == 255 &&
colors[1].rgb.b == 255) {
- *zero_is_white = 1;
+ *zero_is_white = 0;
return 1;
}
}
else if (im->channels == 1) {
if (colors[0].channel[0] == 255 &&
- colors[1].channel[1] == 0) {
- *zero_is_white = 0;
+ colors[1].channel[0] == 0) {
+ *zero_is_white = 1;
return 1;
}
else if (colors[0].channel[0] == 0 &&
- colors[0].channel[0] == 255) {
- *zero_is_white = 1;
+ colors[1].channel[0] == 255) {
+ *zero_is_white = 0;
return 1;
}
}
return 0;
}
+/*
+=item i_get_file_background(im, &bg)
+
+Retrieve the file write background color tag from the image.
+
+If not present, returns black.
+
+=cut
+*/
+
+void
+i_get_file_background(i_img *im, i_color *bg) {
+ if (!i_tags_get_color(&im->tags, "i_background", 0, bg)) {
+ /* black default */
+ bg->channel[0] = bg->channel[1] = bg->channel[2] = 0;
+ }
+ /* always full alpha */
+ bg->channel[3] = 255;
+}
+
+/*
+=item i_get_file_backgroundf(im, &bg)
+
+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.
+
+=cut
+*/
+
+void
+i_get_file_backgroundf(i_img *im, i_fcolor *fbg) {
+ i_color bg;
+
+ 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;
+}
+
/*
=back