Coverage Report

Created: 2025-06-10 07:27

/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
1.29k
ENUM_PTRS_WITH(image_enum_enum_ptrs, gx_image_enum *eptr)
64
476
{
65
476
    int bps;
66
476
    gs_ptr_type_t ret;
67
68
    /* Enumerate the used members of clues.dev_color. */
69
476
    index -= gx_image_enum_num_ptrs;
70
476
    bps = eptr->unpack_bps;
71
476
    if (eptr->spp != 1)
72
0
        bps = 8;
73
476
    else if (bps > 8 || eptr->unpack == sample_unpack_copy)
74
0
        bps = 1;
75
476
    if (index >= (1 << bps) * st_device_color_max_ptrs)         /* done */
76
68
        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
408
    if (eptr->spp == 1) {
80
408
        if (eptr->clues != NULL) {
81
408
            if (eptr->clues[(index/st_device_color_max_ptrs) *
82
408
                (255 / ((1 << bps) - 1))].dev_color.type != 0) {
83
408
                ret = ENUM_USING(st_device_color,
84
408
                                 &eptr->clues[(index / st_device_color_max_ptrs) *
85
408
                                 (255 / ((1 << bps) - 1))].dev_color,
86
408
                                 sizeof(eptr->clues[0].dev_color),
87
408
                                 index % st_device_color_max_ptrs);
88
408
            } else {
89
0
                ret = 0;
90
0
            }
91
408
        } else {
92
0
            ret = 0;
93
0
        }
94
408
    } else {
95
0
        ret = 0;
96
0
    }
97
408
    if (ret == 0)               /* don't stop early */
98
408
        ENUM_RETURN(0);
99
0
    return ret;
100
408
}
101
102
816
#define e1(i,elt) ENUM_PTR(i,gx_image_enum,elt);
103
1.29k
gx_image_enum_do_ptrs(e1)
104
1.29k
#undef e1
105
1.29k
ENUM_PTRS_END
106
107
68
static RELOC_PTRS_WITH(image_enum_reloc_ptrs, gx_image_enum *eptr)
108
68
{
109
68
    int i;
110
111
816
#define r1(i,elt) RELOC_PTR(gx_image_enum,elt);
112
816
    gx_image_enum_do_ptrs(r1)
113
68
#undef r1
114
68
    {
115
68
        int bps = eptr->unpack_bps;
116
117
68
        if (eptr->spp != 1)
118
0
            bps = 8;
119
68
        else if (bps > 8 || eptr->unpack == sample_unpack_copy)
120
0
            bps = 1;
121
68
        if (eptr->spp == 1) {
122
204
        for (i = 0; i <= 255; i += 255 / ((1 << bps) - 1))
123
136
            RELOC_USING(st_device_color,
124
68
                        &eptr->clues[i].dev_color, sizeof(gx_device_color));
125
68
    }
126
68
}
127
68
}
128
68
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
198k
{
152
198k
    const gs_pixel_image_t *pim = (const gs_pixel_image_t *)pic;
153
198k
    int width = pim->Width, height = pim->Height;
154
198k
    int bpc = pim->BitsPerComponent;
155
198k
    gx_image_enum *penum;
156
157
198k
    if (width < 0 || height < 0)
158
0
        return_error(gs_error_rangecheck);
159
198k
    switch (pim->format) {
160
198k
    case gs_image_format_chunky:
161
198k
    case gs_image_format_component_planar:
162
198k
        switch (bpc) {
163
198k
        case 1: case 2: case 4: case 8: case 12: case 16: break;
164
0
        default: return_error(gs_error_rangecheck);
165
198k
        }
166
198k
        break;
167
198k
    case gs_image_format_bit_planar:
168
0
        if (bpc < 1 || bpc > 8)
169
0
            return_error(gs_error_rangecheck);
170
198k
    }
171
198k
    if (prect) {
172
63.8k
        if (prect->p.x < 0 || prect->p.y < 0 ||
173
63.8k
            prect->q.x < prect->p.x || prect->q.y < prect->p.y ||
174
63.8k
            prect->q.x > width || prect->q.y > height
175
63.8k
            )
176
0
            return_error(gs_error_rangecheck);
177
63.8k
    }
178
198k
    *ppenum = NULL;   /* in case alloc fails and caller doesn't check code */
179
198k
    penum = gs_alloc_struct(mem, gx_image_enum, &st_gx_image_enum,
180
198k
                            "gx_default_begin_image");
181
198k
    if (penum == 0)
182
0
        return_error(gs_error_VMerror);
183
198k
    memset(penum, 0, sizeof(gx_image_enum));  /* in case of failure, no dangling pointers */
184
198k
    if (prect) {
185
63.8k
        penum->rect.x = prect->p.x;
186
63.8k
        penum->rect.y = prect->p.y;
187
63.8k
        penum->rect.w = prect->q.x - prect->p.x;
188
63.8k
        penum->rect.h = prect->q.y - prect->p.y;
189
134k
    } else {
190
134k
        penum->rect.x = 0, penum->rect.y = 0;
191
134k
        penum->rect.w = width, penum->rect.h = height;
192
134k
    }
193
198k
    penum->rrect.x = penum->rect.x;
194
198k
    penum->rrect.y = penum->rect.y;
195
198k
    penum->rrect.w = penum->rect.w;
196
198k
    penum->rrect.h = penum->rect.h;
197
198k
    penum->drect.x = penum->rect.x;
198
198k
    penum->drect.y = penum->rect.y;
199
198k
    penum->drect.w = penum->rect.w;
200
198k
    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
198k
    *ppenum = penum;
210
198k
    return 0;
211
198k
}
212
213
/* Convert and restrict to a valid range. */
214
531k
static inline fixed float2fixed_rounded_boxed(double src) {
215
531k
    float v = floor(src*fixed_scale + 0.5);
216
217
531k
    if (v <= min_fixed)
218
3.96k
        return min_fixed;
219
527k
    else if (v >= max_fixed)
220
6.36k
        return max_fixed;
221
521k
    else
222
521k
        return  (fixed)v;
223
531k
}
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
428k
{
230
428k
    int code = 0;
231
232
428k
    if (pmat == 0)
233
428k
        pmat = &ctm_only(pgs);
234
428k
    if (ImageMatrix->xx == pmat->xx && ImageMatrix->xy == pmat->xy &&
235
428k
        ImageMatrix->yx == pmat->yx && ImageMatrix->yy == pmat->yy) {
236
        /* Process common special case separately to accept singular matrix. */
237
109k
        rmat->xx = rmat->yy = 1.;
238
109k
        rmat->xy = rmat->yx = 0.;
239
109k
        rmat->tx = pmat->tx - ImageMatrix->tx;
240
109k
        rmat->ty = pmat->ty - ImageMatrix->ty;
241
319k
    } else {
242
319k
        if ((code = gs_matrix_invert_to_double(ImageMatrix, rmat)) < 0 ||
243
319k
            (code = gs_matrix_multiply_double(rmat, pmat, rmat)) < 0
244
319k
            ) {
245
21
            return code;
246
21
        }
247
319k
    }
248
428k
    return code;
249
428k
}
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
198k
{
264
198k
    const gs_pixel_image_t *pim = (const gs_pixel_image_t *)pic;
265
198k
    gs_image_format_t format = pim->format;
266
198k
    const int width = pim->Width;
267
198k
    const int height = pim->Height;
268
198k
    const int bps = pim->BitsPerComponent;
269
198k
    bool masked = penum->masked;
270
198k
    const float *decode = pim->Decode;
271
198k
    gs_matrix_double mat;
272
198k
    int index_bps;
273
198k
    gs_color_space *pcs = pim->ColorSpace;
274
198k
    gs_logical_operation_t lop = (pgs ? pgs->log_op : lop_default);
275
198k
    int code;
276
198k
    int log2_xbytes = (bps <= 8 ? 0 : arch_log2_sizeof_frac);
277
198k
    int spp, nplanes, spread;
278
198k
    uint bsize;
279
198k
    byte *buffer = NULL;
280
198k
    fixed mtx, mty;
281
198k
    gs_fixed_point row_extent, col_extent, x_extent, y_extent;
282
198k
    bool device_color = true;
283
198k
    gs_fixed_rect obox, cbox;
284
198k
    bool gridfitimages = 0;
285
198k
    bool in_pattern_accumulator;
286
198k
    bool in_smask;
287
198k
    int orthogonal;
288
198k
    int force_interpolation = 0;
289
290
198k
    penum->pcs = NULL;
291
198k
    penum->clues = NULL;
292
198k
    penum->icc_setup.has_transfer = false;
293
198k
    penum->icc_setup.is_lab = false;
294
198k
    penum->icc_setup.must_halftone = false;
295
198k
    penum->icc_setup.need_decode = false;
296
198k
    penum->Width = width;
297
198k
    penum->Height = height;
298
299
198k
    if ((code = gx_image_compute_mat(pgs, pmat, &(pim->ImageMatrix), &mat)) < 0) {
300
18
        return code;
301
18
    }
302
198k
    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
198k
    in_pattern_accumulator = (dev_proc(dev, dev_spec_op)(dev, gxdso_in_pattern_accumulator, NULL, 0));
323
198k
    if (in_pattern_accumulator < 0)
324
144k
        in_pattern_accumulator = 0;
325
326
    /* Figure out if we are orthogonal */
327
198k
    if (mat.xy == 0 && mat.yx == 0)
328
177k
        orthogonal = 1;
329
20.7k
    else if (mat.xx == 0 && mat.yy == 0)
330
7.85k
        orthogonal = 2;
331
12.9k
    else
332
12.9k
        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
198k
    in_smask = (pim->override_in_smask ||
340
198k
                (dev_proc(dev, dev_spec_op)(dev, gxdso_in_smask, NULL, 0)) > 0);
341
198k
    gridfitimages = (in_smask || in_pattern_accumulator) && orthogonal;
342
343
198k
    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
162k
    } else if (!gridfitimages &&
347
162k
               (!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
98.5k
    } else if (gridfitimages && (penum->masked && penum->image_parent_type == 0)) {
351
        /* We don't gridfit imagemasks in a pattern accumulator */
352
64.0k
    } 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
64.0k
    } else if (orthogonal == 1) {
355
51.7k
        if (width == 1 || gridfitimages) {
356
47.7k
            if (mat.xx > 0) {
357
47.7k
                fixed ix0 = int2fixed(fixed2int(float2fixed(mat.tx)));
358
47.7k
                double x1 = mat.tx + mat.xx * width;
359
47.7k
                fixed ix1 = int2fixed(fixed2int_ceiling(float2fixed(x1)));
360
47.7k
                mat.tx = (double)fixed2float(ix0);
361
47.7k
                mat.xx = (double)(fixed2float(ix1 - ix0)/width);
362
47.7k
            } else if (mat.xx < 0) {
363
9
                fixed ix0 = int2fixed(fixed2int_ceiling(float2fixed(mat.tx)));
364
9
                double x1 = mat.tx + mat.xx * width;
365
9
                fixed ix1 = int2fixed(fixed2int(float2fixed(x1)));
366
9
                mat.tx = (double)fixed2float(ix0);
367
9
                mat.xx = (double)(fixed2float(ix1 - ix0)/width);
368
9
            }
369
47.7k
        }
370
51.7k
        if (height == 1 || gridfitimages) {
371
47.7k
            if (mat.yy > 0) {
372
47.5k
                fixed iy0 = int2fixed(fixed2int(float2fixed(mat.ty)));
373
47.5k
                double y1 = mat.ty + mat.yy * height;
374
47.5k
                fixed iy1 = int2fixed(fixed2int_ceiling(float2fixed(y1)));
375
47.5k
                mat.ty = (double)fixed2float(iy0);
376
47.5k
                mat.yy = (double)(fixed2float(iy1 - iy0)/height);
377
47.5k
            } else if (mat.yy < 0) {
378
122
                fixed iy0 = int2fixed(fixed2int_ceiling(float2fixed(mat.ty)));
379
122
                double y1 = mat.ty + mat.yy * height;
380
122
                fixed iy1 = int2fixed(fixed2int(float2fixed(y1)));
381
122
                mat.ty = (double)fixed2float(iy0);
382
122
                mat.yy = ((double)fixed2float(iy1 - iy0)/height);
383
122
            }
384
47.7k
        }
385
51.7k
    } else if (orthogonal == 2) {
386
7.78k
        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
7.78k
        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
7.78k
    }
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
198k
    if (in_pattern_accumulator) {
422
32
        double ome = ((double)(fixed_1 - fixed_epsilon)) / (double)fixed_1; /* One Minus Epsilon */
423
424
32
        if (orthogonal == 1) {
425
32
            if ((mat.xx > -ome && mat.xx < ome) || (mat.yy > -ome && mat.yy < ome)) {
426
21
                force_interpolation = true;
427
21
            }
428
32
        } 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
32
    }
