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