Coverage Report

Created: 2025-06-10 06:59

/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
97.5k
{
152
97.5k
    const gs_pixel_image_t *pim = (const gs_pixel_image_t *)pic;
153
97.5k
    int width = pim->Width, height = pim->Height;
154
97.5k
    int bpc = pim->BitsPerComponent;
155
97.5k
    gx_image_enum *penum;
156
157
97.5k
    if (width < 0 || height < 0)
158
0
        return_error(gs_error_rangecheck);
159
97.5k
    switch (pim->format) {
160
97.5k
    case gs_image_format_chunky:
161
97.5k
    case gs_image_format_component_planar:
162
97.5k
        switch (bpc) {
163
97.5k
        case 1: case 2: case 4: case 8: case 12: case 16: break;
164
0
        default: return_error(gs_error_rangecheck);
165
97.5k
        }
166
97.5k
        break;
167
97.5k
    case gs_image_format_bit_planar:
168
0
        if (bpc < 1 || bpc > 8)
169
0
            return_error(gs_error_rangecheck);
170
97.5k
    }
171
97.5k
    if (prect) {
172
32.0k
        if (prect->p.x < 0 || prect->p.y < 0 ||
173
32.0k
            prect->q.x < prect->p.x || prect->q.y < prect->p.y ||
174
32.0k
            prect->q.x > width || prect->q.y > height
175
32.0k
            )
176
0
            return_error(gs_error_rangecheck);
177
32.0k
    }
178
97.5k
    *ppenum = NULL;   /* in case alloc fails and caller doesn't check code */
179
97.5k
    penum = gs_alloc_struct(mem, gx_image_enum, &st_gx_image_enum,
180
97.5k
                            "gx_default_begin_image");
181
97.5k
    if (penum == 0)
182
0
        return_error(gs_error_VMerror);
183
97.5k
    memset(penum, 0, sizeof(gx_image_enum));  /* in case of failure, no dangling pointers */
184
97.5k
    if (prect) {
185
32.0k
        penum->rect.x = prect->p.x;
186
32.0k
        penum->rect.y = prect->p.y;
187
32.0k
        penum->rect.w = prect->q.x - prect->p.x;
188
32.0k
        penum->rect.h = prect->q.y - prect->p.y;
189
65.5k
    } else {
190
65.5k
        penum->rect.x = 0, penum->rect.y = 0;
191
65.5k
        penum->rect.w = width, penum->rect.h = height;
192
65.5k
    }
193
97.5k
    penum->rrect.x = penum->rect.x;
194
97.5k
    penum->rrect.y = penum->rect.y;
195
97.5k
    penum->rrect.w = penum->rect.w;
196
97.5k
    penum->rrect.h = penum->rect.h;
197
97.5k
    penum->drect.x = penum->rect.x;
198
97.5k
    penum->drect.y = penum->rect.y;
199
97.5k
    penum->drect.w = penum->rect.w;
200
97.5k
    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
97.5k
    *ppenum = penum;
210
97.5k
    return 0;
211
97.5k
}
212
213
/* Convert and restrict to a valid range. */
214
260k
static inline fixed float2fixed_rounded_boxed(double src) {
215
260k
    float v = floor(src*fixed_scale + 0.5);
216
217
260k
    if (v <= min_fixed)
218
4
        return min_fixed;
219
260k
    else if (v >= max_fixed)
220
3
        return max_fixed;
221
260k
    else
222
260k
        return  (fixed)v;
223
260k
}
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
101k
{
230
101k
    int code = 0;
231
232
101k
    if (pmat == 0)
233
100k
        pmat = &ctm_only(pgs);
234
101k
    if (ImageMatrix->xx == pmat->xx && ImageMatrix->xy == pmat->xy &&
235
101k
        ImageMatrix->yx == pmat->yx && ImageMatrix->yy == pmat->yy) {
236
        /* Process common special case separately to accept singular matrix. */
237
62.9k
        rmat->xx = rmat->yy = 1.;
238
62.9k
        rmat->xy = rmat->yx = 0.;
239
62.9k
        rmat->tx = pmat->tx - ImageMatrix->tx;
240
62.9k
        rmat->ty = pmat->ty - ImageMatrix->ty;
241
62.9k
    } else {
242
38.0k
        if ((code = gs_matrix_invert_to_double(ImageMatrix, rmat)) < 0 ||
243
38.0k
            (code = gs_matrix_multiply_double(rmat, pmat, rmat)) < 0
244
38.0k
            ) {
245
8
            return code;
246
8
        }
247
38.0k
    }
248
101k
    return code;
249
101k
}
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
97.5k
{
264
97.5k
    const gs_pixel_image_t *pim = (const gs_pixel_image_t *)pic;
265
97.5k
    gs_image_format_t format = pim->format;
266
97.5k
    const int width = pim->Width;
267
97.5k
    const int height = pim->Height;
268
97.5k
    const int bps = pim->BitsPerComponent;
269
97.5k
    bool masked = penum->masked;
270
97.5k
    const float *decode = pim->Decode;
271
97.5k
    gs_matrix_double mat;
272
97.5k
    int index_bps;
273
97.5k
    gs_color_space *pcs = pim->ColorSpace;
274
97.5k
    gs_logical_operation_t lop = (pgs ? pgs->log_op : lop_default);
275
97.5k
    int code;
276
97.5k
    int log2_xbytes = (bps <= 8 ? 0 : arch_log2_sizeof_frac);
277
97.5k
    int spp, nplanes, spread;
278
97.5k
    uint bsize;
279
97.5k
    byte *buffer = NULL;
280
97.5k
    fixed mtx, mty;
281
97.5k
    gs_fixed_point row_extent, col_extent, x_extent, y_extent;
282
97.5k
    bool device_color = true;
283
97.5k
    gs_fixed_rect obox, cbox;
284
97.5k
    bool gridfitimages = 0;
285
97.5k
    bool in_pattern_accumulator;
286
97.5k
    bool in_smask;
287
97.5k
    int orthogonal;
288
97.5k
    int force_interpolation = 0;
289
290
97.5k
    penum->pcs = NULL;
291
97.5k
    penum->clues = NULL;
292
97.5k
    penum->icc_setup.has_transfer = false;
293
97.5k
    penum->icc_setup.is_lab = false;
294
97.5k
    penum->icc_setup.must_halftone = false;
295
97.5k
    penum->icc_setup.need_decode = false;
296
97.5k
    penum->Width = width;
297
97.5k
    penum->Height = height;
298
299
97.5k
    if ((code = gx_image_compute_mat(pgs, pmat, &(pim->ImageMatrix), &mat)) < 0) {
300
7
        return code;
301
7
    }
302
97.5k
    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
97.5k
    in_pattern_accumulator = (dev_proc(dev, dev_spec_op)(dev, gxdso_in_pattern_accumulator, NULL, 0));
323
97.5k
    if (in_pattern_accumulator < 0)
324
64.0k
        in_pattern_accumulator = 0;
325
326
    /* Figure out if we are orthogonal */
327
97.5k
    if (mat.xy == 0 && mat.yx == 0)
328
96.7k
        orthogonal = 1;
329
799
    else if (mat.xx == 0 && mat.yy == 0)
330
775
        orthogonal = 2;
331
24
    else
332
24
        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
97.5k
    in_smask = (pim->override_in_smask ||
340
97.5k
                (dev_proc(dev, dev_spec_op)(dev, gxdso_in_smask, NULL, 0)) > 0);
341
97.5k
    gridfitimages = (in_smask || in_pattern_accumulator) && orthogonal;
342
343
97.5k
    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
95.8k
    } else if (!gridfitimages &&
347
95.8k
               (!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
68.8k
    } else if (gridfitimages && (penum->masked && penum->image_parent_type == 0)) {
351
        /* We don't gridfit imagemasks in a pattern accumulator */
352
26.9k
    } 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
26.9k
    } else if (orthogonal == 1) {
355
26.2k
        if (width == 1 || gridfitimages) {
356
25.1k
            if (mat.xx > 0) {
357
25.0k
                fixed ix0 = int2fixed(fixed2int(float2fixed(mat.tx)));
358
25.0k
                double x1 = mat.tx + mat.xx * width;
359
25.0k
                fixed ix1 = int2fixed(fixed2int_ceiling(float2fixed(x1)));
360
25.0k
                mat.tx = (double)fixed2float(ix0);
361
25.0k
                mat.xx = (double)(fixed2float(ix1 - ix0)/width);
362
25.0k
            } else if (mat.xx < 0) {
363
6
                fixed ix0 = int2fixed(fixed2int_ceiling(float2fixed(mat.tx)));
364
6
                double x1 = mat.tx + mat.xx * width;
365
6
                fixed ix1 = int2fixed(fixed2int(float2fixed(x1)));
366
6
                mat.tx = (double)fixed2float(ix0);
367
6
                mat.xx = (double)(fixed2float(ix1 - ix0)/width);
368
6
            }
369
25.1k
        }
370
26.2k
        if (height == 1 || gridfitimages) {
371
25.0k
            if (mat.yy > 0) {
372
25.0k
                fixed iy0 = int2fixed(fixed2int(float2fixed(mat.ty)));
373
25.0k
                double y1 = mat.ty + mat.yy * height;
374
25.0k
                fixed iy1 = int2fixed(fixed2int_ceiling(float2fixed(y1)));
375
25.0k
                mat.ty = (double)fixed2float(iy0);
376
25.0k
                mat.yy = (double)(fixed2float(iy1 - iy0)/height);
377
25.0k
            } else if (mat.yy < 0) {
378
41
                fixed iy0 = int2fixed(fixed2int_ceiling(float2fixed(mat.ty)));
379
41
                double y1 = mat.ty + mat.yy * height;
380
41
                fixed iy1 = int2fixed(fixed2int(float2fixed(y1)));
381
41
                mat.ty = (double)fixed2float(iy0);
382
41
                mat.yy = ((double)fixed2float(iy1 - iy0)/height);
383
41
            }
384
25.0k
        }
385
26.2k
    } else if (orthogonal == 2) {
386
729
        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
729
        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
729
    }
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
97.5k
    if (in_pattern_accumulator) {
422
22
        double ome = ((double)(fixed_1 - fixed_epsilon)) / (double)fixed_1; /* One Minus Epsilon */
423
424
22
        if (orthogonal == 1) {
425
22
            if ((mat.xx > -ome && mat.xx < ome) || (mat.yy > -ome && mat.yy < ome)) {
426
20
                force_interpolation = true;
427
20
            }
428
22
        } 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
22
    }
