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) 1997, 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: gximage2.c,v 1.5 2002/08/22 07:12:29 henrys Exp $ */
18
/* ImageType 2 image implementation */
19
#include "math_.h"
20
#include "memory_.h"
21
#include "gx.h"
22
#include "gserrors.h"
23
#include "gsmatrix.h"		/* for gscoord.h */
24
#include "gscoord.h"
25
#include "gscspace.h"
26
#include "gscpixel.h"
27
#include "gsdevice.h"
28
#include "gsiparm2.h"
29
#include "gxgetbit.h"
30
#include "gxiparam.h"
31
#include "gxpath.h"
32
#include "gscolor2.h"
33
 
34
/* Forward references */
35
private dev_proc_begin_typed_image(gx_begin_image2);
36
private image_proc_source_size(gx_image2_source_size);
37
 
38
/* Structure descriptor */
39
private_st_gs_image2();
40
 
41
/* Define the image type for ImageType 2 images. */
42
const gx_image_type_t gs_image_type_2 = {
43
    &st_gs_image2, gx_begin_image2, gx_image2_source_size,
44
    gx_image_no_sput, gx_image_no_sget, gx_image_default_release, 2
45
};
46
 
47
/* Initialize an ImageType 2 image. */
48
void
49
gs_image2_t_init(gs_image2_t * pim)
50
{
51
    pim->type = &gs_image_type_2;
52
    pim->UnpaintedPath = 0;
53
    pim->PixelCopy = false;
54
}
55
 
56
/*
57
 * Compute the device space coordinates and source data size for an
58
 * ImageType 2 image.  This procedure fills in
59
 * image.{Width,Height,ImageMatrix}.
60
 */
61
typedef struct image2_data_s {
62
    gs_point origin;
63
    gs_int_rect bbox;
64
    gs_image1_t image;
65
} image2_data_t;
66
private int
67
image2_set_data(const gs_image2_t * pim, image2_data_t * pid)
68
{
69
    gs_state *pgs = pim->DataSource;
70
    gs_matrix smat;
71
    gs_rect sbox, dbox;
72
 
73
    gs_transform(pgs, pim->XOrigin, pim->YOrigin, &pid->origin);
74
    sbox.q.x = (sbox.p.x = pim->XOrigin) + pim->Width;
75
    sbox.q.y = (sbox.p.y = pim->YOrigin) + pim->Height;
76
    gs_currentmatrix(pgs, &smat);
77
    gs_bbox_transform(&sbox, &smat, &dbox);
78
    pid->bbox.p.x = (int)floor(dbox.p.x);
79
    pid->bbox.p.y = (int)floor(dbox.p.y);
80
    pid->bbox.q.x = (int)ceil(dbox.q.x);
81
    pid->bbox.q.y = (int)ceil(dbox.q.y);
82
    pid->image.Width = pid->bbox.q.x - pid->bbox.p.x;
83
    pid->image.Height = pid->bbox.q.y - pid->bbox.p.y;
84
    pid->image.ImageMatrix = pim->ImageMatrix;
85
    return 0;
86
}
87
 
88
/* Compute the source size of an ImageType 2 image. */
89
private int
90
gx_image2_source_size(const gs_imager_state * pis, const gs_image_common_t * pim,
91
		      gs_int_point * psize)
92
{
93
    image2_data_t idata;
94
 
95
    image2_set_data((const gs_image2_t *)pim, &idata);
96
    psize->x = idata.image.Width;
97
    psize->y = idata.image.Height;
98
    return 0;
99
}
100
 
101
/* Begin an ImageType 2 image. */
102
/* Note that since ImageType 2 images don't have any source data, */
103
/* this procedure does all the work. */
104
private int
105
gx_begin_image2(gx_device * dev,
106
		const gs_imager_state * pis, const gs_matrix * pmat,
107
		const gs_image_common_t * pic, const gs_int_rect * prect,
108
	      const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
109
		gs_memory_t * mem, gx_image_enum_common_t ** pinfo)
