1 /* Copyright (C) 1998, 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: gximage.c,v 1.7 2004/08/04 19:36:12 stefan Exp $ */
18 /* Generic image support */
19 #include "memory_.h"
20 #include "gx.h"
21 #include "gscspace.h"
22 #include "gserrors.h"
23 #include "gsmatrix.h"
24 #include "gsutil.h"
25 #include "gxcolor2.h" /* for lookup map */
26 #include "gxiparam.h"
27 #include "stream.h"
28
29 /* ---------------- Generic image support ---------------- */
30
31 /* Structure descriptors */
32 public_st_gs_image_common();
33 public_st_gs_data_image();
34 public_st_gs_pixel_image();
35
36 /* Initialize the common parts of image structures. */
37 void
gs_image_common_t_init(gs_image_common_t * pic)38 gs_image_common_t_init(gs_image_common_t * pic)
39 {
40 gs_make_identity(&pic->ImageMatrix);
41 }
42 void
gs_data_image_t_init(gs_data_image_t * pim,int num_components)43 gs_data_image_t_init(gs_data_image_t * pim, int num_components)
44 {
45 int i;
46
47 gs_image_common_t_init((gs_image_common_t *) pim);
48 pim->Width = pim->Height = 0;
49 pim->BitsPerComponent = 1;
50 if (num_components >= 0) {
51 for (i = 0; i < num_components * 2; i += 2)
52 pim->Decode[i] = 0, pim->Decode[i + 1] = 1;
53 } else {
54 for (i = 0; i < num_components * -2; i += 2)
55 pim->Decode[i] = 1, pim->Decode[i + 1] = 0;
56 }
57 pim->Interpolate = false;
58 }
59 void
gs_pixel_image_t_init(gs_pixel_image_t * pim,const gs_color_space * color_space)60 gs_pixel_image_t_init(gs_pixel_image_t * pim,
61 const gs_color_space * color_space)
62 {
63 int num_components;
64
65 if (color_space == 0 ||
66 (num_components =
67 gs_color_space_num_components(color_space)) < 0
68 )
69 num_components = 0;
70 gs_data_image_t_init((gs_data_image_t *) pim, num_components);
71 pim->format = gs_image_format_chunky;
72 pim->ColorSpace = color_space;
73 pim->CombineWithColor = false;
74 }
75
76 /* Initialize the common part of an image-processing enumerator. */
77 int
gx_image_enum_common_init(gx_image_enum_common_t * piec,const gs_data_image_t * pic,const gx_image_enum_procs_t * piep,gx_device * dev,int num_components,gs_image_format_t format)78 gx_image_enum_common_init(gx_image_enum_common_t * piec,
79 const gs_data_image_t * pic,
80 const gx_image_enum_procs_t * piep,
81 gx_device * dev, int num_components,
82 gs_image_format_t format)
83 {
84 int bpc = pic->BitsPerComponent;
85 int i;
86
87 piec->image_type = pic->type;
88 piec->procs = piep;
89 piec->dev = dev;
90 piec->id = gs_next_ids(dev->memory, 1);
91 switch (format) {
92 case gs_image_format_chunky:
93 piec->num_planes = 1;
94 piec->plane_depths[0] = bpc * num_components;
95 break;
96 case gs_image_format_component_planar:
97 piec->num_planes = num_components;
98 for (i = 0; i < num_components; ++i)
99 piec->plane_depths[i] = bpc;
100 break;
101 case gs_image_format_bit_planar:
102 piec->num_planes = bpc * num_components;
103 for (i = 0; i < piec->num_planes; ++i)
104 piec->plane_depths[i] = 1;
105 break;
106 default:
107 return_error(gs_error_rangecheck);
108 }
109 for (i = 0; i < piec->num_planes; ++i)
110 piec->plane_widths[i] = pic->Width;
111 return 0;
112 }
113
114 /* Compute the source size of an ordinary image with explicit data. */
115 int
gx_data_image_source_size(const gs_imager_state * pis,const gs_image_common_t * pim,gs_int_point * psize)116 gx_data_image_source_size(const gs_imager_state * pis,
117 const gs_image_common_t * pim, gs_int_point * psize)
118 {
119 const gs_data_image_t *pdi = (const gs_data_image_t *)pim;
120
121 psize->x = pdi->Width;
122 psize->y = pdi->Height;
123 return 0;
124 }
125
126 /* Process the next piece of an image with no source data. */
127 /* This procedure should never be called. */
128 int
gx_no_plane_data(gx_image_enum_common_t * info,const gx_image_plane_t * planes,int height,int * height_used)129 gx_no_plane_data(gx_image_enum_common_t * info,
130 const gx_image_plane_t * planes, int height,
131 int *height_used)
132 {
133 return_error(gs_error_Fatal);
134 }
135
136 /* Clean up after processing an image with no source data. */
137 /* This procedure may be called, but should do nothing. */
138 int
gx_ignore_end_image(gx_image_enum_common_t * info,bool draw_last)139 gx_ignore_end_image(gx_image_enum_common_t * info, bool draw_last)
140 {
141 return 0;
142 }
143
144 /* ---------------- Client procedures ---------------- */
145
146 int
gx_image_data(gx_image_enum_common_t * info,const byte ** plane_data,int data_x,uint raster,int height)147 gx_image_data(gx_image_enum_common_t * info, const byte ** plane_data,
148 int data_x, uint raster, int height)
149 {
150 int num_planes = info->num_planes;
151 gx_image_plane_t planes[gs_image_max_planes];
152 int i;
153
154 #ifdef DEBUG
155 if (num_planes > gs_image_max_planes) {
156 lprintf2("num_planes=%d > gs_image_max_planes=%d!\n",
157 num_planes, gs_image_max_planes);
158 return_error(gs_error_Fatal);
159 }
160 #endif
161 for (i = 0; i < num_planes; ++i) {
162 planes[i].data = plane_data[i];
163 planes[i].data_x = data_x;
164 planes[i].raster = raster;
165 }
166 return gx_image_plane_data(info, planes, height);
167 }
168
169 int
gx_image_plane_data(gx_image_enum_common_t * info,const gx_image_plane_t * planes,int height)170 gx_image_plane_data(gx_image_enum_common_t * info,
171 const gx_image_plane_t * planes, int height)
172 {
173 int ignore_rows_used;
174
175 return gx_image_plane_data_rows(info, planes, height, &ignore_rows_used);
176 }
177
178 int
gx_image_plane_data_rows(gx_image_enum_common_t * info,const gx_image_plane_t * planes,int height,int * rows_used)179 gx_image_plane_data_rows(gx_image_enum_common_t * info,
180 const gx_image_plane_t * planes, int height,
181 int *rows_used)
182 {
183 return info->procs->plane_data(info, planes, height, rows_used);
184 }
185
186 int
gx_image_flush(gx_image_enum_common_t * info)187 gx_image_flush(gx_image_enum_common_t * info)
188 {
189 int (*flush)(gx_image_enum_common_t *) = info->procs->flush;
190
191 return (flush ? flush(info) : 0);
192 }
193
194 bool
gx_image_planes_wanted(const gx_image_enum_common_t * info,byte * wanted)195 gx_image_planes_wanted(const gx_image_enum_common_t *info, byte *wanted)
196 {
197 bool (*planes_wanted)(const gx_image_enum_common_t *, byte *) =
198 info->procs->planes_wanted;
199
200 if (planes_wanted)
201 return planes_wanted(info, wanted);
202 else {
203 memset(wanted, 0xff, info->num_planes);
204 return true;
205 }
206 }
207
208 int
gx_image_end(gx_image_enum_common_t * info,bool draw_last)209 gx_image_end(gx_image_enum_common_t * info, bool draw_last)
210 {
211 return info->procs->end_image(info, draw_last);
212 }
213
214 /* ---------------- Serialization ---------------- */
215
216 /*
217 * Define dummy sput/sget/release procedures for image types that don't
218 * implement these functions.
219 */
220
221 int
gx_image_no_sput(const gs_image_common_t * pic,stream * s,const gs_color_space ** ppcs)222 gx_image_no_sput(const gs_image_common_t *pic, stream *s,
223 const gs_color_space **ppcs)
224 {
225 return_error(gs_error_rangecheck);
226 }
227
228 int
gx_image_no_sget(gs_image_common_t * pic,stream * s,const gs_color_space * pcs)229 gx_image_no_sget(gs_image_common_t *pic, stream *s,
230 const gs_color_space *pcs)
231 {
232 return_error(gs_error_rangecheck);
233 }
234
235 void
gx_image_default_release(gs_image_common_t * pic,gs_memory_t * mem)236 gx_image_default_release(gs_image_common_t *pic, gs_memory_t *mem)
237 {
238 gs_free_object(mem, pic, "gx_image_default_release");
239 }
240
241 #ifdef DEBUG
242 private void
debug_b_print_matrix(const gs_pixel_image_t * pim)243 debug_b_print_matrix(const gs_pixel_image_t *pim)
244 {
245 if_debug6('b', " ImageMatrix=[%g %g %g %g %g %g]\n",
246 pim->ImageMatrix.xx, pim->ImageMatrix.xy,
247 pim->ImageMatrix.yx, pim->ImageMatrix.yy,
248 pim->ImageMatrix.tx, pim->ImageMatrix.ty);
249 }
250 private void
debug_b_print_decode(const gs_pixel_image_t * pim,int num_decode)251 debug_b_print_decode(const gs_pixel_image_t *pim, int num_decode)
252 {
253 if (gs_debug_c('b')) {
254 const char *str = " Decode=[";
255 int i;
256
257 for (i = 0; i < num_decode; str = " ", ++i)
258 dprintf2("%s%g", str, pim->Decode[i]);
259 dputs("]\n");
260 }
261 }
262 #else
263 # define debug_b_print_matrix(pim) DO_NOTHING
264 # define debug_b_print_decode(pim, num_decode) DO_NOTHING
265 #endif
266
267 /* Test whether an image has a default ImageMatrix. */
268 bool
gx_image_matrix_is_default(const gs_data_image_t * pid)269 gx_image_matrix_is_default(const gs_data_image_t *pid)
270 {
271 return (is_xxyy(&pid->ImageMatrix) &&
272 pid->ImageMatrix.xx == pid->Width &&
273 pid->ImageMatrix.yy == -pid->Height &&
274 is_fzero(pid->ImageMatrix.tx) &&
275 pid->ImageMatrix.ty == pid->Height);
276 }
277
278 /* Put a variable-length uint on a stream. */
279 void
sput_variable_uint(stream * s,uint w)280 sput_variable_uint(stream *s, uint w)
281 {
282 for (; w > 0x7f; w >>= 7)
283 sputc(s, (byte)(w | 0x80));
284 sputc(s, (byte)w);
285 }
286
287 /*
288 * Write generic pixel image parameters. The format is the following,
289 * encoded as a variable-length uint in the usual way:
290 * xxxFEDCCBBBBA
291 * A = 0 if standard ImageMatrix, 1 if explicit ImageMatrix
292 * BBBB = BitsPerComponent - 1
293 * CC = format
294 * D = 0 if standard (0..1) Decode, 1 if explicit Decode
295 * E = Interpolate
296 * F = CombineWithColor
297 * xxx = extra information from caller
298 */
299 #define PI_ImageMatrix 0x001
300 #define PI_BPC_SHIFT 1
301 #define PI_BPC_MASK 0xf
302 #define PI_FORMAT_SHIFT 5
303 #define PI_FORMAT_MASK 0x3
304 #define PI_Decode 0x080
305 #define PI_Interpolate 0x100
306 #define PI_CombineWithColor 0x200
307 #define PI_BITS 10
308 /*
309 * Width, encoded as a variable-length uint
310 * Height, encoded ditto
311 * ImageMatrix (if A = 1), per gs_matrix_store/fetch
312 * Decode (if D = 1): blocks of up to 4 components
313 * aabbccdd, where each xx is decoded as:
314 * 00 = default, 01 = swapped default,
315 * 10 = (0,V), 11 = (U,V)
316 * non-defaulted components (up to 8 floats)
317 */
318 int
gx_pixel_image_sput(const gs_pixel_image_t * pim,stream * s,const gs_color_space ** ppcs,int extra)319 gx_pixel_image_sput(const gs_pixel_image_t *pim, stream *s,
320 const gs_color_space **ppcs, int extra)
321 {
322 const gs_color_space *pcs = pim->ColorSpace;
323 int bpc = pim->BitsPerComponent;
324 int num_components = gs_color_space_num_components(pcs);
325 int num_decode;
326 uint control = extra << PI_BITS;
327 float decode_default_1 = 1;
328 int i;
329 uint ignore;
330
331 /* Construct the control word. */
332
333 if (!gx_image_matrix_is_default((const gs_data_image_t *)pim))
334 control |= PI_ImageMatrix;
335 switch (pim->format) {
336 case gs_image_format_chunky:
337 case gs_image_format_component_planar:
338 switch (bpc) {
339 case 1: case 2: case 4: case 8: case 12: break;
340 default: return_error(gs_error_rangecheck);
341 }
342 break;
343 case gs_image_format_bit_planar:
344 if (bpc < 1 || bpc > 8)
345 return_error(gs_error_rangecheck);
346 }
347 control |= (bpc - 1) << PI_BPC_SHIFT;
348 control |= pim->format << PI_FORMAT_SHIFT;
349 num_decode = num_components * 2;
350 if (gs_color_space_get_index(pcs) == gs_color_space_index_Indexed)
351 decode_default_1 = (float)pcs->params.indexed.hival;
352 for (i = 0; i < num_decode; ++i)
353 if (pim->Decode[i] != DECODE_DEFAULT(i, decode_default_1)) {
354 control |= PI_Decode;
355 break;
356 }
357 if (pim->Interpolate)
358 control |= PI_Interpolate;
359 if (pim->CombineWithColor)
360 control |= PI_CombineWithColor;
361
362 /* Write the encoding on the stream. */
363
364 if_debug3('b', "[b]put control=0x%x, Width=%d, Height=%d\n",
365 control, pim->Width, pim->Height);
366 sput_variable_uint(s, control);
367 sput_variable_uint(s, (uint)pim->Width);
368 sput_variable_uint(s, (uint)pim->Height);
369 if (control & PI_ImageMatrix) {
370 debug_b_print_matrix(pim);
371 sput_matrix(s, &pim->ImageMatrix);
372 }
373 if (control & PI_Decode) {
374 int i;
375 uint dflags = 1;
376 float decode[8];
377 int di = 0;
378
379 debug_b_print_decode(pim, num_decode);
380 for (i = 0; i < num_decode; i += 2) {
381 float u = pim->Decode[i], v = pim->Decode[i + 1];
382 float dv = DECODE_DEFAULT(i + 1, decode_default_1);
383
384 if (dflags >= 0x100) {
385 sputc(s, (byte)(dflags & 0xff));
386 sputs(s, (const byte *)decode, di * sizeof(float), &ignore);
387 dflags = 1;
388 di = 0;
389 }
390 dflags <<= 2;
391 if (u == 0 && v == dv)
392 DO_NOTHING;
393 else if (u == dv && v == 0)
394 dflags += 1;
395 else {
396 if (u != 0) {
397 dflags++;
398 decode[di++] = u;
399 }
400 dflags += 2;
401 decode[di++] = v;
402 }
403 }
404 sputc(s, (byte)((dflags << (8 - num_decode)) & 0xff));
405 sputs(s, (const byte *)decode, di * sizeof(float), &ignore);
406 }
407 *ppcs = pcs;
408 return 0;
409 }
410
411 /* Set an image's ImageMatrix to the default. */
412 void
gx_image_matrix_set_default(gs_data_image_t * pid)413 gx_image_matrix_set_default(gs_data_image_t *pid)
414 {
415 pid->ImageMatrix.xx = (float)pid->Width;
416 pid->ImageMatrix.xy = 0;
417 pid->ImageMatrix.yx = 0;
418 pid->ImageMatrix.yy = (float)-pid->Height;
419 pid->ImageMatrix.tx = 0;
420 pid->ImageMatrix.ty = (float)pid->Height;
421 }
422
423 /* Get a variable-length uint from a stream. */
424 int
sget_variable_uint(stream * s,uint * pw)425 sget_variable_uint(stream *s, uint *pw)
426 {
427 uint w = 0;
428 int shift = 0;
429 int ch;
430
431 for (; (ch = sgetc(s)) >= 0x80; shift += 7)
432 w += (ch & 0x7f) << shift;
433 if (ch < 0)
434 return_error(gs_error_ioerror);
435 *pw = w + (ch << shift);
436 return 0;
437 }
438
439 /*
440 * Read generic pixel image parameters.
441 */
442 int
gx_pixel_image_sget(gs_pixel_image_t * pim,stream * s,const gs_color_space * pcs)443 gx_pixel_image_sget(gs_pixel_image_t *pim, stream *s,
444 const gs_color_space *pcs)
445 {
446 uint control;
447 float decode_default_1 = 1;
448 int num_components, num_decode;
449 int i;
450 int code;
451 uint ignore;
452
453 if ((code = sget_variable_uint(s, &control)) < 0 ||
454 (code = sget_variable_uint(s, (uint *)&pim->Width)) < 0 ||
455 (code = sget_variable_uint(s, (uint *)&pim->Height)) < 0
456 )
457 return code;
458 if_debug3('b', "[b]get control=0x%x, Width=%d, Height=%d\n",
459 control, pim->Width, pim->Height);
460 if (control & PI_ImageMatrix) {
461 if ((code = sget_matrix(s, &pim->ImageMatrix)) < 0)
462 return code;
463 debug_b_print_matrix(pim);
464 } else
465 gx_image_matrix_set_default((gs_data_image_t *)pim);
466 pim->BitsPerComponent = ((control >> PI_BPC_SHIFT) & PI_BPC_MASK) + 1;
467 pim->format = (control >> PI_FORMAT_SHIFT) & PI_FORMAT_MASK;
468 pim->ColorSpace = pcs;
469 num_components = gs_color_space_num_components(pcs);
470 num_decode = num_components * 2;
471 if (gs_color_space_get_index(pcs) == gs_color_space_index_Indexed)
472 decode_default_1 = (float)pcs->params.indexed.hival;
473 if (control & PI_Decode) {
474 uint dflags = 0x10000;
475 float *dp = pim->Decode;
476
477 for (i = 0; i < num_decode; i += 2, dp += 2, dflags <<= 2) {
478 if (dflags >= 0x10000) {
479 dflags = sgetc(s) + 0x100;
480 if (dflags < 0x100)
481 return_error(gs_error_ioerror);
482 }
483 switch (dflags & 0xc0) {
484 case 0x00:
485 dp[0] = 0, dp[1] = DECODE_DEFAULT(i + 1, decode_default_1);
486 break;
487 case 0x40:
488 dp[0] = DECODE_DEFAULT(i + 1, decode_default_1), dp[1] = 0;
489 break;
490 case 0x80:
491 dp[0] = 0;
492 if (sgets(s, (byte *)(dp + 1), sizeof(float), &ignore) < 0)
493 return_error(gs_error_ioerror);
494 break;
495 case 0xc0:
496 if (sgets(s, (byte *)dp, sizeof(float) * 2, &ignore) < 0)
497 return_error(gs_error_ioerror);
498 break;
499 }
500 }
501 debug_b_print_decode(pim, num_decode);
502 } else {
503 for (i = 0; i < num_decode; ++i)
504 pim->Decode[i] = DECODE_DEFAULT(i, decode_default_1);
505 }
506 pim->Interpolate = (control & PI_Interpolate) != 0;
507 pim->CombineWithColor = (control & PI_CombineWithColor) != 0;
508 return control >> PI_BITS;
509 }
510
511 /*
512 * Release a pixel image object. Currently this just frees the object.
513 */
514 void
gx_pixel_image_release(gs_pixel_image_t * pic,gs_memory_t * mem)515 gx_pixel_image_release(gs_pixel_image_t *pic, gs_memory_t *mem)
516 {
517 gx_image_default_release((gs_image_common_t *)pic, mem);
518 }
519