#include "image.h"
izoom_t *
ImageZoomAlloc(image_t *img,
int x0,
int y0,
int x1,
int y1,
int xsize,
int ysize,
int rotated)
{
izoom_t *z;
int flip;
if (xsize > IMAGE_MAX_WIDTH ||
ysize > IMAGE_MAX_HEIGHT ||
(x1 - x0) > IMAGE_MAX_WIDTH ||
(y1 - y0) > IMAGE_MAX_HEIGHT)
return (NULL);
if ((z = (izoom_t *)calloc(1, sizeof(izoom_t))) == NULL)
return (NULL);
z->img = img;
z->row = 0;
z->depth = ImageGetDepth(img);
z->rotated = rotated;
if (xsize < 0)
{
flip = 1;
xsize = -xsize;
}
else
{
flip = 0;
}
if (rotated)
{
z->xorig = x1;
z->yorig = y0;
z->width = y1 - y0 + 1;
z->height = x1 - x0 + 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 = x0;
z->yorig = y0;
z->width = x1 - x0 + 1;
z->height = y1 - y0 + 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] = (ib_t *)malloc(z->xsize * z->depth)) == NULL)
{
free(z);
return (NULL);
}
if ((z->rows[1] = (ib_t *)malloc(z->xsize * z->depth)) == NULL)
{
free(z->rows[0]);
free(z);
return (NULL);
}
if ((z->in = (ib_t *)malloc(z->width * z->depth)) == NULL)
{
free(z->rows[0]);
free(z->rows[1]);
free(z);
return (NULL);
}
return (z);
}
void
ImageZoomFill(izoom_t *z,
int iy)
{
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)
ImageGetCol(z->img, z->xorig - iy, z->yorig, z->width, z->in);
else
ImageGetRow(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;
}
}
}
void
ImageZoomQFill(izoom_t *z,
int iy)
{
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)
ImageGetCol(z->img, z->xorig - iy, z->yorig, z->width, z->in);
else
ImageGetRow(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;
}
}
}
void
ImageZoomFree(izoom_t *z)
{
free(z->rows[0]);
free(z->rows[1]);
free(z->in);
free(z);
}