434
435
    /* Can we restrict the amount of image we need? */
436
198k
    while (!pim->imagematrices_are_untrustworthy) /* So we can break out of it */
437
198k
    {
438
198k
        gs_rect rect, rect_src;
439
198k
        gs_matrix mi;
440
198k
        const gs_matrix *m = pgs != NULL ? &ctm_only(pgs) : NULL;
441
198k
        gs_int_rect irect;
442
198k
        if (m == NULL || (code = gs_matrix_invert(m, &mi)) < 0 ||
443
198k
            (code = gs_matrix_multiply(&mi, &pic->ImageMatrix, &mi)) < 0) {
444
            /* Give up trying to shrink the render box, but continue processing */
445
78
            break;
446
78
        }
447
198k
        if (pcpath)
448
72.6k
        {
449
72.6k
            gs_fixed_rect obox;
450
72.6k
            gx_cpath_outer_box(pcpath, &obox);
451
72.6k
            rect.p.x = fixed2float(obox.p.x);
452
72.6k
            rect.p.y = fixed2float(obox.p.y);
453
72.6k
            rect.q.x = fixed2float(obox.q.x);
454
72.6k
            rect.q.y = fixed2float(obox.q.y);
455
72.6k
        }
456
125k
        else
457
125k
        {
458
125k
            rect.p.x = 0;
459
125k
            rect.p.y = 0;
460
125k
            rect.q.x = dev->width;
461
125k
            rect.q.y = dev->height;
462
125k
        }
463
        /* rect is in destination space. Calculate rect_src, in source space. */
464
198k
        code = gs_bbox_transform(&rect, &mi, &rect_src);
465
198k
        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
198k
        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
198k
        irect.p.x = (int)floor(rect_src.p.x);
497
198k
        irect.p.y = (int)floor(rect_src.p.y);
498
198k
        irect.q.x = (int)ceil(rect_src.q.x);
499
198k
        irect.q.y = (int)ceil(rect_src.q.y);
500
        /* We therefore only need to render within irect. Restrict rrect to this. */
501
198k
        if (penum->rrect.x < irect.p.x) {
502
3.19k
            penum->rrect.w -= irect.p.x - penum->rrect.x;
503
3.19k
            if (penum->rrect.w < 0)
504
2.73k
               penum->rrect.w = 0;
505
3.19k
            penum->rrect.x = irect.p.x;
506
3.19k
        }
507
198k
        if (penum->rrect.x + penum->rrect.w > irect.q.x) {
508
35.6k
            penum->rrect.w = irect.q.x - penum->rrect.x;
509
35.6k
            if (penum->rrect.w < 0)
510
33.6k
                penum->rrect.w = 0;
511
35.6k
        }
512
198k
        if (penum->rrect.y < irect.p.y) {
513
31.9k
            penum->rrect.h -= irect.p.y - penum->rrect.y;
514
31.9k
            if (penum->rrect.h < 0)
515
19.9k
                penum->rrect.h = 0;
516
31.9k
            penum->rrect.y = irect.p.y;
517
31.9k
        }
518
198k
        if (penum->rrect.y + penum->rrect.h > irect.q.y) {
519
17.3k
            penum->rrect.h = irect.q.y - penum->rrect.y;
520
17.3k
            if (penum->rrect.h < 0)
521
2.87k
                penum->rrect.h = 0;
522
17.3k
        }
523
198k
        if (penum->drect.x < irect.p.x) {
524
3.19k
            penum->drect.w -= irect.p.x - penum->drect.x;
525
3.19k
            if (penum->drect.w < 0)
526
2.73k
               penum->drect.w = 0;
527
3.19k
            penum->drect.x = irect.p.x;
528
3.19k
        }
529
198k
        if (penum->drect.x + penum->drect.w > irect.q.x) {
530
35.6k
            penum->drect.w = irect.q.x - penum->drect.x;
531
35.6k
            if (penum->drect.w < 0)
532
33.6k
                penum->drect.w = 0;
533
35.6k
        }
534
198k
        if (penum->drect.y < irect.p.y) {
535
31.9k
            penum->drect.h -= irect.p.y - penum->drect.y;
536
31.9k
            if (penum->drect.h < 0)
537
19.9k
                penum->drect.h = 0;
538
31.9k
            penum->drect.y = irect.p.y;
539
31.9k
        }
540
198k
        if (penum->drect.y + penum->drect.h > irect.q.y) {
541
17.3k
            penum->drect.h = irect.q.y - penum->drect.y;
542
17.3k
            if (penum->drect.h < 0)
543
2.87k
                penum->drect.h = 0;
544
17.3k
        }
545
198k
        break; /* Out of the while */
546
198k
    }
