• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   cupsImage zoom routines for CUPS.
3  *
4  *   Copyright 2007-2011 by Apple Inc.
5  *   Copyright 1993-2006 by Easy Software Products.
6  *
7  *   These coded instructions, statements, and computer programs are the
8  *   property of Apple Inc. and are protected by Federal copyright
9  *   law.  Distribution and use rights are outlined in the file "COPYING"
10  *   which should have been included with this file.
11  *
12  * Contents:
13  *
14  *   _cupsImageZoomDelete() - Free a zoom record...
15  *   _cupsImageZoomFill()   - Fill a zoom record...
16  *   _cupsImageZoomNew()    - Allocate a pixel zoom record...
17  *   zoom_bilinear()        - Fill a zoom record with image data utilizing
18  *                            bilinear interpolation.
19  *   zoom_nearest()         - Fill a zoom record quickly using nearest-neighbor
20  *                            sampling.
21  */
22 
23 /*
24  * Include necessary headers...
25  */
26 
27 #include "image-private.h"
28 
29 
30 /*
31  * Local functions...
32  */
33 
34 static void	zoom_bilinear(cups_izoom_t *z, int iy);
35 static void	zoom_nearest(cups_izoom_t *z, int iy);
36 
37 
38 /*
39  * '_cupsImageZoomDelete()' - Free a zoom record...
40  */
41 
42 void
_cupsImageZoomDelete(cups_izoom_t * z)43 _cupsImageZoomDelete(cups_izoom_t *z)	/* I - Zoom record to free */
44 {
45   free(z->rows[0]);
46   free(z->rows[1]);
47   free(z->in);
48   free(z);
49 }
50 
51 
52 /*
53  * '_cupsImageZoomFill()' - Fill a zoom record with image data utilizing bilinear
54  *                         interpolation.
55  */
56 
57 void
_cupsImageZoomFill(cups_izoom_t * z,int iy)58 _cupsImageZoomFill(cups_izoom_t *z,	/* I - Zoom record to fill */
59                    int     iy)		/* I - Zoom image row */
60 {
61   switch (z->type)
62   {
63     case CUPS_IZOOM_FAST :
64         zoom_nearest(z, iy);
65 	break;
66 
67     default :
68         zoom_bilinear(z, iy);
69 	break;
70   }
71 }
72 
73 
74 /*
75  * '_cupsImageZoomNew()' - Allocate a pixel zoom record...
76  */
77 
78 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)79 _cupsImageZoomNew(
80     cups_image_t  *img,			/* I - cupsImage to zoom */
81     int           xc0,			/* I - Upper-lefthand corner */
82     int           yc0,			/* I - ... */
83     int           xc1,			/* I - Lower-righthand corner */
84     int           yc1,			/* I - ... */
85     int           xsize,		/* I - Final width of image */
86     int           ysize,		/* I - Final height of image */
87     int           rotated,		/* I - Non-zero if image is rotated 90 degs */
88     cups_iztype_t type)			/* I - Zoom type */
89 {
90   cups_izoom_t	*z;			/* New zoom record */
91   int		flip;			/* Flip on X axis? */
92 
93 
94   if (xsize > CUPS_IMAGE_MAX_WIDTH ||
95       ysize > CUPS_IMAGE_MAX_HEIGHT ||
96       (xc1 - xc0) > CUPS_IMAGE_MAX_WIDTH ||
97       (yc1 - yc0) > CUPS_IMAGE_MAX_HEIGHT)
98     return (NULL);		/* Protect against integer overflow */
99 
100   if ((z = (cups_izoom_t *)calloc(1, sizeof(cups_izoom_t))) == NULL)
101     return (NULL);
102 
103   z->img     = img;
104   z->row     = 0;
105   z->depth   = cupsImageGetDepth(img);
106   z->rotated = rotated;
107   z->type    = type;
108 
109   if (xsize < 0)
110   {
111     flip  = 1;
112     xsize = -xsize;
113   }
114   else
115   {
116     flip  = 0;
117   }
118 
119   if (rotated)
120   {
121     z->xorig   = xc1;
122     z->yorig   = yc0;
123     z->width   = yc1 - yc0 + 1;
124     z->height  = xc1 - xc0 + 1;
125     z->xsize   = xsize;
126     z->ysize   = ysize;
127     z->xmod    = z->width % z->xsize;
128     z->xstep   = z->width / z->xsize;
129     z->xincr   = 1;
130     z->ymod    = z->height % z->ysize;
131     z->ystep   = z->height / z->ysize;
132     z->yincr   = 1;
133     z->instep  = z->xstep * z->depth;
134     z->inincr  = /* z->xincr * */ z->depth; /* z->xincr is always 1 */
135 
136     if (z->width < img->ysize)
137       z->xmax = z->width;
138     else
139       z->xmax = z->width - 1;
140 
141     if (z->height < img->xsize)
142       z->ymax = z->height;
143     else
144       z->ymax = z->height - 1;
145   }
146   else
147   {
148     z->xorig   = xc0;
149     z->yorig   = yc0;
150     z->width   = xc1 - xc0 + 1;
151     z->height  = yc1 - yc0 + 1;
152     z->xsize   = xsize;
153     z->ysize   = ysize;
154     z->xmod    = z->width % z->xsize;
155     z->xstep   = z->width / z->xsize;
156     z->xincr   = 1;
157     z->ymod    = z->height % z->ysize;
158     z->ystep   = z->height / z->ysize;
159     z->yincr   = 1;
160     z->instep  = z->xstep * z->depth;
161     z->inincr  = /* z->xincr * */ z->depth; /* z->xincr is always 1 */
162 
163     if (z->width < img->xsize)
164       z->xmax = z->width;
165     else
166       z->xmax = z->width - 1;
167 
168     if (z->height < img->ysize)
169       z->ymax = z->height;
170     else
171       z->ymax = z->height - 1;
172   }
173 
174   if (flip)
175   {
176     z->instep = -z->instep;
177     z->inincr = -z->inincr;
178   }
179 
180   if ((z->rows[0] = (cups_ib_t *)malloc(z->xsize * z->depth)) == NULL)
181   {
182     free(z);
183     return (NULL);
184   }
185 
186   if ((z->rows[1] = (cups_ib_t *)malloc(z->xsize * z->depth)) == NULL)
187   {
188     free(z->rows[0]);
189     free(z);
190     return (NULL);
191   }
192 
193   if ((z->in = (cups_ib_t *)malloc(z->width * z->depth)) == NULL)
194   {
195     free(z->rows[0]);
196     free(z->rows[1]);
197     free(z);
198     return (NULL);
199   }
200 
201   return (z);
202 }
203 
204 
205 /*
206  * 'zoom_bilinear()' - Fill a zoom record with image data utilizing bilinear
207  *                     interpolation.
208  */
209 
210 static void
zoom_bilinear(cups_izoom_t * z,int iy)211 zoom_bilinear(cups_izoom_t *z,		/* I - Zoom record to fill */
212               int          iy)		/* I - Zoom image row */
213 {
214   cups_ib_t	*r,			/* Row pointer */
215 		*inptr;			/* Pixel pointer */
216   int		xerr0,			/* X error counter */
217 		xerr1;			/* ... */
218   int		ix,
219 		x,
220 		count,
221 		z_depth,
222 		z_xstep,
223 		z_xincr,
224 		z_instep,
225 		z_inincr,
226 		z_xmax,
227 		z_xmod,
228 		z_xsize;
229 
230 
231   if (iy > z->ymax)
232     iy = z->ymax;
233 
234   z->row ^= 1;
235 
236   z_depth  = z->depth;
237   z_xsize  = z->xsize;
238   z_xmax   = z->xmax;
239   z_xmod   = z->xmod;
240   z_xstep  = z->xstep;
241   z_xincr  = z->xincr;
242   z_instep = z->instep;
243   z_inincr = z->inincr;
244 
245   if (z->rotated)
246     cupsImageGetCol(z->img, z->xorig - iy, z->yorig, z->width, z->in);
247   else
248     cupsImageGetRow(z->img, z->xorig, z->yorig + iy, z->width, z->in);
249 
250   if (z_inincr < 0)
251     inptr = z->in + (z->width - 1) * z_depth;
252   else
253     inptr = z->in;
254 
255   for (x = z_xsize, xerr0 = z_xsize, xerr1 = 0, ix = 0, r = z->rows[z->row];
256        x > 0;
257        x --)
258   {
259     if (ix < z_xmax)
260     {
261       for (count = 0; count < z_depth; count ++)
262         *r++ = (inptr[count] * xerr0 + inptr[z_depth + count] * xerr1) / z_xsize;
263     }
264     else
265     {
266       for (count = 0; count < z_depth; count ++)
267         *r++ = inptr[count];
268     }
269 
270     ix    += z_xstep;
271     inptr += z_instep;
272     xerr0 -= z_xmod;
273     xerr1 += z_xmod;
274 
275     if (xerr0 <= 0)
276     {
277       xerr0 += z_xsize;
278       xerr1 -= z_xsize;
279       ix    += z_xincr;
280       inptr += z_inincr;
281     }
282   }
283 }
284 
285 
286 /*
287  * 'zoom_nearest()' - Fill a zoom record quickly using nearest-neighbor
288  *                    sampling.
289  */
290 
291 static void
zoom_nearest(cups_izoom_t * z,int iy)292 zoom_nearest(cups_izoom_t *z,		/* I - Zoom record to fill */
293              int          iy)		/* I - Zoom image row */
294 {
295   cups_ib_t	*r,			/* Row pointer */
296 		*inptr;			/* Pixel pointer */
297   int		xerr0;			/* X error counter */
298   int		ix,
299 		x,
300 		count,
301 		z_depth,
302 		z_xstep,
303 		z_xincr,
304 		z_instep,
305 		z_inincr,
306 		z_xmod,
307 		z_xsize;
308 
309 
310   if (iy > z->ymax)
311     iy = z->ymax;
312 
313   z->row ^= 1;
314 
315   z_depth  = z->depth;
316   z_xsize  = z->xsize;
317   z_xmod   = z->xmod;
318   z_xstep  = z->xstep;
319   z_xincr  = z->xincr;
320   z_instep = z->instep;
321   z_inincr = z->inincr;
322 
323   if (z->rotated)
324     cupsImageGetCol(z->img, z->xorig - iy, z->yorig, z->width, z->in);
325   else
326     cupsImageGetRow(z->img, z->xorig, z->yorig + iy, z->width, z->in);
327 
328   if (z_inincr < 0)
329     inptr = z->in + (z->width - 1) * z_depth;
330   else
331     inptr = z->in;
332 
333   for (x = z_xsize, xerr0 = z_xsize, ix = 0, r = z->rows[z->row];
334        x > 0;
335        x --)
336   {
337     for (count = 0; count < z_depth; count ++)
338       *r++ = inptr[count];
339 
340     ix    += z_xstep;
341     inptr += z_instep;
342     xerr0 -= z_xmod;
343 
344     if (xerr0 <= 0)
345     {
346       xerr0 += z_xsize;
347       ix    += z_xincr;
348       inptr += z_inincr;
349     }
350   }
351 }
352 
353