110
{
111
    const gs_image2_t *pim = (const gs_image2_t *)pic;
112
    gs_state *pgs = pim->DataSource;
113
    gx_device *sdev = gs_currentdevice(pgs);
114
    int depth = sdev->color_info.depth;
115
    bool pixel_copy = pim->PixelCopy;
116
    bool has_alpha;
117
    bool direct_copy = false;
118
    image2_data_t idata;
119
    byte *row;
120
    uint row_size, source_size;
121
    gx_image_enum_common_t *info;
122
    gs_matrix smat, dmat;
123
    int code;
124
 
125
    /* verify that color models are the same for PixelCopy */
126
    if ( pixel_copy                            &&
127
         memcmp( &dev->color_info,
128
                 &sdev->color_info,
129
                 sizeof(dev->color_info) ) != 0  )
130
        return_error(gs_error_typecheck);
131
 
132
/****** ONLY HANDLE depth <= 8 FOR PixelCopy ******/
133
    if (pixel_copy && depth <= 8)
134
        return_error(gs_error_unregistered);
135
 
136
    gs_image_t_init(&idata.image, gs_currentcolorspace((const gs_state *)pis));
137
 
138
    /* Add Decode entries for K and alpha */
139
    idata.image.Decode[6] = idata.image.Decode[8] = 0.0;
140
    idata.image.Decode[7] = idata.image.Decode[9] = 1.0;
141
    if (pmat == 0) {
142
	gs_currentmatrix((const gs_state *)pis, &dmat);
143
	pmat = &dmat;
144
    } else
145
	dmat = *pmat;
146
    gs_currentmatrix(pgs, &smat);
147
    code = image2_set_data(pim, &idata);
148
    if (code < 0)
149
	return code;
150
/****** ONLY HANDLE SIMPLE CASES FOR NOW ******/
151
    if (idata.bbox.p.x != floor(idata.origin.x))
152
	return_error(gs_error_rangecheck);
153
    if (!(idata.bbox.p.y == floor(idata.origin.y) ||
154
	  idata.bbox.q.y == ceil(idata.origin.y))
155
	)
156
	return_error(gs_error_rangecheck);
157
    source_size = (idata.image.Width * depth + 7) >> 3;
158
    row_size = max(3 * idata.image.Width, source_size);
159
    row = gs_alloc_bytes(mem, row_size, "gx_begin_image2");
160
    if (row == 0)
161
	return_error(gs_error_VMerror);
162
    if (pixel_copy) {
163
	idata.image.BitsPerComponent = depth;
164
	has_alpha = false;	/* no separate alpha channel */
165
 
166
	if ( pcpath == NULL ||
167
	     gx_cpath_includes_rectangle(pcpath,
168
				     int2fixed(idata.bbox.p.x),
169
				     int2fixed(idata.bbox.p.y),
170
				     int2fixed(idata.bbox.q.x),
171
				     int2fixed(idata.bbox.q.y)) ) {
172
	    gs_matrix mat;
173
 
174
 
175
	    /*
176
	     * Figure 7.2 of the Adobe 3010 Supplement says that we should
177
	     * compute CTM x ImageMatrix here, but I'm almost certain it
178
	     * should be the other way around.  Also see gdevx.c.
179
	     */
180
	    gs_matrix_multiply(&idata.image.ImageMatrix, &smat, &mat);
181
	    direct_copy =
182
	        (is_xxyy(&dmat) || is_xyyx(&dmat)) &&
183
#define eqe(e) mat.e == dmat.e
184
	        eqe(xx) && eqe(xy) && eqe(yx) && eqe(yy);
185
#undef eqe
186
        }
187
    } else {
188
	idata.image.BitsPerComponent = 8;
189
 
190
	/* Always use RGB source color for now.
191
         *
192
	 * The source device has alpha if the same RGB values with
193
	 * different alphas map to different pixel values.
194
	 ****** THIS IS NOT GOOD ENOUGH: WE WANT TO SKIP TRANSFERRING
195
	 ****** ALPHA IF THE SOURCE IS CAPABLE OF HAVING ALPHA BUT
196
	 ****** DOESN'T CURRENTLY HAVE ANY ACTUAL ALPHA VALUES DIFFERENT
197
	 ****** FROM 1.
198
	 */
199
	/*
200
	 * Since the default implementation of map_rgb_alpha_color
201
	 * premultiplies the color towards white, we can't just test
202
	 * whether changing alpha has an effect on the color.
203
	 */
204
	{
205
	    gx_color_index trans_black =
206
	    (*dev_proc(sdev, map_rgb_alpha_color))
207
	    (sdev, (gx_color_value) 0, (gx_color_value) 0,
208
	     (gx_color_value) 0, (gx_color_value) 0);
209
 
210
	    has_alpha =
211
		trans_black != (*dev_proc(sdev, map_rgb_alpha_color))
212
		(sdev, (gx_color_value) 0, (gx_color_value) 0,
213
		 (gx_color_value) 0, gx_max_color_value) &&
214
		trans_black != (*dev_proc(sdev, map_rgb_alpha_color))
215
		(sdev, gx_max_color_value, gx_max_color_value,
216
		 gx_max_color_value, gx_max_color_value);
217
	}
218
    }
219
    idata.image.Alpha =
220
	(has_alpha ? gs_image_alpha_last : gs_image_alpha_none);
221
    if (smat.yy < 0) {
222
	/*
223
	 * The source Y axis is reflected.  Reflect the mapping from
224
	 * user space to source data.
225
	 */
226
	idata.image.ImageMatrix.ty += idata.image.Height *
227
	    idata.image.ImageMatrix.yy;
228
	idata.image.ImageMatrix.xy = -idata.image.ImageMatrix.xy;
229
	idata.image.ImageMatrix.yy = -idata.image.ImageMatrix.yy;
230
    }
231
    if (!direct_copy)
232
	code = (*dev_proc(dev, begin_typed_image))
233
	    (dev, pis, pmat, (const gs_image_common_t *)&idata.image, NULL,
234
	     pdcolor, pcpath, mem, &info);
235
    if (code >= 0) {
236
	int y;
237
	gs_int_rect rect;
238
	gs_get_bits_params_t params;
239
	const byte *data;
240
	uint offset = row_size - source_size;
241
 
242
	rect = idata.bbox;
243
	for (y = 0; code >= 0 && y < idata.image.Height; ++y) {
244
	    gs_int_rect *unread = 0;
245
	    int num_unread;
246
 
247
/****** y COMPUTATION IS ROUNDED -- WRONG ******/
248
	    rect.q.y = rect.p.y + 1;
249
	    /* Insist on x_offset = 0 to simplify the conversion loop. */
250
	    params.options =
251
		GB_ALIGN_ANY | (GB_RETURN_COPY | GB_RETURN_POINTER) |
252
		GB_OFFSET_0 | (GB_RASTER_STANDARD | GB_RASTER_ANY) |
253
		GB_PACKING_CHUNKY;
254
	    if (pixel_copy) {
255
		params.options |= GB_COLORS_NATIVE;
256
		params.data[0] = row + offset;
257
		code = (*dev_proc(sdev, get_bits_rectangle))
258
		    (sdev, &rect, &params, &unread);
259
		if (code < 0)
260
		    break;
261
		num_unread = code;
262
		data = params.data[0];
263
		if (direct_copy) {
264
		    /*
265
		     * Copy the pixels directly to the destination.
266
		     * We know that the transformation is only a translation,
267
		     * but we must handle an inverted destination Y axis.
268
		     */
269
		    code = (*dev_proc(dev, copy_color))
270
			(dev, data, 0, row_size, gx_no_bitmap_id,
271
			 (int)(dmat.tx - idata.image.ImageMatrix.tx),
272
			 (int)(dmat.ty - idata.image.ImageMatrix.ty +
273
			       (dmat.yy < 0 ? ~y : y)),
274
			 idata.image.Width, 1);
275
		    continue;
276
		}
277
	    } else {
278
		/*
279
		 * Convert the pixels to pure colors.  This may be very
280
		 * slow and painful.  Eventually we will use indexed color for
281
		 * narrow pixels.
282
		 */
283
		/* Always use RGB source color for now. */
284
		params.options |=
285
		    GB_COLORS_RGB | GB_DEPTH_8 |
286
		    (has_alpha ? GB_ALPHA_LAST : GB_ALPHA_NONE);
287
		params.data[0] = row;
288
		code = (*dev_proc(sdev, get_bits_rectangle))
289
		    (sdev, &rect, &params, &unread);
290
		if (code < 0)
291
		    break;
292
		num_unread = code;
293
		data = params.data[0];
294
	    }
295
	    if (num_unread > 0 && pim->UnpaintedPath) {
296
		/* Add the rectangle(s) to the unpainted path. */
297
		int i;
298
 
299
		for (i = 0; code >= 0 && i < num_unread; ++i)
300
		    code = gx_path_add_rectangle(pim->UnpaintedPath,
301
						 int2fixed(unread[i].p.x),
302
						 int2fixed(unread[i].p.y),
303
						 int2fixed(unread[i].q.x),
304
						 int2fixed(unread[i].q.y));
305
		gs_free_object(dev->memory, unread, "UnpaintedPath unread");
306
	    }
307
	    code = gx_image_data(info, &data, 0, row_size, 1);
308
	    rect.p.y = rect.q.y;
309
	}
310
	if (!direct_copy) {
311
	    if (code >= 0)
312
		code = gx_image_end(info, true);
313
	    else
314
		discard(gx_image_end(info, false));
315
	}
316
    }
317
    gs_free_object(mem, row, "gx_begin_image2");
318
    return (code < 0 ? code : 1);
319
}