Coverage Report

Created: 2026-04-01 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/gxipixel.c
Line
Count
Source
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
1.21k
ENUM_PTRS_WITH(image_enum_enum_ptrs, gx_image_enum *eptr)
64
448
{
65
448
    int bps;
66
448
    gs_ptr_type_t ret;
67
68
    /* Enumerate the used members of clues.dev_color. */
69
448
    index -= gx_image_enum_num_ptrs;
70
448
    bps = eptr->unpack_bps;
71
448
    if (eptr->spp != 1)
72
0
        bps = 8;
73
448
    else if (bps > 8 || eptr->unpack == sample_unpack_copy)
74
0
        bps = 1;
75
448
    if (index >= (1 << bps) * st_device_color_max_ptrs)         /* done */
76
64
        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
384
    if (eptr->spp == 1) {
80
384
        if (eptr->clues != NULL) {
81
384
            if (eptr->clues[(index/st_device_color_max_ptrs) *
82
384
                (255 / ((1 << bps) - 1))].dev_color.type != 0) {
83
384
                ret = ENUM_USING(st_device_color,
84
384
                                 &eptr->clues[(index / st_device_color_max_ptrs) *
85
384
                                 (255 / ((1 << bps) - 1))].dev_color,
86
384
                                 sizeof(eptr->clues[0].dev_color),
87
384
                                 index % st_device_color_max_ptrs);
88
384
            } else {
89
0
                ret = 0;
90
0
            }
91
384
        } else {
92
0
            ret = 0;
93
0
        }
94
384
    } else {
95
0
        ret = 0;
96
0
    }
97
384
    if (ret == 0)               /* don't stop early */
98
384
        ENUM_RETURN(0);
99
0
    return ret;
100
384
}
101
102
768
#define e1(i,elt) ENUM_PTR(i,gx_image_enum,elt);
103
1.21k
gx_image_enum_do_ptrs(e1)
104
1.21k
#undef e1
105
1.21k
ENUM_PTRS_END
106
107
64
static RELOC_PTRS_WITH(image_enum_reloc_ptrs, gx_image_enum *eptr)
108
64
{
109
64
    int i;
110
111
768
#define r1(i,elt) RELOC_PTR(gx_image_enum,elt);
112
768
    gx_image_enum_do_ptrs(r1)
113
64
#undef r1
114
64
    {
115
64
        int bps = eptr->unpack_bps;
116
117
64
        if (eptr->spp != 1)
118
0
            bps = 8;
119
64
        else if (bps > 8 || eptr->unpack == sample_unpack_copy)
120
0
            bps = 1;
121
64
        if (eptr->spp == 1) {
122
192
        for (i = 0; i <= 255; i += 255 / ((1 << bps) - 1))
123
128
            RELOC_USING(st_device_color,
124
64
                        &eptr->clues[i].dev_color, sizeof(gx_device_color));
125
64
    }
126
64
}
127
64
}
128
64
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
1.61M
{
152
1.61M
    const gs_pixel_image_t *pim = (const gs_pixel_image_t *)pic;
153
1.61M
    int width = pim->Width, height = pim->Height;
154
1.61M
    int bpc = pim->BitsPerComponent;
155
1.61M
    gx_image_enum *penum;
156
157
1.61M
    if (width < 0 || height < 0)
158
0
        return_error(gs_error_rangecheck);
159
1.61M
    switch (pim->format) {
160
1.59M
    case gs_image_format_chunky:
161
1.61M
    case gs_image_format_component_planar:
162
1.61M
        switch (bpc) {
163
1.61M
        case 1: case 2: case 4: case 8: case 12: case 16: break;
164
2
        default: return_error(gs_error_rangecheck);
165
1.61M
        }
166
1.61M
        break;
167
1.61M
    case gs_image_format_bit_planar:
168
0
        if (bpc < 1 || bpc > 8)
169
0
            return_error(gs_error_rangecheck);
170
1.61M
    }
171
1.61M
    if (prect) {
172
469k
        if (prect->p.x < 0 || prect->p.y < 0 ||
173
469k
            prect->q.x < prect->p.x || prect->q.y < prect->p.y ||
174
469k
            prect->q.x > width || prect->q.y > height
175
469k
            )
176
0
            return_error(gs_error_rangecheck);
177
469k
    }
178
1.61M
    *ppenum = NULL;   /* in case alloc fails and caller doesn't check code */
179
1.61M
    penum = gs_alloc_struct(mem, gx_image_enum, &st_gx_image_enum,
180
1.61M
                            "gx_default_begin_image");
181
1.61M
    if (penum == 0)
182
0
        return_error(gs_error_VMerror);
183
1.61M
    memset(penum, 0, sizeof(gx_image_enum));  /* in case of failure, no dangling pointers */
184
1.61M
    if (prect) {
185
469k
        penum->rect.x = prect->p.x;
186
469k
        penum->rect.y = prect->p.y;
187
469k
        penum->rect.w = prect->q.x - prect->p.x;
188
469k
        penum->rect.h = prect->q.y - prect->p.y;
189
1.14M
    } else {
190
1.14M
        penum->rect.x = 0, penum->rect.y = 0;
191
1.14M
        penum->rect.w = width, penum->rect.h = height;
192
1.14M
    }
193
1.61M
    penum->rrect.x = penum->rect.x;
194
1.61M
    penum->rrect.y = penum->rect.y;
195
1.61M
    penum->rrect.w = penum->rect.w;
196
1.61M
    penum->rrect.h = penum->rect.h;
197
1.61M
    penum->drect.x = penum->rect.x;
198
1.61M
    penum->drect.y = penum->rect.y;
199
1.61M
    penum->drect.w = penum->rect.w;
200
1.61M
    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
1.61M
    *ppenum = penum;
210
1.61M
    return 0;
211
1.61M
}
212
213
/* Convert and restrict to a valid range. */
214
4.33M
static inline fixed float2fixed_rounded_boxed(double src) {
215
4.33M
    float v = floor(src*fixed_scale + 0.5);
216
217
4.33M
    if (v <= min_fixed)
218
10.3k
        return min_fixed;
219
4.32M
    else if (v >= max_fixed)
220
46.5k
        return max_fixed;
221
4.27M
    else
222
4.27M
        return  (fixed)v;
223
4.33M
}
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
2.64M
{
230
2.64M
    int code = 0;
231
232
2.64M
    if (pmat == 0)
233
2.57M
        pmat = &ctm_only(pgs);
234
2.64M
    if (ImageMatrix->xx == pmat->xx && ImageMatrix->xy == pmat->xy &&
235
904k
        ImageMatrix->yx == pmat->yx && ImageMatrix->yy == pmat->yy) {
236
        /* Process common special case separately to accept singular matrix. */
237
904k
        rmat->xx = rmat->yy = 1.;
238
904k
        rmat->xy = rmat->yx = 0.;
239
904k
        rmat->tx = pmat->tx - ImageMatrix->tx;
240
904k
        rmat->ty = pmat->ty - ImageMatrix->ty;
241
1.73M
    } else {
242
1.73M
        if ((code = gs_matrix_invert_to_double(ImageMatrix, rmat)) < 0 ||
243
1.73M
            (code = gs_matrix_multiply_double(rmat, pmat, rmat)) < 0
244
1.73M
            ) {
245
127
            return code;
246
127
        }
247
1.73M
    }
248
2.64M
    return code;
249
2.64M
}
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
1.61M
{
264
1.61M
    const gs_pixel_image_t *pim = (const gs_pixel_image_t *)pic;
265
1.61M
    gs_image_format_t format = pim->format;
266
1.61M
    const int width = pim->Width;
267
1.61M
    const int height = pim->Height;
268
1.61M
    const int bps = pim->BitsPerComponent;
269
1.61M
    bool masked = penum->masked;
270
1.61M
    const float *decode = pim->Decode;
271
1.61M
    gs_matrix_double mat;
272
1.61M
    int index_bps;
273
1.61M
    gs_color_space *pcs = pim->ColorSpace;
274
1.61M
    gs_logical_operation_t lop = (pgs ? pgs->log_op : lop_default);
275
1.61M
    int code;
276
1.61M
    int log2_xbytes = (bps <= 8 ? 0 : arch_log2_sizeof_frac);
277
1.61M
    int spp, nplanes, spread;
278
1.61M
    uint bsize;
279
1.61M
    byte *buffer = NULL;
280
1.61M
    fixed mtx, mty;
281
1.61M
    gs_fixed_point row_extent, col_extent, x_extent, y_extent;
282
1.61M
    bool device_color = true;
283
1.61M
    gs_fixed_rect obox, cbox;
284
1.61M
    bool gridfitimages = 0;
285
1.61M
    bool in_pattern_accumulator;
286
1.61M
    bool in_smask;
287
1.61M
    int orthogonal;
288
1.61M
    int force_interpolation = 0;
289
290
1.61M
    penum->pcs = NULL;
291
1.61M
    penum->clues = NULL;
292
1.61M
    penum->icc_setup.has_transfer = false;
293
1.61M
    penum->icc_setup.is_lab = false;
294
1.61M
    penum->icc_setup.must_halftone = false;
295
1.61M
    penum->icc_setup.need_decode = false;
296
1.61M
    penum->Width = width;
297
1.61M
    penum->Height = height;
298
299
1.61M
    if ((code = gx_image_compute_mat(pgs, pmat, &(pim->ImageMatrix), &mat)) < 0) {
300
96
        return code;
301
96
    }
302
1.61M
    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
1.61M
    in_pattern_accumulator = ((dev_proc(dev, dev_spec_op)(dev, gxdso_in_pattern_accumulator, NULL, 0)) > 0);
323
324
    /* Figure out if we are orthogonal */
325
1.61M
    if (mat.xy == 0 && mat.yx == 0)
326
1.39M
        orthogonal = 1;
327
219k
    else if (mat.xx == 0 && mat.yy == 0)
328
119k
        orthogonal = 2;
329
99.9k
    else
330
99.9k
        orthogonal = 0;
331
332
    /* If we are in a pattern accumulator, we choose to always grid fit
333
     * orthogonal images. We do this by asking the device whether we
334
     * should grid fit. This allows us to avoid nasty blank lines around
335
     * the edges of cells. Similarly, for smasks.
336
     */
337
1.61M
    in_smask = (pim->override_in_smask ||
338
1.61M
                (dev_proc(dev, dev_spec_op)(dev, gxdso_in_smask, NULL, 0)) > 0);
339
1.61M
    gridfitimages = (in_smask || in_pattern_accumulator) && orthogonal;
340
341
1.61M
    if (pgs != NULL && pgs->show_gstate != NULL) {
342
        /* If we're a graphics state, and we're in a text object, then we
343
         * must be in a type3 font. Don't fiddle with it. */
344
1.24M
    } else if (!gridfitimages &&
345
945k
               (!penum->masked || penum->image_parent_type != 0)) {
346
        /* Other than for images we are specifically looking to grid fit (such as
347
         * ones in a pattern device), we only grid fit imagemasks */
348
758k
    } else if (gridfitimages && (penum->masked && penum->image_parent_type == 0)) {
349
        /* We don't gridfit imagemasks in a pattern accumulator */
350
479k
    } else if (pgs != NULL && pgs->fill_adjust.x == 0 && pgs->fill_adjust.y == 0) {
351
        /* If fill adjust is disabled, so is grid fitting */
352
474k
    } else if (orthogonal == 1) {
353
336k
        if (width == 1 || gridfitimages) {
354
289k
            if (mat.xx > 0) {
355
289k
                fixed ix0 = int2fixed(fixed2int(float2fixed(mat.tx)));
356
289k
                double x1 = mat.tx + mat.xx * width;
357
289k
                fixed ix1 = int2fixed(fixed2int_ceiling(float2fixed(x1)));
358
289k
                mat.tx = (double)fixed2float(ix0);
359
289k
                mat.xx = (double)(fixed2float(ix1 - ix0)/width);
360
289k
            } else if (mat.xx < 0) {
361
185
                fixed ix0 = int2fixed(fixed2int_ceiling(float2fixed(mat.tx)));
362
185
                double x1 = mat.tx + mat.xx * width;
363
185
                fixed ix1 = int2fixed(fixed2int(float2fixed(x1)));
364
185
                mat.tx = (double)fixed2float(ix0);
365
185
                mat.xx = (double)(fixed2float(ix1 - ix0)/width);
366
185
            }
367
289k
        }
368
336k
        if (height == 1 || gridfitimages) {
369
289k
            if (mat.yy > 0) {
370
262k
                fixed iy0 = int2fixed(fixed2int(float2fixed(mat.ty)));
371
262k
                double y1 = mat.ty + mat.yy * height;
372
262k
                fixed iy1 = int2fixed(fixed2int_ceiling(float2fixed(y1)));
373
262k
                mat.ty = (double)fixed2float(iy0);
374
262k
                mat.yy = (double)(fixed2float(iy1 - iy0)/height);
375
262k
            } else if (mat.yy < 0) {
376
27.5k
                fixed iy0 = int2fixed(fixed2int_ceiling(float2fixed(mat.ty)));
377
27.5k
                double y1 = mat.ty + mat.yy * height;
378
27.5k
                fixed iy1 = int2fixed(fixed2int(float2fixed(y1)));
379
27.5k
                mat.ty = (double)fixed2float(iy0);
380
27.5k
                mat.yy = ((double)fixed2float(iy1 - iy0)/height);
381
27.5k
            }
382
289k
        }
383
336k
    } else if (orthogonal == 2) {
384
113k
        if (height == 1 || gridfitimages) {
385
8
            if (mat.yx > 0) {
386
8
                fixed ix0 = int2fixed(fixed2int(float2fixed(mat.tx)));
387
8
                double x1 = mat.tx + mat.yx * height;
388
8
                fixed ix1 = int2fixed(fixed2int_ceiling(float2fixed(x1)));
389
8
                mat.tx = (double)fixed2float(ix0);
390
8
                mat.yx = (double)(fixed2float(ix1 - ix0)/height);
391
8
            } else if (mat.yx < 0) {
392
0
                fixed ix0 = int2fixed(fixed2int_ceiling(float2fixed(mat.tx)));
393
0
                double x1 = mat.tx + mat.yx * height;
394
0
                fixed ix1 = int2fixed(fixed2int(float2fixed(x1)));
395
0
                mat.tx = (double)fixed2float(ix0);
396
0
                mat.yx = (double)(fixed2float(ix1 - ix0)/height);
397
0
            }
398
8
        }
399
113k
        if (width == 1 || gridfitimages) {
400
0
            if (mat.xy > 0) {
401
0
                fixed iy0 = int2fixed(fixed2int(float2fixed(mat.ty)));
402
0
                double y1 = mat.ty + mat.xy * width;
403
0
                fixed iy1 = int2fixed(fixed2int_ceiling(float2fixed(y1)));
404
0
                mat.ty = (double)fixed2float(iy0);
405
0
                mat.xy = (double)(fixed2float(iy1 - iy0)/width);
406
0
            } else if (mat.xy < 0) {
407
0
                fixed iy0 = int2fixed(fixed2int_ceiling(float2fixed(mat.ty)));
408
0
                double y1 = mat.ty + mat.xy * width;
409
0
                fixed iy1 = int2fixed(fixed2int(float2fixed(y1)));
410
0
                mat.ty = (double)fixed2float(iy0);
411
0
                mat.xy = ((double)fixed2float(iy1 - iy0)/width);
412
0
            }
413
0
        }
414
113k
    }
415
416
    /* When rendering to a pattern accumulator, if we are downscaling
417
     * then enable interpolation, as otherwise dropouts can cause
418
     * serious problems. */
419
1.61M
    if (in_pattern_accumulator) {
420
6.26k
        double ome = ((double)(fixed_1 - fixed_epsilon)) / (double)fixed_1; /* One Minus Epsilon */
421
422
6.26k
        if (orthogonal == 1) {
423
1.93k
            if ((mat.xx > -ome && mat.xx < ome) || (mat.yy > -ome && mat.yy < ome)) {
424
278
                force_interpolation = true;
425
278
            }
426
4.32k
        } else if (orthogonal == 2) {
427
4.31k
            if ((mat.xy > -ome && mat.xy < ome) || (mat.yx > -ome && mat.yx < ome)) {
428
0
                force_interpolation = true;
429
0
            }
430
4.31k
        }
431
6.26k
    }
432
433
    /* Can we restrict the amount of image we need? */
434
1.61M
    while (!pim->imagematrices_are_untrustworthy) /* So we can break out of it */
435
1.61M
    {
436
1.61M
        gs_rect rect, rect_src;
437
1.61M
        gs_matrix mi;
438
1.61M
        const gs_matrix *m = pgs != NULL ? &ctm_only(pgs) : NULL;
439
1.61M
        gs_int_rect irect;
440
1.61M
        if (m == NULL || (code = gs_matrix_invert(m, &mi)) < 0 ||
441
1.61M
            (code = gs_matrix_multiply(&mi, &pic->ImageMatrix, &mi)) < 0) {
442
            /* Give up trying to shrink the render box, but continue processing */
443
7.10k
            break;
444
7.10k
        }
445
1.61M
        if (pcpath)
446
704k
        {
447
704k
            gs_fixed_rect obox;
448
704k
            gx_cpath_outer_box(pcpath, &obox);
449
704k
            rect.p.x = fixed2float(obox.p.x);
450
704k
            rect.p.y = fixed2float(obox.p.y);
451
704k
            rect.q.x = fixed2float(obox.q.x);
452
704k
            rect.q.y = fixed2float(obox.q.y);
453
704k
        }
454
907k
        else
455
907k
        {
456
907k
            rect.p.x = 0;
457
907k
            rect.p.y = 0;
458
907k
            rect.q.x = dev->width;
459
907k
            rect.q.y = dev->height;
460
907k
        }
461
        /* rect is in destination space. Calculate rect_src, in source space. */
462
1.61M
        code = gs_bbox_transform(&rect, &mi, &rect_src);
463
1.61M
        if (code < 0) {
464
            /* Give up trying to shrink the render/decode boxes, but continue processing */
465
0
            break;
466
0
        }
467
        /* Need to expand the region to allow for the fact that the mitchell
468
         * scaler reads multiple pixels in. */
469
        /* If mi.{xx,yy} > 1 then we are downscaling. During downscaling,
470
         * the support increases to ensure that we don't lose pixels contributions
471
         * entirely. */
472
1.61M
        if (pim->Interpolate)
473
36
        {
474
36
            float support = any_abs(mi.xx);
475
36
            int isupport;
476
36
            if (any_abs(mi.yy) > support)
477
0
                support = any_abs(mi.yy);
478
36
            if (any_abs(mi.xy) > support)
479
0
                support = any_abs(mi.xy);
480
36
            if (any_abs(mi.yx) > support)
481
0
                support = any_abs(mi.yx);
482
            /* If upscaling (support < 1) then we need 2 extra lines on each side of the source region
483
             * (2 being the maximum support for mitchell scaling).
484
             * If downscaling, then the number of lines is increased to avoid individual
485
             * contributions dropping out. */
486
36
            isupport = 2; /* Mitchell support. */
487
36
            if (support > 1)
488
1
                isupport = (int)ceil(isupport * support);
489
36
            rect_src.p.x -= isupport;
490
36
            rect_src.p.y -= isupport;
491
36
            rect_src.q.x += isupport;
492
36
            rect_src.q.y += isupport+1; /* +1 is a fudge! */
493
36
        }
494
1.61M
        irect.p.x = (int)floor(rect_src.p.x);
495
1.61M
        irect.p.y = (int)floor(rect_src.p.y);
496
1.61M
        irect.q.x = (int)ceil(rect_src.q.x);
497
1.61M
        irect.q.y = (int)ceil(rect_src.q.y);
498
        /* We therefore only need to render within irect. Restrict rrect to this. */
499
1.61M
        if (penum->rrect.x < irect.p.x) {
500
73.2k
            penum->rrect.w -= irect.p.x - penum->rrect.x;
501
73.2k
            if (penum->rrect.w < 0)
502
64.7k
               penum->rrect.w = 0;
503
73.2k
            penum->rrect.x = irect.p.x;
504
73.2k
        }
505
1.61M
        if (penum->rrect.x + penum->rrect.w > irect.q.x) {
506
179k
            penum->rrect.w = irect.q.x - penum->rrect.x;
507
179k
            if (penum->rrect.w < 0)
508
150k
                penum->rrect.w = 0;
509
179k
        }
510
1.61M
        if (penum->rrect.y < irect.p.y) {
511
176k
            penum->rrect.h -= irect.p.y - penum->rrect.y;
512
176k
            if (penum->rrect.h < 0)
513
96.6k
                penum->rrect.h = 0;
514
176k
            penum->rrect.y = irect.p.y;
515
176k
        }
516
1.61M
        if (penum->rrect.y + penum->rrect.h > irect.q.y) {
517
115k
            penum->rrect.h = irect.q.y - penum->rrect.y;
518
115k
            if (penum->rrect.h < 0)
519
21.3k
                penum->rrect.h = 0;
520
115k
        }
521
1.61M
        if (penum->drect.x < irect.p.x) {
522
73.2k
            penum->drect.w -= irect.p.x - penum->drect.x;
523
73.2k
            if (penum->drect.w < 0)
524
64.7k
               penum->drect.w = 0;
525
73.2k
            penum->drect.x = irect.p.x;
526
73.2k
        }
527
1.61M
        if (penum->drect.x + penum->drect.w > irect.q.x) {
528
179k
            penum->drect.w = irect.q.x - penum->drect.x;
529
179k
            if (penum->drect.w < 0)
530
150k
                penum->drect.w = 0;
531
179k
        }
532
1.61M
        if (penum->drect.y < irect.p.y) {
533
176k
            penum->drect.h -= irect.p.y - penum->drect.y;
534
176k
            if (penum->drect.h < 0)
535
96.6k
                penum->drect.h = 0;
536
176k
            penum->drect.y = irect.p.y;
537
176k
        }
538
1.61M
        if (penum->drect.y + penum->drect.h > irect.q.y) {
539
115k
            penum->drect.h = irect.q.y - penum->drect.y;
540
115k
            if (penum->drect.h < 0)
541
21.3k
                penum->drect.h = 0;
542
115k
        }
543
1.61M
        break; /* Out of the while */
544
1.61M
    }
545
    /* Check for the intersection being null */
546
1.61M
    if (penum->drect.x + penum->drect.w <= penum->rect.x  ||
547
1.46M
        penum->rect.x  + penum->rect.w  <= penum->drect.x ||
548
1.40M
        penum->drect.y + penum->drect.h <= penum->rect.y  ||
549
1.38M
        penum->rect.y  + penum->rect.h  <= penum->drect.y)
550
251k
    {
551
          /* Something may have gone wrong with the floating point above.
552
           * set the region to something sane. */
553
251k
        penum->drect.x = penum->rect.x;
554
251k
        penum->drect.y = penum->rect.y;
555
251k
        penum->drect.w = 0;
556
251k
        penum->drect.h = 0;
557
251k
    }
558
1.61M
    if (penum->rrect.x + penum->rrect.w <= penum->drect.x  ||
559
1.46M
        penum->drect.x + penum->drect.w  <= penum->rrect.x ||
560
1.36M
        penum->rrect.y + penum->rrect.h <= penum->drect.y  ||
561
1.36M
        penum->drect.y + penum->drect.h  <= penum->rrect.y)
562
251k
    {
563
          /* Something may have gone wrong with the floating point above.
564
           * set the region to something sane. */
565
251k
        penum->rrect.x = penum->drect.x;
566
251k
        penum->rrect.y = penum->drect.y;
567
251k
        penum->rrect.w = 0;
568
251k
        penum->rrect.h = 0;
569
251k
    }
570
571
    /*penum->matrix = mat;*/
572
1.61M
    penum->matrix.xx = mat.xx;
573
1.61M
    penum->matrix.xy = mat.xy;
574
1.61M
    penum->matrix.yx = mat.yx;
575
1.61M
    penum->matrix.yy = mat.yy;
576
1.61M
    penum->matrix.tx = mat.tx;
577
1.61M
    penum->matrix.ty = mat.ty;
578
1.61M
    if_debug6m('b', mem, " [%g %g %g %g %g %g]\n",
579
1.61M
              mat.xx, mat.xy, mat.yx, mat.yy, mat.tx, mat.ty);
580
    /* following works for 1, 2, 4, 8, 12, 16 */
581
1.61M
    index_bps = (bps < 8 ? bps >> 1 : (bps >> 2) + 1);
582
    /*
583
     * Compute extents with distance transformation.
584
     */
585
1.61M
    if (mat.tx > 0)
586
1.35M
        mtx = float2fixed(mat.tx);
587
265k
    else { /* Use positive values to ensure round down. */
588
265k
        int f = (int)-mat.tx + 1;
589
590
265k
        mtx = float2fixed(mat.tx + f) - int2fixed(f);
591
265k
    }
592
1.61M
    if (mat.ty > 0)
593
603k
        mty = float2fixed(mat.ty);
594
1.01M
    else {  /* Use positive values to ensure round down. */
595
1.01M
        int f = (int)-mat.ty + 1;
596
597
1.01M
        mty = float2fixed(mat.ty + f) - int2fixed(f);
598
1.01M
    }
599
600
1.61M
    row_extent.x = float2fixed_rounded_boxed(width * mat.xx);
601
1.61M
    row_extent.y =
602
1.61M
        (is_fzero(mat.xy) ? fixed_0 :
603
1.61M
         float2fixed_rounded_boxed(width * mat.xy));
604
1.61M
    col_extent.x =
605
1.61M
        (is_fzero(mat.yx) ? fixed_0 :
606
1.61M
         float2fixed_rounded_boxed(height * mat.yx));
607
1.61M
    col_extent.y = float2fixed_rounded_boxed(height * mat.yy);
608
1.61M
    gx_image_enum_common_init((gx_image_enum_common_t *)penum,
609
1.61M
                              (const gs_data_image_t *)pim,
610
1.61M
                              &image1_enum_procs, dev,
611
1.61M
                              (masked ? 1 : (penum->alpha ? cs_num_components(pcs)+1 : cs_num_components(pcs))),
612
1.61M
                              format);
613
1.61M
    if (penum->rect.w == width && penum->rect.h == height) {
614
1.25M
        x_extent = row_extent;
615
1.25M
        y_extent = col_extent;
616
1.25M
    } else {
617
365k
        int rw = penum->rect.w, rh = penum->rect.h;
618
619
365k
        x_extent.x = float2fixed_rounded_boxed(rw * mat.xx);
620
365k
        x_extent.y =
621
365k
            (is_fzero(mat.xy) ? fixed_0 :
622
365k
             float2fixed_rounded_boxed(rw * mat.xy));
623
365k
        y_extent.x =
624
365k
            (is_fzero(mat.yx) ? fixed_0 :
625
365k
             float2fixed_rounded_boxed(rh * mat.yx));
626
365k
        y_extent.y = float2fixed_rounded_boxed(rh * mat.yy);
627
365k
    }
628
    /* Set icolor0 and icolor1 to point to image clues locations if we have
629
       1spp or an imagemask, otherwise image clues is not used and
630
       we have these values point to other member variables */
631
1.61M
    if (masked || cs_num_components(pcs) == 1) {
632
        /* Go ahead and allocate now if not already done.  For a mask
633
           we really should only do 2 values. For now, the goal is to
634
           eliminate the 256 bytes for the >8bpp image enumerator */
635
938k
        penum->clues = (gx_image_clue*) gs_alloc_bytes(mem, sizeof(gx_image_clue)*256,
636
938k
                             "gx_image_enum_begin");
637
938k
        if (penum->clues == NULL) {
638
0
            code = gs_error_VMerror;
639
0
            goto fail;
640
0
        }
641
938k
        penum->icolor0 = &(penum->clues[0].dev_color);
642
938k
        penum->icolor1 = &(penum->clues[255].dev_color);
643
938k
    } else {
644
680k
        penum->icolor0 = &(penum->icolor0_val);
645
680k
        penum->icolor1 = &(penum->icolor1_val);
646
680k
    }
647
1.61M
    penum->icolor0->tag = penum->icolor1->tag = device_current_tag(dev);
648
649
1.61M
    if (masked) {       /* This is imagemask. */
650
567k
        if (bps != 1 || pcs != NULL || penum->alpha || decode[0] == decode[1]) {
651
52
            code = gs_error_rangecheck;
652
52
            goto fail;
653
52
        }
654
        /* Initialize color entries 0 and 255. */
655
567k
        set_nonclient_dev_color(penum->icolor0, gx_no_color_index);
656
567k
        set_nonclient_dev_color(penum->icolor1, gx_no_color_index);
657
567k
        *(penum->icolor1) = *pdcolor;
658
567k
        memcpy(&penum->map[0].table.lookup4x1to32[0],
659
567k
               (decode[0] < decode[1] ? lookup4x1to32_inverted :
660
567k
                lookup4x1to32_identity),
661
567k
               16 * 4);
662
567k
        penum->map[0].decoding = sd_none;
663
567k
        spp = 1;
664
567k
        lop = rop3_know_S_0(lop);
665
1.05M
    } else {                    /* This is image, not imagemask. */
666
1.05M
        const gs_color_space_type *pcst = pcs->type;
667
1.05M
        int b_w_color;
668
669
1.05M
        spp = cs_num_components(pcs);
670
1.05M
        if (spp < 0) {          /* Pattern not allowed */
671
0
            code = gs_error_rangecheck;
672
0
            goto fail;
673
0
        }
674
1.05M
        if (penum->alpha)
675
0
            ++spp;
676
        /* Use a less expensive format if possible. */
677
1.05M
        switch (format) {
678
0
        case gs_image_format_bit_planar:
679
0
            if (bps > 1)
680
0
                break;
681
0
            format = gs_image_format_component_planar;
682
24.6k
        case gs_image_format_component_planar:
683
24.6k
            if (spp == 1)
684
0
                format = gs_image_format_chunky;
685
1.05M
        default:                /* chunky */
686
1.05M
            break;
687
1.05M
        }
688
689
1.05M
        if (pcs->cmm_icc_profile_data != NULL) {
690
1.02M
            device_color = false;
691
1.02M
        } else {
692
25.3k
            device_color = (*pcst->concrete_space) (pcs, pgs) == pcs;
693
25.3k
        }
694
695
1.05M
        code = image_init_colors(penum, bps, spp, format, decode, pgs, dev,
696
1.05M
                          pcs, &device_color);
697
1.05M
        if (code < 0) {
698
6
            gs_free_object(mem, penum->clues, "gx_image_enum_begin");
699
6
            gs_free_object(mem, penum, "gx_default_begin_image");
700
6
            return gs_throw(code, "Image colors initialization failed");
701
6
        }
702
        /* If we have a CIE based color space and the icc equivalent profile
703
           is not yet set, go ahead and handle that now.  It may already
704
           be done due to the above init_colors which may go through remap. */
705
1.05M
        if (gs_color_space_is_PSCIE(pcs) && pcs->icc_equivalent == NULL) {
706
0
            code = gs_colorspace_set_icc_equivalent((gs_color_space *)pcs, &(penum->icc_setup.is_lab),
707
0
                                                pgs->memory);
708
0
            if (code < 0)
709
0
                goto fail;
710
0
            if (penum->icc_setup.is_lab) {
711
                /* Free what ever profile was created and use the icc manager's
712
                   cielab profile */
713
0
                gs_color_space *curr_pcs = (gs_color_space *)pcs;
714
0
                rc_decrement(curr_pcs->icc_equivalent,"gx_image_enum_begin");
715
0
                gsicc_adjust_profile_rc(curr_pcs->cmm_icc_profile_data, -1,"gx_image_enum_begin");
716
0
                curr_pcs->cmm_icc_profile_data = pgs->icc_manager->lab_profile;
717
0
                gsicc_adjust_profile_rc(curr_pcs->cmm_icc_profile_data, 1,"gx_image_enum_begin");
718
0
            }
719
0
        }
720
        /* Try to transform non-default RasterOps to something */
721
        /* that we implement less expensively. */
722
1.05M
        if (!pim->CombineWithColor)
723
1.04M
            lop = rop3_know_T_0(lop);
724
4.42k
        else if ((rop3_uses_T(lop) && color_draws_b_w(dev, pdcolor) == 0))
725
4.23k
            lop = rop3_know_T_0(lop);
726
727
1.05M
        if (lop != rop3_S &&    /* if best case, no more work needed */
728
1.05M
            !rop3_uses_T(lop) && bps == 1 && spp == 1 &&
729
392
            (b_w_color =
730
392
             color_draws_b_w(dev, penum->icolor0)) >= 0 &&
731
392
            color_draws_b_w(dev, penum->icolor1) == (b_w_color ^ 1)
732
1.05M
            ) {
733
392
            if (b_w_color) {    /* Swap the colors and invert the RasterOp source. */
734
392
                gx_device_color dcolor;
735
736
392
                dcolor = *(penum->icolor0);
737
392
                *(penum->icolor0) = *(penum->icolor1);
738
392
                *(penum->icolor1) = dcolor;
739
392
                lop = rop3_invert_S(lop);
740
392
            }
741
            /*
742
             * At this point, we know that the source pixels
743
             * correspond directly to the S input for the raster op,
744
             * i.e., icolor0 is black and icolor1 is white.
745
             */
746
392
            switch (lop) {
747
0
                case rop3_D & rop3_S:
748
                    /* Implement this as an inverted mask writing 0s. */
749
0
                    *(penum->icolor1) = *(penum->icolor0);
750
                    /* (falls through) */
751
0
                case rop3_D | rop3_not(rop3_S):
752
                    /* Implement this as an inverted mask writing 1s. */
753
0
                    memcpy(&penum->map[0].table.lookup4x1to32[0],
754
0
                           lookup4x1to32_inverted, 16 * 4);
755
0
                  rmask:        /* Fill in the remaining parameters for a mask. */
756
0
                    penum->masked = masked = true;
757
0
                    set_nonclient_dev_color(penum->icolor0, gx_no_color_index);
758
0
                    penum->map[0].decoding = sd_none;
759
0
                    lop = rop3_T;
760
0
                    break;
761
0
                case rop3_D & rop3_not(rop3_S):
762
                    /* Implement this as a mask writing 0s. */
763
0
                    *(penum->icolor1) = *(penum->icolor0);
764
                    /* (falls through) */
765
0
                case rop3_D | rop3_S:
766
                    /* Implement this as a mask writing 1s. */
767
0
                    memcpy(&penum->map[0].table.lookup4x1to32[0],
768
0
                           lookup4x1to32_identity, 16 * 4);
769
0
                    goto rmask;
770
392
                default:
771
392
                    ;
772
392
            }
773
392
        }
774
1.05M
    }
775
1.61M
    penum->device_color = device_color;
776
    /*
777
     * Adjust width upward for unpacking up to 7 trailing bits in
778
     * the row, plus 1 byte for end-of-run, plus up to 7 leading
779
     * bits for data_x offset within a packed byte.
780
     */
781
1.61M
    bsize = ((bps > 8 ? width * 2 : width) + 15) * spp;
782
1.61M
    buffer = gs_alloc_bytes(mem, bsize, "image buffer");
783
1.61M
    if (buffer == 0) {
784
5
        code = gs_error_VMerror;
785
5
        goto fail;
786
5
    }
787
1.61M
    penum->bps = bps;
788
1.61M
    penum->unpack_bps = bps;
789
1.61M
    penum->log2_xbytes = log2_xbytes;
790
1.61M
    penum->spp = spp;
791
1.61M
    switch (format) {
792
1.59M
    case gs_image_format_chunky:
793
1.59M
        nplanes = 1;
794
1.59M
        spread = 1 << log2_xbytes;
795
1.59M
        break;
796
24.6k
    case gs_image_format_component_planar:
797
24.6k
        nplanes = spp;
798
24.6k
        spread = spp << log2_xbytes;
799
24.6k
        break;
800
0
    case gs_image_format_bit_planar:
801
0
        nplanes = spp * bps;
802
0
        spread = spp << log2_xbytes;
803
0
        break;
804
0
    default:
805
        /* No other cases are possible (checked by gx_image_enum_alloc). */
806
0
        return_error(gs_error_Fatal);
807
1.61M
    }
808
1.61M
    penum->num_planes = nplanes;
809
1.61M
    penum->spread = spread;
810
    /*
811
     * If we're asked to interpolate in a partial image, we have to
812
     * assume that the client either really only is interested in
813
     * the given sub-image, or else is constructing output out of
814
     * overlapping pieces.
815
     */
816
1.61M
    penum->interpolate = force_interpolation ? interp_force : pim->Interpolate ? interp_on : interp_off;
817
1.61M
    penum->x_extent = x_extent;
818
1.61M
    penum->y_extent = y_extent;
819
1.61M
    penum->posture =
820
1.61M
        ((x_extent.y | y_extent.x) == 0 ? image_portrait :
821
1.61M
         (x_extent.x | y_extent.y) == 0 ? image_landscape :
822
219k
         image_skewed);
823
1.61M
    penum->pgs = pgs;
824
1.61M
    if (pgs != NULL)
825
1.61M
        penum->pgs_level = pgs->level;
826
1.61M
    penum->pcs = pcs;
827
1.61M
    rc_increment_cs(pcs); /* Grab a ref (will decrement in gx_image1_end_image() */
828
1.61M
    penum->memory = mem;
829
1.61M
    penum->buffer = buffer;
830
1.61M
    penum->buffer_size = bsize;
831
1.61M
    penum->line = NULL;
832
1.61M
    penum->icc_link = NULL;
833
1.61M
    penum->color_cache = NULL;
834
1.61M
    penum->ht_buffer = NULL;
835
1.61M
    penum->thresh_buffer = NULL;
836
1.61M
    penum->use_cie_range = false;
837
1.61M
    penum->line_size = 0;
838
1.61M
    penum->use_rop = lop != (masked ? rop3_T : rop3_S);
839
#ifdef DEBUG
840
    if (gs_debug_c('*')) {
841
        if (penum->use_rop)
842
            dmprintf1(mem, "[%03x]", lop);
843
        dmprintf5(mem, "%c%d%c%dx%d ",
844
                 (masked ? (color_is_pure(pdcolor) ? 'm' : 'h') : 'i'),
845
                 bps,
846
                 (penum->posture == image_portrait ? ' ' :
847
                  penum->posture == image_landscape ? 'L' : 'T'),
848
                 width, height);
849
    }
850
#endif
851
1.61M
    penum->slow_loop = 0;
852
1.61M
    if (pcpath == 0) {
853
908k
        (*dev_proc(dev, get_clipping_box)) (dev, &obox);
854
908k
        cbox = obox;
855
908k
        penum->clip_image = 0;
856
908k
    } else
857
710k
        penum->clip_image =
858
710k
            (gx_cpath_outer_box(pcpath, &obox) |        /* not || */
859
710k
             gx_cpath_inner_box(pcpath, &cbox) ?
860
709k
             0 : image_clip_region);
861
1.61M
    penum->clip_outer = obox;
862
1.61M
    penum->clip_inner = cbox;
863
1.61M
    penum->log_op = rop3_T;     /* rop device takes care of this */
864
1.61M
    penum->clip_dev = 0;        /* in case we bail out */
865
1.61M
    penum->rop_dev = 0;         /* ditto */
866
1.61M
    penum->scaler = 0;          /* ditto */
867
    /*
868
     * If all four extrema of the image fall within the clipping
869
     * rectangle, clipping is never required.  When making this check,
870
     * we must carefully take into account the fact that we only care
871
     * about pixel centers.
872
     */
873
1.61M
    {
874
1.61M
        fixed
875
1.61M
            epx = min(row_extent.x, 0) + min(col_extent.x, 0),
876
1.61M
            eqx = max(row_extent.x, 0) + max(col_extent.x, 0),
877
1.61M
            epy = min(row_extent.y, 0) + min(col_extent.y, 0),
878
1.61M
            eqy = max(row_extent.y, 0) + max(col_extent.y, 0);
879
880
1.61M
        {
881
1.61M
            int hwx, hwy;
882
883
1.61M
            switch (penum->posture) {
884
1.39M
                case image_portrait:
885
1.39M
                    hwx = width, hwy = height;
886
1.39M
                    break;
887
119k
                case image_landscape:
888
119k
                    hwx = height, hwy = width;
889
119k
                    break;
890
99.8k
                default:
891
99.8k
                    hwx = hwy = 0;
892
1.61M
            }
893
            /*
894
             * If the image is only 1 sample wide or high,
895
             * and is less than 1 device pixel wide or high,
896
             * move it slightly so that it covers pixel centers.
897
             * This is a hack to work around a bug in some old
898
             * versions of TeX/dvips, which use 1-bit-high images
899
             * to draw horizontal and vertical lines without
900
             * positioning them properly.
901
             */
902
1.61M
            if (hwx == 1 && eqx - epx < fixed_1) {
903
21
                fixed diff =
904
21
                arith_rshift_1(row_extent.x + col_extent.x);
905
906
21
                mtx = (((mtx + diff) | fixed_half) & -fixed_half) - diff;
907
21
            }
908
1.61M
            if (hwy == 1 && eqy - epy < fixed_1) {
909
23
                fixed diff =
910
23
                arith_rshift_1(row_extent.y + col_extent.y);
911
912
23
                mty = (((mty + diff) | fixed_half) & -fixed_half) - diff;
913
23
            }
914
1.61M
        }
915
1.61M
        if_debug5m('b', mem, "[b]Image: %sspp=%d, bps=%d, mt=(%g,%g)\n",
916
1.61M
                   (masked? "masked, " : ""), spp, bps,
917
1.61M
                   fixed2float(mtx), fixed2float(mty));
918
1.61M
        if_debug9m('b', mem,
919
1.61M
                   "[b]   cbox=(%g,%g),(%g,%g), obox=(%g,%g),(%g,%g), clip_image=0x%x\n",
920
1.61M
                   fixed2float(cbox.p.x), fixed2float(cbox.p.y),
921
1.61M
                   fixed2float(cbox.q.x), fixed2float(cbox.q.y),
922
1.61M
                   fixed2float(obox.p.x), fixed2float(obox.p.y),
923
1.61M
                   fixed2float(obox.q.x), fixed2float(obox.q.y),
924
1.61M
                   penum->clip_image);
925
        /* These DDAs enumerate the starting position of each source pixel
926
         * row in device space. */
927
1.61M
        dda_init(penum->dda.row.x, mtx, col_extent.x, height);
928
1.61M
        dda_init(penum->dda.row.y, mty, col_extent.y, height);
929
1.61M
        if (dda_will_overflow(penum->dda.row.x) ||
930
1.61M
            dda_will_overflow(penum->dda.row.y))
931
0
        {
932
0
            code = gs_error_rangecheck;
933
0
            goto fail;
934
0
        }
935
1.61M
        if (penum->posture == image_portrait) {
936
1.39M
            penum->dst_width = row_extent.x;
937
1.39M
            penum->dst_height = col_extent.y;
938
1.39M
        } else {
939
219k
            penum->dst_width = col_extent.x;
940
219k
            penum->dst_height = row_extent.y;
941
219k
        }
942
        /* For gs_image_class_0_interpolate. */
943
1.61M
        penum->yi0 = fixed2int_pixround_perfect(dda_current(penum->dda.row.y)); /* For gs_image_class_0_interpolate. */
944
1.61M
        if (penum->rect.y) {
945
319k
            int y = penum->rect.y;
946
947
38.9M
            while (y--) {
948
38.6M
                dda_next(penum->dda.row.x);
949
38.6M
                dda_next(penum->dda.row.y);
950
38.6M
            }
951
319k
        }
952
1.61M
        penum->cur.x = penum->prev.x = dda_current(penum->dda.row.x);
953
1.61M
        penum->cur.y = penum->prev.y = dda_current(penum->dda.row.y);
954
        /* These DDAs enumerate the starting positions of each row of our
955
         * source pixel data, in the subrectangle ('strip') that we are
956
         * actually rendering. */
957
1.61M
        dda_init(penum->dda.strip.x, penum->cur.x, row_extent.x, width);
958
1.61M
        dda_init(penum->dda.strip.y, penum->cur.y, row_extent.y, width);
959
1.61M
        if (dda_will_overflow(penum->dda.strip.x) ||
960
1.61M
            dda_will_overflow(penum->dda.strip.y))
961
0
        {
962
0
            code = gs_error_rangecheck;
963
0
            goto fail;
964
0
        }
965
1.61M
        if (penum->rect.x) {
966
6.62k
            dda_advance(penum->dda.strip.x, penum->rect.x);
967
6.62k
            dda_advance(penum->dda.strip.y, penum->rect.x);
968
6.62k
        }
969
1.61M
        {
970
1.61M
            fixed ox = dda_current(penum->dda.strip.x);
971
1.61M
            fixed oy = dda_current(penum->dda.strip.y);
972
973
1.61M
            if (!penum->clip_image)     /* i.e., not clip region */
974
1.61M
                penum->clip_image =
975
1.61M
                    (fixed_pixround(ox + epx) < fixed_pixround(cbox.p.x) ?
976
1.52M
                     image_clip_xmin : 0) +
977
1.61M
                    (fixed_pixround(ox + eqx) >= fixed_pixround(cbox.q.x) ?
978
1.22M
                     image_clip_xmax : 0) +
979
1.61M
                    (fixed_pixround(oy + epy) < fixed_pixround(cbox.p.y) ?
980
1.27M
                     image_clip_ymin : 0) +
981
1.61M
                    (fixed_pixround(oy + eqy) >= fixed_pixround(cbox.q.y) ?
982
1.09M
                     image_clip_ymax : 0);
983
1.61M
        }
984
1.61M
    }
985
0
    penum->y = 0;
986
1.61M
    penum->used.x = 0;
987
1.61M
    penum->used.y = 0;
988
1.61M
    if (penum->clip_image && pcpath) {  /* Set up the clipping device. */
989
402k
        gx_device_clip *cdev =
990
402k
            gs_alloc_struct(mem, gx_device_clip,
991
402k
                            &st_device_clip, "image clipper");
992
993
402k
        if (cdev == NULL) {
994
0
            code = gs_error_VMerror;
995
0
            goto fail;
996
0
        }
997
402k
        gx_make_clip_device_in_heap(cdev, pcpath, dev, mem);
998
402k
        penum->clip_dev = cdev;
999
402k
        penum->dev = (gx_device *)cdev; /* Will restore this in a mo. Hacky! */
1000
402k
    }
1001
1.61M
    if (penum->use_rop) {       /* Set up the RasterOp source device. */
1002
274
        gx_device_rop_texture *rtdev;
1003
1004
274
        code = gx_alloc_rop_texture_device(&rtdev, mem,
1005
274
                                           "image RasterOp");
1006
274
        if (code < 0)
1007
0
            goto fail;
1008
        /* The 'target' must not be NULL for gx_make_rop_texture_device */
1009
274
        if (!penum->clip_dev && !dev)
1010
0
            return_error(gs_error_undefined);
1011
1012
274
        gx_make_rop_texture_device(rtdev,
1013
274
                                   (penum->clip_dev != 0 ?
1014
263
                                    (gx_device *) penum->clip_dev :
1015
274
                                    dev), lop, pdcolor);
1016
274
        gx_device_retain((gx_device *)rtdev, true);
1017
274
        penum->rop_dev = rtdev;
1018
274
        penum->dev = (gx_device *)rtdev; /* Will restore this in a mo. Hacky! */
1019
274
    }
1020
1.61M
    {
1021
1.61M
        static sample_unpack_proc_t procs[2][6] = {
1022
1.61M
        {   sample_unpack_1, sample_unpack_2,
1023
1.61M
            sample_unpack_4, sample_unpack_8,
1024
1.61M
            sample_unpack_12, sample_unpack_16
1025
1.61M
        },
1026
1.61M
        {   sample_unpack_1_interleaved, sample_unpack_2_interleaved,
1027
1.61M
            sample_unpack_4_interleaved, sample_unpack_8_interleaved,
1028
1.61M
            sample_unpack_12, sample_unpack_16
1029
1.61M
        }};
1030
1.61M
        int num_planes = penum->num_planes;
1031
1.61M
        bool interleaved = (num_planes == 1 && penum->plane_depths[0] != penum->bps);
1032
1.61M
        irender_proc_t render_fn = NULL;
1033
1.61M
        int i;
1034
1035
1.61M
        if (interleaved) {
1036
656k
            int num_components = penum->plane_depths[0] / penum->bps;
1037
1038
1.97M
            for (i = 1; i < num_components; i++) {
1039
1.32M
                if (decode[0] != decode[i * 2 + 0] ||
1040
1.32M
                    decode[1] != decode[i * 2 + 1])
1041
10
                    break;
1042
1.32M
            }
1043
656k
            if (i == num_components)
1044
656k
                interleaved = false; /* Use single table. */
1045
656k
        }
1046
1.61M
        penum->unpack = procs[interleaved][index_bps];
1047
1048
1.61M
        if_debug1m('b', mem, "[b]unpack=%d\n", bps);
1049
        /* Set up pixel0 for image class procedures. */
1050
1.61M
        penum->dda.pixel0 = penum->dda.strip;
1051
1.61M
        penum->skip_next_line = NULL;
1052
6.54M
        for (i = 0; i < gx_image_class_table_count; ++i) {
1053
6.54M
            code = gx_image_class_table[i](penum, &render_fn);
1054
6.54M
            if (code < 0)
1055
0
                goto fail;
1056
1057
6.54M
            if (render_fn != NULL) {
1058
1.61M
                penum->render = render_fn;
1059
1.61M
                break;
1060
1.61M
            }
1061
6.54M
        }
1062
1.61M
        penum->dev = dev; /* Restore this (in case it was changed to cdev or rtdev) */
1063
1.61M
        if (i == gx_image_class_table_count) {
1064
            /* No available class can handle this image. */
1065
0
            return_error(gs_error_rangecheck);
1066
0
        }
1067
1.61M
    }
1068
1.61M
    return 0;
1069
1070
57
fail:
1071
57
    gs_free_object(mem, buffer, "image buffer");
1072
57
    gs_free_object(mem, penum->clues, "gx_image_enum_begin");
1073
57
    if (penum->clip_dev != NULL) {
1074
0
        rc_decrement(penum->clip_dev, "error in gx_begin_image1");
1075
0
        penum->clip_dev = NULL;
1076
0
    }
1077
57
    gs_free_object(mem, penum->clip_dev, "image clipper");
1078
57
    rc_decrement_cs(penum->pcs, "error in gx_begin_image1");
1079
57
    penum->pcs = NULL;
1080
57
    gs_free_object(mem, penum, "gx_begin_image1");
1081
57
    return code;
1082
1.61M
}
1083
1084
/* If a drawing color is black or white, return 0 or 1 respectively, */
1085
/* otherwise return -1. */
1086
static int
1087
color_draws_b_w(gx_device * dev, const gx_drawing_color * pdcolor)
1088
5.01k
{
1089
5.01k
    if (color_is_pure(pdcolor)) {
1090
5.01k
        gx_color_value rgb[3];
1091
1092
5.01k
        (*dev_proc(dev, map_color_rgb)) (dev, gx_dc_pure_color(pdcolor),
1093
5.01k
                                         rgb);
1094
5.01k
        if (!(rgb[0] | rgb[1] | rgb[2]))
1095
4.62k
            return 0;
1096
392
        if ((rgb[0] & rgb[1] & rgb[2]) == gx_max_color_value)
1097
392
            return 1;
1098
392
    }
1099
0
    return -1;
1100
5.01k
}
1101
1102
1103
static void
1104
image_cache_decode(gx_image_enum *penum, byte input, byte *output, bool scale)
1105
0
{
1106
0
    float temp;
1107
1108
0
    switch ( penum->map[0].decoding ) {
1109
0
        case sd_none:
1110
0
            *output = input;
1111
0
            break;
1112
0
        case sd_lookup:
1113
0
            temp = penum->map[0].decode_lookup[input >> 4]*255.0f;
1114
0
            if (temp > 255) temp = 255;
1115
0
            if (temp < 0 ) temp = 0;
1116
0
            *output = (unsigned char) temp;
1117
0
            break;
1118
0
        case sd_compute:
1119
0
            temp = penum->map[0].decode_base +
1120
0
                (float) input * penum->map[0].decode_factor;
1121
0
            if (scale) {
1122
0
                temp = temp * 255.0;
1123
0
            }
1124
0
            if (temp > 255) temp = 255;
1125
0
            if (temp < 0 ) temp = 0;
1126
0
            *output = (unsigned char) temp;
1127
0
            break;
1128
0
        default:
1129
0
            *output = 0;
1130
0
            break;
1131
0
    }
1132
0
}
1133
1134
static bool
1135
decode_range_needed(gx_image_enum *penum)
1136
0
{
1137
0
    bool scale = true;
1138
1139
0
    if (penum->map[0].decoding == sd_compute) {
1140
0
        if (!(gs_color_space_is_ICC(penum->pcs) ||
1141
0
            gs_color_space_is_PSCIE(penum->pcs))) {
1142
0
            scale = false;
1143
0
        }
1144
0
    }
1145
0
    return scale;
1146
0
}
1147
1148
/* A special case where we go ahead and initialize the whole index cache with
1149
   contone.  Device colors.  If we are halftoning we will then go ahead and
1150
   apply the thresholds to the device contone values.  Only used for gray,
1151
   rgb or cmyk source colors (No DeviceN for now) */