434
435
    /* Can we restrict the amount of image we need? */
436
97.5k
    while (!pim->imagematrices_are_untrustworthy) /* So we can break out of it */
437
97.5k
    {
438
97.5k
        gs_rect rect, rect_src;
439
97.5k
        gs_matrix mi;
440
97.5k
        const gs_matrix *m = pgs != NULL ? &ctm_only(pgs) : NULL;
441
97.5k
        gs_int_rect irect;
442
97.5k
        if (m == NULL || (code = gs_matrix_invert(m, &mi)) < 0 ||
443
97.5k
            (code = gs_matrix_multiply(&mi, &pic->ImageMatrix, &mi)) < 0) {
444
            /* Give up trying to shrink the render box, but continue processing */
445
32
            break;
446
32
        }
447
97.4k
        if (pcpath)
448
17.7k
        {
449
17.7k
            gs_fixed_rect obox;
450
17.7k
            gx_cpath_outer_box(pcpath, &obox);
451
17.7k
            rect.p.x = fixed2float(obox.p.x);
452
17.7k
            rect.p.y = fixed2float(obox.p.y);
453
17.7k
            rect.q.x = fixed2float(obox.q.x);
454
17.7k
            rect.q.y = fixed2float(obox.q.y);
455
17.7k
        }
456
79.7k
        else
457
79.7k
        {
458
79.7k
            rect.p.x = 0;
459
79.7k
            rect.p.y = 0;
460
79.7k
            rect.q.x = dev->width;
461
79.7k
            rect.q.y = dev->height;
462
79.7k
        }
463
        /* rect is in destination space. Calculate rect_src, in source space. */
464
97.4k
        code = gs_bbox_transform(&rect, &mi, &rect_src);
465
97.4k
        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
97.4k
        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
97.4k
        irect.p.x = (int)floor(rect_src.p.x);
497
97.4k
        irect.p.y = (int)floor(rect_src.p.y);
498
97.4k
        irect.q.x = (int)ceil(rect_src.q.x);
499
97.4k
        irect.q.y = (int)ceil(rect_src.q.y);
500
        /* We therefore only need to render within irect. Restrict rrect to this. */
501
97.4k
        if (penum->rrect.x < irect.p.x) {
502
104
            penum->rrect.w -= irect.p.x - penum->rrect.x;
503
104
            if (penum->rrect.w < 0)
504
6
               penum->rrect.w = 0;
505
104
            penum->rrect.x = irect.p.x;
506
104
        }
507
97.4k
        if (penum->rrect.x + penum->rrect.w > irect.q.x) {
508
538
            penum->rrect.w = irect.q.x - penum->rrect.x;
509
538
            if (penum->rrect.w < 0)
510
182
                penum->rrect.w = 0;
511
538
        }
512
97.4k
        if (penum->rrect.y < irect.p.y) {
513
8.31k
            penum->rrect.h -= irect.p.y - penum->rrect.y;
514
8.31k
            if (penum->rrect.h < 0)
515
196
                penum->rrect.h = 0;
516
8.31k
            penum->rrect.y = irect.p.y;
517
8.31k
        }
518
97.4k
        if (penum->rrect.y + penum->rrect.h > irect.q.y) {
519
7.70k
            penum->rrect.h = irect.q.y - penum->rrect.y;
520
7.70k
            if (penum->rrect.h < 0)
521
13
                penum->rrect.h = 0;
522
7.70k
        }
523
97.4k
        if (penum->drect.x < irect.p.x) {
524
104
            penum->drect.w -= irect.p.x - penum->drect.x;
525
104
            if (penum->drect.w < 0)
526
6
               penum->drect.w = 0;
527
104
            penum->drect.x = irect.p.x;
528
104
        }
529
97.4k
        if (penum->drect.x + penum->drect.w > irect.q.x) {
530
538
            penum->drect.w = irect.q.x - penum->drect.x;
531
538
            if (penum->drect.w < 0)
532
182
                penum->drect.w = 0;
533
538
        }
534
97.4k
        if (penum->drect.y < irect.p.y) {
535
8.31k
            penum->drect.h -= irect.p.y - penum->drect.y;
536
8.31k
            if (penum->drect.h < 0)
537
196
                penum->drect.h = 0;
538
8.31k
            penum->drect.y = irect.p.y;
539
8.31k
        }
540
97.4k
        if (penum->drect.y + penum->drect.h > irect.q.y) {
541
7.70k
            penum->drect.h = irect.q.y - penum->drect.y;
542
7.70k
            if (penum->drect.h < 0)
543
13
                penum->drect.h = 0;
544
7.70k
        }
545
97.4k
        break; /* Out of the while */
546
97.4k
    }