547
    /* Check for the intersection being null */
548
198k
    if (penum->drect.x + penum->drect.w <= penum->rect.x  ||
549
198k
        penum->rect.x  + penum->rect.w  <= penum->drect.x ||
550
198k
        penum->drect.y + penum->drect.h <= penum->rect.y  ||
551
198k
        penum->rect.y  + penum->rect.h  <= penum->drect.y)
552
38.2k
    {
553
          /* Something may have gone wrong with the floating point above.
554
           * set the region to something sane. */
555
38.2k
        penum->drect.x = penum->rect.x;
556
38.2k
        penum->drect.y = penum->rect.y;
557
38.2k
        penum->drect.w = 0;
558
38.2k
        penum->drect.h = 0;
559
38.2k
    }
560
198k
    if (penum->rrect.x + penum->rrect.w <= penum->drect.x  ||
561
198k
        penum->drect.x + penum->drect.w  <= penum->rrect.x ||
562
198k
        penum->rrect.y + penum->rrect.h <= penum->drect.y  ||
563
198k
        penum->drect.y + penum->drect.h  <= penum->rrect.y)
564
38.2k
    {
565
          /* Something may have gone wrong with the floating point above.
566
           * set the region to something sane. */
567
38.2k
        penum->rrect.x = penum->drect.x;
568
38.2k
        penum->rrect.y = penum->drect.y;
569
38.2k
        penum->rrect.w = 0;
570
38.2k
        penum->rrect.h = 0;
571
38.2k
    }
