Coverage Report

Created: 2025-06-10 07:19

/src/ghostpdl/base/gxipixel.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2025 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Common code for ImageType 1 and 4 initialization */
18
#include "gx.h"
19
#include "math_.h"
20
#include "memory_.h"
21
#include "gpcheck.h"
22
#include "gscdefs.h"            /* for image class table */
23
#include "gserrors.h"
24
#include "gsstruct.h"
25
#include "gsutil.h"
26
#include "gxfixed.h"
27
#include "gxfrac.h"
28
#include "gxarith.h"
29
#include "gxmatrix.h"
30
#include "gsccolor.h"
31
#include "gspaint.h"
32
#include "gzstate.h"
33
#include "gxdevice.h"
34
#include "gzpath.h"
35
#include "gzcpath.h"
36
#include "gxdevmem.h"
37
#include "gximage.h"
38
#include "gxiparam.h"
39
#include "gdevmrop.h"
40
#include "gscspace.h"
41
#include "gscindex.h"
42
#include "gsicc_cache.h"
43
#include "gsicc_cms.h"
44
#include "gsicc_manage.h"
45
#include "gxdevsop.h"
46
47
/* Structure descriptors */
48
private_st_gx_image_enum();
49
50
/* Image class procedures */
51
extern_gx_image_class_table();
52
53
/* Enumerator procedures */
54
static const gx_image_enum_procs_t image1_enum_procs = {
55
    gx_image1_plane_data, gx_image1_end_image, gx_image1_flush
56
};
57
58
/* GC procedures */
59
gs_private_st_ptrs2(st_color_cache, gx_image_color_cache_t, "gx_image_color_cache",
60
                    color_cache_enum_ptrs, color_cache_reloc_ptrs,
61
                    is_transparent, device_contone);
62
static
63
874
ENUM_PTRS_WITH(image_enum_enum_ptrs, gx_image_enum *eptr)
64
322
{
65
322
    int bps;
66
322
    gs_ptr_type_t ret;
67
68
    /* Enumerate the used members of clues.dev_color. */
69
322
    index -= gx_image_enum_num_ptrs;
70
322
    bps = eptr->unpack_bps;
71
322
    if (eptr->spp != 1)
72
0
        bps = 8;
73
322
    else if (bps > 8 || eptr->unpack == sample_unpack_copy)
74
0
        bps = 1;
75
322
    if (index >= (1 << bps) * st_device_color_max_ptrs)         /* done */
76
46
        return 0;
77
    /* the clues may have been cleared by gx_image_free_enum, but not freed in that */
78
    /* function due to being at a different save level. Only trace if dev_color.type != 0. */
79
276
    if (eptr->spp == 1) {
80
276
        if (eptr->clues != NULL) {
81
276
            if (eptr->clues[(index/st_device_color_max_ptrs) *
82
276
                (255 / ((1 << bps) - 1))].dev_color.type != 0) {
83
276
                ret = ENUM_USING(st_device_color,
84
276
                                 &eptr->clues[(index / st_device_color_max_ptrs) *
85
276
                                 (255 / ((1 << bps) - 1))].dev_color,
86
276
                                 sizeof(eptr->clues[0].dev_color),
87
276
                                 index % st_device_color_max_ptrs);
88
276
            } else {
89
0
                ret = 0;
90
0
            }
91
276
        } else {
92
0
            ret = 0;
93
0
        }
94
276
    } else {
95
0
        ret = 0;
96
0
    }
97
276
    if (ret == 0)               /* don't stop early */
98
276
        ENUM_RETURN(0);
99
0
    return ret;
100
276
}
101
102
552
#define e1(i,elt) ENUM_PTR(i,gx_image_enum,elt);
103
874
gx_image_enum_do_ptrs(e1)
104
874
#undef e1
105
874
ENUM_PTRS_END
106
107
46
static RELOC_PTRS_WITH(image_enum_reloc_ptrs, gx_image_enum *eptr)
108
46
{
109
46
    int i;
110
111
552
#define r1(i,elt) RELOC_PTR(gx_image_enum,elt);
112
552
    gx_image_enum_do_ptrs(r1)
113
46
#undef r1
114
46
    {
115
46
        int bps = eptr->unpack_bps;
116
117
46
        if (eptr->spp != 1)
118
0
            bps = 8;
119
46
        else if (bps > 8 || eptr->unpack == sample_unpack_copy)
120
0
            bps = 1;
121
46
        if (eptr->spp == 1) {
122
138
        for (i = 0; i <= 255; i += 255 / ((1 << bps) - 1))
123
92
            RELOC_USING(st_device_color,
124
46
                        &eptr->clues[i].dev_color, sizeof(gx_device_color));
125
46
    }
126
46
}
127
46
}
128
46
RELOC_PTRS_END
129
130
/* Forward declarations */
131
static int color_draws_b_w(gx_device * dev,
132
                            const gx_drawing_color * pdcolor);
133
static int image_init_colors(gx_image_enum * penum, int bps, int spp,
134
                               gs_image_format_t format,
135
                               const float *decode,
136
                               const gs_gstate * pgs, gx_device * dev,
137
                               const gs_color_space * pcs, bool * pdcb);
138
139
/* Procedures for unpacking the input data into bytes or fracs. */
140
/*extern SAMPLE_UNPACK_PROC(sample_unpack_copy); *//* declared above */
141
142
/*
143
 * Do common initialization for processing an ImageType 1 or 4 image.
144
 * Allocate the enumerator and fill in the following members:
145
 *      rect
146
 */
147
int
148
gx_image_enum_alloc(const gs_image_common_t * pic,
149
                    const gs_int_rect * prect, gs_memory_t * mem,
150
                    gx_image_enum **ppenum)
151
154k
{
152
154k
    const gs_pixel_image_t *pim = (const gs_pixel_image_t *)pic;
153
154k
    int width = pim->Width, height = pim->Height;
154
154k
    int bpc = pim->BitsPerComponent;
155
154k
    gx_image_enum *penum;
156
157
154k
    if (width < 0 || height < 0)
158
0
        return_error(gs_error_rangecheck);
159
154k
    switch (pim->format) {
160
154k
    case gs_image_format_chunky:
161
154k
    case gs_image_format_component_planar:
162
154k
        switch (bpc) {
163
154k
        case 1: case 2: case 4: case 8: case 12: case 16: break;
164
0
        default: return_error(gs_error_rangecheck);
165
154k
        }
166
154k
        break;
167
154k
    case gs_image_format_bit_planar:
168
0
        if (bpc < 1 || bpc > 8)
169
0
            return_error(gs_error_rangecheck);
170
154k
    }
171
154k
    if (prect) {
172
48.0k
        if (prect->p.x < 0 || prect->p.y < 0 ||
173
48.0k
            prect->q.x < prect->p.x || prect->q.y < prect->p.y ||
174
48.0k
            prect->q.x > width || prect->q.y > height
175
48.0k
            )
176
0
            return_error(gs_error_rangecheck);
177
48.0k
    }
178
154k
    *ppenum = NULL;   /* in case alloc fails and caller doesn't check code */
179
154k
    penum = gs_alloc_struct(mem, gx_image_enum, &st_gx_image_enum,
180
154k
                            "gx_default_begin_image");
181
154k
    if (penum == 0)
182
0
        return_error(gs_error_VMerror);
183
154k
    memset(penum, 0, sizeof(gx_image_enum));  /* in case of failure, no dangling pointers */
184
154k
    if (prect) {
185
48.0k
        penum->rect.x = prect->p.x;
186
48.0k
        penum->rect.y = prect->p.y;
187
48.0k
        penum->rect.w = prect->q.x - prect->p.x;
188
48.0k
        penum->rect.h = prect->q.y - prect->p.y;
189
106k
    } else {
190
106k
        penum->rect.x = 0, penum->rect.y = 0;
191
106k
        penum->rect.w = width, penum->rect.h = height;
192
106k
    }
193
154k
    penum->rrect.x = penum->rect.x;
194
154k
    penum->rrect.y = penum->rect.y;
195
154k
    penum->rrect.w = penum->rect.w;
196
154k
    penum->rrect.h = penum->rect.h;
197
154k
    penum->drect.x = penum->rect.x;
198
154k
    penum->drect.y = penum->rect.y;
199
154k
    penum->drect.w = penum->rect.w;
200
154k
    penum->drect.h = penum->rect.h;
201
#ifdef DEBUG
202
    if (gs_debug_c('b')) {
203
        dmlprintf2(mem, "[b]Image: w=%d h=%d", width, height);
204
        if (prect)
205
            dmprintf4(mem, " ((%d,%d),(%d,%d))",
206
                     prect->p.x, prect->p.y, prect->q.x, prect->q.y);
207
    }
208
#endif
209
154k
    *ppenum = penum;
210
154k
    return 0;
211
154k
}
212
213
/* Convert and restrict to a valid range. */
214
419k
static inline fixed float2fixed_rounded_boxed(double src) {
215
419k
    float v = floor(src*fixed_scale + 0.5);
216
217
419k
    if (v <= min_fixed)
218
8.81k
        return min_fixed;
219
410k
    else if (v >= max_fixed)
220
4.93k
        return max_fixed;
221
405k
    else
222
405k
        return  (fixed)v;
223
419k
}
224
225
/* Compute the image matrix combining the ImageMatrix with either the pmat or the pgs ctm */
226
int
227
gx_image_compute_mat(const gs_gstate *pgs, const gs_matrix *pmat, const gs_matrix *ImageMatrix,
228
                     gs_matrix_double *rmat)