547
    /* Check for the intersection being null */
548
97.5k
    if (penum->drect.x + penum->drect.w <= penum->rect.x  ||
549
97.5k
        penum->rect.x  + penum->rect.w  <= penum->drect.x ||
550
97.5k
        penum->drect.y + penum->drect.h <= penum->rect.y  ||
551
97.5k
        penum->rect.y  + penum->rect.h  <= penum->drect.y)
552
443
    {
553
          /* Something may have gone wrong with the floating point above.
554
           * set the region to something sane. */
555
443
        penum->drect.x = penum->rect.x;
556
443
        penum->drect.y = penum->rect.y;
557
443
        penum->drect.w = 0;
558
443
        penum->drect.h = 0;
559
443
    }
560
97.5k
    if (penum->rrect.x + penum->rrect.w <= penum->drect.x  ||
561
97.5k
        penum->drect.x + penum->drect.w  <= penum->rrect.x ||
562
97.5k
        penum->rrect.y + penum->rrect.h <= penum->drect.y  ||
563
97.5k
        penum->drect.y + penum->drect.h  <= penum->rrect.y)
564
443
    {
565
          /* Something may have gone wrong with the floating point above.
566
           * set the region to something sane. */
567
443
        penum->rrect.x = penum->drect.x;
568
443
        penum->rrect.y = penum->drect.y;
569
443
        penum->rrect.w = 0;
570
443
        penum->rrect.h = 0;
571
443
    }
572
573
    /*penum->matrix = mat;*/
574
97.5k
    penum->matrix.xx = mat.xx;
575
97.5k
    penum->matrix.xy = mat.xy;
576
97.5k
    penum->matrix.yx = mat.yx;
577
97.5k
    penum->matrix.yy = mat.yy;
578
97.5k
    penum->matrix.tx = mat.tx;
579
97.5k
    penum->matrix.ty = mat.ty;
580
97.5k
    if_debug6m('b', mem, " [%g %g %g %g %g %g]\n",
581
97.5k
              mat.xx, mat.xy, mat.yx, mat.yy, mat.tx, mat.ty);
582
    /* following works for 1, 2, 4, 8, 12, 16 */
583
97.5k
    index_bps = (bps < 8 ? bps >> 1 : (bps >> 2) + 1);
584
    /*
585
     * Compute extents with distance transformation.
586
     */
587
97.5k
    if (mat.tx > 0)
588
84.8k
        mtx = float2fixed(mat.tx);
589
12.7k
    else { /* Use positive values to ensure round down. */
590
12.7k
        int f = (int)-mat.tx + 1;
591
592
12.7k
        mtx = float2fixed(mat.tx + f) - int2fixed(f);
593
12.7k
    }
594
97.5k
    if (mat.ty > 0)
595
10.8k
        mty = float2fixed(mat.ty);
596
86.6k
    else {  /* Use positive values to ensure round down. */
597
86.6k
        int f = (int)-mat.ty + 1;
598
599
86.6k
        mty = float2fixed(mat.ty + f) - int2fixed(f);
600
86.6k
    }
601
602
97.5k
    row_extent.x = float2fixed_rounded_boxed(width * mat.xx);
603
97.5k
    row_extent.y =
604
97.5k
        (is_fzero(mat.xy) ? fixed_0 :
605
97.5k
         float2fixed_rounded_boxed(width * mat.xy));
606
97.5k
    col_extent.x =
607
97.5k
        (is_fzero(mat.yx) ? fixed_0 :
608
97.5k
         float2fixed_rounded_boxed(height * mat.yx));
609
97.5k
    col_extent.y = float2fixed_rounded_boxed(height * mat.yy);
610
97.5k
    gx_image_enum_common_init((gx_image_enum_common_t *)penum,
611
97.5k
                              (const gs_data_image_t *)pim,
612
97.5k
                              &image1_enum_procs, dev,
613
97.5k
                              (masked ? 1 : (penum->alpha ? cs_num_components(pcs)+1 : cs_num_components(pcs))),
614
97.5k
                              format);
615
97.5k
    if (penum->rect.w == width && penum->rect.h == height) {
616
65.5k
        x_extent = row_extent;
617
65.5k
        y_extent = col_extent;
618
65.5k
    } else {
619
31.9k
        int rw = penum->rect.w, rh = penum->rect.h;
620
621
31.9k
        x_extent.x = float2fixed_rounded_boxed(rw * mat.xx);
622
31.9k
        x_extent.y =
623
31.9k
            (is_fzero(mat.xy) ? fixed_0 :
624
31.9k
             float2fixed_rounded_boxed(rw * mat.xy));
625
31.9k
        y_extent.x =
626
31.9k
            (is_fzero(mat.yx) ? fixed_0 :
627
31.9k
             float2fixed_rounded_boxed(rh * mat.yx));
628
31.9k
        y_extent.y = float2fixed_rounded_boxed(rh * mat.yy);
629
31.9k
    }
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
97.5k
    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
21.8k
        penum->clues = (gx_image_clue*) gs_alloc_bytes(mem, sizeof(gx_image_clue)*256,
638
21.8k
                             "gx_image_enum_begin");
639
21.8k
        if (penum->clues == NULL) {
640
0
            code = gs_error_VMerror;
641
0
            goto fail;
642
0
        }
643
21.8k
        penum->icolor0 = &(penum->clues[0].dev_color);
644
21.8k
        penum->icolor1 = &(penum->clues[255].dev_color);
645
75.6k
    } else {
646
75.6k
        penum->icolor0 = &(penum->icolor0_val);
647
75.6k
        penum->icolor1 = &(penum->icolor1_val);
648
75.6k
    }
649
97.5k
    penum->icolor0->tag = penum->icolor1->tag = device_current_tag(dev);
