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