572
573
    /*penum->matrix = mat;*/
574
198k
    penum->matrix.xx = mat.xx;
575
198k
    penum->matrix.xy = mat.xy;
576
198k
    penum->matrix.yx = mat.yx;
577
198k
    penum->matrix.yy = mat.yy;
578
198k
    penum->matrix.tx = mat.tx;
579
198k
    penum->matrix.ty = mat.ty;
580
198k
    if_debug6m('b', mem, " [%g %g %g %g %g %g]\n",
581
198k
              mat.xx, mat.xy, mat.yx, mat.yy, mat.tx, mat.ty);
582
    /* following works for 1, 2, 4, 8, 12, 16 */
583
198k
    index_bps = (bps < 8 ? bps >> 1 : (bps >> 2) + 1);
584
    /*
585
     * Compute extents with distance transformation.
586
     */
587
198k
    if (mat.tx > 0)
588
165k
        mtx = float2fixed(mat.tx);
589
32.6k
    else { /* Use positive values to ensure round down. */
590
32.6k
        int f = (int)-mat.tx + 1;
591
592
32.6k
        mtx = float2fixed(mat.tx + f) - int2fixed(f);
593
32.6k
    }
594
198k
    if (mat.ty > 0)
595
45.7k
        mty = float2fixed(mat.ty);
596
152k
    else {  /* Use positive values to ensure round down. */
597
152k
        int f = (int)-mat.ty + 1;
598
599
152k
        mty = float2fixed(mat.ty + f) - int2fixed(f);
600
152k
    }
601
602
198k
    row_extent.x = float2fixed_rounded_boxed(width * mat.xx);
603
198k
    row_extent.y =
604
198k
        (is_fzero(mat.xy) ? fixed_0 :
605
198k
         float2fixed_rounded_boxed(width * mat.xy));
606
198k
    col_extent.x =
607
198k
        (is_fzero(mat.yx) ? fixed_0 :
608
198k
         float2fixed_rounded_boxed(height * mat.yx));
609
198k
    col_extent.y = float2fixed_rounded_boxed(height * mat.yy);
610
198k
    gx_image_enum_common_init((gx_image_enum_common_t *)penum,
611
198k
                              (const gs_data_image_t *)pim,
612
198k
                              &image1_enum_procs, dev,
613
198k
                              (masked ? 1 : (penum->alpha ? cs_num_components(pcs)+1 : cs_num_components(pcs))),
614
198k
                              format);
615
198k
    if (penum->rect.w == width && penum->rect.h == height) {
616
146k
        x_extent = row_extent;
617
146k
        y_extent = col_extent;
618
146k
    } else {
619
52.5k
        int rw = penum->rect.w, rh = penum->rect.h;
620
621
52.5k
        x_extent.x = float2fixed_rounded_boxed(rw * mat.xx);
622
52.5k
        x_extent.y =
623
52.5k
            (is_fzero(mat.xy) ? fixed_0 :
624
52.5k
             float2fixed_rounded_boxed(rw * mat.xy));
625
52.5k
        y_extent.x =
626
52.5k
            (is_fzero(mat.yx) ? fixed_0 :
627
52.5k
             float2fixed_rounded_boxed(rh * mat.yx));
628
52.5k
        y_extent.y = float2fixed_rounded_boxed(rh * mat.yy);
629
52.5k
    }
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
198k
    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
86.3k
        penum->clues = (gx_image_clue*) gs_alloc_bytes(mem, sizeof(gx_image_clue)*256,
638
86.3k
                             "gx_image_enum_begin");
639
86.3k
        if (penum->clues == NULL) {
640
0
            code = gs_error_VMerror;
641
0
            goto fail;
642
0
        }
643
86.3k
        penum->icolor0 = &(penum->clues[0].dev_color);
644
86.3k
        penum->icolor1 = &(penum->clues[255].dev_color);
645
112k
    } else {
646
112k
        penum->icolor0 = &(penum->icolor0_val);
647
112k
        penum->icolor1 = &(penum->icolor1_val);
648
112k
    }
649
198k
    penum->icolor0->tag = penum->icolor1->tag = device_current_tag(dev);
650
651
198k
    if (masked) {       /* This is imagemask. */
652
52.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
52.3k
        set_nonclient_dev_color(penum->icolor0, gx_no_color_index);
658
52.3k
        set_nonclient_dev_color(penum->icolor1, gx_no_color_index);
659
52.3k
        *(penum->icolor1) = *pdcolor;
660
52.3k
        memcpy(&penum->map[0].table.lookup4x1to32[0],
661
52.3k
               (decode[0] < decode[1] ? lookup4x1to32_inverted :
662
52.3k
                lookup4x1to32_identity),
663
52.3k
               16 * 4);
664
52.3k
        penum->map[0].decoding = sd_none;
665
52.3k
        spp = 1;
666
52.3k
        lop = rop3_know_S_0(lop);
667
146k
    } else {                    /* This is image, not imagemask. */
668
146k
        const gs_color_space_type *pcst = pcs->type;
669
146k
        int b_w_color;
670
671
146k
        spp = cs_num_components(pcs);
672
146k
        if (spp < 0) {          /* Pattern not allowed */
673
0
            code = gs_error_rangecheck;
674
0
            goto fail;
675
0
        }
676
146k
        if (penum->alpha)
677
0
            ++spp;
678
        /* Use a less expensive format if possible. */
679
146k
        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
4
        case gs_image_format_component_planar:
685
4
            if (spp == 1)
686
0
                format = gs_image_format_chunky;
687
146k
        default:                /* chunky */
688
146k
            break;
689
146k
        }
690
691
146k
        if (pcs->cmm_icc_profile_data != NULL) {
692
144k
            device_color = false;
693
144k
        } else {
694
1.50k
            device_color = (*pcst->concrete_space) (pcs, pgs) == pcs;
695
1.50k
        }
696
697
146k
        code = image_init_colors(penum, bps, spp, format, decode, pgs, dev,
698
146k
                          pcs, &device_color);
699
146k
        if (code < 0) {
700
0
            gs_free_object(mem, penum->clues, "gx_image_enum_begin");
701
0
            gs_free_object(mem, penum, "gx_default_begin_image");
702
0
            return gs_throw(code, "Image colors initialization failed");
703
0
        }
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
146k
        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
146k
        if (!pim->CombineWithColor)
