Coverage Report

Created: 2025-08-28 07:06

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