1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
7
This software is distributed under license and may not be copied, modified
8
or distributed except as expressly authorized under the terms of that
9
license. Refer to licensing information at http://www.artifex.com/
10
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
11
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
14
/* $Id: gximage.c 8767 2008-05-21 19:46:47Z giles $ */
15
/* Generic image support */
22
#include "gxcolor2.h" /* for lookup map */
26
/* ---------------- Generic image support ---------------- */
28
/* Structure descriptors */
29
public_st_gs_image_common();
30
public_st_gs_data_image();
31
public_st_gs_pixel_image();
33
/* Initialize the common parts of image structures. */
35
gs_image_common_t_init(gs_image_common_t * pic)
37
gs_make_identity(&pic->ImageMatrix);
40
gs_data_image_t_init(gs_data_image_t * pim, int num_components)
44
gs_image_common_t_init((gs_image_common_t *) pim);
45
pim->Width = pim->Height = 0;
46
pim->BitsPerComponent = 1;
47
if (num_components >= 0) {
48
for (i = 0; i < num_components * 2; i += 2)
49
pim->Decode[i] = 0, pim->Decode[i + 1] = 1;
51
for (i = 0; i < num_components * -2; i += 2)
52
pim->Decode[i] = 1, pim->Decode[i + 1] = 0;
54
pim->Interpolate = false;
57
gs_pixel_image_t_init(gs_pixel_image_t * pim,
58
gs_color_space * color_space)
62
if (color_space == 0 ||
64
gs_color_space_num_components(color_space)) < 0
67
gs_data_image_t_init((gs_data_image_t *) pim, num_components);
68
pim->format = gs_image_format_chunky;
69
pim->ColorSpace = color_space;
70
pim->CombineWithColor = false;
73
/* Initialize the common part of an image-processing enumerator. */
75
gx_image_enum_common_init(gx_image_enum_common_t * piec,
76
const gs_data_image_t * pic,
77
const gx_image_enum_procs_t * piep,
78
gx_device * dev, int num_components,
79
gs_image_format_t format)
81
int bpc = pic->BitsPerComponent;
84
piec->image_type = pic->type;
87
piec->id = gs_next_ids(dev->memory, 1);
88
piec->skipping = false;
90
case gs_image_format_chunky:
92
piec->plane_depths[0] = bpc * num_components;
94
case gs_image_format_component_planar:
95
piec->num_planes = num_components;
96
for (i = 0; i < num_components; ++i)
97
piec->plane_depths[i] = bpc;
99
case gs_image_format_bit_planar:
100
piec->num_planes = bpc * num_components;
101
for (i = 0; i < piec->num_planes; ++i)
102
piec->plane_depths[i] = 1;
105
return_error(gs_error_rangecheck);
107
for (i = 0; i < piec->num_planes; ++i)
108
piec->plane_widths[i] = pic->Width;
112
/* Compute the source size of an ordinary image with explicit data. */
114
gx_data_image_source_size(const gs_imager_state * pis,
115
const gs_image_common_t * pim, gs_int_point * psize)
117
const gs_data_image_t *pdi = (const gs_data_image_t *)pim;
119
psize->x = pdi->Width;
120
psize->y = pdi->Height;
124
/* Process the next piece of an image with no source data. */
125
/* This procedure should never be called. */
127
gx_no_plane_data(gx_image_enum_common_t * info,
128
const gx_image_plane_t * planes, int height,
131
return_error(gs_error_Fatal);
134
/* Clean up after processing an image with no source data. */
135
/* This procedure may be called, but should do nothing. */
137
gx_ignore_end_image(gx_image_enum_common_t * info, bool draw_last)
142
/* ---------------- Client procedures ---------------- */
145
gx_image_data(gx_image_enum_common_t * info, const byte ** plane_data,
146
int data_x, uint raster, int height)
148
int num_planes = info->num_planes;
149
gx_image_plane_t planes[GS_IMAGE_MAX_COMPONENTS];
153
if (num_planes > GS_IMAGE_MAX_COMPONENTS) {
154
lprintf2("num_planes=%d > GS_IMAGE_MAX_COMPONENTS=%d!\n",
155
num_planes, GS_IMAGE_MAX_COMPONENTS);
156
return_error(gs_error_Fatal);
159
for (i = 0; i < num_planes; ++i) {
160
planes[i].data = plane_data[i];
161
planes[i].data_x = data_x;
162
planes[i].raster = raster;
164
return gx_image_plane_data(info, planes, height);
168
gx_image_plane_data(gx_image_enum_common_t * info,
169
const gx_image_plane_t * planes, int height)
171
int ignore_rows_used;
173
return gx_image_plane_data_rows(info, planes, height, &ignore_rows_used);
177
gx_image_plane_data_rows(gx_image_enum_common_t * info,
178
const gx_image_plane_t * planes, int height,
181
return info->procs->plane_data(info, planes, height, rows_used);
185
gx_image_flush(gx_image_enum_common_t * info)
187
int (*flush)(gx_image_enum_common_t *) = info->procs->flush;
189
return (flush ? flush(info) : 0);
193
gx_image_planes_wanted(const gx_image_enum_common_t *info, byte *wanted)
195
bool (*planes_wanted)(const gx_image_enum_common_t *, byte *) =
196
info->procs->planes_wanted;
199
return planes_wanted(info, wanted);
201
memset(wanted, 0xff, info->num_planes);
207
gx_image_end(gx_image_enum_common_t * info, bool draw_last)
209
return info->procs->end_image(info, draw_last);
212
/* ---------------- Serialization ---------------- */
215
* Define dummy sput/sget/release procedures for image types that don't
216
* implement these functions.
220
gx_image_no_sput(const gs_image_common_t *pic, stream *s,
221
const gs_color_space **ppcs)
223
return_error(gs_error_rangecheck);
227
gx_image_no_sget(gs_image_common_t *pic, stream *s,
230
return_error(gs_error_rangecheck);
234
gx_image_default_release(gs_image_common_t *pic, gs_memory_t *mem)
236
gs_free_object(mem, pic, "gx_image_default_release");
241
debug_b_print_matrix(const gs_pixel_image_t *pim)
243
if_debug6('b', " ImageMatrix=[%g %g %g %g %g %g]\n",
244
pim->ImageMatrix.xx, pim->ImageMatrix.xy,
245
pim->ImageMatrix.yx, pim->ImageMatrix.yy,
246
pim->ImageMatrix.tx, pim->ImageMatrix.ty);
249
debug_b_print_decode(const gs_pixel_image_t *pim, int num_decode)
251
if (gs_debug_c('b')) {
252
const char *str = " Decode=[";
255
for (i = 0; i < num_decode; str = " ", ++i)
256
dprintf2("%s%g", str, pim->Decode[i]);
261
# define debug_b_print_matrix(pim) DO_NOTHING
262
# define debug_b_print_decode(pim, num_decode) DO_NOTHING
265
/* Test whether an image has a default ImageMatrix. */
267
gx_image_matrix_is_default(const gs_data_image_t *pid)
269
return (is_xxyy(&pid->ImageMatrix) &&
270
pid->ImageMatrix.xx == pid->Width &&
271
pid->ImageMatrix.yy == -pid->Height &&
272
is_fzero(pid->ImageMatrix.tx) &&
273
pid->ImageMatrix.ty == pid->Height);
276
/* Put a variable-length uint on a stream. */
278
sput_variable_uint(stream *s, uint w)
280
for (; w > 0x7f; w >>= 7)
281
sputc(s, (byte)(w | 0x80));
286
* Write generic pixel image parameters. The format is the following,
287
* encoded as a variable-length uint in the usual way:
289
* A = 0 if standard ImageMatrix, 1 if explicit ImageMatrix
290
* BBBB = BitsPerComponent - 1
292
* D = 0 if standard (0..1) Decode, 1 if explicit Decode
294
* F = CombineWithColor
295
* xxx = extra information from caller
297
#define PI_ImageMatrix 0x001
298
#define PI_BPC_SHIFT 1
299
#define PI_BPC_MASK 0xf
300
#define PI_FORMAT_SHIFT 5
301
#define PI_FORMAT_MASK 0x3
302
#define PI_Decode 0x080
303
#define PI_Interpolate 0x100
304
#define PI_CombineWithColor 0x200
307
* Width, encoded as a variable-length uint
308
* Height, encoded ditto
309
* ImageMatrix (if A = 1), per gs_matrix_store/fetch
310
* Decode (if D = 1): blocks of up to 4 components
311
* aabbccdd, where each xx is decoded as:
312
* 00 = default, 01 = swapped default,
313
* 10 = (0,V), 11 = (U,V)
314
* non-defaulted components (up to 8 floats)
317
gx_pixel_image_sput(const gs_pixel_image_t *pim, stream *s,
318
const gs_color_space **ppcs, int extra)
320
const gs_color_space *pcs = pim->ColorSpace;
321
int bpc = pim->BitsPerComponent;
322
int num_components = gs_color_space_num_components(pcs);
324
uint control = extra << PI_BITS;
325
float decode_default_1 = 1;
329
/* Construct the control word. */
331
if (!gx_image_matrix_is_default((const gs_data_image_t *)pim))
332
control |= PI_ImageMatrix;
333
switch (pim->format) {
334
case gs_image_format_chunky:
335
case gs_image_format_component_planar:
337
case 1: case 2: case 4: case 8: case 12: break;
338
default: return_error(gs_error_rangecheck);
341
case gs_image_format_bit_planar:
342
if (bpc < 1 || bpc > 8)
343
return_error(gs_error_rangecheck);
345
control |= (bpc - 1) << PI_BPC_SHIFT;
346
control |= pim->format << PI_FORMAT_SHIFT;
347
num_decode = num_components * 2;
348
if (gs_color_space_get_index(pcs) == gs_color_space_index_Indexed)
349
decode_default_1 = (float)pcs->params.indexed.hival;
350
for (i = 0; i < num_decode; ++i)
351
if (pim->Decode[i] != DECODE_DEFAULT(i, decode_default_1)) {
352
control |= PI_Decode;
355
if (pim->Interpolate)
356
control |= PI_Interpolate;
357
if (pim->CombineWithColor)
358
control |= PI_CombineWithColor;
360
/* Write the encoding on the stream. */
362
if_debug3('b', "[b]put control=0x%x, Width=%d, Height=%d\n",
363
control, pim->Width, pim->Height);
364
sput_variable_uint(s, control);
365
sput_variable_uint(s, (uint)pim->Width);
366
sput_variable_uint(s, (uint)pim->Height);
367
if (control & PI_ImageMatrix) {
368
debug_b_print_matrix(pim);
369
sput_matrix(s, &pim->ImageMatrix);
371
if (control & PI_Decode) {
377
debug_b_print_decode(pim, num_decode);
378
for (i = 0; i < num_decode; i += 2) {
379
float u = pim->Decode[i], v = pim->Decode[i + 1];
380
float dv = DECODE_DEFAULT(i + 1, decode_default_1);
382
if (dflags >= 0x100) {
383
sputc(s, (byte)(dflags & 0xff));
384
sputs(s, (const byte *)decode, di * sizeof(float), &ignore);
389
if (u == 0 && v == dv)
391
else if (u == dv && v == 0)
402
sputc(s, (byte)((dflags << (8 - num_decode)) & 0xff));
403
sputs(s, (const byte *)decode, di * sizeof(float), &ignore);
409
/* Set an image's ImageMatrix to the default. */
411
gx_image_matrix_set_default(gs_data_image_t *pid)
413
pid->ImageMatrix.xx = (float)pid->Width;
414
pid->ImageMatrix.xy = 0;
415
pid->ImageMatrix.yx = 0;
416
pid->ImageMatrix.yy = (float)-pid->Height;
417
pid->ImageMatrix.tx = 0;
418
pid->ImageMatrix.ty = (float)pid->Height;
421
/* Get a variable-length uint from a stream. */
423
sget_variable_uint(stream *s, uint *pw)
429
for (; (ch = sgetc(s)) >= 0x80; shift += 7)
430
w += (ch & 0x7f) << shift;
432
return_error(gs_error_ioerror);
433
*pw = w + (ch << shift);
438
* Read generic pixel image parameters.
441
gx_pixel_image_sget(gs_pixel_image_t *pim, stream *s,
445
float decode_default_1 = 1;
446
int num_components, num_decode;
451
if ((code = sget_variable_uint(s, &control)) < 0 ||
452
(code = sget_variable_uint(s, (uint *)&pim->Width)) < 0 ||
453
(code = sget_variable_uint(s, (uint *)&pim->Height)) < 0
456
if_debug3('b', "[b]get control=0x%x, Width=%d, Height=%d\n",
457
control, pim->Width, pim->Height);
458
if (control & PI_ImageMatrix) {
459
if ((code = sget_matrix(s, &pim->ImageMatrix)) < 0)
461
debug_b_print_matrix(pim);
463
gx_image_matrix_set_default((gs_data_image_t *)pim);
464
pim->BitsPerComponent = ((control >> PI_BPC_SHIFT) & PI_BPC_MASK) + 1;
465
pim->format = (control >> PI_FORMAT_SHIFT) & PI_FORMAT_MASK;
466
pim->ColorSpace = pcs;
467
num_components = gs_color_space_num_components(pcs);
468
num_decode = num_components * 2;
469
if (gs_color_space_get_index(pcs) == gs_color_space_index_Indexed)
470
decode_default_1 = (float)pcs->params.indexed.hival;
471
if (control & PI_Decode) {
472
uint dflags = 0x10000;
473
float *dp = pim->Decode;
475
for (i = 0; i < num_decode; i += 2, dp += 2, dflags <<= 2) {
476
if (dflags >= 0x10000) {
477
dflags = sgetc(s) + 0x100;
479
return_error(gs_error_ioerror);
481
switch (dflags & 0xc0) {
483
dp[0] = 0, dp[1] = DECODE_DEFAULT(i + 1, decode_default_1);
486
dp[0] = DECODE_DEFAULT(i + 1, decode_default_1), dp[1] = 0;
490
if (sgets(s, (byte *)(dp + 1), sizeof(float), &ignore) < 0)
491
return_error(gs_error_ioerror);
494
if (sgets(s, (byte *)dp, sizeof(float) * 2, &ignore) < 0)
495
return_error(gs_error_ioerror);
499
debug_b_print_decode(pim, num_decode);
501
for (i = 0; i < num_decode; ++i)
502
pim->Decode[i] = DECODE_DEFAULT(i, decode_default_1);
504
pim->Interpolate = (control & PI_Interpolate) != 0;
505
pim->CombineWithColor = (control & PI_CombineWithColor) != 0;
506
return control >> PI_BITS;
510
* Release a pixel image object. Currently this just frees the object.
513
gx_pixel_image_release(gs_pixel_image_t *pic, gs_memory_t *mem)
515
gx_image_default_release((gs_image_common_t *)pic, mem);