229
269k
{
230
269k
    int code = 0;
231
232
269k
    if (pmat == 0)
233
269k
        pmat = &ctm_only(pgs);
234
269k
    if (ImageMatrix->xx == pmat->xx && ImageMatrix->xy == pmat->xy &&
235
269k
        ImageMatrix->yx == pmat->yx && ImageMatrix->yy == pmat->yy) {
236
        /* Process common special case separately to accept singular matrix. */
237
82.5k
        rmat->xx = rmat->yy = 1.;
238
82.5k
        rmat->xy = rmat->yx = 0.;
239
82.5k
        rmat->tx = pmat->tx - ImageMatrix->tx;
240
82.5k
        rmat->ty = pmat->ty - ImageMatrix->ty;
241
186k
    } else {
242
186k
        if ((code = gs_matrix_invert_to_double(ImageMatrix, rmat)) < 0 ||
243
186k
            (code = gs_matrix_multiply_double(rmat, pmat, rmat)) < 0
244
186k
            ) {
245
6
            return code;
246
6
        }
247
186k
    }
248
269k
    return code;
249
269k
}
250
251
/*
252
 * Finish initialization for processing an ImageType 1 or 4 image.
253
 * Assumes the following members of *penum are set in addition to those
254
 * set by gx_image_enum_alloc:
255
 *      alpha, use_mask_color, mask_color (if use_mask_color is true),
256
 *      masked, adjust
257
 */
258
int
259
gx_image_enum_begin(gx_device * dev, const gs_gstate * pgs,
260
                    const gs_matrix *pmat, const gs_image_common_t * pic,
261
                const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
262
                gs_memory_t * mem, gx_image_enum *penum)
