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) 1994, 1995, 1996, 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: gxi16bit.c,v 1.2 2005/06/08 14:00:32 igor Exp $ */
18
/* 16-bit image procedures */
19
#include "gx.h"
20
#include "memory_.h"
21
#include "gpcheck.h"
22
#include "gserrors.h"
23
#include "gxfixed.h"
24
#include "gxfrac.h"
25
#include "gxarith.h"
26
#include "gxmatrix.h"
27
#include "gsccolor.h"
28
#include "gspaint.h"
29
#include "gxdevice.h"
30
#include "gxcmap.h"
31
#include "gxdcolor.h"
32
#include "gxistate.h"
33
#include "gxdevmem.h"
34
#include "gxcpath.h"
35
#include "gximage.h"
36
 
37
/* ---------------- Unpacking procedures ---------------- */
38
 
39
private const byte *
40
sample_unpack_16(byte * bptr, int *pdata_x, const byte * data,
41
		 int data_x, uint dsize, const sample_map *ignore_smap, int spread,
42
		 int ignore_num_components_per_plane)
43
{
44
    /* Assuming an identity map for all components. */
45
    register frac *bufp = (frac *) bptr;
46
    uint dskip = data_x << 1;
47
    const byte *psrc = data + dskip;
48
#define inc_bufp(bp, n) bp = (frac *)((byte *)(bp) + (n))
49
    uint sample;
50
    int left = dsize - dskip;
51
 
52
    while (left > 2) {
53
	sample = ((uint) psrc[0] << 8) + psrc[1];
54
	*bufp = (frac)((frac_1 * (sample + 1)) >> 16);
55
	inc_bufp(bufp, spread);
56
	psrc += 2;
57
	left -= 2;
58
    }
59
    *pdata_x = 0;
60
    return bptr;
61
}
62
 
63
const sample_unpack_proc_t sample_unpack_16_proc = sample_unpack_16;
64
 
65
/* ---------------- Rendering procedures ---------------- */
66
 
67
/* ------ Rendering for 16-bit samples ------ */
68
 
69
#define FRACS_PER_LONG (arch_sizeof_long / arch_sizeof_frac)
70
typedef union {
71
    frac v[GS_IMAGE_MAX_COLOR_COMPONENTS];
72
#define LONGS_PER_COLOR_FRACS\
73
  ((GS_IMAGE_MAX_COLOR_COMPONENTS + FRACS_PER_LONG - 1) / FRACS_PER_LONG)
74
    long all[LONGS_PER_COLOR_FRACS];	/* for fast comparison */
75
} color_fracs;
76
 
77
#define LONGS_PER_4_FRACS ((FRACS_PER_LONG + 3) / 4)
78
#if LONGS_PER_4_FRACS == 1
79
#  define COLOR_FRACS_4_EQ(f1, f2)\
80
     ((f1).all[0] == (f2).all[0])
81
#else
82
#if LONGS_PER_4_FRACS == 2
83
#  define COLOR_FRACS_4_EQ(f1, f2)\
84
     ((f1).all[0] == (f2).all[0] && (f1).all[1] == (f2).all[1])
85
#endif
86
#endif
87
 
88
/* Test whether a color is transparent. */
89
private bool
90
mask_color16_matches(const frac *v, const gx_image_enum *penum,
91
		   int num_components)
92
{
93
    int i;
94
 
95
    for (i = num_components * 2, v += num_components - 1; (i -= 2) >= 0; --v)
96
	if (*v < penum->mask_color.values[i] ||
97
	    *v > penum->mask_color.values[i + 1]
98
	    )
99
	    return false;
100
    return true;
101
}
102
 
103
/* Render an image with more than 8 bits per sample. */
104
/* The samples have been expanded into fracs. */
105
private int
106
image_render_frac(gx_image_enum * penum, const byte * buffer, int data_x,
107
		  uint w, int h, gx_device * dev)
