}
/*
-=item i_img_init(img)
+=item i_img_init(C<img>)
=category Image Implementation
-Imager interal initialization of images.
+Imager internal initialization of images.
Currently this does very little, in the future it may be used to
support threads, or color profiles.
}
/*
-=item i_img_destroy(img)
-
+=item i_img_destroy(C<img>)
+=order 90
=category Image creation/destruction
=synopsis i_img_destroy(img)
}
/*
-=item i_img_setmask(im, ch_mask)
-
+=item i_img_setmask(C<im>, C<ch_mask>)
+=category Image Information
=synopsis // only channel 0 writeable
=synopsis i_img_setmask(img, 0x01);
-Set the image channel mask for I<im> to I<ch_mask>.
+Set the image channel mask for C<im> to C<ch_mask>.
+
+The image channel mask gives some control over which channels can be
+written to in the image.
=cut
*/
/*
-=item i_img_getmask(im)
+=item i_img_getmask(C<im>)
+=category Image Information
+=synopsis int mask = i_img_getmask(img);
-=synopsis mask = i_img_getmask(img);
-
-Get the image channel mask for I<im>.
+Get the image channel mask for C<im>.
=cut
*/
i_img_getmask(i_img *im) { return im->ch_mask; }
/*
-=item i_img_getchannels(im)
-
-=synopsis channels = i_img_getchannels(img);
+=item i_img_getchannels(C<im>)
+=category Image Information
+=synopsis int channels = i_img_getchannels(img);
-Get the number of channels in I<im>.
+Get the number of channels in C<im>.
=cut
*/
i_img_getchannels(i_img *im) { return im->channels; }
/*
-=item i_img_get_width(im)
-
-=synopsis width = i_img_get_width(im);
+=item i_img_get_width(C<im>)
+=category Image Information
+=synopsis i_img_dim width = i_img_get_width(im);
Returns the width in pixels of the image.
}
/*
-=item i_img_get_height(im)
-
-=synopsis height = i_img_get_height(im);
+=item i_img_get_height(C<im>)
+=category Image Information
+=synopsis i_img_dim height = i_img_get_height(im);
Returns the height in pixels of the image.
}
/*
-=item i_copyto_trans(im, src, x1, y1, x2, y2, tx, ty, trans)
+=item i_copyto_trans(C<im>, C<src>, C<x1>, C<y1>, C<x2>, C<y2>, C<tx>, C<ty>, C<trans>)
=category Image
-(x1,y1) (x2,y2) specifies the region to copy (in the source coordinates)
-(tx,ty) specifies the upper left corner for the target image.
-pass NULL in trans for non transparent i_colors.
+(C<x1>,C<y1>) (C<x2>,C<y2>) specifies the region to copy (in the
+source coordinates) (C<tx>,C<ty>) specifies the upper left corner for
+the target image. pass NULL in C<trans> for non transparent i_colors.
=cut
*/
}
/*
-=item i_copy(src)
+=item i_copy(source)
=category Image
-Creates a new image that is a copy of src.
+Creates a new image that is a copy of the image C<source>.
Tags are not copied, only the image data.
}
-/*
-=item i_flipxy(im, axis)
-
-Flips the image inplace around the axis specified.
-Returns 0 if parameters are invalid.
-
- im - Image pointer
- axis - 0 = x, 1 = y, 2 = both
-
-=cut
-*/
-
-undef_int
-i_flipxy(i_img *im, int direction) {
- int x, x2, y, y2, xm, ym;
- int xs = im->xsize;
- int ys = im->ysize;
-
- mm_log((1, "i_flipxy(im %p, direction %d)\n", im, direction ));
-
- if (!im) return 0;
-
- switch (direction) {
- case XAXIS: /* Horizontal flip */
- xm = xs/2;
- ym = ys;
- for(y=0; y<ym; y++) {
- x2 = xs-1;
- for(x=0; x<xm; x++) {
- i_color val1, val2;
- i_gpix(im, x, y, &val1);
- i_gpix(im, x2, y, &val2);
- i_ppix(im, x, y, &val2);
- i_ppix(im, x2, y, &val1);
- x2--;
- }
- }
- break;
- case YAXIS: /* Vertical flip */
- xm = xs;
- ym = ys/2;
- y2 = ys-1;
- for(y=0; y<ym; y++) {
- for(x=0; x<xm; x++) {
- i_color val1, val2;
- i_gpix(im, x, y, &val1);
- i_gpix(im, x, y2, &val2);
- i_ppix(im, x, y, &val2);
- i_ppix(im, x, y2, &val1);
- }
- y2--;
- }
- break;
- case XYAXIS: /* Horizontal and Vertical flip */
- xm = xs/2;
- ym = ys/2;
- y2 = ys-1;
- for(y=0; y<ym; y++) {
- x2 = xs-1;
- for(x=0; x<xm; x++) {
- i_color val1, val2;
- i_gpix(im, x, y, &val1);
- i_gpix(im, x2, y2, &val2);
- i_ppix(im, x, y, &val2);
- i_ppix(im, x2, y2, &val1);
-
- i_gpix(im, x2, y, &val1);
- i_gpix(im, x, y2, &val2);
- i_ppix(im, x2, y, &val2);
- i_ppix(im, x, y2, &val1);
- x2--;
- }
- y2--;
- }
- if (xm*2 != xs) { /* odd number of column */
- mm_log((1, "i_flipxy: odd number of columns\n"));
- x = xm;
- y2 = ys-1;
- for(y=0; y<ym; y++) {
- i_color val1, val2;
- i_gpix(im, x, y, &val1);
- i_gpix(im, x, y2, &val2);
- i_ppix(im, x, y, &val2);
- i_ppix(im, x, y2, &val1);
- y2--;
- }
- }
- if (ym*2 != ys) { /* odd number of rows */
- mm_log((1, "i_flipxy: odd number of rows\n"));
- y = ym;
- x2 = xs-1;
- for(x=0; x<xm; x++) {
- i_color val1, val2;
- i_gpix(im, x, y, &val1);
- i_gpix(im, x2, y, &val2);
- i_ppix(im, x, y, &val2);
- i_ppix(im, x2, y, &val1);
- x2--;
- }
- }
- break;
- default:
- mm_log((1, "i_flipxy: direction is invalid\n" ));
- return 0;
- }
- return 1;
-}
-
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);
i_clear_error();
mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis));
-
if (Axis == XAXIS) {
hsize = (int)(0.5 + im->xsize * Value);
if (hsize < 1) {
i_gpix(im, Mx, i, &val1);
i_gpix(im, mx, i, &val2);
-
- for (k=0; k<im->channels; 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; k<im->channels; k++) {
+ PictureValue[k] += l1[l] * val1.channel[k];
+ PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
+ }
+ }
+ }
+
+ 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;
}
}
- for(k=0;k<im->channels;k++) {
- psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
- val.channel[k]=minmax(0,255,psave);
+ else {
+ for(k=0;k<im->channels;k++) {
+ psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
+ val.channel[k]=minmax(0,255,psave);
+ }
}
i_ppix(new_img, j, i, &val);
}
i_gpix(im, i, Mx, &val1);
i_gpix(im, i, mx, &val2);
- for (k=0; k<im->channels; 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; k<im->channels; k++) {
+ PictureValue[k] += l1[l] * val1.channel[k];
+ PictureValue[k] += l0[lMax-l-1] * val2.channel[k];
+ }
+ }
+ }
+ 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;
}
}
- for (k=0; k<im->channels; k++) {
- psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
- val.channel[k] = minmax(0, 255, psave);
+ else {
+ for(k=0;k<im->channels;k++) {
+ psave = (short)(0.5+(PictureValue[k] / LanczosWidthFactor));
+ val.channel[k]=minmax(0,255,psave);
+ }
}
i_ppix(new_img, i, j, &val);
}
nxsize = (int) ((float) im->xsize * scx);
if (nxsize < 1) {
nxsize = 1;
- scx = 1 / im->xsize;
+ scx = 1.0 / im->xsize;
}
nysize = (int) ((float) im->ysize * scy);
if (nysize < 1) {
nysize = 1;
- scy = 1 / im->ysize;
+ scy = 1.0 / im->ysize;
}
+ im_assert(scx != 0 && scy != 0);
new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels);
}
/*
-=item i_sametype(i_img *im, int xsize, int ysize)
+=item i_sametype(C<im>, C<xsize>, C<ysize>)
=category Image creation/destruction
=synopsis i_img *img = i_sametype(src, width, height);
}
/*
-=item i_sametype_chans(i_img *im, int xsize, int ysize, int channels)
+=item i_sametype_chans(C<im>, C<xsize>, C<ysize>, C<channels>)
=category Image creation/destruction
=synopsis i_img *img = i_sametype_chans(src, width, height, channels);
=cut
*/
+
float
i_img_diff(i_img *im1,i_img *im2) {
int x,y,ch,xb,yb,chb;
return tdiff;
}
+/*
+=item i_img_diffd(im1, im2)
+
+Calculates the sum of the squares of the differences between
+correspoding channels in two images.
+
+If the images are not the same size then only the common area is
+compared, hence even if images are different sizes this function
+can return zero.
+
+This is like i_img_diff() but looks at floating point samples instead.
+
+=cut
+*/
+
+double
+i_img_diffd(i_img *im1,i_img *im2) {
+ int x,y,ch,xb,yb,chb;
+ double tdiff;
+ i_fcolor val1,val2;
+
+ mm_log((1,"i_img_diffd(im1 0x%x,im2 0x%x)\n",im1,im2));
+
+ xb=(im1->xsize<im2->xsize)?im1->xsize:im2->xsize;
+ yb=(im1->ysize<im2->ysize)?im1->ysize:im2->ysize;
+ chb=(im1->channels<im2->channels)?im1->channels:im2->channels;
+
+ mm_log((1,"i_img_diff: xb=%d xy=%d chb=%d\n",xb,yb,chb));
+
+ tdiff=0;
+ 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];
+ tdiff += sdiff * sdiff;
+ }
+ }
+ mm_log((1,"i_img_diffd <- (%.2f)\n",tdiff));
+
+ return tdiff;
+}
+
/* just a tiny demo of haar wavelets */
i_img*
/* 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
/*
=item i_img_is_monochrome(img, &zero_is_white)
+=category Image Information
+
Tests an image to check it meets our monochrome tests.
The idea is that a file writer can use this to test where it should
-write the image in whatever bi-level format it uses, eg. pbm for pnm.
+write the image in whatever bi-level format it uses, eg. C<pbm> for
+C<pnm>.
For performance of encoders we require monochrome images:
=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<zero_is_white> is set to non-zero if the first palette entry is white.
=cut
*/
/*
=item i_get_file_background(im, &bg)
+=category Files
+
Retrieve the file write background color tag from the image.
If not present, returns black.
/*
=item i_get_file_backgroundf(im, &bg)
+=category Files
+
Retrieve the file write background color tag from the image as a
floating point color.