263
154k
{
264
154k
    const gs_pixel_image_t *pim = (const gs_pixel_image_t *)pic;
265
154k
    gs_image_format_t format = pim->format;
266
154k
    const int width = pim->Width;
267
154k
    const int height = pim->Height;
268
154k
    const int bps = pim->BitsPerComponent;
269
154k
    bool masked = penum->masked;
270
154k
    const float *decode = pim->Decode;
271
154k
    gs_matrix_double mat;
272
154k
    int index_bps;
273
154k
    gs_color_space *pcs = pim->ColorSpace;
274
154k
    gs_logical_operation_t lop = (pgs ? pgs->log_op : lop_default);
275
154k
    int code;
276
154k
    int log2_xbytes = (bps <= 8 ? 0 : arch_log2_sizeof_frac);
277
154k
    int spp, nplanes, spread;
278
154k
    uint bsize;
279
154k
    byte *buffer = NULL;
280
154k
    fixed mtx, mty;
281
154k
    gs_fixed_point row_extent, col_extent, x_extent, y_extent;
282
154k
    bool device_color = true;
283
154k
    gs_fixed_rect obox, cbox;
284
154k
    bool gridfitimages = 0;
285
154k
    bool in_pattern_accumulator;
286
154k
    bool in_smask;
287
154k
    int orthogonal;
288
154k
    int force_interpolation = 0;
289
290
154k
    penum->pcs = NULL;
291
154k
    penum->clues = NULL;
292
154k
    penum->icc_setup.has_transfer = false;
293
154k
    penum->icc_setup.is_lab = false;
294
154k
    penum->icc_setup.must_halftone = false;
295
154k
    penum->icc_setup.need_decode = false;
296
154k
    penum->Width = width;
297
154k
    penum->Height = height;
298
299
154k
    if ((code = gx_image_compute_mat(pgs, pmat, &(pim->ImageMatrix), &mat)) < 0) {
300
3
        return code;
301
3
    }
302
154k
    lop = lop_sanitize(lop);
303
    /* Grid fit: A common construction in postscript/PDF files is for images
304
     * to be constructed as a series of 'stacked' 1 pixel high images.
305
     * Furthermore, many of these are implemented as an imagemask plotted on
306
     * top of thin rectangles. The different fill rules for images and line
307
     * art produces problems; line art fills a pixel if any part of it is
308
     * touched - images only fill a pixel if the centre of the pixel is
309
     * covered. Bug 692666 is such a problem.
310
     *
311
     * As a workaround for this problem, the code below was introduced. The
312
     * concept is that orthogonal images can be 'grid fitted' (or 'stretch')
313
     * to entirely cover pixels that they touch. Initially I had this working
314
     * for all images regardless of type, but as testing has proceeded, this
315
     * showed more and more regressions, so I've cut the cases back in which
316
     * this code is used until it now only triggers on imagemasks that are
317
     * either 1 pixel high, or wide, and then not if we are rendering a
318
     * glyph (such as from a type3 font).
319
     */
320
321
    /* Ask the device if we are in a pattern accumulator */
322
154k
    in_pattern_accumulator = (dev_proc(dev, dev_spec_op)(dev, gxdso_in_pattern_accumulator, NULL, 0));
323
154k
    if (in_pattern_accumulator < 0)
324
115k
        in_pattern_accumulator = 0;
325
326
    /* Figure out if we are orthogonal */
327
154k
    if (mat.xy == 0 && mat.yx == 0)
328
128k
        orthogonal = 1;
329
26.5k
    else if (mat.xx == 0 && mat.yy == 0)
330
6.49k
        orthogonal = 2;
331
20.0k
    else
332
20.0k
        orthogonal = 0;
333
334
    /* If we are in a pattern accumulator, we choose to always grid fit
335
     * orthogonal images. We do this by asking the device whether we
336
     * should grid fit. This allows us to avoid nasty blank lines around
337
     * the edges of cells. Similarly, for smasks.
338
     */
339
154k
    in_smask = (pim->override_in_smask ||
340
154k
                (dev_proc(dev, dev_spec_op)(dev, gxdso_in_smask, NULL, 0)) > 0);
341
154k
    gridfitimages = (in_smask || in_pattern_accumulator) && orthogonal;
342
343
154k
    if (pgs != NULL && pgs->show_gstate != NULL) {
344
        /* If we're a graphics state, and we're in a text object, then we
345
         * must be in a type3 font. Don't fiddle with it. */
346
126k
    } else if (!gridfitimages &&
347
126k
               (!penum->masked || penum->image_parent_type != 0)) {
348
        /* Other than for images we are specifically looking to grid fit (such as
349
         * ones in a pattern device), we only grid fit imagemasks */
350
82.2k
    } else if (gridfitimages && (penum->masked && penum->image_parent_type == 0)) {
351
        /* We don't gridfit imagemasks in a pattern accumulator */
352
44.3k
    } else if (pgs != NULL && pgs->fill_adjust.x == 0 && pgs->fill_adjust.y == 0) {
353
        /* If fill adjust is disabled, so is grid fitting */
354
44.3k
    } else if (orthogonal == 1) {
355
34.8k
        if (width == 1 || gridfitimages) {
356
31.3k
            if (mat.xx > 0) {
357
31.3k
                fixed ix0 = int2fixed(fixed2int(float2fixed(mat.tx)));
358
31.3k
                double x1 = mat.tx + mat.xx * width;
359
31.3k
                fixed ix1 = int2fixed(fixed2int_ceiling(float2fixed(x1)));
360
31.3k
                mat.tx = (double)fixed2float(ix0);
361
31.3k
                mat.xx = (double)(fixed2float(ix1 - ix0)/width);
362
31.3k
            } else if (mat.xx < 0) {
363
7
                fixed ix0 = int2fixed(fixed2int_ceiling(float2fixed(mat.tx)));
364
7
                double x1 = mat.tx + mat.xx * width;
365
7
                fixed ix1 = int2fixed(fixed2int(float2fixed(x1)));
366
7
                mat.tx = (double)fixed2float(ix0);
367
7
                mat.xx = (double)(fixed2float(ix1 - ix0)/width);
368
7
            }
369
31.3k
        }
370
34.8k
        if (height == 1 || gridfitimages) {
371
31.3k
            if (mat.yy > 0) {
372
31.3k
                fixed iy0 = int2fixed(fixed2int(float2fixed(mat.ty)));
373
31.3k
                double y1 = mat.ty + mat.yy * height;
374
31.3k
                fixed iy1 = int2fixed(fixed2int_ceiling(float2fixed(y1)));
375
31.3k
                mat.ty = (double)fixed2float(iy0);
376
31.3k
                mat.yy = (double)(fixed2float(iy1 - iy0)/height);
377
31.3k
            } else if (mat.yy < 0) {
378
60
                fixed iy0 = int2fixed(fixed2int_ceiling(float2fixed(mat.ty)));
379
60
                double y1 = mat.ty + mat.yy * height;
380
60
                fixed iy1 = int2fixed(fixed2int(float2fixed(y1)));
381
60
                mat.ty = (double)fixed2float(iy0);
382
60
                mat.yy = ((double)fixed2float(iy1 - iy0)/height);
383
60
            }
384
31.3k
        }
385
34.8k
    } else if (orthogonal == 2) {
386
6.45k
        if (height == 1 || gridfitimages) {
387
0
            if (mat.yx > 0) {
388
0
                fixed ix0 = int2fixed(fixed2int(float2fixed(mat.tx)));
389
0
                double x1 = mat.tx + mat.yx * height;
390
0
                fixed ix1 = int2fixed(fixed2int_ceiling(float2fixed(x1)));
391
0
                mat.tx = (double)fixed2float(ix0);
392
0
                mat.yx = (double)(fixed2float(ix1 - ix0)/height);
393
0
            } else if (mat.yx < 0) {
394
0
                fixed ix0 = int2fixed(fixed2int_ceiling(float2fixed(mat.tx)));
395
0
                double x1 = mat.tx + mat.yx * height;
396
0
                fixed ix1 = int2fixed(fixed2int(float2fixed(x1)));
397
0
                mat.tx = (double)fixed2float(ix0);
398
0
                mat.yx = (double)(fixed2float(ix1 - ix0)/height);
399
0
            }
400
0
        }
401
6.45k
        if (width == 1 || gridfitimages) {
402
0
            if (mat.xy > 0) {
403
0
                fixed iy0 = int2fixed(fixed2int(float2fixed(mat.ty)));
404
0
                double y1 = mat.ty + mat.xy * width;
405
0
                fixed iy1 = int2fixed(fixed2int_ceiling(float2fixed(y1)));
406
0
                mat.ty = (double)fixed2float(iy0);
407
0
                mat.xy = (double)(fixed2float(iy1 - iy0)/width);
408
0
            } else if (mat.xy < 0) {
409
0
                fixed iy0 = int2fixed(fixed2int_ceiling(float2fixed(mat.ty)));
410
0
                double y1 = mat.ty + mat.xy * width;
411
0
                fixed iy1 = int2fixed(fixed2int(float2fixed(y1)));
412
0
                mat.ty = (double)fixed2float(iy0);
413
0
                mat.xy = ((double)fixed2float(iy1 - iy0)/width);
414
0
            }
415
0
        }
416
6.45k
    }
417
418
    /* When rendering to a pattern accumulator, if we are downscaling
419
     * then enable interpolation, as otherwise dropouts can cause
420
     * serious problems. */
421
154k
    if (in_pattern_accumulator) {
422
39
        double ome = ((double)(fixed_1 - fixed_epsilon)) / (double)fixed_1; /* One Minus Epsilon */
423
424
39
        if (orthogonal == 1) {
425
29
            if ((mat.xx > -ome && mat.xx < ome) || (mat.yy > -ome && mat.yy < ome)) {
426
3
                force_interpolation = true;
427
3
            }
428
29
        } else if (orthogonal == 2) {
429
0
            if ((mat.xy > -ome && mat.xy < ome) || (mat.yx > -ome && mat.yx < ome)) {
430
0
                force_interpolation = true;
431
0
            }
432
0
        }
433
39
    }
434
435
    /* Can we restrict the amount of image we need? */
436
154k
    while (!pim->imagematrices_are_untrustworthy) /* So we can break out of it */
437
154k
    {
438
154k
        gs_rect rect, rect_src;
439
154k
        gs_matrix mi;
440
154k
        const gs_matrix *m = pgs != NULL ? &ctm_only(pgs) : NULL;
441
154k
        gs_int_rect irect;
442
154k
        if (m == NULL || (code = gs_matrix_invert(m, &mi)) < 0 ||
443
154k
            (code = gs_matrix_multiply(&mi, &pic->ImageMatrix, &mi)) < 0) {
444
            /* Give up trying to shrink the render box, but continue processing */
445
76
            break;
446
76
        }
447
154k
        if (pcpath)
448
60.4k
        {
449
60.4k
            gs_fixed_rect obox;
450
60.4k
            gx_cpath_outer_box(pcpath, &obox);
451
60.4k
            rect.p.x = fixed2float(obox.p.x);
452
60.4k
            rect.p.y = fixed2float(obox.p.y);
453
60.4k
            rect.q.x = fixed2float(obox.q.x);
454
60.4k
            rect.q.y = fixed2float(obox.q.y);
455
60.4k
        }
456
94.5k
        else
457
94.5k
        {
458
94.5k
            rect.p.x = 0;
459
94.5k
            rect.p.y = 0;
460
94.5k
            rect.q.x = dev->width;
461
94.5k
            rect.q.y = dev->height;
462
94.5k
        }
463
        /* rect is in destination space. Calculate rect_src, in source space. */
464
154k
        code = gs_bbox_transform(&rect, &mi, &rect_src);
465
154k
        if (code < 0) {
466
            /* Give up trying to shrink the render/decode boxes, but continue processing */
467
0
            break;
468
0
        }
469
        /* Need to expand the region to allow for the fact that the mitchell
470
         * scaler reads multiple pixels in. */
471
        /* If mi.{xx,yy} > 1 then we are downscaling. During downscaling,
472
         * the support increases to ensure that we don't lose pixels contributions
473
         * entirely. */
474
154k
        if (pim->Interpolate)
475
0
        {
476
0
            float support = any_abs(mi.xx);
477
0
            int isupport;
478
0
            if (any_abs(mi.yy) > support)
479
0
                support = any_abs(mi.yy);
480
0
            if (any_abs(mi.xy) > support)
481
0
                support = any_abs(mi.xy);
482
0
            if (any_abs(mi.yx) > support)
483
0
                support = any_abs(mi.yx);
484
            /* If upscaling (support < 1) then we need 2 extra lines on each side of the source region
485
             * (2 being the maximum support for mitchell scaling).
486
             * If downscaling, then the number of lines is increased to avoid individual
487
             * contributions dropping out. */
488
0
            isupport = 2; /* Mitchell support. */
489
0
            if (support > 1)
490
0
                isupport = (int)ceil(isupport * support);
491
0
            rect_src.p.x -= isupport;
492
0
            rect_src.p.y -= isupport;
493
0
            rect_src.q.x += isupport;
494
0
            rect_src.q.y += isupport+1; /* +1 is a fudge! */
495
0
        }
496
154k
        irect.p.x = (int)floor(rect_src.p.x);
497
154k
        irect.p.y = (int)floor(rect_src.p.y);
498
154k
        irect.q.x = (int)ceil(rect_src.q.x);
499
154k
        irect.q.y = (int)ceil(rect_src.q.y);
500
        /* We therefore only need to render within irect. Restrict rrect to this. */
501
154k
        if (penum->rrect.x < irect.p.x) {
502
1.02k
            penum->rrect.w -= irect.p.x - penum->rrect.x;
503
1.02k
            if (penum->rrect.w < 0)
504
781
               penum->rrect.w = 0;
505
1.02k
            penum->rrect.x = irect.p.x;
506
1.02k
        }
507
154k
        if (penum->rrect.x + penum->rrect.w > irect.q.x) {
508
29.0k
            penum->rrect.w = irect.q.x - penum->rrect.x;
509
29.0k
            if (penum->rrect.w < 0)
510
27.4k
                penum->rrect.w = 0;
511
29.0k
        }
512
154k
        if (penum->rrect.y < irect.p.y) {
513
22.9k
            penum->rrect.h -= irect.p.y - penum->rrect.y;
514
22.9k
            if (penum->rrect.h < 0)
515
13.3k
                penum->rrect.h = 0;
516
22.9k
            penum->rrect.y = irect.p.y;
517
22.9k
        }
518
154k
        if (penum->rrect.y + penum->rrect.h > irect.q.y) {
519
10.0k
            penum->rrect.h = irect.q.y - penum->rrect.y;
520
10.0k
            if (penum->rrect.h < 0)
521
278
                penum->rrect.h = 0;
522
10.0k
        }
523
154k
        if (penum->drect.x < irect.p.x) {
524
1.02k
            penum->drect.w -= irect.p.x - penum->drect.x;
525
1.02k
            if (penum->drect.w < 0)
526
781
               penum->drect.w = 0;
527
1.02k
            penum->drect.x = irect.p.x;
528
1.02k
        }
529
154k
        if (penum->drect.x + penum->drect.w > irect.q.x) {
530
29.0k
            penum->drect.w = irect.q.x - penum->drect.x;
531
29.0k
            if (penum->drect.w < 0)
532
27.4k
                penum->drect.w = 0;
533
29.0k
        }
534
154k
        if (penum->drect.y < irect.p.y) {
535
22.9k
            penum->drect.h -= irect.p.y - penum->drect.y;
536
22.9k
            if (penum->drect.h < 0)
537
13.3k
                penum->drect.h = 0;
538
22.9k
            penum->drect.y = irect.p.y;
539
22.9k
        }
540
154k
        if (penum->drect.y + penum->drect.h > irect.q.y) {
541
10.0k
            penum->drect.h = irect.q.y - penum->drect.y;
542
10.0k
            if (penum->drect.h < 0)
543
278
                penum->drect.h = 0;
544
10.0k
        }
545
154k
        break; /* Out of the while */
546
154k
    }
547
    /* Check for the intersection being null */
548
154k
    if (penum->drect.x + penum->drect.w <= penum->rect.x  ||
549
154k
        penum->rect.x  + penum->rect.w  <= penum->drect.x ||
550
154k
        penum->drect.y + penum->drect.h <= penum->rect.y  ||
551
154k
        penum->rect.y  + penum->rect.h  <= penum->drect.y)
552
29.9k
    {
553
          /* Something may have gone wrong with the floating point above.
554
           * set the region to something sane. */
555
29.9k
        penum->drect.x = penum->rect.x;
556
29.9k
        penum->drect.y = penum->rect.y;
557
29.9k
        penum->drect.w = 0;
558
29.9k
        penum->drect.h = 0;
559
29.9k
    }
560
154k
    if (penum->rrect.x + penum->rrect.w <= penum->drect.x  ||
561
154k
        penum->drect.x + penum->drect.w  <= penum->rrect.x ||
562
154k
        penum->rrect.y + penum->rrect.h <= penum->drect.y  ||
563
154k
        penum->drect.y + penum->drect.h  <= penum->rrect.y)
564
29.9k
    {
565
          /* Something may have gone wrong with the floating point above.
566
           * set the region to something sane. */
567
29.9k
        penum->rrect.x = penum->drect.x;
568
29.9k
        penum->rrect.y = penum->drect.y;
569
29.9k
        penum->rrect.w = 0;
570
29.9k
        penum->rrect.h = 0;
571
29.9k
    }
572
573
    /*penum->matrix = mat;*/
574
154k
    penum->matrix.xx = mat.xx;
575
154k
    penum->matrix.xy = mat.xy;
576
154k
    penum->matrix.yx = mat.yx;
577
154k
    penum->matrix.yy = mat.yy;
578
154k
    penum->matrix.tx = mat.tx;
579
154k
    penum->matrix.ty = mat.ty;
580
154k
    if_debug6m('b', mem, " [%g %g %g %g %g %g]\n",
581
154k
              mat.xx, mat.xy, mat.yx, mat.yy, mat.tx, mat.ty);
582
    /* following works for 1, 2, 4, 8, 12, 16 */
583
154k
    index_bps = (bps < 8 ? bps >> 1 : (bps >> 2) + 1);
584
    /*
585
     * Compute extents with distance transformation.
586
     */
587
154k
    if (mat.tx > 0)
588
134k
        mtx = float2fixed(mat.tx);
589
20.1k
    else { /* Use positive values to ensure round down. */
590
20.1k
        int f = (int)-mat.tx + 1;
591
592
20.1k
        mtx = float2fixed(mat.tx + f) - int2fixed(f);
593
20.1k
    }
594
154k
    if (mat.ty > 0)
595
38.0k
        mty = float2fixed(mat.ty);
596
116k
    else {  /* Use positive values to ensure round down. */
597
116k
        int f = (int)-mat.ty + 1;
598
599
116k
        mty = float2fixed(mat.ty + f) - int2fixed(f);
600
116k
    }
601
602
154k
    row_extent.x = float2fixed_rounded_boxed(width * mat.xx);
603
154k
    row_extent.y =
604
154k
        (is_fzero(mat.xy) ? fixed_0 :
605
154k
         float2fixed_rounded_boxed(width * mat.xy));
606
154k
    col_extent.x =
607
154k
        (is_fzero(mat.yx) ? fixed_0 :
608
154k
         float2fixed_rounded_boxed(height * mat.yx));
609
154k
    col_extent.y = float2fixed_rounded_boxed(height * mat.yy);
610
154k
    gx_image_enum_common_init((gx_image_enum_common_t *)penum,
611
154k
                              (const gs_data_image_t *)pim,
612
154k
                              &image1_enum_procs, dev,
613
154k
                              (masked ? 1 : (penum->alpha ? cs_num_components(pcs)+1 : cs_num_components(pcs))),
614
154k
                              format);
615
154k
    if (penum->rect.w == width && penum->rect.h == height) {
616
117k
        x_extent = row_extent;
617
117k
        y_extent = col_extent;
618
117k
    } else {
619
37.8k
        int rw = penum->rect.w, rh = penum->rect.h;
620
621
37.8k
        x_extent.x = float2fixed_rounded_boxed(rw * mat.xx);
622
37.8k
        x_extent.y =
623
37.8k
            (is_fzero(mat.xy) ? fixed_0 :
624
37.8k
             float2fixed_rounded_boxed(rw * mat.xy));
625
37.8k
        y_extent.x =
626
37.8k
            (is_fzero(mat.yx) ? fixed_0 :
627
37.8k
             float2fixed_rounded_boxed(rh * mat.yx));
628
37.8k
        y_extent.y = float2fixed_rounded_boxed(rh * mat.yy);
629
37.8k
    }
630
    /* Set icolor0 and icolor1 to point to image clues locations if we have
631
       1spp or an imagemask, otherwise image clues is not used and
632
       we have these values point to other member variables */
633
154k
    if (masked || cs_num_components(pcs) == 1) {
634
        /* Go ahead and allocate now if not already done.  For a mask
635
           we really should only do 2 values. For now, the goal is to
636
           eliminate the 256 bytes for the >8bpp image enumerator */
637
101k
        penum->clues = (gx_image_clue*) gs_alloc_bytes(mem, sizeof(gx_image_clue)*256,
638
101k
                             "gx_image_enum_begin");
639
101k
        if (penum->clues == NULL) {
640
0
            code = gs_error_VMerror;
641
0
            goto fail;
642
0
        }
643
101k
        penum->icolor0 = &(penum->clues[0].dev_color);
644
101k
        penum->icolor1 = &(penum->clues[255].dev_color);
645
101k
    } else {
646
53.8k
        penum->icolor0 = &(penum->icolor0_val);
647
53.8k
        penum->icolor1 = &(penum->icolor1_val);
648
53.8k
    }
649
154k
    penum->icolor0->tag = penum->icolor1->tag = device_current_tag(dev);
650
651
154k
    if (masked) {       /* This is imagemask. */
652
41.3k
        if (bps != 1 || pcs != NULL || penum->alpha || decode[0] == decode[1]) {
653
1
            code = gs_error_rangecheck;
654
1
            goto fail;
655
1
        }
656
        /* Initialize color entries 0 and 255. */
657
41.3k
        set_nonclient_dev_color(penum->icolor0, gx_no_color_index);
658
41.3k
        set_nonclient_dev_color(penum->icolor1, gx_no_color_index);
659
41.3k
        *(penum->icolor1) = *pdcolor;
660
41.3k
        memcpy(&penum->map[0].table.lookup4x1to32[0],
661
41.3k
               (decode[0] < decode[1] ? lookup4x1to32_inverted :
662
41.3k
                lookup4x1to32_identity),
663
41.3k
               16 * 4);
664
41.3k
        penum->map[0].decoding = sd_none;
665
41.3k
        spp = 1;
666
41.3k
        lop = rop3_know_S_0(lop);
667
113k
    } else {                    /* This is image, not imagemask. */
668
113k
        const gs_color_space_type *pcst = pcs->type;
669
113k
        int b_w_color;
670
671
113k
        spp = cs_num_components(pcs);
672
113k
        if (spp < 0) {          /* Pattern not allowed */
673
0
            code = gs_error_rangecheck;
674
0
            goto fail;
675
0
        }
676
113k
        if (penum->alpha)
677
0
            ++spp;
678
        /* Use a less expensive format if possible. */
679
113k
        switch (format) {
680
0
        case gs_image_format_bit_planar:
681
0
            if (bps > 1)
682
0
                break;
683
0
            format = gs_image_format_component_planar;
684
0
        case gs_image_format_component_planar:
685
0
            if (spp == 1)
686
0
                format = gs_image_format_chunky;
687
113k
        default:                /* chunky */
688
113k
            break;
689
113k
        }
690
691
113k
        if (pcs->cmm_icc_profile_data != NULL) {
692
112k
            device_color = false;
693
112k
        } else {
694
1.24k
            device_color = (*pcst->concrete_space) (pcs, pgs) == pcs;
695
1.24k
        }
696
697
113k
        code = image_init_colors(penum, bps, spp, format, decode, pgs, dev,
698
113k
                          pcs, &device_color);
699
113k
        if (code < 0) {
700
3
            gs_free_object(mem, penum->clues, "gx_image_enum_begin");
701
3
            gs_free_object(mem, penum, "gx_default_begin_image");
702
3
            return gs_throw(code, "Image colors initialization failed");
703
3
        }
704
        /* If we have a CIE based color space and the icc equivalent profile
705
           is not yet set, go ahead and handle that now.  It may already
706
           be done due to the above init_colors which may go through remap. */
707
113k
        if (gs_color_space_is_PSCIE(pcs) && pcs->icc_equivalent == NULL) {
708
0
            code = gs_colorspace_set_icc_equivalent((gs_color_space *)pcs, &(penum->icc_setup.is_lab),
709
0
                                                pgs->memory);
710
0
            if (code < 0)
711
0
                goto fail;
712
0
            if (penum->icc_setup.is_lab) {
713
                /* Free what ever profile was created and use the icc manager's
714
                   cielab profile */
715
0
                gs_color_space *curr_pcs = (gs_color_space *)pcs;
716
0
                rc_decrement(curr_pcs->icc_equivalent,"gx_image_enum_begin");
717
0
                gsicc_adjust_profile_rc(curr_pcs->cmm_icc_profile_data, -1,"gx_image_enum_begin");
718
0
                curr_pcs->cmm_icc_profile_data = pgs->icc_manager->lab_profile;
719
0
                gsicc_adjust_profile_rc(curr_pcs->cmm_icc_profile_data, 1,"gx_image_enum_begin");
720
0
            }
721
0
        }
722
        /* Try to transform non-default RasterOps to something */
723
        /* that we implement less expensively. */
724
113k
        if (!pim->CombineWithColor)
725
113k
            lop = rop3_know_T_0(lop);
726
0
        else if ((rop3_uses_T(lop) && color_draws_b_w(dev, pdcolor) == 0))
727
0
            lop = rop3_know_T_0(lop);
728
729
113k
        if (lop != rop3_S &&    /* if best case, no more work needed */
730
113k
            !rop3_uses_T(lop) && bps == 1 && spp == 1 &&
731
113k
            (b_w_color =
732
0
             color_draws_b_w(dev, penum->icolor0)) >= 0 &&
733
113k
            color_draws_b_w(dev, penum->icolor1) == (b_w_color ^ 1)
734
113k
            ) {
735
0
            if (b_w_color) {    /* Swap the colors and invert the RasterOp source. */
736
0
                gx_device_color dcolor;
737
738
0
                dcolor = *(penum->icolor0);
739
0
                *(penum->icolor0) = *(penum->icolor1);
740
0
                *(penum->icolor1) = dcolor;
741
0
                lop = rop3_invert_S(lop);
742
0
            }
743
            /*
744
             * At this point, we know that the source pixels
745
             * correspond directly to the S input for the raster op,
746
             * i.e., icolor0 is black and icolor1 is white.
747
             */
748
0
            switch (lop) {
749
0
                case rop3_D & rop3_S:
750
                    /* Implement this as an inverted mask writing 0s. */
751
0
                    *(penum->icolor1) = *(penum->icolor0);
752
                    /* (falls through) */
753
0
                case rop3_D | rop3_not(rop3_S):
754
                    /* Implement this as an inverted mask writing 1s. */
755
0
                    memcpy(&penum->map[0].table.lookup4x1to32[0],
756
0
                           lookup4x1to32_inverted, 16 * 4);
757
0
                  rmask:        /* Fill in the remaining parameters for a mask. */
758
0
                    penum->masked = masked = true;
759
0
                    set_nonclient_dev_color(penum->icolor0, gx_no_color_index);
760
0
                    penum->map[0].decoding = sd_none;
761
0
                    lop = rop3_T;
762
0
                    break;
763
0
                case rop3_D & rop3_not(rop3_S):
764
                    /* Implement this as a mask writing 0s. */
765
0
                    *(penum->icolor1) = *(penum->icolor0);
766
                    /* (falls through) */
767
0
                case rop3_D | rop3_S:
768
                    /* Implement this as a mask writing 1s. */
769
0
                    memcpy(&penum->map[0].table.lookup4x1to32[0],
770
0
                           lookup4x1to32_identity, 16 * 4);
771
0
                    goto rmask;
772
0
                default:
773
0
                    ;
774
0
            }
775
0
        }
776
113k
    }
777
154k
    penum->device_color = device_color;
778
    /*
779
     * Adjust width upward for unpacking up to 7 trailing bits in
780
     * the row, plus 1 byte for end-of-run, plus up to 7 leading
781
     * bits for data_x offset within a packed byte.
782
     */
783
154k
    bsize = ((bps > 8 ? width * 2 : width) + 15) * spp;
784
154k
    buffer = gs_alloc_bytes(mem, bsize, "image buffer");
785
154k
    if (buffer == 0) {
786
0
        code = gs_error_VMerror;
787
0
        goto fail;
788
0
    }
789
154k
    penum->bps = bps;
790
154k
    penum->unpack_bps = bps;
791
154k
    penum->log2_xbytes = log2_xbytes;
792
154k
    penum->spp = spp;
793
154k
    switch (format) {
794
154k
    case gs_image_format_chunky:
795
154k
        nplanes = 1;
796
154k
        spread = 1 << log2_xbytes;
797
154k
        break;
798
0
    case gs_image_format_component_planar:
799
0
        nplanes = spp;
800
0
        spread = spp << log2_xbytes;
801
0
        break;
802
0
    case gs_image_format_bit_planar:
803
0
        nplanes = spp * bps;
804
0
        spread = spp << log2_xbytes;
805
0
        break;
806
0
    default:
807
        /* No other cases are possible (checked by gx_image_enum_alloc). */
808
0
        return_error(gs_error_Fatal);
809
154k
    }
810
154k
    penum->num_planes = nplanes;
811
154k
    penum->spread = spread;
812
    /*
813
     * If we're asked to interpolate in a partial image, we have to
814
     * assume that the client either really only is interested in
815
     * the given sub-image, or else is constructing output out of
816
     * overlapping pieces.
817
     */
818
154k
    penum->interpolate = force_interpolation ? interp_force : pim->Interpolate ? interp_on : interp_off;
819
154k
    penum->x_extent = x_extent;
820
154k
    penum->y_extent = y_extent;
821
154k
    penum->posture =
822
154k
        ((x_extent.y | y_extent.x) == 0 ? image_portrait :
823
154k
         (x_extent.x | y_extent.y) == 0 ? image_landscape :
824
26.5k
         image_skewed);
825
154k
    penum->pgs = pgs;
826
154k
    if (pgs != NULL)
827
154k
        penum->pgs_level = pgs->level;
828
154k
    penum->pcs = pcs;
829
154k
    rc_increment_cs(pcs); /* Grab a ref (will decrement in gx_image1_end_image() */
830
154k
    penum->memory = mem;
831
154k
    penum->buffer = buffer;
832
154k
    penum->buffer_size = bsize;
833
154k
    penum->line = NULL;
834
154k
    penum->icc_link = NULL;
835
154k
    penum->color_cache = NULL;
836
154k
    penum->ht_buffer = NULL;
837
154k
    penum->thresh_buffer = NULL;
838
154k
    penum->use_cie_range = false;
839
154k
    penum->line_size = 0;
840
154k
    penum->use_rop = lop != (masked ? rop3_T : rop3_S);
841
#ifdef DEBUG
842
    if (gs_debug_c('*')) {
843
        if (penum->use_rop)
844
            dmprintf1(mem, "[%03x]", lop);
845
        dmprintf5(mem, "%c%d%c%dx%d ",
846
                 (masked ? (color_is_pure(pdcolor) ? 'm' : 'h') : 'i'),
847
                 bps,
848
                 (penum->posture == image_portrait ? ' ' :
849
                  penum->posture == image_landscape ? 'L' : 'T'),
850
                 width, height);
851
    }
852
#endif
853
154k
    penum->slow_loop = 0;
854
154k
    if (pcpath == 0) {
855
94.5k
        (*dev_proc(dev, get_clipping_box)) (dev, &obox);
856
94.5k
        cbox = obox;
857
94.5k
        penum->clip_image = 0;
858
94.5k
    } else
859
60.4k
        penum->clip_image =
860
60.4k
            (gx_cpath_outer_box(pcpath, &obox) |        /* not || */
861
60.4k
             gx_cpath_inner_box(pcpath, &cbox) ?
862
60.3k
             0 : image_clip_region);
863
154k
    penum->clip_outer = obox;
864
154k
    penum->clip_inner = cbox;
865
154k
    penum->log_op = rop3_T;     /* rop device takes care of this */
866
154k
    penum->clip_dev = 0;        /* in case we bail out */
867
154k
    penum->rop_dev = 0;         /* ditto */
868
154k
    penum->scaler = 0;          /* ditto */
869
    /*
870
     * If all four extrema of the image fall within the clipping
871
     * rectangle, clipping is never required.  When making this check,
872
     * we must carefully take into account the fact that we only care
873
     * about pixel centers.
874
     */
875
154k
    {
876
154k
        fixed
877
154k
            epx = min(row_extent.x, 0) + min(col_extent.x, 0),
878
154k
            eqx = max(row_extent.x, 0) + max(col_extent.x, 0),
879
154k
            epy = min(row_extent.y, 0) + min(col_extent.y, 0),
880
154k
            eqy = max(row_extent.y, 0) + max(col_extent.y, 0);
881
882
154k
        {
883
154k
            int hwx, hwy;
884
885
154k
            switch (penum->posture) {
886
128k
                case image_portrait:
887
128k
                    hwx = width, hwy = height;
888
128k
                    break;
889
6.50k
                case image_landscape:
890
6.50k
                    hwx = height, hwy = width;
891
6.50k
                    break;
892
20.0k
                default:
893
20.0k
                    hwx = hwy = 0;
894
154k
            }
895
            /*
896
             * If the image is only 1 sample wide or high,
897
             * and is less than 1 device pixel wide or high,
898
             * move it slightly so that it covers pixel centers.
899
             * This is a hack to work around a bug in some old
900
             * versions of TeX/dvips, which use 1-bit-high images
901
             * to draw horizontal and vertical lines without
902
             * positioning them properly.
903
             */
904
154k
            if (hwx == 1 && eqx - epx < fixed_1) {
905
4
                fixed diff =
906
4
                arith_rshift_1(row_extent.x + col_extent.x);
907
908
4
                mtx = (((mtx + diff) | fixed_half) & -fixed_half) - diff;
909
4
            }
910
154k
            if (hwy == 1 && eqy - epy < fixed_1) {
911
2
                fixed diff =
912
2
                arith_rshift_1(row_extent.y + col_extent.y);
913
914
2
                mty = (((mty + diff) | fixed_half) & -fixed_half) - diff;
915
2
            }
916
154k
        }
917
154k
        if_debug5m('b', mem, "[b]Image: %sspp=%d, bps=%d, mt=(%g,%g)\n",
918
154k
                   (masked? "masked, " : ""), spp, bps,
919
154k
                   fixed2float(mtx), fixed2float(mty));
920
154k
        if_debug9m('b', mem,
921
154k
                   "[b]   cbox=(%g,%g),(%g,%g), obox=(%g,%g),(%g,%g), clip_image=0x%x\n",
922
154k
                   fixed2float(cbox.p.x), fixed2float(cbox.p.y),
923
154k
                   fixed2float(cbox.q.x), fixed2float(cbox.q.y),
924
154k
                   fixed2float(obox.p.x), fixed2float(obox.p.y),
925
154k
                   fixed2float(obox.q.x), fixed2float(obox.q.y),
926
154k
                   penum->clip_image);
927
        /* These DDAs enumerate the starting position of each source pixel
928
         * row in device space. */
929
154k
        dda_init(penum->dda.row.x, mtx, col_extent.x, height);
930
154k
        dda_init(penum->dda.row.y, mty, col_extent.y, height);
931
154k
        if (dda_will_overflow(penum->dda.row.x) ||
932
154k
            dda_will_overflow(penum->dda.row.y))
933
0
        {
934
0
            code = gs_error_rangecheck;
935
0
            goto fail;
936
0
        }
937
154k
        if (penum->posture == image_portrait) {
938
128k
            penum->dst_width = row_extent.x;
939
128k
            penum->dst_height = col_extent.y;
940
128k
        } else {
941
26.5k
            penum->dst_width = col_extent.x;
942
26.5k
            penum->dst_height = row_extent.y;
943
26.5k
        }
944
        /* For gs_image_class_0_interpolate. */
945
154k
        penum->yi0 = fixed2int_pixround_perfect(dda_current(penum->dda.row.y)); /* For gs_image_class_0_interpolate. */
946
154k
        if (penum->rect.y) {
947
33.8k
            int y = penum->rect.y;
948
949
3.74M
            while (y--) {
950
3.71M
                dda_next(penum->dda.row.x);
951
3.71M
                dda_next(penum->dda.row.y);
952
3.71M
            }
953
33.8k
        }
954
154k
        penum->cur.x = penum->prev.x = dda_current(penum->dda.row.x);
955
154k
        penum->cur.y = penum->prev.y = dda_current(penum->dda.row.y);
956
        /* These DDAs enumerate the starting positions of each row of our
957
         * source pixel data, in the subrectangle ('strip') that we are
958
         * actually rendering. */
959
154k
        dda_init(penum->dda.strip.x, penum->cur.x, row_extent.x, width);
960
154k
        dda_init(penum->dda.strip.y, penum->cur.y, row_extent.y, width);
961
154k
        if (dda_will_overflow(penum->dda.strip.x) ||
962
154k
            dda_will_overflow(penum->dda.strip.y))
963
0
        {
964
0
            code = gs_error_rangecheck;
965
0
            goto fail;
966
0
        }
967
154k
        if (penum->rect.x) {
968
169
            dda_advance(penum->dda.strip.x, penum->rect.x);
969
169
            dda_advance(penum->dda.strip.y, penum->rect.x);
970
169
        }
971
154k
        {
972
154k
            fixed ox = dda_current(penum->dda.strip.x);
973
154k
            fixed oy = dda_current(penum->dda.strip.y);
974
975
154k
            if (!penum->clip_image)     /* i.e., not clip region */
976
154k
                penum->clip_image =
977
154k
                    (fixed_pixround(ox + epx) < fixed_pixround(cbox.p.x) ?
978
151k
                     image_clip_xmin : 0) +
979
154k
                    (fixed_pixround(ox + eqx) >= fixed_pixround(cbox.q.x) ?
980
110k
                     image_clip_xmax : 0) +
981
154k
                    (fixed_pixround(oy + epy) < fixed_pixround(cbox.p.y) ?
982
121k
                     image_clip_ymin : 0) +
983
154k
                    (fixed_pixround(oy + eqy) >= fixed_pixround(cbox.q.y) ?
984
116k
                     image_clip_ymax : 0);
985
154k
        }
986
154k
    }
987
0
    penum->y = 0;
988
154k
    penum->used.x = 0;
989
154k
    penum->used.y = 0;
990
154k
    if (penum->clip_image && pcpath) {  /* Set up the clipping device. */
991
40.5k
        gx_device_clip *cdev =
992
40.5k
            gs_alloc_struct(mem, gx_device_clip,
993
40.5k
                            &st_device_clip, "image clipper");
994
995
40.5k
        if (cdev == NULL) {
996
0
            code = gs_error_VMerror;
997
0
            goto fail;
998
0
        }
999
40.5k
        gx_make_clip_device_in_heap(cdev, pcpath, dev, mem);
1000
40.5k
        penum->clip_dev = cdev;
1001
40.5k
        penum->dev = (gx_device *)cdev; /* Will restore this in a mo. Hacky! */
1002
40.5k
    }
1003
154k
    if (penum->use_rop) {       /* Set up the RasterOp source device. */
1004
0
        gx_device_rop_texture *rtdev;
1005
1006
0
        code = gx_alloc_rop_texture_device(&rtdev, mem,
1007
0
                                           "image RasterOp");
1008
0
        if (code < 0)
1009
0
            goto fail;
1010
        /* The 'target' must not be NULL for gx_make_rop_texture_device */
1011
0
        if (!penum->clip_dev && !dev)
1012
0
            return_error(gs_error_undefined);
1013
1014
0
        gx_make_rop_texture_device(rtdev,
1015
0
                                   (penum->clip_dev != 0 ?
1016
0
                                    (gx_device *) penum->clip_dev :
1017
0
                                    dev), lop, pdcolor);
1018
0
        gx_device_retain((gx_device *)rtdev, true);
1019
0
        penum->rop_dev = rtdev;
1020
0
        penum->dev = (gx_device *)rtdev; /* Will restore this in a mo. Hacky! */
1021
0
    }
1022
154k
    {
1023
154k
        static sample_unpack_proc_t procs[2][6] = {
1024
154k
        {   sample_unpack_1, sample_unpack_2,
1025
154k
            sample_unpack_4, sample_unpack_8,
1026
154k
            sample_unpack_12, sample_unpack_16
1027
154k
        },
1028
154k
        {   sample_unpack_1_interleaved, sample_unpack_2_interleaved,
1029
154k
            sample_unpack_4_interleaved, sample_unpack_8_interleaved,
1030
154k
            sample_unpack_12, sample_unpack_16
1031
154k
        }};
1032
154k
        int num_planes = penum->num_planes;
1033
154k
        bool interleaved = (num_planes == 1 && penum->plane_depths[0] != penum->bps);
1034
154k
        irender_proc_t render_fn = NULL;
1035
154k
        int i;
1036
1037
154k
        if (interleaved) {
1038
53.8k
            int num_components = penum->plane_depths[0] / penum->bps;
1039
1040
164k
            for (i = 1; i < num_components; i++) {
1041
110k
                if (decode[0] != decode[i * 2 + 0] ||
1042
110k
                    decode[1] != decode[i * 2 + 1])
1043
0
                    break;
1044
110k
            }
1045
53.8k
            if (i == num_components)
1046
53.8k
                interleaved = false; /* Use single table. */
1047
53.8k
        }
1048
154k
        penum->unpack = procs[interleaved][index_bps];
1049
1050
154k
        if_debug1m('b', mem, "[b]unpack=%d\n", bps);
1051
        /* Set up pixel0 for image class procedures. */
1052
154k
        penum->dda.pixel0 = penum->dda.strip;
1053
154k
        penum->skip_next_line = NULL;
1054
641k
        for (i = 0; i < gx_image_class_table_count; ++i) {
1055
641k
            code = gx_image_class_table[i](penum, &render_fn);
1056
641k
            if (code < 0)
1057
0
                goto fail;
1058
1059
641k
            if (render_fn != NULL) {
1060
154k
                penum->render = render_fn;
1061
154k
                break;
1062
154k
            }
1063
641k
        }
1064
154k
        penum->dev = dev; /* Restore this (in case it was changed to cdev or rtdev) */
1065
154k
        if (i == gx_image_class_table_count) {
1066
            /* No available class can handle this image. */
1067
0
            return_error(gs_error_rangecheck);
1068
0
        }
1069
154k
    }
1070
154k
    return 0;
1071
1072
1
fail:
1073
1
    gs_free_object(mem, buffer, "image buffer");
1074
1
    gs_free_object(mem, penum->clues, "gx_image_enum_begin");
1075
1
    if (penum->clip_dev != NULL) {
1076
0
        rc_decrement(penum->clip_dev, "error in gx_begin_image1");
1077
0
        penum->clip_dev = NULL;
1078
0
    }
1079
1
    gs_free_object(mem, penum->clip_dev, "image clipper");
1080
1
    rc_decrement_cs(penum->pcs, "error in gx_begin_image1");
1081
1
    penum->pcs = NULL;
1082
1
    gs_free_object(mem, penum, "gx_begin_image1");
1083
1
    return code;
1084
154k
}
1085
1086
/* If a drawing color is black or white, return 0 or 1 respectively, */
1087
/* otherwise return -1. */
1088
static int
1089
color_draws_b_w(gx_device * dev, const gx_drawing_color * pdcolor)
1090
0
{
1091
0
    if (color_is_pure(pdcolor)) {
1092
0
        gx_color_value rgb[3];
1093
1094
0
        (*dev_proc(dev, map_color_rgb)) (dev, gx_dc_pure_color(pdcolor),
1095
0
                                         rgb);
1096
0
        if (!(rgb[0] | rgb[1] | rgb[2]))
1097
0
            return 0;
1098
0
        if ((rgb[0] & rgb[1] & rgb[2]) == gx_max_color_value)
1099
0
            return 1;
1100
0
    }
1101
0
    return -1;
1102
0
}
1103
1104
1105
static void
1106
image_cache_decode(gx_image_enum *penum, byte input, byte *output, bool scale)
1107
0
{
1108
0
    float temp;
1109
1110
0
    switch ( penum->map[0].decoding ) {
1111
0
        case sd_none:
1112
0
            *output = input;
1113
0
            break;
1114
0
        case sd_lookup:
1115
0
            temp = penum->map[0].decode_lookup[input >> 4]*255.0f;
1116
0
            if (temp > 255) temp = 255;
1117
0
            if (temp < 0 ) temp = 0;
1118
0
            *output = (unsigned char) temp;
1119
0
            break;
1120
0
        case sd_compute:
1121
0
            temp = penum->map[0].decode_base +
1122
0
                (float) input * penum->map[0].decode_factor;
1123
0
            if (scale) {
1124
0
                temp = temp * 255.0;
1125
0
            }
1126
0
            if (temp > 255) temp = 255;
1127
0
            if (temp < 0 ) temp = 0;
1128
0
            *output = (unsigned char) temp;
1129
0
            break;
1130
0
        default:
1131
0
            *output = 0;
1132
0
            break;
1133
0
    }
1134
0
}
1135
1136
static bool
1137
decode_range_needed(gx_image_enum *penum)
1138
0
{
1139
0
    bool scale = true;
1140
1141
0
    if (penum->map[0].decoding == sd_compute) {
1142
0
        if (!(gs_color_space_is_ICC(penum->pcs) ||
1143
0
            gs_color_space_is_PSCIE(penum->pcs))) {
1144
0
            scale = false;
1145
0
        }
1146
0
    }
1147
0
    return scale;
1148
0
}
1149
1150
/* A special case where we go ahead and initialize the whole index cache with
1151
   contone.  Device colors.  If we are halftoning we will then go ahead and
1152
   apply the thresholds to the device contone values.  Only used for gray,
1153
   rgb or cmyk source colors (No DeviceN for now) */