725
146k
            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
146k
        if (lop != rop3_S &&    /* if best case, no more work needed */
730
146k
            !rop3_uses_T(lop) && bps == 1 && spp == 1 &&
731
146k
            (b_w_color =
732
0
             color_draws_b_w(dev, penum->icolor0)) >= 0 &&
733
146k
            color_draws_b_w(dev, penum->icolor1) == (b_w_color ^ 1)
734
146k
            ) {
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
146k
    }
777
198k
    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
198k
    bsize = ((bps > 8 ? width * 2 : width) + 15) * spp;
784
198k
    buffer = gs_alloc_bytes(mem, bsize, "image buffer");
785
198k
    if (buffer == 0) {
786
0
        code = gs_error_VMerror;
787
0
        goto fail;
788
0
    }
789
198k
    penum->bps = bps;
790
198k
    penum->unpack_bps = bps;
791
198k
    penum->log2_xbytes = log2_xbytes;
792
198k
    penum->spp = spp;
793
198k
    switch (format) {
794
198k
    case gs_image_format_chunky:
795
198k
        nplanes = 1;
796
198k
        spread = 1 << log2_xbytes;
797
198k
        break;
798
4
    case gs_image_format_component_planar:
799
4
        nplanes = spp;
800
4
        spread = spp << log2_xbytes;
801
4
        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
198k
    }
810
198k
    penum->num_planes = nplanes;
811
198k
    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
198k
    penum->interpolate = force_interpolation ? interp_force : pim->Interpolate ? interp_on : interp_off;
819
198k
    penum->x_extent = x_extent;
820
198k
    penum->y_extent = y_extent;
821
198k
    penum->posture =
822
198k
        ((x_extent.y | y_extent.x) == 0 ? image_portrait :
823
198k
         (x_extent.x | y_extent.y) == 0 ? image_landscape :
824
20.7k
         image_skewed);
825
198k
    penum->pgs = pgs;
826
198k
    if (pgs != NULL)
827
198k
        penum->pgs_level = pgs->level;
828
198k
    penum->pcs = pcs;
829
198k
    rc_increment_cs(pcs); /* Grab a ref (will decrement in gx_image1_end_image() */
830
198k
    penum->memory = mem;
831
198k
    penum->buffer = buffer;
832
198k
    penum->buffer_size = bsize;
833
198k
    penum->line = NULL;
834
198k
    penum->icc_link = NULL;
835
198k
    penum->color_cache = NULL;
836
198k
    penum->ht_buffer = NULL;
837
198k
    penum->thresh_buffer = NULL;
838
198k
    penum->use_cie_range = false;
839
198k
    penum->line_size = 0;
840
198k
    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
198k
    penum->slow_loop = 0;
854
198k
    if (pcpath == 0) {
855
125k
        (*dev_proc(dev, get_clipping_box)) (dev, &obox);
856
125k
        cbox = obox;
857
125k
        penum->clip_image = 0;
858
125k
    } else
859
72.6k
        penum->clip_image =
860
72.6k
            (gx_cpath_outer_box(pcpath, &obox) |        /* not || */
861
72.6k
             gx_cpath_inner_box(pcpath, &cbox) ?
862
72.4k
             0 : image_clip_region);
863
198k
    penum->clip_outer = obox;
864
198k
    penum->clip_inner = cbox;
865
198k
    penum->log_op = rop3_T;     /* rop device takes care of this */
866
198k
    penum->clip_dev = 0;        /* in case we bail out */
867
198k
    penum->rop_dev = 0;         /* ditto */
868
198k
    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
198k
    {
876
198k
        fixed
877
198k
            epx = min(row_extent.x, 0) + min(col_extent.x, 0),
878
198k
            eqx = max(row_extent.x, 0) + max(col_extent.x, 0),
879
198k
            epy = min(row_extent.y, 0) + min(col_extent.y, 0),
880
198k
            eqy = max(row_extent.y, 0) + max(col_extent.y, 0);
881
882
198k
        {
883
198k
            int hwx, hwy;
884
885
198k
            switch (penum->posture) {
886
177k
                case image_portrait:
887
177k
                    hwx = width, hwy = height;
888
177k
                    break;
889
7.85k
                case image_landscape:
890
7.85k
                    hwx = height, hwy = width;
891
7.85k
                    break;
892
12.9k
                default:
893
12.9k
                    hwx = hwy = 0;
894
198k
            }
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
198k
            if (hwx == 1 && eqx - epx < fixed_1) {
905
6
                fixed diff =
906
6
                arith_rshift_1(row_extent.x + col_extent.x);
907
908
6
                mtx = (((mtx + diff) | fixed_half) & -fixed_half) - diff;
909
6
            }
910
198k
            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
198k
        }
917
198k
        if_debug5m('b', mem, "[b]Image: %sspp=%d, bps=%d, mt=(%g,%g)\n",
918
198k
                   (masked? "masked, " : ""), spp, bps,
919
198k
                   fixed2float(mtx), fixed2float(mty));
920
198k
        if_debug9m('b', mem,
921
198k
                   "[b]   cbox=(%g,%g),(%g,%g), obox=(%g,%g),(%g,%g), clip_image=0x%x\n",
922
198k
                   fixed2float(cbox.p.x), fixed2float(cbox.p.y),
923
198k
                   fixed2float(cbox.q.x), fixed2float(cbox.q.y),
924
198k
                   fixed2float(obox.p.x), fixed2float(obox.p.y),
925
198k
                   fixed2float(obox.q.x), fixed2float(obox.q.y),
926
198k
                   penum->clip_image);
927
        /* These DDAs enumerate the starting position of each source pixel
928
         * row in device space. */
929
198k
        dda_init(penum->dda.row.x, mtx, col_extent.x, height);
930
198k
        dda_init(penum->dda.row.y, mty, col_extent.y, height);
931
198k
        if (dda_will_overflow(penum->dda.row.x) ||
932
198k
            dda_will_overflow(penum->dda.row.y))
933
0
        {
934
0
            code = gs_error_rangecheck;
935
0
            goto fail;
936
0
        }
937
198k
        if (penum->posture == image_portrait) {
938
177k
            penum->dst_width = row_extent.x;
939
177k
            penum->dst_height = col_extent.y;
940
177k
        } else {
941
20.7k
            penum->dst_width = col_extent.x;
942
20.7k
            penum->dst_height = row_extent.y;
943
20.7k
        }
944
        /* For gs_image_class_0_interpolate. */
945
198k
        penum->yi0 = fixed2int_pixround_perfect(dda_current(penum->dda.row.y)); /* For gs_image_class_0_interpolate. */
946
198k
        if (penum->rect.y) {
947
46.6k
            int y = penum->rect.y;
948
949
4.72M
            while (y--) {
950
4.68M
                dda_next(penum->dda.row.x);
951
4.68M
                dda_next(penum->dda.row.y);
952
4.68M
            }
953
46.6k
        }
954
198k
        penum->cur.x = penum->prev.x = dda_current(penum->dda.row.x);
955
198k
        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
198k
        dda_init(penum->dda.strip.x, penum->cur.x, row_extent.x, width);
960
198k
        dda_init(penum->dda.strip.y, penum->cur.y, row_extent.y, width);
961
198k
        if (dda_will_overflow(penum->dda.strip.x) ||
962
198k
            dda_will_overflow(penum->dda.strip.y))
963
0
        {
964
0
            code = gs_error_rangecheck;
965
0
            goto fail;
966
0
        }
967
198k
        if (penum->rect.x) {
968
269
            dda_advance(penum->dda.strip.x, penum->rect.x);
969
269
            dda_advance(penum->dda.strip.y, penum->rect.x);
970
269
        }
971
198k
        {
972
198k
            fixed ox = dda_current(penum->dda.strip.x);
973
198k
            fixed oy = dda_current(penum->dda.strip.y);
974
975
198k
            if (!penum->clip_image)     /* i.e., not clip region */
976
198k
                penum->clip_image =
977
198k
                    (fixed_pixround(ox + epx) < fixed_pixround(cbox.p.x) ?
978
192k
                     image_clip_xmin : 0) +
979
198k
                    (fixed_pixround(ox + eqx) >= fixed_pixround(cbox.q.x) ?
980
132k
                     image_clip_xmax : 0) +
981
198k
                    (fixed_pixround(oy + epy) < fixed_pixround(cbox.p.y) ?
982
152k
                     image_clip_ymin : 0) +
983
198k
                    (fixed_pixround(oy + eqy) >= fixed_pixround(cbox.q.y) ?
984
146k
                     image_clip_ymax : 0);
985
198k
        }
986
198k
    }
