Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
38
gs_image_common_t_init(gs_image_common_t * pic)
39
{
40
    gs_make_identity(&pic->ImageMatrix);
41
}
42
void
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
}