1154
/* TO DO  Add in PSCIE decoder */
1155
int
1156
image_init_color_cache(gx_image_enum * penum, int bps, int spp)
1157
38.9k
{
1158
38.9k
    int num_des_comp = penum->dev->color_info.num_components;
1159
38.9k
    int num_src_comp;
1160
38.9k
    int num_entries = 1 << bps;
1161
38.9k
    bool need_decode = penum->icc_setup.need_decode;
1162
38.9k
    bool has_transfer = penum->icc_setup.has_transfer;
1163
38.9k
    byte value;
1164
38.9k
    bool decode_scale = true;
1165
38.9k
    int k, kk;
1166
38.9k
    byte psrc[4];
1167
38.9k
    byte *temp_buffer;
1168
38.9k
    byte *byte_ptr;
1169
38.9k
    bool is_indexed = (gs_color_space_get_index(penum->pcs) ==
1170
38.9k
                                            gs_color_space_index_Indexed);
1171
38.9k
    bool free_temp_buffer = true;
1172
38.9k
    gsicc_bufferdesc_t input_buff_desc;
1173
38.9k
    gsicc_bufferdesc_t output_buff_desc;
1174
38.9k
    gx_color_value conc[GX_DEVICE_COLOR_MAX_COMPONENTS];
1175
38.9k
    int code;
1176
1177
38.9k
    if (penum->icc_link == NULL) {
1178
0
        return gs_rethrow(-1, "ICC Link not created during image render color");
1179
0
    }
1180
38.9k
    if (is_indexed) {
1181
741
        num_src_comp = gs_color_space_num_components(penum->pcs->base_space);
1182
38.1k
    } else {
1183
        /* Detect case where cache is not needed.  Colors are already in the
1184
           device space.  Need to fast track this one and halftone row directly.
1185
           Detected in gximono.c by looking if penum->color_cache is NULL */
1186
38.1k
        if (penum->icc_link->is_identity && !need_decode && !has_transfer) {
1187
38.1k
            return 0;
1188
38.1k
        }
1189
22
        num_src_comp = 1;
1190
22
    }
1191
    /* Allocate cache of device contone values */
1192
763
    penum->color_cache = gs_alloc_struct(penum->memory, gx_image_color_cache_t,
1193
763
                                         &st_color_cache,
1194
763
                                         "image_init_color_cache");
1195
763
    if (penum->color_cache == NULL)
1196
0
        return_error(gs_error_VMerror);
1197
1198
763
    penum->color_cache->device_contone = (byte*) gs_alloc_bytes(penum->memory,
1199
763
                   num_des_comp * num_entries * sizeof(byte), "image_init_color_cache");
1200
763
    penum->color_cache->is_transparent = (bool*) gs_alloc_bytes(penum->memory,
1201
763
             num_entries * sizeof(bool), "image_init_color_cache");
1202
763
    if (penum->color_cache->device_contone == NULL || penum->color_cache->is_transparent == NULL) {
1203
0
        gs_free_object(penum->memory, penum->color_cache->device_contone, "image_init_color_cache");
1204
0
        gs_free_object(penum->memory, penum->color_cache->is_transparent, "image_init_color_cache");
1205
0
        gs_free_object(penum->memory, penum->color_cache, "image_init_color_cache");
1206
0
        penum->color_cache = NULL;
1207
0
        return_error(gs_error_VMerror);
1208
0
    }
1209
    /* Initialize */
1210
763
    memset(penum->color_cache->is_transparent,0,num_entries * sizeof(bool));
1211
    /* Depending upon if we need decode and ICC CM, fill the cache a couple
1212
       different ways. If the link is the identity, then we don't need to do any
1213
       color conversions except for potentially a decode.  This is written in
1214
       the manner shown below so that the common case of no decode and indexed
1215
       image with a look-up-table uses the table data directly or does as many
1216
       operations with memcpy as we can */
1217
    /* Need to check the decode output range so we know how we need to scale.
1218
       We want 8 bit output */
1219
763
    if (need_decode) {
1220
0
        decode_scale = decode_range_needed(penum);
1221
0
    }
1222
763
    if (penum->icc_link->is_identity) {
1223
        /* No CM needed.  */
1224
0
        if (need_decode || has_transfer) {
1225
            /* Slower case.  This could be sped up later to avoid the tests
1226
               within the loop by use of specialized loops.  */
1227
0
            for (k = 0; k < num_entries; k++) {
1228
                /* Data is in k */
1229
0
                if (need_decode) {
1230
0
                    image_cache_decode(penum, k, &value, decode_scale);
1231
0
                } else {
1232
0
                    value = k;
1233
0
                }
1234
                /* Data is in value */
1235
0
                if (is_indexed) {
1236
0
                    gs_cspace_indexed_lookup_bytes(penum->pcs, value, psrc);
1237
0
                } else {
1238
0
                    psrc[0] = value;
1239
0
                }
1240
                /* Data is in psrc */
1241
                /* These silly transforms need to go away. ToDo. */
1242
0
                if (has_transfer) {
1243
0
                    for (kk = 0; kk < num_des_comp; kk++) {
1244
0
                        conc[kk] = gx_color_value_from_byte(psrc[kk]);
1245
0
                    }
1246
0
                    cmap_transfer(&(conc[0]), penum->pgs, penum->dev);
1247
0
                    for (kk = 0; kk < num_des_comp; kk++) {
1248
0
                        psrc[kk] = gx_color_value_to_byte(conc[kk]);
1249
0
                    }
1250
0
                }
1251
0
                memcpy(&(penum->color_cache->device_contone[k * num_des_comp]),
1252
0
                               psrc, num_des_comp);
1253
0
            }
1254
0
        } else {
1255
            /* Indexing only.  No CM, decode or transfer functions. */
1256
0
            for (k = 0; k < num_entries; k++) {
1257
0
                gs_cspace_indexed_lookup_bytes(penum->pcs, (float)k, psrc);
1258
0
                memcpy(&(penum->color_cache->device_contone[k * num_des_comp]),
1259
0
                           psrc, num_des_comp);
1260
0
            }
1261
0
        }
1262
763
    } else {
1263
        /* Need CM */
1264
        /* We need to worry about if the source is indexed and if we need
1265
           to decode first.  Then we can apply CM. Create a temp buffer in
1266
           the source space and then transform it with one call */
1267
763
        temp_buffer = (byte*) gs_alloc_bytes(penum->memory,
1268
763
                                             (size_t)num_entries * num_src_comp,
1269
763
                                             "image_init_color_cache");
1270
763
        if (temp_buffer == NULL)
1271
0
            return_error(gs_error_VMerror);
1272
1273
763
        if (need_decode) {
1274
0
            if (is_indexed) {
1275
                /* Decode and lookup in index */
1276
0
                for (k = 0; k < num_entries; k++) {
1277
0
                    image_cache_decode(penum, k, &value, decode_scale);
1278
0
                    gs_cspace_indexed_lookup_bytes(penum->pcs, value, psrc);
1279
0
                    memcpy(&(temp_buffer[k * num_src_comp]), psrc, num_src_comp);
1280
0
                }
1281
0
            } else {
1282
                /* Decode only */
1283
0
                for (k = 0; k < num_entries; k++) {
1284
0
                    image_cache_decode(penum, k, &(temp_buffer[k]), decode_scale);
1285
0
                }
1286
0
            }
1287
763
        } else {
1288
            /* No Decode */
1289
763
            if (is_indexed) {
1290
                /* If index uses a num_entries sized table then just use its pointer */
1291
741
                if (penum->pcs->params.indexed.use_proc ||
1292
741
                    penum->pcs->params.indexed.hival < (num_entries - 1)) {
1293
                    /* Have to do the slow way */
1294
3.35k
                    for (k = 0; k <= penum->pcs->params.indexed.hival; k++) {
1295
3.26k
                        gs_cspace_indexed_lookup_bytes(penum->pcs, (float)k, psrc);
1296
3.26k
                        memcpy(&(temp_buffer[k * num_src_comp]), psrc, num_src_comp);
1297
3.26k
                    }
1298
                    /* just use psrc results from converting 'hival' to fill the remaining slots */
1299
18.0k
                    for (; k < num_entries; k++) {
1300
17.9k
                        memcpy(&(temp_buffer[k * num_src_comp]), psrc, num_src_comp);
1301
17.9k
                    }
1302
658
                } else {
1303
                    /* Use the index table directly. */
1304
658
                    gs_free_object(penum->memory, temp_buffer, "image_init_color_cache");
1305
658
                    free_temp_buffer = false;
1306
658
                    temp_buffer = (byte *)(penum->pcs->params.indexed.lookup.table.data);
1307
658
                }
1308
741
            } else {
1309
                /* CM only */
1310
5.65k
                for (k = 0; k < num_entries; k++) {
1311
5.63k
                    temp_buffer[k] = k;
1312
5.63k
                }
1313
22
            }
1314
763
        }
1315
        /* Set up the buffer descriptors. */
1316
763
        gsicc_init_buffer(&input_buff_desc, num_src_comp, 1, false, false, false,
1317
763
                          0, num_entries * num_src_comp, 1, num_entries);
1318
763
        gsicc_init_buffer(&output_buff_desc, num_des_comp, 1, false, false, false,
1319
763
                          0, num_entries * num_des_comp,
1320
763
                      1, num_entries);
1321
763
        code = (penum->icc_link->procs.map_buffer)(penum->dev, penum->icc_link,
1322
763
                                            &input_buff_desc, &output_buff_desc,
1323
763
                                            (void*) temp_buffer,
1324
763
                                            (void*) penum->color_cache->device_contone);
1325
763
        if (code < 0)
1326
0
            return gs_rethrow(code, "Failure to map color buffer");
1327
1328
        /* Check if we need to apply any transfer functions.  If so then do it now */
1329
763
        if (has_transfer) {
1330
0
            for (k = 0; k < num_entries; k++) {
1331
0
                byte_ptr =
1332
0
                    &(penum->color_cache->device_contone[k * num_des_comp]);
1333
0
                for (kk = 0; kk < num_des_comp; kk++) {
1334
0
                    conc[kk] = gx_color_value_from_byte(byte_ptr[kk]);
1335
0
                }
1336
0
                cmap_transfer(&(conc[0]), penum->pgs, penum->dev);
1337
0
                for (kk = 0; kk < num_des_comp; kk++) {
1338
0
                    byte_ptr[kk] = gx_color_value_to_byte(conc[kk]);
1339
0
                }
1340
0
            }
1341
0
        }
1342
763
        if (free_temp_buffer)
1343
105
            gs_free_object(penum->memory, temp_buffer, "image_init_color_cache");
1344
763
    }
1345
763
    return 0;
1346
763
}
1347
1348
/* Export this for use by image_render_ functions */
1349
void
1350
image_init_clues(gx_image_enum * penum, int bps, int spp)
1351
105k
{
1352
    /* Initialize the color table */
1353
105k
#define ictype(i)\
1354
105k
  penum->clues[i].dev_color.type
1355
1356
105k
    switch ((spp == 1 ? bps : 8)) {
1357
79.5k
        case 8:         /* includes all color images */
1358
79.5k
            {
1359
79.5k
                register gx_image_clue *pcht = &penum->clues[0];
1360
79.5k
                register int n = 64;    /* 8 bits means 256 clues, do   */
1361
                                        /* 4 at a time for efficiency   */
1362
5.08M
                do {
1363
5.08M
                    pcht[0].dev_color.type =
1364
5.08M
                        pcht[1].dev_color.type =
1365
5.08M
                        pcht[2].dev_color.type =
1366
5.08M
                        pcht[3].dev_color.type =
1367
5.08M
                        gx_dc_type_none;
1368
5.08M
                    pcht[0].key = pcht[1].key =
1369
5.08M
                        pcht[2].key = pcht[3].key = 0;
1370
5.08M
                    pcht += 4;
1371
5.08M
                }
1372
5.08M
                while (--n > 0);
1373
79.5k
                penum->clues[0].key = 1;        /* guarantee no hit */
1374
79.5k
                break;
1375
0
            }
1376
46
        case 4:
1377
46
            ictype(17) = ictype(2 * 17) = ictype(3 * 17) =
1378
46
                ictype(4 * 17) = ictype(6 * 17) = ictype(7 * 17) =
1379
46
                ictype(8 * 17) = ictype(9 * 17) = ictype(11 * 17) =
1380
46
                ictype(12 * 17) = ictype(13 * 17) = ictype(14 * 17) =
1381
46
                gx_dc_type_none;
1382
            /* falls through */
1383
140
        case 2:
1384
140
            ictype(5 * 17) = ictype(10 * 17) = gx_dc_type_none;
1385
105k
#undef ictype
1386
105k
    }
1387
105k
}
1388
1389
/* Initialize the color mapping tables for a non-mask image. */
1390
static int
1391
image_init_colors(gx_image_enum * penum, int bps, int spp,
1392
                  gs_image_format_t format, const float *decode /*[spp*2] */ ,
1393
                  const gs_gstate * pgs, gx_device * dev,
1394
                  const gs_color_space * pcs, bool * pdcb)