987
0
    penum->y = 0;
988
198k
    penum->used.x = 0;
989
198k
    penum->used.y = 0;
990
198k
    if (penum->clip_image && pcpath) {  /* Set up the clipping device. */
991
56.0k
        gx_device_clip *cdev =
992
56.0k
            gs_alloc_struct(mem, gx_device_clip,
993
56.0k
                            &st_device_clip, "image clipper");
994
995
56.0k
        if (cdev == NULL) {
996
0
            code = gs_error_VMerror;
997
0
            goto fail;
998
0
        }
999
56.0k
        gx_make_clip_device_in_heap(cdev, pcpath, dev, mem);
1000
56.0k
        penum->clip_dev = cdev;
1001
56.0k
        penum->dev = (gx_device *)cdev; /* Will restore this in a mo. Hacky! */
1002
56.0k
    }
1003
198k
    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
198k
    {
1023
198k
        static sample_unpack_proc_t procs[2][6] = {
1024
198k
        {   sample_unpack_1, sample_unpack_2,
1025
198k
            sample_unpack_4, sample_unpack_8,
1026
198k
            sample_unpack_12, sample_unpack_16
1027
198k
        },
1028
198k
        {   sample_unpack_1_interleaved, sample_unpack_2_interleaved,
1029
198k
            sample_unpack_4_interleaved, sample_unpack_8_interleaved,
1030
198k
            sample_unpack_12, sample_unpack_16
1031
198k
        }};
1032
198k
        int num_planes = penum->num_planes;
1033
198k
        bool interleaved = (num_planes == 1 && penum->plane_depths[0] != penum->bps);
1034
198k
        irender_proc_t render_fn = NULL;
1035
198k
        int i;
1036
1037
198k
        if (interleaved) {
1038
112k
            int num_components = penum->plane_depths[0] / penum->bps;
1039
1040
340k
            for (i = 1; i < num_components; i++) {
1041
228k
                if (decode[0] != decode[i * 2 + 0] ||
1042
228k
                    decode[1] != decode[i * 2 + 1])
1043
0
                    break;
1044
228k
            }
1045
112k
            if (i == num_components)
1046
112k
                interleaved = false; /* Use single table. */
1047
112k
        }
1048
198k
        penum->unpack = procs[interleaved][index_bps];
1049
1050
198k
        if_debug1m('b', mem, "[b]unpack=%d\n", bps);
1051
        /* Set up pixel0 for image class procedures. */
1052
198k
        penum->dda.pixel0 = penum->dda.strip;
1053
198k
        penum->skip_next_line = NULL;
1054
859k
        for (i = 0; i < gx_image_class_table_count; ++i) {
1055
859k
            code = gx_image_class_table[i](penum, &render_fn);
1056
859k
            if (code < 0)
1057
0
                goto fail;
1058
1059
859k
            if (render_fn != NULL) {
1060
198k
                penum->render = render_fn;
1061
198k
                break;
1062
198k
            }
1063
859k
        }
1064
198k
        penum->dev = dev; /* Restore this (in case it was changed to cdev or rtdev) */
1065
198k
        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
198k
    }
1070
198k
    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
198k
}
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
0
{
1158
0
    int num_des_comp = penum->dev->color_info.num_components;
1159
0
    int num_src_comp;
1160
0
    int num_entries = 1 << bps;
1161
0
    bool need_decode = penum->icc_setup.need_decode;
1162
0
    bool has_transfer = penum->icc_setup.has_transfer;
1163
0
    byte value;
1164
0
    bool decode_scale = true;
1165
0
    int k, kk;
1166
0
    byte psrc[4];
1167
0
    byte *temp_buffer;
1168
0
    byte *byte_ptr;
1169
0
    bool is_indexed = (gs_color_space_get_index(penum->pcs) ==
1170
0
                                            gs_color_space_index_Indexed);
1171
0
    bool free_temp_buffer = true;
1172
0
    gsicc_bufferdesc_t input_buff_desc;
1173
0
    gsicc_bufferdesc_t output_buff_desc;
1174
0
    gx_color_value conc[GX_DEVICE_COLOR_MAX_COMPONENTS];
1175
0
    int code;
1176
1177
0
    if (penum->icc_link == NULL) {
1178
0
        return gs_rethrow(-1, "ICC Link not created during image render color");
1179
0
    }
1180
0
    if (is_indexed) {
1181
0
        num_src_comp = gs_color_space_num_components(penum->pcs->base_space);
1182
0
    } 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
0
        if (penum->icc_link->is_identity && !need_decode && !has_transfer) {
1187
0
            return 0;
1188
0
        }
1189
0
        num_src_comp = 1;
1190
0
    }
