Coverage Report

Created: 2025-06-10 06:49

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