650
651
97.5k
    if (masked) {       /* This is imagemask. */
652
3.55k
        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
3.55k
        set_nonclient_dev_color(penum->icolor0, gx_no_color_index);
658
3.55k
        set_nonclient_dev_color(penum->icolor1, gx_no_color_index);
659
3.55k
        *(penum->icolor1) = *pdcolor;
660
3.55k
        memcpy(&penum->map[0].table.lookup4x1to32[0],
661
3.55k
               (decode[0] < decode[1] ? lookup4x1to32_inverted :
662
3.55k
                lookup4x1to32_identity),
663
3.55k
               16 * 4);
664
3.55k
        penum->map[0].decoding = sd_none;
665
3.55k
        spp = 1;
666
3.55k
        lop = rop3_know_S_0(lop);
667
93.9k
    } else {                    /* This is image, not imagemask. */
668
93.9k
        const gs_color_space_type *pcst = pcs->type;
669
93.9k
        int b_w_color;
670
671
93.9k
        spp = cs_num_components(pcs);
672
93.9k
        if (spp < 0) {          /* Pattern not allowed */
673
0
            code = gs_error_rangecheck;
674
0
            goto fail;
675
0
        }
676
93.9k
        if (penum->alpha)
677
0
            ++spp;
678
        /* Use a less expensive format if possible. */
679
93.9k
        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
93.9k
        default:                /* chunky */
688
93.9k
            break;
689
93.9k
        }
690
691
93.9k
        if (pcs->cmm_icc_profile_data != NULL) {
692
92.6k
            device_color = false;
693
92.6k
        } else {
694
1.28k
            device_color = (*pcst->concrete_space) (pcs, pgs) == pcs;
695
1.28k
        }
696
697
93.9k
        code = image_init_colors(penum, bps, spp, format, decode, pgs, dev,
698
93.9k
                          pcs, &device_color);
699
93.9k
        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
93.9k
        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
93.9k
        if (!pim->CombineWithColor)
725
93.9k
            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
93.9k
        if (lop != rop3_S &&    /* if best case, no more work needed */
730
93.9k
            !rop3_uses_T(lop) && bps == 1 && spp == 1 &&
731
93.9k
            (b_w_color =
732
0
             color_draws_b_w(dev, penum->icolor0)) >= 0 &&
733
93.9k
            color_draws_b_w(dev, penum->icolor1) == (b_w_color ^ 1)
734
93.9k
            ) {
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
93.9k
    }
777
97.5k
    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
97.5k
    bsize = ((bps > 8 ? width * 2 : width) + 15) * spp;
784
97.5k
    buffer = gs_alloc_bytes(mem, bsize, "image buffer");
785
97.5k
    if (buffer == 0) {
786
0
        code = gs_error_VMerror;
787
0
        goto fail;
788
0
    }
789
97.5k
    penum->bps = bps;
790
97.5k
    penum->unpack_bps = bps;
791
97.5k
    penum->log2_xbytes = log2_xbytes;
792
97.5k
    penum->spp = spp;
793
97.5k
    switch (format) {
794
97.5k
    case gs_image_format_chunky:
795
97.5k
        nplanes = 1;
796
97.5k
        spread = 1 << log2_xbytes;
797
97.5k
        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
97.5k
    }
810
97.5k
    penum->num_planes = nplanes;
811
97.5k
    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
97.5k
    penum->interpolate = force_interpolation ? interp_force : pim->Interpolate ? interp_on : interp_off;
819
97.5k
    penum->x_extent = x_extent;
820
97.5k
    penum->y_extent = y_extent;
821
97.5k
    penum->posture =
822
97.5k
        ((x_extent.y | y_extent.x) == 0 ? image_portrait :
823
97.5k
         (x_extent.x | y_extent.y) == 0 ? image_landscape :
824
799
         image_skewed);
825
97.5k
    penum->pgs = pgs;
826
97.5k
    if (pgs != NULL)
827
97.5k
        penum->pgs_level = pgs->level;
828
97.5k
    penum->pcs = pcs;
829
97.5k
    rc_increment_cs(pcs); /* Grab a ref (will decrement in gx_image1_end_image() */
830
97.5k
    penum->memory = mem;
831
97.5k
    penum->buffer = buffer;
832
97.5k
    penum->buffer_size = bsize;
833
97.5k
    penum->line = NULL;
834
97.5k
    penum->icc_link = NULL;
835
97.5k
    penum->color_cache = NULL;
836
97.5k
    penum->ht_buffer = NULL;
837
97.5k
    penum->thresh_buffer = NULL;
838
97.5k
    penum->use_cie_range = false;
839
97.5k
    penum->line_size = 0;
840
97.5k
    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
97.5k
    penum->slow_loop = 0;
854
97.5k
    if (pcpath == 0) {
855
79.7k
        (*dev_proc(dev, get_clipping_box)) (dev, &obox);
856
79.7k
        cbox = obox;
857
79.7k
        penum->clip_image = 0;
858
79.7k
    } else
859
17.7k
        penum->clip_image =
860
17.7k
            (gx_cpath_outer_box(pcpath, &obox) |        /* not || */
861
17.7k
             gx_cpath_inner_box(pcpath, &cbox) ?
862
17.7k
             0 : image_clip_region);
863
97.5k
    penum->clip_outer = obox;
864
97.5k
    penum->clip_inner = cbox;
865
97.5k
    penum->log_op = rop3_T;     /* rop device takes care of this */
866
97.5k
    penum->clip_dev = 0;        /* in case we bail out */
867
97.5k
    penum->rop_dev = 0;         /* ditto */
868
97.5k
    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