1191
    /* Allocate cache of device contone values */
1192
0
    penum->color_cache = gs_alloc_struct(penum->memory, gx_image_color_cache_t,
1193
0
                                         &st_color_cache,
1194
0
                                         "image_init_color_cache");
1195
0
    if (penum->color_cache == NULL)
1196
0
        return_error(gs_error_VMerror);
1197
1198
0
    penum->color_cache->device_contone = (byte*) gs_alloc_bytes(penum->memory,
1199
0
                   num_des_comp * num_entries * sizeof(byte), "image_init_color_cache");
1200
0
    penum->color_cache->is_transparent = (bool*) gs_alloc_bytes(penum->memory,
1201
0
             num_entries * sizeof(bool), "image_init_color_cache");
1202
0
    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
0
    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
0
    if (need_decode) {
1220
0
        decode_scale = decode_range_needed(penum);
1221
0
    }
1222
0
    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
0
    } 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
0
        temp_buffer = (byte*) gs_alloc_bytes(penum->memory,
1268
0
                                             (size_t)num_entries * num_src_comp,
1269
0
                                             "image_init_color_cache");
1270
0
        if (temp_buffer == NULL)
1271
0
            return_error(gs_error_VMerror);
1272
1273
0
        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
0
        } else {
1288
            /* No Decode */
1289
0
            if (is_indexed) {
1290
                /* If index uses a num_entries sized table then just use its pointer */
1291
0
                if (penum->pcs->params.indexed.use_proc ||
1292
0
                    penum->pcs->params.indexed.hival < (num_entries - 1)) {
1293
                    /* Have to do the slow way */
1294
0
                    for (k = 0; k <= penum->pcs->params.indexed.hival; k++) {
1295
0
                        gs_cspace_indexed_lookup_bytes(penum->pcs, (float)k, psrc);
1296
0
                        memcpy(&(temp_buffer[k * num_src_comp]), psrc, num_src_comp);
1297
0
                    }
1298
                    /* just use psrc results from converting 'hival' to fill the remaining slots */
1299
0
                    for (; k < num_entries; k++) {
1300
0
                        memcpy(&(temp_buffer[k * num_src_comp]), psrc, num_src_comp);
1301
0
                    }
1302
0
                } else {
1303
                    /* Use the index table directly. */
1304
0
                    gs_free_object(penum->memory, temp_buffer, "image_init_color_cache");
1305
0
                    free_temp_buffer = false;
1306
0
                    temp_buffer = (byte *)(penum->pcs->params.indexed.lookup.table.data);
1307
0
                }
1308
0
            } else {
1309
                /* CM only */
1310
0
                for (k = 0; k < num_entries; k++) {
1311
0
                    temp_buffer[k] = k;
1312
0
                }
1313
0
            }
1314
0
        }
1315
        /* Set up the buffer descriptors. */
1316
0
        gsicc_init_buffer(&input_buff_desc, num_src_comp, 1, false, false, false,
1317
0
                          0, num_entries * num_src_comp, 1, num_entries);
1318
0
        gsicc_init_buffer(&output_buff_desc, num_des_comp, 1, false, false, false,
1319
0
                          0, num_entries * num_des_comp,
1320
0
                      1, num_entries);
1321
0
        code = (penum->icc_link->procs.map_buffer)(penum->dev, penum->icc_link,
1322
0
                                            &input_buff_desc, &output_buff_desc,
1323
0
                                            (void*) temp_buffer,
1324
0
                                            (void*) penum->color_cache->device_contone);
1325
0
        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
0
        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
0
        if (free_temp_buffer)
1343
0
            gs_free_object(penum->memory, temp_buffer, "image_init_color_cache");
1344
0
    }
1345
0
    return 0;