1395
113k
{
1396
113k
    int ci, decode_type, code;
1397
113k
    static const float default_decode[] = {
1398
113k
        0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0
1399
113k
    };
1400
1401
    /* Clues are only used with image_mono_render */
1402
113k
    if (spp == 1) {
1403
59.7k
        image_init_clues(penum, bps, spp);
1404
59.7k
    }
1405
113k
    decode_type = 3; /* 0=custom, 1=identity, 2=inverted, 3=impossible */
1406
281k
    for (ci = 0; ci < spp; ci +=2 ) {
1407
167k
        decode_type &= (decode[ci] == 0. && decode[ci + 1] == 1.) |
1408
167k
                       (decode[ci] == 1. && decode[ci + 1] == 0.) << 1;
1409
167k
    }
1410
1411
    /* Initialize the maps from samples to intensities. */
1412
337k
    for (ci = 0; ci < spp; ci++) {
1413
224k
        sample_map *pmap = &penum->map[ci];
1414
1415
        /* If the decoding is [0 1] or [1 0], we can fold it */
1416
        /* into the expansion of the sample values; */
1417
        /* otherwise, we have to use the floating point method. */
1418
1419
224k
        const float *this_decode = &decode[ci * 2];
1420
224k
        const float *map_decode;        /* decoding used to */
1421
                                        /* construct the expansion map */
1422
224k
        const float *real_decode;       /* decoding for expanded samples */
1423
1424
224k
        map_decode = real_decode = this_decode;
1425
224k
        if (!(decode_type & 1)) {
1426
910
            if ((decode_type & 2) && bps <= 8) {
1427
47
                real_decode = default_decode;
1428
863
            } else {
1429
863
                *pdcb = false;
1430
863
                map_decode = default_decode;
1431
863
            }
1432
910
        }
1433
224k
        if (bps > 2 || format != gs_image_format_chunky) {
1434
223k
            if (bps <= 8)
1435
223k
                image_init_map(&pmap->table.lookup8[0], 1 << bps,
1436
223k
                               map_decode);
1437
223k
        } else {                /* The map index encompasses more than one pixel. */
1438
503
            byte map[4];
1439
503
            register int i;
1440
1441
503
            image_init_map(&map[0], 1 << bps, map_decode);
1442
503
            switch (bps) {
1443
456
                case 1:
1444
456
                    {
1445
456
                        register bits32 *p = &pmap->table.lookup4x1to32[0];
1446
1447
456
                        if (map[0] == 0 && map[1] == 0xff)
1448
454
                            memcpy((byte *) p, lookup4x1to32_identity, 16 * 4);
1449
2
                        else if (map[0] == 0xff && map[1] == 0)
1450
2
                            memcpy((byte *) p, lookup4x1to32_inverted, 16 * 4);
1451
0
                        else
1452
0
                            for (i = 0; i < 16; i++, p++)
1453
0
                                ((byte *) p)[0] = map[i >> 3],
1454
0
                                    ((byte *) p)[1] = map[(i >> 2) & 1],
1455
0
                                    ((byte *) p)[2] = map[(i >> 1) & 1],
1456
0
                                    ((byte *) p)[3] = map[i & 1];
1457
456
                    }
1458
456
                    break;
1459
47
                case 2:
1460
47
                    {
1461
47
                        register bits16 *p = &pmap->table.lookup2x2to16[0];
1462
1463
799
                        for (i = 0; i < 16; i++, p++)
1464
752
                            ((byte *) p)[0] = map[i >> 2],
1465
752
                                ((byte *) p)[1] = map[i & 3];
1466
47
                    }
1467
47
                    break;
1468
503
            }
1469
503
        }
1470
224k
        pmap->decode_base /* = decode_lookup[0] */  = real_decode[0];
1471
224k
        pmap->decode_factor =
1472
224k
            (real_decode[1] - real_decode[0]) /
1473
224k
            (bps <= 8 ? 255.0 : (float)frac_1);
1474
224k
        pmap->decode_max /* = decode_lookup[15] */  = real_decode[1];
1475
224k
        if (decode_type) {
1476
223k
            pmap->decoding = sd_none;
1477
223k
            pmap->inverted = map_decode[0] != 0;
1478
223k
        } else if (bps <= 4) {
1479
44
            int step = 15 / ((1 << bps) - 1);
1480
44
            int i;
1481
1482
44
            pmap->decoding = sd_lookup;
1483
168
            for (i = 15 - step; i > 0; i -= step)
1484
124
                pmap->decode_lookup[i] = pmap->decode_base +
1485
124
                    i * (255.0 / 15) * pmap->decode_factor;
1486
44
            pmap->inverted = 0;
1487
819
        } else {
1488
819
            pmap->decoding = sd_compute;
1489
819
            pmap->inverted = 0;
1490
819
        }
1491
224k
        if (spp == 1) {         /* and ci == 0 *//* Pre-map entries 0 and 255. */
1492
59.7k
            gs_client_color cc;
1493
1494
            /* Image clues are used in this case */
1495
59.7k
            cc.paint.values[0] = real_decode[0];
1496
59.7k
            code = (*pcs->type->remap_color) (&cc, pcs, penum->icolor0,
1497
59.7k
                                       pgs, dev, gs_color_select_source);
1498
59.7k
            if (code < 0)
1499
3
                return code;
1500
59.7k
            cc.paint.values[0] = real_decode[1];
1501
59.7k
            code = (*pcs->type->remap_color) (&cc, pcs, penum->icolor1,
1502
59.7k
                                       pgs, dev, gs_color_select_source);
1503
59.7k
            if (code < 0)
1504
0
                return code;
1505
59.7k
        }
1506
224k
    }
1507
113k
    return 0;
1508
113k
}
1509
/* Construct a mapping table for sample values. */
1510
/* map_size is 2, 4, 16, or 256.  Note that 255 % (map_size - 1) == 0, */
1511
/* so the division 0xffffL / (map_size - 1) is always exact. */
1512
void
1513
image_init_map(byte * map, int map_size, const float *decode)
1514
224k
{
1515
224k
    float min_v = decode[0];
1516
224k
    float diff_v = decode[1] - min_v;
1517
1518
224k
    if (diff_v == 1 || diff_v == -1) {  /* We can do the stepping with integers, without overflow. */
1519
224k
        byte *limit = map + map_size;
1520
224k
        uint value = (uint)(min_v * 0xffffL);
1521
224k
        int diff = (int)(diff_v * (0xffffL / (map_size - 1)));
1522
1523
57.4M
        for (; map != limit; map++, value += diff)
1524
57.2M
            *map = value >> 8;
1525
224k
    } else {                    /* Step in floating point, with clamping. */
1526
0
        int i;
1527
1528
0
        for (i = 0; i < map_size; ++i) {
1529
0
            int value = (int)((min_v + diff_v * i / (map_size - 1)) * 255);
1530
1531
0
            map[i] = (value < 0 ? 0 : value > 255 ? 255 : value);
1532
0
        }
1533
0
    }
1534
224k
}
1535
1536
/*
1537
 * Scale a pair of mask_color values to match the scaling of each sample to
1538
 * a full byte, and complement and swap them if the map incorporates
1539
 * a Decode = [1 0] inversion.
1540
 */
1541
void
1542
gx_image_scale_mask_colors(gx_image_enum *penum, int component_index)
1543
90
{
1544
90
    uint scale = 255 / ((1 << penum->bps) - 1);
1545
90
    uint *values = &penum->mask_color.values[component_index * 2];
1546
90
    uint v0 = values[0] *= scale;
1547
90
    uint v1 = values[1] *= scale;
1548
1549
90
    if (penum->map[component_index].decoding == sd_none &&
1550
90
        penum->map[component_index].inverted
1551
90
        ) {
1552
0
        values[0] = 255 - v1;
1553
0
        values[1] = 255 - v0;
1554
0
    }
1555
90
}
1556
1557
/* Used to indicate for ICC procesing if we have decoding to do */
1558
bool
1559
gx_has_transfer(const gs_gstate *pgs, int num_comps)
1560
57.2k
{
1561
57.2k
    int k;
1562
1563
57.2k
    for (k = 0; k < num_comps; k++) {
1564
57.2k
        if (pgs->effective_transfer[k]->proc != gs_identity_transfer) {
1565
57.2k
            return(true);
1566
57.2k
        }
1567
57.2k
    }
1568
0
    return(false);
1569
57.2k
}