97.5k
    {
876
97.5k
        fixed
877
97.5k
            epx = min(row_extent.x, 0) + min(col_extent.x, 0),
878
97.5k
            eqx = max(row_extent.x, 0) + max(col_extent.x, 0),
879
97.5k
            epy = min(row_extent.y, 0) + min(col_extent.y, 0),
880
97.5k
            eqy = max(row_extent.y, 0) + max(col_extent.y, 0);
881
882
97.5k
        {
883
97.5k
            int hwx, hwy;
884
885
97.5k
            switch (penum->posture) {
886
96.7k
                case image_portrait:
887
96.7k
                    hwx = width, hwy = height;
888
96.7k
                    break;
889
775
                case image_landscape:
890
775
                    hwx = height, hwy = width;
891
775
                    break;
892
24
                default:
893
24
                    hwx = hwy = 0;
894
97.5k
            }
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
97.5k
            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
97.5k
            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
97.5k
        }
917
97.5k
        if_debug5m('b', mem, "[b]Image: %sspp=%d, bps=%d, mt=(%g,%g)\n",
918
97.5k
                   (masked? "masked, " : ""), spp, bps,
919
97.5k
                   fixed2float(mtx), fixed2float(mty));
920
97.5k
        if_debug9m('b', mem,
921
97.5k
                   "[b]   cbox=(%g,%g),(%g,%g), obox=(%g,%g),(%g,%g), clip_image=0x%x\n",
922
97.5k
                   fixed2float(cbox.p.x), fixed2float(cbox.p.y),
923
97.5k
                   fixed2float(cbox.q.x), fixed2float(cbox.q.y),
924
97.5k
                   fixed2float(obox.p.x), fixed2float(obox.p.y),
925
97.5k
                   fixed2float(obox.q.x), fixed2float(obox.q.y),
926
97.5k
                   penum->clip_image);
927
        /* These DDAs enumerate the starting position of each source pixel
928
         * row in device space. */
929
97.5k
        dda_init(penum->dda.row.x, mtx, col_extent.x, height);
930
97.5k
        dda_init(penum->dda.row.y, mty, col_extent.y, height);
931
97.5k
        if (dda_will_overflow(penum->dda.row.x) ||
932
97.5k
            dda_will_overflow(penum->dda.row.y))
933
0
        {
934
0
            code = gs_error_rangecheck;
935
0
            goto fail;
936
0
        }
937
97.5k
        if (penum->posture == image_portrait) {
938
96.7k
            penum->dst_width = row_extent.x;
939
96.7k
            penum->dst_height = col_extent.y;
940
96.7k
        } else {
941
799
            penum->dst_width = col_extent.x;
942
799
            penum->dst_height = row_extent.y;
943
799
        }
944
        /* For gs_image_class_0_interpolate. */
945
97.5k
        penum->yi0 = fixed2int_pixround_perfect(dda_current(penum->dda.row.y)); /* For gs_image_class_0_interpolate. */
946
97.5k
        if (penum->rect.y) {
947
30.0k
            int y = penum->rect.y;
948
949
4.01M
            while (y--) {
950
3.98M
                dda_next(penum->dda.row.x);
951
3.98M
                dda_next(penum->dda.row.y);
952
3.98M
            }
953
30.0k
        }
954
97.5k
        penum->cur.x = penum->prev.x = dda_current(penum->dda.row.x);
955
97.5k
        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
97.5k
        dda_init(penum->dda.strip.x, penum->cur.x, row_extent.x, width);
960
97.5k
        dda_init(penum->dda.strip.y, penum->cur.y, row_extent.y, width);
961
97.5k
        if (dda_will_overflow(penum->dda.strip.x) ||
962
97.5k
            dda_will_overflow(penum->dda.strip.y))
963
0
        {
964
0
            code = gs_error_rangecheck;
965
0
            goto fail;
966
0
        }
967
97.5k
        if (penum->rect.x) {
968
87
            dda_advance(penum->dda.strip.x, penum->rect.x);
969
87
            dda_advance(penum->dda.strip.y, penum->rect.x);
970
87
        }
971
97.5k
        {
972
97.5k
            fixed ox = dda_current(penum->dda.strip.x);
973
97.5k
            fixed oy = dda_current(penum->dda.strip.y);
974
975
97.5k
            if (!penum->clip_image)     /* i.e., not clip region */
976
97.4k
                penum->clip_image =
977
97.4k
                    (fixed_pixround(ox + epx) < fixed_pixround(cbox.p.x) ?
978
97.1k
                     image_clip_xmin : 0) +
979
97.4k
                    (fixed_pixround(ox + eqx) >= fixed_pixround(cbox.q.x) ?
980
71.9k
                     image_clip_xmax : 0) +
981
97.4k
                    (fixed_pixround(oy + epy) < fixed_pixround(cbox.p.y) ?
982
68.9k
                     image_clip_ymin : 0) +
983
97.4k
                    (fixed_pixround(oy + eqy) >= fixed_pixround(cbox.q.y) ?
984
88.9k
                     image_clip_ymax : 0);
985
97.5k
        }
986
97.5k
    }
987
0
    penum->y = 0;
988
97.5k
    penum->used.x = 0;
989
97.5k
    penum->used.y = 0;
990
97.5k
    if (penum->clip_image && pcpath) {  /* Set up the clipping device. */
991
14.7k
        gx_device_clip *cdev =
992
14.7k
            gs_alloc_struct(mem, gx_device_clip,
993
14.7k
                            &st_device_clip, "image clipper");
994
995
14.7k
        if (cdev == NULL) {
996
0
            code = gs_error_VMerror;
997
0
            goto fail;
998
0
        }
999
14.7k
        gx_make_clip_device_in_heap(cdev, pcpath, dev, mem);
1000
14.7k
        penum->clip_dev = cdev;
1001
14.7k
        penum->dev = (gx_device *)cdev; /* Will restore this in a mo. Hacky! */
1002
14.7k
    }
1003
97.5k
    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
97.5k
    {
1023
97.5k
        static sample_unpack_proc_t procs[2][6] = {
1024
97.5k
        {   sample_unpack_1, sample_unpack_2,
1025
97.5k
            sample_unpack_4, sample_unpack_8,
1026
97.5k
            sample_unpack_12, sample_unpack_16
1027
97.5k
        },
1028
97.5k
        {   sample_unpack_1_interleaved, sample_unpack_2_interleaved,
1029
97.5k
            sample_unpack_4_interleaved, sample_unpack_8_interleaved,
1030
97.5k
            sample_unpack_12, sample_unpack_16
1031
97.5k
        }};
1032
97.5k
        int num_planes = penum->num_planes;
1033
97.5k
        bool interleaved = (num_planes == 1 && penum->plane_depths[0] != penum->bps);
1034
97.5k
        irender_proc_t render_fn = NULL;
1035
97.5k
        int i;
1036
1037
97.5k
        if (interleaved) {
1038
75.6k
            int num_components = penum->plane_depths[0] / penum->bps;
1039
1040
229k
            for (i = 1; i < num_components; i++) {
1041
153k
                if (decode[0] != decode[i * 2 + 0] ||
1042
153k
                    decode[1] != decode[i * 2 + 1])
1043
0
                    break;
1044
153k
            }
1045
75.6k
            if (i == num_components)
1046
75.6k
                interleaved = false; /* Use single table. */
1047
75.6k
        }
1048
97.5k
        penum->unpack = procs[interleaved][index_bps];
1049
1050
97.5k
        if_debug1m('b', mem, "[b]unpack=%d\n", bps);
1051
        /* Set up pixel0 for image class procedures. */
1052
97.5k
        penum->dda.pixel0 = penum->dda.strip;
1053
97.5k
        penum->skip_next_line = NULL;
1054
455k
        for (i = 0; i < gx_image_class_table_count; ++i) {
1055
455k
            code = gx_image_class_table[i](penum, &render_fn);
1056
455k
            if (code < 0)
1057
0
                goto fail;
1058
1059
455k
            if (render_fn != NULL) {
1060
97.5k
                penum->render = render_fn;
1061
97.5k
                break;
1062
97.5k
            }
1063
455k
        }
1064
97.5k
        penum->dev = dev; /* Restore this (in case it was changed to cdev or rtdev) */
1065
97.5k
        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
97.5k
    }
1070
97.5k
    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