1346
0
}
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
97.1k
{
1352
    /* Initialize the color table */
1353
97.1k
#define ictype(i)\
1354
97.1k
  penum->clues[i].dev_color.type
1355
1356
97.1k
    switch ((spp == 1 ? bps : 8)) {
1357
66.3k
        case 8:         /* includes all color images */
1358
66.3k
            {
1359
66.3k
                register gx_image_clue *pcht = &penum->clues[0];
1360
66.3k
                register int n = 64;    /* 8 bits means 256 clues, do   */
1361
                                        /* 4 at a time for efficiency   */
1362
4.24M
                do {
1363
4.24M
                    pcht[0].dev_color.type =
1364
4.24M
                        pcht[1].dev_color.type =
1365
4.24M
                        pcht[2].dev_color.type =
1366
4.24M
                        pcht[3].dev_color.type =
1367
4.24M
                        gx_dc_type_none;
1368
4.24M
                    pcht[0].key = pcht[1].key =
1369
4.24M
                        pcht[2].key = pcht[3].key = 0;
1370
4.24M
                    pcht += 4;
1371
4.24M
                }
1372
4.24M
                while (--n > 0);
1373
66.3k
                penum->clues[0].key = 1;        /* guarantee no hit */
1374
66.3k
                break;
1375
0
            }
1376
138
        case 4:
1377
138
            ictype(17) = ictype(2 * 17) = ictype(3 * 17) =
1378
138
                ictype(4 * 17) = ictype(6 * 17) = ictype(7 * 17) =
1379
138
                ictype(8 * 17) = ictype(9 * 17) = ictype(11 * 17) =
1380
138
                ictype(12 * 17) = ictype(13 * 17) = ictype(14 * 17) =
1381
138
                gx_dc_type_none;
1382
            /* falls through */
1383
252
        case 2:
1384
252
            ictype(5 * 17) = ictype(10 * 17) = gx_dc_type_none;
1385
97.1k
#undef ictype
1386
97.1k
    }
1387
97.1k
}
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
146k
{
1396
146k
    int ci, decode_type, code;
1397
146k
    static const float default_decode[] = {
1398
146k
        0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0
1399
146k
    };
1400
1401
    /* Clues are only used with image_mono_render */
1402
146k
    if (spp == 1) {
1403
34.0k
        image_init_clues(penum, bps, spp);
1404
34.0k
    }
1405
146k
    decode_type = 3; /* 0=custom, 1=identity, 2=inverted, 3=impossible */
1406
404k
    for (ci = 0; ci < spp; ci +=2 ) {
1407
258k
        decode_type &= (decode[ci] == 0. && decode[ci + 1] == 1.) |
1408
258k
                       (decode[ci] == 1. && decode[ci + 1] == 0.) << 1;
1409
258k
    }
1410
1411
    /* Initialize the maps from samples to intensities. */
1412
520k
    for (ci = 0; ci < spp; ci++) {
1413
374k
        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
374k
        const float *this_decode = &decode[ci * 2];
1420
374k
        const float *map_decode;        /* decoding used to */
1421
                                        /* construct the expansion map */
1422
374k
        const float *real_decode;       /* decoding for expanded samples */
1423
1424
374k
        map_decode = real_decode = this_decode;
1425
374k
        if (!(decode_type & 1)) {
1426
1.01k
            if ((decode_type & 2) && bps <= 8) {
1427
42
                real_decode = default_decode;
1428
970
            } else {
1429
970
                *pdcb = false;
1430
970
                map_decode = default_decode;
1431
970
            }
1432
1.01k
        }
1433
374k
        if (bps > 2 || format != gs_image_format_chunky) {
1434
373k
            if (bps <= 8)
1435
373k
                image_init_map(&pmap->table.lookup8[0], 1 << bps,
1436
373k
                               map_decode);
1437
373k
        } else {                /* The map index encompasses more than one pixel. */
1438
895
            byte map[4];
1439
895
            register int i;
1440
1441
895
            image_init_map(&map[0], 1 << bps, map_decode);
1442
895
            switch (bps) {
1443
838
                case 1:
1444
838
                    {
1445
838
                        register bits32 *p = &pmap->table.lookup4x1to32[0];
1446
1447
838
                        if (map[0] == 0 && map[1] == 0xff)
1448
835
                            memcpy((byte *) p, lookup4x1to32_identity, 16 * 4);
1449
3
                        else if (map[0] == 0xff && map[1] == 0)
1450
3
                            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
838
                    }
1458
838
                    break;
1459
57
                case 2:
1460
57
                    {
1461
57
                        register bits16 *p = &pmap->table.lookup2x2to16[0];
1462
1463
969
                        for (i = 0; i < 16; i++, p++)
1464
912
                            ((byte *) p)[0] = map[i >> 2],
1465
912
                                ((byte *) p)[1] = map[i & 3];
1466
57
                    }
1467
57
                    break;
1468
895
            }
1469
895
        }
1470
374k
        pmap->decode_base /* = decode_lookup[0] */  = real_decode[0];
1471
374k
        pmap->decode_factor =
1472
374k
            (real_decode[1] - real_decode[0]) /
1473
374k
            (bps <= 8 ? 255.0 : (float)frac_1);
1474
374k
        pmap->decode_max /* = decode_lookup[15] */  = real_decode[1];
1475
374k
        if (decode_type) {
1476
373k
            pmap->decoding = sd_none;
1477
373k
            pmap->inverted = map_decode[0] != 0;
1478
373k
        } else if (bps <= 4) {
1479
62
            int step = 15 / ((1 << bps) - 1);
1480
62
            int i;
1481
1482
62
            pmap->decoding = sd_lookup;
1483
306
            for (i = 15 - step; i > 0; i -= step)
1484
244
                pmap->decode_lookup[i] = pmap->decode_base +
1485
244
                    i * (255.0 / 15) * pmap->decode_factor;
1486
62
            pmap->inverted = 0;
1487
908
        } else {
1488
908
            pmap->decoding = sd_compute;
1489
908
            pmap->inverted = 0;
1490
908
        }
1491
374k
        if (spp == 1) {         /* and ci == 0 *//* Pre-map entries 0 and 255. */
1492
34.0k
            gs_client_color cc;
1493
1494
            /* Image clues are used in this case */
1495
34.0k
            cc.paint.values[0] = real_decode[0];
1496
34.0k
            code = (*pcs->type->remap_color) (&cc, pcs, penum->icolor0,
1497
34.0k
                                       pgs, dev, gs_color_select_source);
1498
34.0k
            if (code < 0)
1499
0
                return code;
1500
34.0k
            cc.paint.values[0] = real_decode[1];
1501
34.0k
            code = (*pcs->type->remap_color) (&cc, pcs, penum->icolor1,
1502
34.0k
                                       pgs, dev, gs_color_select_source);
1503
34.0k
            if (code < 0)
1504
0
                return code;
1505
34.0k
        }
1506
374k
    }
1507
146k
    return 0;
1508
146k
}
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
374k
{
1515
374k
    float min_v = decode[0];
1516
374k
    float diff_v = decode[1] - min_v;
1517
1518
374k
    if (diff_v == 1 || diff_v == -1) {  /* We can do the stepping with integers, without overflow. */
1519
374k
        byte *limit = map + map_size;
1520
374k
        uint value = (uint)(min_v * 0xffffL);
1521
374k
        int diff = (int)(diff_v * (0xffffL / (map_size - 1)));
1522
1523
95.9M
        for (; map != limit; map++, value += diff)
1524
95.5M
            *map = value >> 8;
1525
374k
    } 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
374k
}
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
27
{
1544
27
    uint scale = 255 / ((1 << penum->bps) - 1);
1545
27
    uint *values = &penum->mask_color.values[component_index * 2];
1546
27
    uint v0 = values[0] *= scale;
1547
27
    uint v1 = values[1] *= scale;
1548
1549
27
    if (penum->map[component_index].decoding == sd_none &&
1550
27
        penum->map[component_index].inverted
1551
27
        ) {
1552
0
        values[0] = 255 - v1;
1553
0
        values[1] = 255 - v0;
1554
0
    }
1555
27
}
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
116k
{
1561
116k
    int k;
1562
1563
116k
    for (k = 0; k < num_comps; k++) {
1564
116k
        if (pgs->effective_transfer[k]->proc != gs_identity_transfer) {
1565
116k
            return(true);
1566
116k
        }
1567
116k
    }
1568
0
    return(false);
1569
116k
}