Coverage Report

Created: 2025-06-10 06:56

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