97.5k
}
1085
1086
/* If a drawing color is black or white, return 0 or 1 respectively, */
1087
/* otherwise return -1. */
1088
static int
1089
color_draws_b_w(gx_device * dev, const gx_drawing_color * pdcolor)
1090
0
{
1091
0
    if (color_is_pure(pdcolor)) {
1092
0
        gx_color_value rgb[3];
1093
1094
0
        (*dev_proc(dev, map_color_rgb)) (dev, gx_dc_pure_color(pdcolor),
1095
0
                                         rgb);
1096
0
        if (!(rgb[0] | rgb[1] | rgb[2]))
1097
0
            return 0;
1098
0
        if ((rgb[0] & rgb[1] & rgb[2]) == gx_max_color_value)
1099
0
            return 1;
1100
0
    }
1101
0
    return -1;
1102
0
}
1103
1104
1105
static void
1106
image_cache_decode(gx_image_enum *penum, byte input, byte *output, bool scale)
1107
0
{
1108
0
    float temp;
1109
1110
0
    switch ( penum->map[0].decoding ) {
1111
0
        case sd_none:
1112
0
            *output = input;
1113
0
            break;
1114
0
        case sd_lookup:
1115
0
            temp = penum->map[0].decode_lookup[input >> 4]*255.0f;
1116
0
            if (temp > 255) temp = 255;
1117
0
            if (temp < 0 ) temp = 0;
1118
0
            *output = (unsigned char) temp;
1119
0
            break;
1120
0
        case sd_compute:
1121
0
            temp = penum->map[0].decode_base +
1122
0
                (float) input * penum->map[0].decode_factor;
1123
0
            if (scale) {
1124
0
                temp = temp * 255.0;
1125
0
            }
1126
0
            if (temp > 255) temp = 255;
1127
0
            if (temp < 0 ) temp = 0;
1128
0
            *output = (unsigned char) temp;
1129
0
            break;
1130
0
        default:
1131
0
            *output = 0;
1132
0
            break;
1133
0
    }
1134
0
}
1135
1136
static bool
1137
decode_range_needed(gx_image_enum *penum)
1138
0
{
1139
0
    bool scale = true;
1140
1141
0
    if (penum->map[0].decoding == sd_compute) {
1142
0
        if (!(gs_color_space_is_ICC(penum->pcs) ||
1143
0
            gs_color_space_is_PSCIE(penum->pcs))) {
1144
0
            scale = false;
1145
0
        }
1146
0
    }
1147
0
    return scale;
1148
0
}
1149
1150
/* A special case where we go ahead and initialize the whole index cache with
1151
   contone.  Device colors.  If we are halftoning we will then go ahead and
1152
   apply the thresholds to the device contone values.  Only used for gray,
1153
   rgb or cmyk source colors (No DeviceN for now) */
