#include "image-private.h"
static void zoom_bilinear(cups_izoom_t *z, int iy);
static void zoom_nearest(cups_izoom_t *z, int iy);
void
_cupsImageZoomDelete(cups_izoom_t *z)
{
free(z->rows[0]);
free(z->rows[1]);
free(z->in);
free(z);
}
void
_cupsImageZoomFill(cups_izoom_t *z,
int iy)
{
switch (z->type)
{
case CUPS_IZOOM_FAST :
zoom_nearest(z, iy);
break;
default :
zoom_bilinear(z, iy);
break;
}
}
cups_izoom_t *
_cupsImageZoomNew(
cups_image_t *img,
int xc0,
int yc0,
int xc1,
int yc1,
int xsize,
int ysize,
int rotated,
cups_iztype_t type)
{
cups_izoom_t *z;
int flip;
if (xsize > CUPS_IMAGE_MAX_WIDTH ||
ysize > CUPS_IMAGE_MAX_HEIGHT ||
(xc1 - xc0) > CUPS_IMAGE_MAX_WIDTH ||
(yc1 - yc0) > CUPS_IMAGE_MAX_HEIGHT)
return (NULL);
if ((z = (cups_izoom_t *)calloc(1, sizeof(cups_izoom_t))) == NULL)
return (NULL);
z->img = img;
z->row = 0;
z->depth = cupsImageGetDepth(img);
z->rotated = rotated;
z->type = type;
if (xsize < 0)
{
flip = 1;
xsize = -xsize;
}
else
{
flip = 0;
}
if (rotated)
{
z->xorig = xc1;
z->yorig = yc0;
z->width = yc1 - yc0 + 1;
z->height = xc1 - xc0 + 1;
z->xsize = xsize;
z->ysize = ysize;
z->xmod = z->width % z->xsize;
z->xstep = z->width / z->xsize;
z->xincr = 1;
z->ymod = z->height % z->ysize;
z->ystep = z->height / z->ysize;
z->yincr = 1;
z->instep = z->xstep * z->depth;
z->inincr = z->xincr * z->depth;
if (z->width < img->ysize)
z->xmax = z->width;
else
z->xmax = z->width - 1;
if (z->height < img->xsize)
z->ymax = z->height;
else
z->ymax = z->height - 1;
}
else
{
z->xorig = xc0;
z->yorig = yc0;
z->width = xc1 - xc0 + 1;
z->height = yc1 - yc0 + 1;
z->xsize = xsize;
z->ysize = ysize;
z->xmod = z->width % z->xsize;
z->xstep = z->width / z->xsize;
z->xincr = 1;
z->ymod = z->height % z->ysize;
z->ystep = z->height / z->ysize;
z->yincr = 1;
z->instep = z->xstep * z->depth;
z->inincr = z->xincr * z->depth;
if (z->width < img->xsize)
z->xmax = z->width;
else
z->xmax = z->width - 1;
if (z->height < img->ysize)
z->ymax = z->height;
else
z->ymax = z->height - 1;
}
if (flip)
{
z->instep = -z->instep;
z->inincr = -z->inincr;
}
if ((z->rows[0] = (cups_ib_t *)malloc(z->xsize * z->depth)) == NULL)
{
free(z);
return (NULL);
}
if ((z->rows[1] = (cups_ib_t *)malloc(z->xsize * z->depth)) == NULL)
{
free(z->rows[0]);
free(z);
return (NULL);
}
if ((z->in = (cups_ib_t *)malloc(z->width * z->depth)) == NULL)
{
free(z->rows[0]);
free(z->rows[1]);
free(z);
return (NULL);
}
return (z);
}
static void
zoom_bilinear(cups_izoom_t *z,
int iy)
{
cups_ib_t *r,
*inptr;
int xerr0,
xerr1;
int ix,
x,
count,
z_depth,
z_xstep,
z_xincr,
z_instep,
z_inincr,
z_xmax,
z_xmod,
z_xsize;
if (iy > z->ymax)
iy = z->ymax;
z->row ^= 1;
z_depth = z->depth;
z_xsize = z->xsize;
z_xmax = z->xmax;
z_xmod = z->xmod;
z_xstep = z->xstep;
z_xincr = z->xincr;
z_instep = z->instep;
z_inincr = z->inincr;
if (z->rotated)
cupsImageGetCol(z->img, z->xorig - iy, z->yorig, z->width, z->in);
else
cupsImageGetRow(z->img, z->xorig, z->yorig + iy, z->width, z->in);
if (z_inincr < 0)
inptr = z->in + (z->width - 1) * z_depth;
else
inptr = z->in;
for (x = z_xsize, xerr0 = z_xsize, xerr1 = 0, ix = 0, r = z->rows[z->row];
x > 0;
x --)
{
if (ix < z_xmax)
{
for (count = 0; count < z_depth; count ++)
*r++ = (inptr[count] * xerr0 + inptr[z_depth + count] * xerr1) / z_xsize;
}
else
{
for (count = 0; count < z_depth; count ++)
*r++ = inptr[count];
}
ix += z_xstep;
inptr += z_instep;
xerr0 -= z_xmod;
xerr1 += z_xmod;
if (xerr0 <= 0)
{
xerr0 += z_xsize;
xerr1 -= z_xsize;
ix += z_xincr;
inptr += z_inincr;
}
}
}
static void
zoom_nearest(cups_izoom_t *z,
int iy)
{
cups_ib_t *r,
*inptr;
int xerr0;
int ix,
x,
count,
z_depth,
z_xstep,
z_xincr,
z_instep,
z_inincr,
z_xmod,
z_xsize;
if (iy > z->ymax)
iy = z->ymax;
z->row ^= 1;
z_depth = z->depth;
z_xsize = z->xsize;
z_xmod = z->xmod;
z_xstep = z->xstep;
z_xincr = z->xincr;
z_instep = z->instep;
z_inincr = z->inincr;
if (z->rotated)
cupsImageGetCol(z->img, z->xorig - iy, z->yorig, z->width, z->in);
else
cupsImageGetRow(z->img, z->xorig, z->yorig + iy, z->width, z->in);
if (z_inincr < 0)
inptr = z->in + (z->width - 1) * z_depth;
else
inptr = z->in;
for (x = z_xsize, xerr0 = z_xsize, ix = 0, r = z->rows[z->row];
x > 0;
x --)
{
for (count = 0; count < z_depth; count ++)
*r++ = inptr[count];
ix += z_xstep;
inptr += z_instep;
xerr0 -= z_xmod;
if (xerr0 <= 0)
{
xerr0 += z_xsize;
ix += z_xincr;
inptr += z_inincr;
}
}
}