Coverage Report

Created: 2025-06-10 06:58

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