1154
/* TO DO  Add in PSCIE decoder */
1155
int
1156
image_init_color_cache(gx_image_enum * penum, int bps, int spp)
1157
0
{
1158
0
    int num_des_comp = penum->dev->color_info.num_components;
1159
0
    int num_src_comp;
1160
0
    int num_entries = 1 << bps;
1161
0
    bool need_decode = penum->icc_setup.need_decode;
1162
0
    bool has_transfer = penum->icc_setup.has_transfer;
1163
0
    byte value;
1164
0
    bool decode_scale = true;
1165
0
    int k, kk;
1166
0
    byte psrc[4];
1167
0
    byte *temp_buffer;
1168
0
    byte *byte_ptr;
1169
0
    bool is_indexed = (gs_color_space_get_index(penum->pcs) ==
1170
0
                                            gs_color_space_index_Indexed);
1171
0
    bool free_temp_buffer = true;
1172
0
    gsicc_bufferdesc_t input_buff_desc;
1173
0
    gsicc_bufferdesc_t output_buff_desc;
1174
0
    gx_color_value conc[GX_DEVICE_COLOR_MAX_COMPONENTS];
1175
0
    int code;
1176
1177
0
    if (penum->icc_link == NULL) {
1178
0
        return gs_rethrow(-1, "ICC Link not created during image render color");
1179
0
    }
1180
0
    if (is_indexed) {
1181
0
        num_src_comp = gs_color_space_num_components(penum->pcs->base_space);
1182
0
    } else {
1183
        /* Detect case where cache is not needed.  Colors are already in the
1184
           device space.  Need to fast track this one and halftone row directly.
1185
           Detected in gximono.c by looking if penum->color_cache is NULL */
1186
0
        if (penum->icc_link->is_identity && !need_decode && !has_transfer) {
1187
0
            return 0;
1188
0
        }
1189
0
        num_src_comp = 1;
1190
0
    }
1191
    /* Allocate cache of device contone values */
1192
0
    penum->color_cache = gs_alloc_struct(penum->memory, gx_image_color_cache_t,
1193
0
                                         &st_color_cache,
1194
0
                                         "image_init_color_cache");
1195
0
    if (penum->color_cache == NULL)
1196
0
        return_error(gs_error_VMerror);
1197
1198
0
    penum->color_cache->device_contone = (byte*) gs_alloc_bytes(penum->memory,
1199
0
                   num_des_comp * num_entries * sizeof(byte), "image_init_color_cache");
1200
0
    penum->color_cache->is_transparent = (bool*) gs_alloc_bytes(penum->memory,
1201
0
             num_entries * sizeof(bool), "image_init_color_cache");
1202
0
    if (penum->color_cache->device_contone == NULL || penum->color_cache->is_transparent == NULL) {
1203
0
        gs_free_object(penum->memory, penum->color_cache->device_contone, "image_init_color_cache");
1204
0
        gs_free_object(penum->memory, penum->color_cache->is_transparent, "image_init_color_cache");
1205
0
        gs_free_object(penum->memory, penum->color_cache, "image_init_color_cache");
1206
0
        penum->color_cache = NULL;
1207
0
        return_error(gs_error_VMerror);
1208
0
    }
1209
    /* Initialize */
1210
0
    memset(penum->color_cache->is_transparent,0,num_entries * sizeof(bool));
1211
    /* Depending upon if we need decode and ICC CM, fill the cache a couple
1212
       different ways. If the link is the identity, then we don't need to do any
1213
       color conversions except for potentially a decode.  This is written in
1214
       the manner shown below so that the common case of no decode and indexed
1215
       image with a look-up-table uses the table data directly or does as many
1216
       operations with memcpy as we can */
1217
    /* Need to check the decode output range so we know how we need to scale.
1218
       We want 8 bit output */
1219
0
    if (need_decode) {
1220
0
        decode_scale = decode_range_needed(penum);
1221
0
    }
1222
0
    if (penum->icc_link->is_identity) {
1223
        /* No CM needed.  */
1224
0
        if (need_decode || has_transfer) {
1225
            /* Slower case.  This could be sped up later to avoid the tests
1226
               within the loop by use of specialized loops.  */
1227
0
            for (k = 0; k < num_entries; k++) {
1228
                /* Data is in k */
1229
0
                if (need_decode) {
1230
0
                    image_cache_decode(penum, k, &value, decode_scale);
1231
0
                } else {
1232
0
                    value = k;
1233
0
                }
1234
                /* Data is in value */
1235
0
                if (is_indexed) {
1236
0
                    gs_cspace_indexed_lookup_bytes(penum->pcs, value, psrc);
1237
0
                } else {
1238
0
                    psrc[0] = value;
1239
0
                }
1240
                /* Data is in psrc */
1241
                /* These silly transforms need to go away. ToDo. */
1242
0
                if (has_transfer) {
1243
0
                    for (kk = 0; kk < num_des_comp; kk++) {
1244
0
                        conc[kk] = gx_color_value_from_byte(psrc[kk]);
1245
0
                    }
1246
0
                    cmap_transfer(&(conc[0]), penum->pgs, penum->dev);
1247
0
                    for (kk = 0; kk < num_des_comp; kk++) {
1248
0
                        psrc[kk] = gx_color_value_to_byte(conc[kk]);
1249
0
                    }
1250
0
                }
1251
0
                memcpy(&(penum->color_cache->device_contone[k * num_des_comp]),
1252
0
                               psrc, num_des_comp);
1253
0
            }
1254
0
        } else {
1255
            /* Indexing only.  No CM, decode or transfer functions. */
1256
0
            for (k = 0; k < num_entries; k++) {
1257
0
                gs_cspace_indexed_lookup_bytes(penum->pcs, (float)k, psrc);
1258
0
                memcpy(&(penum->color_cache->device_contone[k * num_des_comp]),
1259
0
                           psrc, num_des_comp);
1260
0
            }
1261
0
        }
1262
0
    } else {
1263
        /* Need CM */
1264
        /* We need to worry about if the source is indexed and if we need
1265
           to decode first.  Then we can apply CM. Create a temp buffer in
1266
           the source space and then transform it with one call */
1267
0
        temp_buffer = (byte*) gs_alloc_bytes(penum->memory,
1268
0
                                             (size_t)num_entries * num_src_comp,
1269
0
                                             "image_init_color_cache");
1270
0
        if (temp_buffer == NULL)
1271
0
            return_error(gs_error_VMerror);
1272
1273
0
        if (need_decode) {
1274
0
            if (is_indexed) {
1275
                /* Decode and lookup in index */
1276
0
                for (k = 0; k < num_entries; k++) {
1277
0
                    image_cache_decode(penum, k, &value, decode_scale);
1278
0
                    gs_cspace_indexed_lookup_bytes(penum->pcs, value, psrc);
1279
0
                    memcpy(&(temp_buffer[k * num_src_comp]), psrc, num_src_comp);
1280
0
                }
1281
0
            } else {
1282
                /* Decode only */
1283
0
                for (k = 0; k < num_entries; k++) {
1284
0
                    image_cache_decode(penum, k, &(temp_buffer[k]), decode_scale);
1285
0
                }
1286
0
            }
1287
0
        } else {
1288
            /* No Decode */
1289
0
            if (is_indexed) {
1290
                /* If index uses a num_entries sized table then just use its pointer */
1291
0
                if (penum->pcs->params.indexed.use_proc ||
1292
0
                    penum->pcs->params.indexed.hival < (num_entries - 1)) {
1293
                    /* Have to do the slow way */
1294
0
                    for (k = 0; k <= penum->pcs->params.indexed.hival; k++) {
1295
0
                        gs_cspace_indexed_lookup_bytes(penum->pcs, (float)k, psrc);
1296
0
                        memcpy(&(temp_buffer[k * num_src_comp]), psrc, num_src_comp);
1297
0
                    }
1298
                    /* just use psrc results from converting 'hival' to fill the remaining slots */
1299
0
                    for (; k < num_entries; k++) {
1300
0
                        memcpy(&(temp_buffer[k * num_src_comp]), psrc, num_src_comp);
1301
0
                    }
1302
0
                } else {
1303
                    /* Use the index table directly. */
1304
0
                    gs_free_object(penum->memory, temp_buffer, "image_init_color_cache");
1305
0
                    free_temp_buffer = false;
1306
0
                    temp_buffer = (byte *)(penum->pcs->params.indexed.lookup.table.data);
1307
0
                }
1308
0
            } else {
1309
                /* CM only */
1310
0
                for (k = 0; k < num_entries; k++) {
1311
0
                    temp_buffer[k] = k;
1312
0
                }
1313
0
            }
1314
0
        }
1315
        /* Set up the buffer descriptors. */
1316
0
        gsicc_init_buffer(&input_buff_desc, num_src_comp, 1, false, false, false,
1317
0
                          0, num_entries * num_src_comp, 1, num_entries);
1318
0
        gsicc_init_buffer(&output_buff_desc, num_des_comp, 1, false, false, false,
1319
0
                          0, num_entries * num_des_comp,
1320
0
                      1, num_entries);
1321
0
        code = (penum->icc_link->procs.map_buffer)(penum->dev, penum->icc_link,
1322
0
                                            &input_buff_desc, &output_buff_desc,
1323
0
                                            (void*) temp_buffer,
1324
0
                                            (void*) penum->color_cache->device_contone);
1325
0
        if (code < 0)
1326
0
            return gs_rethrow(code, "Failure to map color buffer");
1327
1328
        /* Check if we need to apply any transfer functions.  If so then do it now */
1329
0
        if (has_transfer) {
1330
0
            for (k = 0; k < num_entries; k++) {
1331
0
                byte_ptr =
1332
0
                    &(penum->color_cache->device_contone[k * num_des_comp]);
1333
0
                for (kk = 0; kk < num_des_comp; kk++) {
1334
0
                    conc[kk] = gx_color_value_from_byte(byte_ptr[kk]);
1335
0
                }
1336
0
                cmap_transfer(&(conc[0]), penum->pgs, penum->dev);
1337
0
                for (kk = 0; kk < num_des_comp; kk++) {
1338
0
                    byte_ptr[kk] = gx_color_value_to_byte(conc[kk]);
1339
0
                }
1340
0
            }
1341
0
        }
1342
0
        if (free_temp_buffer)
1343
0
            gs_free_object(penum->memory, temp_buffer, "image_init_color_cache");
1344
0
    }
1345
0
    return 0;
1346
0
}
1347
1348
/* Export this for use by image_render_ functions */
1349
void
1350
image_init_clues(gx_image_enum * penum, int bps, int spp)
1351
35.3k
{
1352
    /* Initialize the color table */
1353
35.3k
#define ictype(i)\
1354
35.3k
  penum->clues[i].dev_color.type
1355
1356
35.3k
    switch ((spp == 1 ? bps : 8)) {
1357
33.8k
        case 8:         /* includes all color images */
1358
33.8k
            {
1359
33.8k
                register gx_image_clue *pcht = &penum->clues[0];
1360
33.8k
                register int n = 64;    /* 8 bits means 256 clues, do   */
1361
                                        /* 4 at a time for efficiency   */
1362
2.16M
                do {
1363
2.16M
                    pcht[0].dev_color.type =
1364
2.16M
                        pcht[1].dev_color.type =
1365
2.16M
                        pcht[2].dev_color.type =
1366
2.16M
                        pcht[3].dev_color.type =
1367
2.16M
                        gx_dc_type_none;
1368
2.16M
                    pcht[0].key = pcht[1].key =
1369
2.16M
                        pcht[2].key = pcht[3].key = 0;
1370
2.16M
                    pcht += 4;
1371
2.16M
                }
1372
2.16M
                while (--n > 0);
1373
33.8k
                penum->clues[0].key = 1;        /* guarantee no hit */
1374
33.8k
                break;
1375
0
            }
1376
12
        case 4:
1377
12
            ictype(17) = ictype(2 * 17) = ictype(3 * 17) =
1378
12
                ictype(4 * 17) = ictype(6 * 17) = ictype(7 * 17) =
1379
12
                ictype(8 * 17) = ictype(9 * 17) = ictype(11 * 17) =
1380
12
                ictype(12 * 17) = ictype(13 * 17) = ictype(14 * 17) =
1381
12
                gx_dc_type_none;
1382
            /* falls through */
1383
68
        case 2:
1384
68
            ictype(5 * 17) = ictype(10 * 17) = gx_dc_type_none;
1385
35.3k
#undef ictype
1386
35.3k
    }
1387
35.3k
}
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
93.9k
{
1396
93.9k
    int ci, decode_type, code;
1397
93.9k
    static const float default_decode[] = {
1398
93.9k
        0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0
1399
93.9k
    };
1400
1401
    /* Clues are only used with image_mono_render */
1402
93.9k
    if (spp == 1) {
1403
18.3k
        image_init_clues(penum, bps, spp);
1404
18.3k
    }
1405
93.9k
    decode_type = 3; /* 0=custom, 1=identity, 2=inverted, 3=impossible */
1406
263k
    for (ci = 0; ci < spp; ci +=2 ) {
1407
169k
        decode_type &= (decode[ci] == 0. && decode[ci + 1] == 1.) |
1408
169k
                       (decode[ci] == 1. && decode[ci + 1] == 0.) << 1;
1409
169k
    }
1410
1411
    /* Initialize the maps from samples to intensities. */
1412
341k
    for (ci = 0; ci < spp; ci++) {
1413
247k
        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
247k
        const float *this_decode = &decode[ci * 2];
1420
247k
        const float *map_decode;        /* decoding used to */
1421
                                        /* construct the expansion map */
1422
247k
        const float *real_decode;       /* decoding for expanded samples */
1423
1424
247k
        map_decode = real_decode = this_decode;
1425
247k
        if (!(decode_type & 1)) {
1426
86
            if ((decode_type & 2) && bps <= 8) {
1427
0
                real_decode = default_decode;
1428
86
            } else {
1429
86
                *pdcb = false;
1430
86
                map_decode = default_decode;
1431
86
            }
1432
86
        }
1433
247k
        if (bps > 2 || format != gs_image_format_chunky) {
1434
246k
            if (bps <= 8)
1435
246k
                image_init_map(&pmap->table.lookup8[0], 1 << bps,
1436
246k
                               map_decode);
1437
246k
        } else {                /* The map index encompasses more than one pixel. */
1438
1.41k
            byte map[4];
1439
1.41k
            register int i;
1440
1441
1.41k
            image_init_map(&map[0], 1 << bps, map_decode);
1442
1.41k
            switch (bps) {
1443
1.39k
                case 1:
1444
1.39k
                    {
1445
1.39k
                        register bits32 *p = &pmap->table.lookup4x1to32[0];
1446
1447
1.39k
                        if (map[0] == 0 && map[1] == 0xff)
1448
1.39k
                            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
1.39k
                    }
1458
1.39k
                    break;
1459
28
                case 2:
1460
28
                    {
1461
28
                        register bits16 *p = &pmap->table.lookup2x2to16[0];
1462
1463
476
                        for (i = 0; i < 16; i++, p++)
1464
448
                            ((byte *) p)[0] = map[i >> 2],
1465
448
                                ((byte *) p)[1] = map[i & 3];
1466
28
                    }
1467
28
                    break;
1468
1.41k
            }
1469
1.41k
        }
1470
247k
        pmap->decode_base /* = decode_lookup[0] */  = real_decode[0];
1471
247k
        pmap->decode_factor =
1472
247k
            (real_decode[1] - real_decode[0]) /
1473
247k
            (bps <= 8 ? 255.0 : (float)frac_1);
1474
247k
        pmap->decode_max /* = decode_lookup[15] */  = real_decode[1];
1475
247k
        if (decode_type) {
1476
247k
            pmap->decoding = sd_none;
1477
247k
            pmap->inverted = map_decode[0] != 0;
1478
247k
        } else if (bps <= 4) {
1479
32
            int step = 15 / ((1 << bps) - 1);
1480
32
            int i;
1481
1482
32
            pmap->decoding = sd_lookup;
1483
130
            for (i = 15 - step; i > 0; i -= step)
1484
98
                pmap->decode_lookup[i] = pmap->decode_base +
1485
98
                    i * (255.0 / 15) * pmap->decode_factor;
1486
32
            pmap->inverted = 0;
1487
54
        } else {
1488
54
            pmap->decoding = sd_compute;
1489
54
            pmap->inverted = 0;
1490
54
        }
1491
247k
        if (spp == 1) {         /* and ci == 0 *//* Pre-map entries 0 and 255. */
1492
18.3k
            gs_client_color cc;
1493
1494
            /* Image clues are used in this case */
1495
18.3k
            cc.paint.values[0] = real_decode[0];
1496
18.3k
            code = (*pcs->type->remap_color) (&cc, pcs, penum->icolor0,
1497
18.3k
                                       pgs, dev, gs_color_select_source);
1498
18.3k
            if (code < 0)
1499
0
                return code;
1500
18.3k
            cc.paint.values[0] = real_decode[1];
1501
18.3k
            code = (*pcs->type->remap_color) (&cc, pcs, penum->icolor1,
1502
18.3k
                                       pgs, dev, gs_color_select_source);
1503
18.3k
            if (code < 0)
1504
0
                return code;
1505
18.3k
        }
1506
247k
    }
1507
93.9k
    return 0;
1508
93.9k
}
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
252k
{
1515
252k
    float min_v = decode[0];
1516
252k
    float diff_v = decode[1] - min_v;
1517
1518
252k
    if (diff_v == 1 || diff_v == -1) {  /* We can do the stepping with integers, without overflow. */
1519
252k
        byte *limit = map + map_size;
1520
252k
        uint value = (uint)(min_v * 0xffffL);
1521
252k
        int diff = (int)(diff_v * (0xffffL / (map_size - 1)));
1522
1523
64.4M
        for (; map != limit; map++, value += diff)
1524
64.2M
            *map = value >> 8;
1525
252k
    } 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
252k
}
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
3
{
1544
3
    uint scale = 255 / ((1 << penum->bps) - 1);
1545
3
    uint *values = &penum->mask_color.values[component_index * 2];
1546
3
    uint v0 = values[0] *= scale;
1547
3
    uint v1 = values[1] *= scale;
1548
1549
3
    if (penum->map[component_index].decoding == sd_none &&
1550
3
        penum->map[component_index].inverted
1551
3
        ) {
1552
0
        values[0] = 255 - v1;
1553
0
        values[1] = 255 - v0;
1554
0
    }
1555
3
}
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
77.7k
{
1561
77.7k
    int k;
1562
1563
311k
    for (k = 0; k < num_comps; k++) {
1564
234k
        if (pgs->effective_transfer[k]->proc != gs_identity_transfer) {
1565
0
            return(true);
1566
0
        }
1567
234k
    }
1568
77.7k
    return(false);
1569
77.7k
}