1152
/* TO DO  Add in PSCIE decoder */
1153
int
1154
image_init_color_cache(gx_image_enum * penum, int bps, int spp)
1155
70.1k
{
1156
70.1k
    int num_des_comp = penum->dev->color_info.num_components;
1157
70.1k
    int num_src_comp;
1158
70.1k
    int num_entries = 1 << bps;
1159
70.1k
    bool need_decode = penum->icc_setup.need_decode;
1160
70.1k
    bool has_transfer = penum->icc_setup.has_transfer;
1161
70.1k
    byte value;
1162
70.1k
    bool decode_scale = true;
1163
70.1k
    int k, kk;
1164
70.1k
    byte psrc[4];
1165
70.1k
    byte *temp_buffer;
1166
70.1k
    byte *byte_ptr;
1167
70.1k
    bool is_indexed = (gs_color_space_get_index(penum->pcs) ==
1168
70.1k
                                            gs_color_space_index_Indexed);
1169
70.1k
    bool free_temp_buffer = true;
1170
70.1k
    gsicc_bufferdesc_t input_buff_desc;
1171
70.1k
    gsicc_bufferdesc_t output_buff_desc;
1172
70.1k
    gx_color_value conc[GX_DEVICE_COLOR_MAX_COMPONENTS];
1173
70.1k
    int code;
1174
1175
70.1k
    if (penum->icc_link == NULL) {
1176
0
        return gs_rethrow(-1, "ICC Link not created during image render color");
1177
0
    }
1178
70.1k
    if (is_indexed) {
1179
1.49k
        num_src_comp = gs_color_space_num_components(penum->pcs->base_space);
1180
68.7k
    } else {
1181
        /* Detect case where cache is not needed.  Colors are already in the
1182
           device space.  Need to fast track this one and halftone row directly.
1183
           Detected in gximono.c by looking if penum->color_cache is NULL */
1184
68.7k
        if (penum->icc_link->is_identity && !need_decode && !has_transfer) {
1185
68.4k
            return 0;
1186
68.4k
        }
1187
252
        num_src_comp = 1;
1188
252
    }
1189
    /* Allocate cache of device contone values */
1190
1.74k
    penum->color_cache = gs_alloc_struct(penum->memory, gx_image_color_cache_t,
1191
1.74k
                                         &st_color_cache,
1192
1.74k
                                         "image_init_color_cache");
1193
1.74k
    if (penum->color_cache == NULL)
1194
0
        return_error(gs_error_VMerror);
1195
1196
1.74k
    penum->color_cache->device_contone = (byte*) gs_alloc_bytes(penum->memory,
1197
1.74k
                   (size_t)num_des_comp * num_entries * sizeof(byte), "image_init_color_cache");
1198
1.74k
    penum->color_cache->is_transparent = (bool*) gs_alloc_bytes(penum->memory,
1199
1.74k
             (size_t)num_entries * sizeof(bool), "image_init_color_cache");
1200
1.74k
    if (penum->color_cache->device_contone == NULL || penum->color_cache->is_transparent == NULL) {
1201
0
        gs_free_object(penum->memory, penum->color_cache->device_contone, "image_init_color_cache");
1202
0
        gs_free_object(penum->memory, penum->color_cache->is_transparent, "image_init_color_cache");
1203
0
        gs_free_object(penum->memory, penum->color_cache, "image_init_color_cache");
1204
0
        penum->color_cache = NULL;
1205
0
        return_error(gs_error_VMerror);
1206
0
    }
1207
    /* Initialize */
1208
1.74k
    memset(penum->color_cache->is_transparent,0,num_entries * sizeof(bool));
1209
    /* Depending upon if we need decode and ICC CM, fill the cache a couple
1210
       different ways. If the link is the identity, then we don't need to do any
1211
       color conversions except for potentially a decode.  This is written in
1212
       the manner shown below so that the common case of no decode and indexed
1213
       image with a look-up-table uses the table data directly or does as many
1214
       operations with memcpy as we can */
1215
    /* Need to check the decode output range so we know how we need to scale.
1216
       We want 8 bit output */
1217
1.74k
    if (need_decode) {
1218
0
        decode_scale = decode_range_needed(penum);
1219
0
    }
1220
1.74k
    if (penum->icc_link->is_identity) {
1221
        /* No CM needed.  */
1222
0
        if (need_decode || has_transfer) {
1223
            /* Slower case.  This could be sped up later to avoid the tests
1224
               within the loop by use of specialized loops.  */
1225
0
            for (k = 0; k < num_entries; k++) {
1226
                /* Data is in k */
1227
0
                if (need_decode) {
1228
0
                    image_cache_decode(penum, k, &value, decode_scale);
1229
0
                } else {
1230
0
                    value = k;
1231
0
                }
1232
                /* Data is in value */
1233
0
                if (is_indexed) {
1234
0
                    gs_cspace_indexed_lookup_bytes(penum->pcs, value, psrc);
1235
0
                } else {
1236
0
                    psrc[0] = value;
1237
0
                }
1238
                /* Data is in psrc */
1239
                /* These silly transforms need to go away. ToDo. */
1240
0
                if (has_transfer) {
1241
0
                    for (kk = 0; kk < num_des_comp; kk++) {
1242
0
                        conc[kk] = gx_color_value_from_byte(psrc[kk]);
1243
0
                    }
1244
0
                    cmap_transfer(&(conc[0]), penum->pgs, penum->dev);
1245
0
                    for (kk = 0; kk < num_des_comp; kk++) {
1246
0
                        psrc[kk] = gx_color_value_to_byte(conc[kk]);
1247
0
                    }
1248
0
                }
1249
0
                memcpy(&(penum->color_cache->device_contone[k * num_des_comp]),
1250
0
                               psrc, num_des_comp);
1251
0
            }
1252
0
        } else {
1253
            /* Indexing only.  No CM, decode or transfer functions. */
1254
0
            for (k = 0; k < num_entries; k++) {
1255
0
                gs_cspace_indexed_lookup_bytes(penum->pcs, (float)k, psrc);
1256
0
                memcpy(&(penum->color_cache->device_contone[k * num_des_comp]),
1257
0
                           psrc, num_des_comp);
1258
0
            }
1259
0
        }
1260
1.74k
    } else {
1261
        /* Need CM */
1262
        /* We need to worry about if the source is indexed and if we need
1263
           to decode first.  Then we can apply CM. Create a temp buffer in
1264
           the source space and then transform it with one call */
1265
1.74k
        temp_buffer = (byte*) gs_alloc_bytes(penum->memory,
1266
1.74k
                                             (size_t)num_entries * num_src_comp,
1267
1.74k
                                             "image_init_color_cache");
1268
1.74k
        if (temp_buffer == NULL)
1269
0
            return_error(gs_error_VMerror);
1270
1271
1.74k
        if (need_decode) {
1272
0
            if (is_indexed) {
1273
                /* Decode and lookup in index */
1274
0
                for (k = 0; k < num_entries; k++) {
1275
0
                    image_cache_decode(penum, k, &value, decode_scale);
1276
0
                    gs_cspace_indexed_lookup_bytes(penum->pcs, value, psrc);
1277
0
                    memcpy(&(temp_buffer[k * num_src_comp]), psrc, num_src_comp);
1278
0
                }
1279
0
            } else {
1280
                /* Decode only */
1281
0
                for (k = 0; k < num_entries; k++) {
1282
0
                    image_cache_decode(penum, k, &(temp_buffer[k]), decode_scale);
1283
0
                }
1284
0
            }
1285
1.74k
        } else {
1286
            /* No Decode */
1287
1.74k
            if (is_indexed) {
1288
                /* If index uses a num_entries sized table then just use its pointer */
1289
1.49k
                if (penum->pcs->params.indexed.use_proc ||
1290
1.49k
                    penum->pcs->params.indexed.hival < (num_entries - 1)) {
1291
                    /* Have to do the slow way */
1292
6.22k
                    for (k = 0; k <= penum->pcs->params.indexed.hival; k++) {
1293
6.05k
                        gs_cspace_indexed_lookup_bytes(penum->pcs, (float)k, psrc);
1294
6.05k
                        memcpy(&(temp_buffer[k * num_src_comp]), psrc, num_src_comp);
1295
6.05k
                    }
1296
                    /* just use psrc results from converting 'hival' to fill the remaining slots */
1297
36.6k
                    for (; k < num_entries; k++) {
1298
36.4k
                        memcpy(&(temp_buffer[k * num_src_comp]), psrc, num_src_comp);
1299
36.4k
                    }
1300
1.32k
                } else {
1301
                    /* Use the index table directly. */
1302
1.32k
                    gs_free_object(penum->memory, temp_buffer, "image_init_color_cache");
1303
1.32k
                    free_temp_buffer = false;
1304
1.32k
                    temp_buffer = (byte *)(penum->pcs->params.indexed.lookup.table.data);
1305
1.32k
                }
1306
1.49k
            } else {
1307
                /* CM only */
1308
64.7k
                for (k = 0; k < num_entries; k++) {
1309
64.5k
                    temp_buffer[k] = k;
1310
64.5k
                }
1311
252
            }
1312
1.74k
        }
1313
        /* Set up the buffer descriptors. */
1314
1.74k
        gsicc_init_buffer(&input_buff_desc, num_src_comp, 1, false, false, false,
1315
1.74k
                          0, num_entries * num_src_comp, 1, num_entries);
1316
1.74k
        gsicc_init_buffer(&output_buff_desc, num_des_comp, 1, false, false, false,
1317
1.74k
                          0, num_entries * num_des_comp,
1318
1.74k
                      1, num_entries);
1319
1.74k
        code = (penum->icc_link->procs.map_buffer)(penum->dev, penum->icc_link,
1320
1.74k
                                            &input_buff_desc, &output_buff_desc,
1321
1.74k
                                            (void*) temp_buffer,
1322
1.74k
                                            (void*) penum->color_cache->device_contone);
1323
1.74k
        if (code < 0)
1324
0
            return gs_rethrow(code, "Failure to map color buffer");
1325
1326
        /* Check if we need to apply any transfer functions.  If so then do it now */
1327
1.74k
        if (has_transfer) {
1328
0
            for (k = 0; k < num_entries; k++) {
1329
0
                byte_ptr =
1330
0
                    &(penum->color_cache->device_contone[k * num_des_comp]);
1331
0
                for (kk = 0; kk < num_des_comp; kk++) {
1332
0
                    conc[kk] = gx_color_value_from_byte(byte_ptr[kk]);
1333
0
                }
1334
0
                cmap_transfer(&(conc[0]), penum->pgs, penum->dev);
1335
0
                for (kk = 0; kk < num_des_comp; kk++) {
1336
0
                    byte_ptr[kk] = gx_color_value_to_byte(conc[kk]);
1337
0
                }
1338
0
            }
1339
0
        }
1340
1.74k
        if (free_temp_buffer)
1341
418
            gs_free_object(penum->memory, temp_buffer, "image_init_color_cache");
1342
1.74k
    }
1343
1.74k
    return 0;
1344
1.74k
}
1345
1346
/* Export this for use by image_render_ functions */
1347
void
1348
image_init_clues(gx_image_enum * penum, int bps, int spp)
1349
931k
{
1350
    /* Initialize the color table */
1351
931k
#define ictype(i)\
1352
931k
  penum->clues[i].dev_color.type
1353
1354
931k
    switch ((spp == 1 ? bps : 8)) {
1355
625k
        case 8:         /* includes all color images */
1356
625k
            {
1357
625k
                register gx_image_clue *pcht = &penum->clues[0];
1358
625k
                register int n = 64;    /* 8 bits means 256 clues, do   */
1359
                                        /* 4 at a time for efficiency   */
1360
40.0M
                do {
1361
40.0M
                    pcht[0].dev_color.type =
1362
40.0M
                        pcht[1].dev_color.type =
1363
40.0M
                        pcht[2].dev_color.type =
1364
40.0M
                        pcht[3].dev_color.type =
1365
40.0M
                        gx_dc_type_none;
1366
40.0M
                    pcht[0].key = pcht[1].key =
1367
40.0M
                        pcht[2].key = pcht[3].key = 0;
1368
40.0M
                    pcht += 4;
1369
40.0M
                }
1370
40.0M
                while (--n > 0);
1371
625k
                penum->clues[0].key = 1;        /* guarantee no hit */
1372
625k
                break;
1373
0
            }
1374
610
        case 4:
1375
610
            ictype(17) = ictype(2 * 17) = ictype(3 * 17) =
1376
610
                ictype(4 * 17) = ictype(6 * 17) = ictype(7 * 17) =
1377
610
                ictype(8 * 17) = ictype(9 * 17) = ictype(11 * 17) =
1378
610
                ictype(12 * 17) = ictype(13 * 17) = ictype(14 * 17) =
1379
610
                gx_dc_type_none;
1380
            /* falls through */
1381
1.65k
        case 2:
1382
1.65k
            ictype(5 * 17) = ictype(10 * 17) = gx_dc_type_none;
1383
931k
#undef ictype
1384
931k
    }
1385
931k
}
1386
1387
/* Initialize the color mapping tables for a non-mask image. */
1388
static int
1389
image_init_colors(gx_image_enum * penum, int bps, int spp,
1390
                  gs_image_format_t format, const float *decode /*[spp*2] */ ,
1391
                  const gs_gstate * pgs, gx_device * dev,
1392
                  const gs_color_space * pcs, bool * pdcb)
