Coverage Report

Created: 2025-06-10 07:06

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