108
{
109
    const gs_imager_state *pis = penum->pis;
110
    gs_logical_operation_t lop = penum->log_op;
111
    gx_dda_fixed_point pnext;
112
    image_posture posture = penum->posture;
113
    fixed xl, ytf;
114
    fixed pdyx, pdyy;		/* edge of parallelogram */
115
    int yt = penum->yci, iht = penum->hci;
116
    const gs_color_space *pcs = penum->pcs;
117
    cs_proc_remap_color((*remap_color)) = pcs->type->remap_color;
118
    gs_client_color cc;
119
    bool device_color = penum->device_color;
120
    const gx_color_map_procs *cmap_procs = gx_get_cmap_procs(pis, dev);
121
    cmap_proc_rgb((*map_rgb)) = cmap_procs->map_rgb;
122
    cmap_proc_cmyk((*map_cmyk)) = cmap_procs->map_cmyk;
123
    bool use_mask_color = penum->use_mask_color;
124
    gx_device_color devc1, devc2;
125
    gx_device_color *pdevc = &devc1;
126
    gx_device_color *pdevc_next = &devc2;
127
    int spp = penum->spp;
128
    const frac *psrc_initial = (const frac *)buffer + data_x * spp;
129
    const frac *psrc = psrc_initial;
130
    const frac *rsrc = psrc + spp; /* psrc + spp at start of run */
131
    fixed xrun;			/* x at start of run */
132
    int irun;			/* int xrun */
133
    fixed yrun;			/* y ditto */
134
    color_fracs run;		/* run value */
135
    color_fracs next;		/* next sample value */
136
    const frac *bufend = psrc + w;
137
    int code = 0, mcode = 0;
138
 
139
    if (h == 0)
140
	return 0;
141
    pnext = penum->dda.pixel0;
142
    xrun = xl = dda_current(pnext.x);
143
    irun = fixed2int_var_rounded(xrun);
144
    yrun = ytf = dda_current(pnext.y);
145
    pdyx = dda_current(penum->dda.row.x) - penum->cur.x;
146
    pdyy = dda_current(penum->dda.row.y) - penum->cur.y;
147
    if_debug5('b', "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n",
148
	      penum->y, data_x, w, fixed2float(xl), fixed2float(ytf));
149
    memset(&run, 0, sizeof(run));
150
    memset(&next, 0, sizeof(next));
151
    /* Ensure that we don't get any false dev_color_eq hits. */
152
    set_nonclient_dev_color(&devc1, gx_no_color_index);
153
    set_nonclient_dev_color(&devc2, gx_no_color_index);
154
    cs_full_init_color(&cc, pcs);
155
    run.v[0] = ~psrc[0];	/* force remap */
156
 
157
    while (psrc < bufend) {
158
	next.v[0] = psrc[0];
159
	switch (spp) {
160
	    case 4:		/* may be CMYK */
161
		next.v[1] = psrc[1];
162
		next.v[2] = psrc[2];
163
		next.v[3] = psrc[3];
164
		psrc += 4;
165
		if (COLOR_FRACS_4_EQ(next, run))
166
		    goto inc;
167
		if (use_mask_color && mask_color16_matches(next.v, penum, 4)) {
168
		    color_set_null(pdevc_next);
169
		    goto f;
170
		}
171
		if (device_color) {
172
		    (*map_cmyk) (next.v[0], next.v[1],
173
				 next.v[2], next.v[3],
174
				 pdevc_next, pis, dev,
175
				 gs_color_select_source);
176
		    goto f;
177
		}
178
		decode_frac(next.v[0], cc, 0);
179
		decode_frac(next.v[1], cc, 1);
180
		decode_frac(next.v[2], cc, 2);
181
		decode_frac(next.v[3], cc, 3);
182
		if_debug4('B', "[B]cc[0..3]=%g,%g,%g,%g\n",
183
			  cc.paint.values[0], cc.paint.values[1],
184
			  cc.paint.values[2], cc.paint.values[3]);
185
		if_debug1('B', "[B]cc[3]=%g\n",
186
			  cc.paint.values[3]);
187
		break;
188
	    case 3:		/* may be RGB */
189
		next.v[1] = psrc[1];
190
		next.v[2] = psrc[2];
191
		psrc += 3;
192
		if (COLOR_FRACS_4_EQ(next, run))
193
		    goto inc;
194
		if (use_mask_color && mask_color16_matches(next.v, penum, 3)) {
195
		    color_set_null(pdevc_next);
196
		    goto f;
197
		}
198
		if (device_color) {
199
		    (*map_rgb) (next.v[0], next.v[1],
200
				next.v[2], pdevc_next, pis, dev,
201
				gs_color_select_source);
202
		    goto f;
203
		}
204
		decode_frac(next.v[0], cc, 0);
205
		decode_frac(next.v[1], cc, 1);
206
		decode_frac(next.v[2], cc, 2);
207
		if_debug3('B', "[B]cc[0..2]=%g,%g,%g\n",
208
			  cc.paint.values[0], cc.paint.values[1],
209
			  cc.paint.values[2]);
210
		break;
211
	    case 1:		/* may be Gray */
212
		psrc++;
213
		if (next.v[0] == run.v[0])
214
		    goto inc;
215
		if (use_mask_color && mask_color16_matches(next.v, penum, 1)) {
216
		    color_set_null(pdevc_next);
217
		    goto f;
218
		}
219
		if (device_color) {
220
		    (*map_rgb) (next.v[0], next.v[0],
221
				next.v[0], pdevc_next, pis, dev,
222
				gs_color_select_source);
223
		    goto f;
224
		}
225
		decode_frac(next.v[0], cc, 0);
226
		if_debug1('B', "[B]cc[0]=%g\n",
227
			  cc.paint.values[0]);
228
		break;
229
	    default:		/* DeviceN */
230
		{
231
		    int i;
232
 
233
		    for (i = 1; i < spp; ++i)
234
			next.v[i] = psrc[i];
235
		    psrc += spp;
236
		    if (!memcmp(next.v, run.v, spp * sizeof(next.v[0])))
237
			goto inc;
238
		    if (use_mask_color &&
239
			mask_color16_matches(next.v, penum, spp)
240
			) {
241
			color_set_null(pdevc_next);
242
			goto f;
243
		    }
244
		    for (i = 0; i < spp; ++i)
245
			decode_frac(next.v[i], cc, i);
246
#ifdef DEBUG
247
		    if (gs_debug_c('B')) {
248
			dprintf2("[B]cc[0..%d]=%g", spp - 1,
249
				 cc.paint.values[0]);
250
			for (i = 1; i < spp; ++i)
251
			    dprintf1(",%g", cc.paint.values[i]);
252
			dputs("\n");
253
		    }
254
#endif
255
		}
256
		break;
257
	}
258
	mcode = remap_color(&cc, pcs, pdevc_next, pis, dev,
259
			   gs_color_select_source);
260
	if (mcode < 0)
261
	    goto fill;
262
f:
263
	if_debug7('B', "[B]0x%x,0x%x,0x%x,0x%x -> %ld,%ld,0x%lx\n",
264
		  next.v[0], next.v[1], next.v[2], next.v[3],
265
		  pdevc_next->colors.binary.color[0],
266
		  pdevc_next->colors.binary.color[1],
267
		  (ulong) pdevc_next->type);
268
	/* Even though the supplied colors don't match, */
269
	/* the device colors might. */
270
	if (!dev_color_eq(devc1, devc2)) {
271
	    /* Fill the region between xrun/irun and xl */
272
	    gx_device_color *ptemp;
273
 
274
fill:
275
	    if (posture != image_portrait) {	/* Parallelogram */
276
		code = (*dev_proc(dev, fill_parallelogram))
277
		    (dev, xrun, yrun,
278
		     xl - xrun, ytf - yrun, pdyx, pdyy,
279
		     pdevc, lop);
280
	    } else {		/* Rectangle */
281
		int xi = irun;
282
		int wi = (irun = fixed2int_var_rounded(xl)) - xi;
283
 
284
		if (wi < 0)
285
		    xi += wi, wi = -wi;
286
		code = gx_fill_rectangle_device_rop(xi, yt,
287
						  wi, iht, pdevc, dev, lop);
288
	    }
289
	    if (code < 0)
290
		goto err;
291
	    rsrc = psrc;
292
	    if ((code = mcode) < 0)
293
		goto err;
294
	    ptemp = pdevc;
295
	    pdevc = pdevc_next;
296
	    pdevc_next = ptemp;
297
	    xrun = xl;
298
	    yrun = ytf;
299
	}
300
	run = next;
301
inc:
302
	xl = dda_next(pnext.x);
303
	ytf = dda_next(pnext.y);
304
    }
305
    /* Fill the final run. */
306
    code = (*dev_proc(dev, fill_parallelogram))
307
	(dev, xrun, yrun, xl - xrun, ytf - yrun, pdyx, pdyy, pdevc, lop);
308
    return (code < 0 ? code : 1);
309
 
310
    /* Save position if error, in case we resume. */
311
err:
312
    penum->used.x = (rsrc - spp - psrc_initial) / spp;
313
    penum->used.y = 0;
314
    return code;
315
}