1393
1.05M
{
1394
1.05M
    int ci, decode_type, code;
1395
1.05M
    static const float default_decode[] = {
1396
1.05M
        0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0
1397
1.05M
    };
1398
1399
    /* Clues are only used with image_mono_render */
1400
1.05M
    if (spp == 1) {
1401
371k
        image_init_clues(penum, bps, spp);
1402
371k
    }
1403
1.05M
    decode_type = 3; /* 0=custom, 1=identity, 2=inverted, 3=impossible */
1404
2.78M
    for (ci = 0; ci < spp; ci +=2 ) {
1405
1.73M
        decode_type &= (decode[ci] == 0. && decode[ci + 1] == 1.) |
1406
1.73M
                       (decode[ci] == 1. && decode[ci + 1] == 0.) << 1;
1407
1.73M
    }
1408
1409
    /* Initialize the maps from samples to intensities. */
1410
3.49M
    for (ci = 0; ci < spp; ci++) {
1411
2.44M
        sample_map *pmap = &penum->map[ci];
1412
1413
        /* If the decoding is [0 1] or [1 0], we can fold it */
1414
        /* into the expansion of the sample values; */
1415
        /* otherwise, we have to use the floating point method. */
1416
1417
2.44M
        const float *this_decode = &decode[ci * 2];
1418
2.44M
        const float *map_decode;        /* decoding used to */
1419
                                        /* construct the expansion map */
1420
2.44M
        const float *real_decode;       /* decoding for expanded samples */
1421
1422
2.44M
        map_decode = real_decode = this_decode;
1423
2.44M
        if (!(decode_type & 1)) {
1424
5.96k
            if ((decode_type & 2) && bps <= 8) {
1425
544
                real_decode = default_decode;
1426
5.42k
            } else {
1427
5.42k
                *pdcb = false;
1428
5.42k
                map_decode = default_decode;
1429
5.42k
            }
1430
5.96k
        }
1431
2.44M
        if (bps > 2 || format != gs_image_format_chunky) {
1432
2.42M
            if (bps <= 8)
1433
2.42M
                image_init_map(&pmap->table.lookup8[0], 1 << bps,
1434
2.42M
                               map_decode);
1435
2.42M
        } else {                /* The map index encompasses more than one pixel. */
1436
23.1k
            byte map[4];
1437
23.1k
            register int i;
1438
1439
23.1k
            image_init_map(&map[0], 1 << bps, map_decode);
1440
23.1k
            switch (bps) {
1441
22.5k
                case 1:
1442
22.5k
                    {
1443
22.5k
                        register bits32 *p = &pmap->table.lookup4x1to32[0];
1444
1445
22.5k
                        if (map[0] == 0 && map[1] == 0xff)
1446
22.5k
                            memcpy((byte *) p, lookup4x1to32_identity, 16 * 4);
1447
40
                        else if (map[0] == 0xff && map[1] == 0)
1448
40
                            memcpy((byte *) p, lookup4x1to32_inverted, 16 * 4);
1449
0
                        else
1450
0
                            for (i = 0; i < 16; i++, p++)
1451
0
                                ((byte *) p)[0] = map[i >> 3],
1452
0
                                    ((byte *) p)[1] = map[(i >> 2) & 1],
1453
0
                                    ((byte *) p)[2] = map[(i >> 1) & 1],
1454
0
                                    ((byte *) p)[3] = map[i & 1];
1455
22.5k
                    }
1456
22.5k
                    break;
1457
525
                case 2:
1458
525
                    {
1459
525
                        register bits16 *p = &pmap->table.lookup2x2to16[0];
1460
1461
8.92k
                        for (i = 0; i < 16; i++, p++)
1462
8.40k
                            ((byte *) p)[0] = map[i >> 2],
1463
8.40k
                                ((byte *) p)[1] = map[i & 3];
1464
525
                    }
1465
525
                    break;
1466
23.1k
            }
1467
23.1k
        }
1468
2.44M
        pmap->decode_base /* = decode_lookup[0] */  = real_decode[0];
1469
2.44M
        pmap->decode_factor =
1470
2.44M
            (real_decode[1] - real_decode[0]) /
1471
2.44M
            (bps <= 8 ? 255.0 : (float)frac_1);
1472
2.44M
        pmap->decode_max /* = decode_lookup[15] */  = real_decode[1];
1473
2.44M
        if (decode_type) {
1474
2.44M
            pmap->decoding = sd_none;
1475
2.44M
            pmap->inverted = map_decode[0] != 0;
1476
2.44M
        } else if (bps <= 4) {
1477
573
            int step = 15 / ((1 << bps) - 1);
1478
573
            int i;
1479
1480
573
            pmap->decoding = sd_lookup;
1481
3.00k
            for (i = 15 - step; i > 0; i -= step)
1482
2.42k
                pmap->decode_lookup[i] = pmap->decode_base +
1483
2.42k
                    i * (255.0 / 15) * pmap->decode_factor;
1484
573
            pmap->inverted = 0;
1485
4.84k
        } else {
1486
4.84k
            pmap->decoding = sd_compute;
1487
4.84k
            pmap->inverted = 0;
1488
4.84k
        }
1489
2.44M
        if (spp == 1) {         /* and ci == 0 *//* Pre-map entries 0 and 255. */
1490
371k
            gs_client_color cc;
1491
1492
            /* Image clues are used in this case */
1493
371k
            cc.paint.values[0] = real_decode[0];
1494
371k
            code = (*pcs->type->remap_color) (&cc, pcs, penum->icolor0,
1495
371k
                                       pgs, dev, gs_color_select_source);
1496
371k
            if (code < 0)
1497
6
                return code;
1498
371k
            cc.paint.values[0] = real_decode[1];
1499
371k
            code = (*pcs->type->remap_color) (&cc, pcs, penum->icolor1,
1500
371k
                                       pgs, dev, gs_color_select_source);
1501
371k
            if (code < 0)
1502
0
                return code;
1503
371k
        }
1504
2.44M
    }
1505
1.05M
    return 0;
1506
1.05M
}
1507
/* Construct a mapping table for sample values. */
1508
/* map_size is 2, 4, 16, or 256.  Note that 255 % (map_size - 1) == 0, */
1509
/* so the division 0xffffL / (map_size - 1) is always exact. */
1510
void
1511
image_init_map(byte * map, int map_size, const float *decode)
1512
2.45M
{
1513
2.45M
    float min_v = decode[0];
1514
2.45M
    float diff_v = decode[1] - min_v;
1515
1516
2.45M
    if (diff_v == 1 || diff_v == -1) {  /* We can do the stepping with integers, without overflow. */
1517
2.45M
        byte *limit = map + map_size;
1518
2.45M
        uint value = (uint)(min_v * 0xffffL);
1519
2.45M
        int diff = (int)(diff_v * (0xffffL / (map_size - 1)));
1520
1521
624M
        for (; map != limit; map++, value += diff)
1522
622M
            *map = value >> 8;
1523
2.45M
    } else {                    /* Step in floating point, with clamping. */
1524
0
        int i;
1525
1526
0
        for (i = 0; i < map_size; ++i) {
1527
0
            int value = (int)((min_v + diff_v * i / (map_size - 1)) * 255);
1528
1529
0
            map[i] = (value < 0 ? 0 : value > 255 ? 255 : value);
1530
0
        }
1531
0
    }
1532
2.45M
}
1533
1534
/*
1535
 * Scale a pair of mask_color values to match the scaling of each sample to
1536
 * a full byte, and complement and swap them if the map incorporates
1537
 * a Decode = [1 0] inversion.
1538
 */
1539
void
1540
gx_image_scale_mask_colors(gx_image_enum *penum, int component_index)
1541
1.45k
{
1542
1.45k
    uint scale = 255 / ((1 << penum->bps) - 1);
1543
1.45k
    uint *values = &penum->mask_color.values[component_index * 2];
1544
1.45k
    uint v0 = values[0] *= scale;
1545
1.45k
    uint v1 = values[1] *= scale;
1546
1547
1.45k
    if (penum->map[component_index].decoding == sd_none &&
1548
726
        penum->map[component_index].inverted
1549
1.45k
        ) {
1550
0
        values[0] = 255 - v1;
1551
0
        values[1] = 255 - v0;
1552
0
    }
1553
1.45k
}
1554
1555
/* Used to indicate for ICC procesing if we have decoding to do */
1556
bool
1557
gx_has_transfer(const gs_gstate *pgs, int num_comps)
1558
704k
{
1559
704k
    int k;
1560
1561
1.85M
    for (k = 0; k < num_comps; k++) {
1562
1.43M
        if (pgs->effective_transfer[k]->proc != gs_identity_transfer) {
1563
290k
            return(true);
1564
290k
        }
1565
1.43M
    }
1566
413k
    return(false);
1567
704k
}