Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/gxidata.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2021 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.,  1305 Grant Avenue - Suite 200, Novato,
13
   CA 94945, U.S.A., +1(415)492-9861, for further information.
14
*/
15
16
17
/* Generic image enumeration and cleanup */
18
#include "gx.h"
19
#include "memory_.h"
20
#include "gserrors.h"
21
#include "gxdevice.h"
22
#include "gxcpath.h"
23
#include "gximage.h"
24
#include "gsicc_cache.h"
25
#ifdef WITH_CAL
26
#include "cal.h"
27
#endif
28
29
/* Forward declarations */
30
static void update_strip(gx_image_enum *penum);
31
static void repack_bit_planes(const gx_image_plane_t *src_planes,
32
                               const ulong *offsets, int num_planes,
33
                               byte *buffer, int width,
34
                               const sample_lookup_t * ptab, int spread);
35
static gx_device *setup_image_device(const gx_image_enum *penum);
36
37
/* Process the next piece of an ImageType 1 image. */
38
int
39
gx_image1_plane_data(gx_image_enum_common_t * info,
40
                     const gx_image_plane_t * planes, int height,
41
                     int *rows_used)
42
5.06M
{
43
5.06M
    gx_image_enum *penum = (gx_image_enum *) info;
44
5.06M
    gx_device *dev;
45
5.06M
    const int y = penum->y;
46
5.06M
    int y_end = min(y + height, penum->rect.h);
47
5.06M
    int width_spp = penum->rect.w * penum->spp;
48
5.06M
    int num_planes = penum->num_planes;
49
5.06M
    int num_components_per_plane = 1;
50
51
5.06M
#define BCOUNT(plane)   /* bytes per data row */\
52
5.14M
  (((penum->rect.w + (plane).data_x) * penum->spp * penum->bps / num_planes\
53
5.14M
    + 7) >> 3)
54
55
5.06M
    fixed adjust = penum->adjust;
56
5.06M
    ulong offsets[GS_IMAGE_MAX_COMPONENTS];
57
5.06M
    int ignore_data_x;
58
5.06M
    bool bit_planar = penum->num_planes > penum->spp;
59
5.06M
    int code;
60
61
5.06M
    if (height == 0) {
62
0
        *rows_used = 0;
63
0
        return 0;
64
0
    }
65
5.06M
    dev = setup_image_device(penum);
66
67
    /* Now render complete rows. */
68
69
5.06M
    if (penum->used.y) {
70
        /*
71
         * Processing was interrupted by an error.  Skip over rows
72
         * already processed.
73
         */
74
0
        int px;
75
76
0
        for (px = 0; px < num_planes; ++px)
77
0
            offsets[px] = (size_t)planes[px].raster * penum->used.y;
78
0
        penum->used.y = 0;
79
0
    } else
80
5.06M
        memset(offsets, 0, num_planes * sizeof(offsets[0]));
81
5.06M
    if (num_planes == 1 && penum->plane_depths[0] != penum->bps) {
82
        /* A single plane with multiple components. */
83
2.57M
        num_components_per_plane = penum->plane_depths[0] / penum->bps;
84
2.57M
    }
85
12.1M
    for (; penum->y < y_end; penum->y++) {
86
7.06M
        int px;
87
7.06M
        const byte *buffer;
88
7.06M
        int sourcex;
89
7.06M
        int x_used = penum->used.x;
90
7.06M
        int skip = 0;
91
92
        /* Bump DDA's if it doesn't cause overflow */
93
7.06M
        penum->cur.x = dda_current(penum->dda.row.x);
94
7.06M
        if (max_int - any_abs(penum->dda.row.x.step.dQ) > any_abs(penum->cur.x))
95
7.06M
            dda_next(penum->dda.row.x);
96
7.06M
        penum->cur.y = dda_current(penum->dda.row.y);
97
7.06M
        if (max_int - any_abs(penum->dda.row.y.step.dQ) > any_abs(penum->cur.y))
98
7.06M
            dda_next(penum->dda.row.y);
99
100
7.06M
        if (penum->interpolate == interp_off) {
101
7.06M
            if (penum->skip_next_line) {
102
1.82M
                if (penum->skip_next_line(penum, dev))
103
49.9k
                    goto mt;
104
5.24M
            } else {
105
5.24M
                switch (penum->posture) {
106
5.18M
                    case image_portrait:
107
5.18M
                        {   /* Precompute integer y and height, */
108
                            /* and check for clipping. */
109
5.18M
                            fixed yc = penum->cur.y,
110
5.18M
                                yn = dda_current(penum->dda.row.y);
111
112
5.18M
                            if (yn < yc) {
113
195k
                                fixed temp = yn;
114
115
195k
                                yn = yc;
116
195k
                                yc = temp;
117
195k
                            }
118
5.18M
                            yc -= adjust;
119
5.18M
                            if (yc >= penum->clip_outer.q.y)
120
659k
                                goto mt;
121
4.52M
                            yn += adjust;
122
4.52M
                            if (yn <= penum->clip_outer.p.y)
123
495k
                                goto mt;
124
4.02M
                            penum->yci = fixed2int_pixround_perfect(yc);
125
4.02M
                            penum->hci = fixed2int_pixround_perfect(yn) - penum->yci;
126
4.02M
                            if (penum->hci == 0)
127
913k
                                goto mt;
128
4.02M
                            if_debug2m('b', penum->memory, "[b]yci=%d, hci=%d\n",
129
3.11M
                                       penum->yci, penum->hci);
130
3.11M
                        }
131
0
                        break;
132
10.5k
                    case image_landscape:
133
10.5k
                        {   /* Check for no pixel centers in x. */
134
10.5k
                            fixed xc = penum->cur.x,
135
10.5k
                                xn = dda_current(penum->dda.row.x);
136
137
10.5k
                            if (xn < xc) {
138
223
                                fixed temp = xn;
139
140
223
                                xn = xc;
141
223
                                xc = temp;
142
223
                            }
143
10.5k
                            xc -= adjust;
144
10.5k
                            if (xc >= penum->clip_outer.q.x)
145
0
                                goto mt;
146
10.5k
                            xn += adjust;
147
10.5k
                            if (xn <= penum->clip_outer.p.x)
148
1
                                goto mt;
149
10.5k
                            penum->xci = fixed2int_pixround_perfect(xc);
150
10.5k
                            penum->wci = fixed2int_pixround_perfect(xn) - penum->xci;
151
10.5k
                            if (penum->wci == 0)
152
3.33k
                                goto mt;
153
10.5k
                            if_debug2m('b', penum->memory, "[b]xci=%d, wci=%d\n",
154
7.24k
                                       penum->xci, penum->wci);
155
7.24k
                        }
156
0
                        break;
157
45.5k
                    case image_skewed:
158
45.5k
                        ;
159
5.24M
                }
160
5.24M
            }
161
7.06M
        }
162
4.94M
        if (0)
163
0
        {
164
2.12M
        mt:
165
2.12M
            skip = 1;
166
2.12M
        }
167
7.06M
        if (bit_planar) {
168
            /* Repack the bit planes into byte-wide samples. */
169
170
0
            buffer = penum->buffer;
171
0
            sourcex = 0;
172
0
            if (!skip)
173
0
                for (px = 0; px < num_planes; px += penum->bps)
174
0
                    repack_bit_planes(planes, offsets, penum->bps, penum->buffer,
175
0
                                      penum->rect.w, &penum->map[px].table,
176
0
                                      penum->spread);
177
0
            for (px = 0; px < num_planes; ++px)
178
0
                offsets[px] += planes[px].raster;
179
7.06M
        } else {
180
            /*
181
             * Normally, we unpack the data into the buffer, but if
182
             * there is only one plane and we don't need to expand the
183
             * input samples, we may use the data directly.
184
             */
185
7.06M
            sourcex = planes[0].data_x;
186
7.06M
            if (!skip)
187
4.94M
                buffer =
188
4.94M
                    (*penum->unpack)(penum->buffer, &sourcex,
189
4.94M
                                     planes[0].data + offsets[0],
190
4.94M
                                     planes[0].data_x, BCOUNT(planes[0]),
191
4.94M
                                     &penum->map[0], penum->spread, num_components_per_plane);
192
2.12M
            else
193
2.12M
                buffer = NULL;
194
195
7.06M
            offsets[0] += planes[0].raster;
196
7.27M
            for (px = 1; px < num_planes; ++px) {
197
207k
                if (!skip)
198
207k
                    (*penum->unpack)(penum->buffer + (px << penum->log2_xbytes),
199
207k
                                     &ignore_data_x,
200
207k
                                     planes[px].data + offsets[px],
201
207k
                                     planes[px].data_x, BCOUNT(planes[px]),
202
207k
                                     &penum->map[px], penum->spread, 1);
203
207k
                offsets[px] += planes[px].raster;
204
207k
            }
205
7.06M
        }
206
#ifdef DEBUG
207
        if (gs_debug_c('b'))
208
            dmprintf1(dev->memory, "[b]image1 y=%d\n", y);
209
        if (gs_debug_c('B')) {
210
            int i, n = width_spp;
211
            byte *buftemp = (buffer == NULL) ? penum->buffer : (byte *)buffer;
212
213
            if (penum->bps > 8)
214
                n *= 2;
215
            else if (penum->bps == 1 && penum->unpack_bps == 8)
216
                n = (n + 7) / 8;
217
            dmlputs(dev->memory, "[B]row:");
218
            for (i = 0; i < n; i++)
219
                dmprintf1(dev->memory, " %02x", buftemp[i]);
220
            dmputs(dev->memory, "\n");
221
        }
222
#endif
223
7.06M
        if (!skip)
224
4.94M
        {
225
4.94M
            update_strip(penum);
226
4.94M
            if (x_used) {
227
                /*
228
                 * Processing was interrupted by an error.  Skip over pixels
229
                 * already processed.
230
                 */
231
0
                dda_advance(penum->dda.pixel0.x, x_used);
232
0
                dda_advance(penum->dda.pixel0.y, x_used);
233
0
                penum->used.x = 0;
234
0
            }
235
4.94M
            if_debug2m('b', penum->memory, "[b]pixel0 x=%g, y=%g\n",
236
4.94M
                       fixed2float(dda_current(penum->dda.pixel0.x)),
237
4.94M
                       fixed2float(dda_current(penum->dda.pixel0.y)));
238
4.94M
            code = (*penum->render)(penum, buffer, sourcex + x_used,
239
4.94M
                                    width_spp - x_used * penum->spp, 1, dev);
240
4.94M
            if (code < 0) {
241
                /* Error or interrupt, restore original state. */
242
0
                penum->used.x += x_used;
243
0
                if (!penum->used.y) {
244
0
                    dda_previous(penum->dda.row.x);
245
0
                    dda_previous(penum->dda.row.y);
246
0
                    dda_translate(penum->dda.strip.x,
247
0
                                  penum->prev.x - penum->cur.x);
248
0
                    dda_translate(penum->dda.strip.y,
249
0
                                  penum->prev.y - penum->cur.y);
250
0
                }
251
0
                goto out;
252
0
            }
253
4.94M
            penum->prev = penum->cur;
254
4.94M
        }
255
7.06M
    }
256
5.06M
    if (penum->y < penum->rect.h) {
257
4.74M
        code = 0;
258
4.74M
    } else {
259
        /* End of input data.  Render any left-over buffered data. */
260
326k
        code = gx_image1_flush(info);
261
326k
        if (code >= 0)
262
326k
            code = 1;
263
326k
    }
264
5.06M
out:
265
    /* Note that caller must call end_image */
266
    /* for both error and normal termination. */
267
5.06M
    *rows_used = penum->y - y;
268
5.06M
    return code;
269
5.06M
}
270
271
/* Flush any buffered data. */
272
int
273
gx_image1_flush(gx_image_enum_common_t * info)
274
674k
{
275
674k
    gx_image_enum *penum = (gx_image_enum *)info;
276
674k
    int width_spp = penum->rect.w * penum->spp;
277
674k
    fixed adjust = penum->adjust;
278
279
674k
    penum->cur.x = dda_current(penum->dda.row.x);
280
674k
    penum->cur.y = dda_current(penum->dda.row.y);
281
674k
    switch (penum->posture) {
282
670k
        case image_portrait:
283
670k
            {
284
670k
                fixed yc = penum->cur.y;
285
286
670k
                penum->yci = fixed2int_rounded(yc - adjust);
287
670k
                penum->hci = fixed2int_rounded(yc + adjust) - penum->yci;
288
670k
            }
289
670k
            break;
290
1.35k
        case image_landscape:
291
1.35k
            {
292
1.35k
                fixed xc = penum->cur.x;
293
294
1.35k
                penum->xci = fixed2int_rounded(xc - adjust);
295
1.35k
                penum->wci = fixed2int_rounded(xc + adjust) - penum->xci;
296
1.35k
            }
297
1.35k
            break;
298
3.09k
        case image_skewed:  /* pacify compilers */
299
3.09k
            ;
300
674k
    }
301
674k
    update_strip(penum);
302
674k
    penum->prev = penum->cur;
303
674k
    return (*penum->render)(penum, NULL, 0, width_spp, 0,
304
674k
                            setup_image_device(penum));
305
674k
}
306
307
/* Update the strip DDA when moving to a new row. */
308
static void
309
update_strip(gx_image_enum *penum)
310
5.61M
{
311
312
5.61M
#if 1
313
    /* Old code. */
314
5.61M
    dda_translate(penum->dda.strip.x, penum->cur.x - penum->prev.x);
315
5.61M
    dda_translate(penum->dda.strip.y, penum->cur.y - penum->prev.y);
316
5.61M
    penum->dda.pixel0 = penum->dda.strip;
317
#else
318
    /* A better precision with stromng dda_advance -
319
       doesn't work becauae gx_image1_plane_data
320
       doesn't call it at each step. */
321
    gx_dda_fixed_point temp;
322
323
    temp.x.state = penum->dda.strip.x.state;
324
    temp.y.state = penum->dda.strip.y.state;
325
    temp.x.step = penum->dda.row.x.step;
326
    temp.y.step = penum->dda.row.y.step;
327
    dda_next(temp.x);
328
    dda_next(temp.y);
329
    penum->dda.strip.x.state = temp.x.state;
330
    penum->dda.strip.y.state = temp.y.state;
331
    penum->dda.pixel0 = penum->dda.strip;
332
#endif
333
5.61M
}
334
335
/*
336
 * Repack 1 to 8 individual bit planes into 8-bit samples.
337
 * buffer is aligned, and includes padding to an 8-byte boundary.
338
 * This procedure repacks one row, so the only relevant members of
339
 * src_planes are data and data_x (not raster).
340
 */
341
static void
342
repack_bit_planes(const gx_image_plane_t *src_planes, const ulong *offsets,
343
                  int num_planes, byte *buffer, int width,
344
                  const sample_lookup_t * ptab, int spread)
345
0
{
346
0
    gx_image_plane_t planes[8];
347
0
    byte *zeros = 0;
348
0
    byte *dest = buffer;
349
0
    int any_data_x = 0;
350
0
    bool direct = (spread == 1 && ptab->lookup8[0] == 0 &&
351
0
                   ptab->lookup8[255] == 255);
352
0
    int pi, x;
353
0
    gx_image_plane_t *pp;
354
355
    /*
356
     * Set up the row pointers, taking data_x and null planes into account.
357
     * If there are any null rows, we need to create a block of zeros in
358
     * order to avoid tests in the loop.
359
     */
360
0
    for (pi = 0, pp = planes; pi < num_planes; ++pi, ++pp)
361
0
        if (src_planes[pi].data == 0) {
362
0
            if (!zeros) {
363
0
                zeros = buffer + width - ((width + 7) >> 3);
364
0
            }
365
0
            pp->data = zeros;
366
0
            pp->data_x = 0;
367
0
        } else {
368
0
            int dx = src_planes[pi].data_x;
369
370
0
            pp->data = src_planes[pi].data + (dx >> 3) + offsets[pi];
371
0
            any_data_x |= (pp->data_x = dx & 7);
372
0
        }
373
0
    if (zeros)
374
0
        memset(zeros, 0, buffer + width - zeros);
375
376
    /*
377
     * Now process the data, in blocks of one input byte column
378
     * (8 output bytes).
379
     */
380
0
    for (x = 0; x < width; x += 8) {
381
0
        bits32 w0 = 0, w1 = 0;
382
#if ARCH_IS_BIG_ENDIAN
383
        static const bits32 expand[16] = {
384
            0x00000000, 0x00000001, 0x00000100, 0x00000101,
385
            0x00010000, 0x00010001, 0x00010100, 0x00010101,
386
            0x01000000, 0x01000001, 0x01000100, 0x01000101,
387
            0x01010000, 0x01010001, 0x01010100, 0x01010101
388
        };
389
#else
390
0
        static const bits32 expand[16] = {
391
0
            0x00000000, 0x01000000, 0x00010000, 0x01010000,
392
0
            0x00000100, 0x01000100, 0x00010100, 0x01010100,
393
0
            0x00000001, 0x01000001, 0x00010001, 0x01010001,
394
0
            0x00000101, 0x01000101, 0x00010101, 0x01010101
395
0
        };
396
0
#endif
397
398
0
        if (any_data_x) {
399
0
            for (pi = 0, pp = planes; pi < num_planes; ++pi, ++pp) {
400
0
                uint b = *(pp->data++);
401
0
                int dx = pp->data_x;
402
403
0
                if (dx) {
404
0
                    b <<= dx;
405
0
                    if (x + 8 - dx < width)
406
0
                        b += *pp->data >> (8 - dx);
407
0
                }
408
0
                w0 = (w0 << 1) | expand[b >> 4];
409
0
                w1 = (w1 << 1) | expand[b & 0xf];
410
0
            }
411
0
        } else {
412
0
            for (pi = 0, pp = planes; pi < num_planes; ++pi, ++pp) {
413
0
                uint b = *(pp->data++);
414
415
0
                w0 = (w0 << 1) | expand[b >> 4];
416
0
                w1 = (w1 << 1) | expand[b & 0xf];
417
0
            }
418
0
        }
419
        /*
420
         * We optimize spread == 1 and identity ptab together, although
421
         * we could subdivide these 2 cases into 4 if we wanted.
422
         */
423
0
        if (direct) {
424
0
            ((bits32 *)dest)[0] = w0;
425
0
            ((bits32 *)dest)[1] = w1;
426
0
            dest += 8;
427
0
        } else {
428
0
#define MAP_BYTE(v) (ptab->lookup8[(byte)(v)])
429
0
            dest[0] = MAP_BYTE(w0 >> 24); dest += spread;
430
0
            dest[1] = MAP_BYTE(w0 >> 16); dest += spread;
431
0
            dest[2] = MAP_BYTE(w0 >> 8); dest += spread;
432
0
            dest[3] = MAP_BYTE(w0); dest += spread;
433
0
            dest[4] = MAP_BYTE(w1 >> 24); dest += spread;
434
0
            dest[5] = MAP_BYTE(w1 >> 16); dest += spread;
435
0
            dest[6] = MAP_BYTE(w1 >> 8); dest += spread;
436
0
            dest[7] = MAP_BYTE(w1); dest += spread;
437
0
#undef MAP_BYTE
438
0
        }
439
0
    }
440
0
}
441
442
/* Set up the device for drawing an image. */
443
static gx_device *
444
setup_image_device(const gx_image_enum *penum)
445
5.74M
{
446
5.74M
    gx_device *dev = penum->dev;
447
448
5.74M
    if (penum->clip_dev) {
449
2.70M
        gx_device_clip *cdev = penum->clip_dev;
450
451
2.70M
        gx_device_set_target((gx_device_forward *)cdev, dev);
452
2.70M
        dev = (gx_device *) cdev;
453
2.70M
    }
454
5.74M
    if (penum->rop_dev) {
455
0
        gx_device_rop_texture *rtdev = penum->rop_dev;
456
457
0
        gx_device_set_target((gx_device_forward *)rtdev, dev);
458
0
        dev = (gx_device *) rtdev;
459
0
    }
460
5.74M
    return dev;
461
5.74M
}
462
463
/* Clean up by releasing the buffers. */
464
/* Currently we ignore draw_last. */
465
int
466
gx_image1_end_image(gx_image_enum_common_t * info, bool draw_last)
467
330k
{
468
330k
    gx_image_enum *penum = (gx_image_enum *) info;
469
330k
    gs_memory_t *mem = penum->memory;
470
330k
    stream_image_scale_state *scaler = penum->scaler;
471
472
330k
    if_debug2m('b', penum->memory, "[b]%send_image, y=%d\n",
473
330k
               (penum->y < penum->rect.h ? "premature " : ""), penum->y);
474
330k
    if (draw_last) {
475
330k
        int code = gx_image_flush(info);
476
477
330k
        if (code < 0)
478
0
            return code;
479
330k
    }
480
481
330k
    if (penum->tpr_state != NULL) {
482
141k
        transform_pixel_region_data data;
483
141k
        gx_device *dev = penum->dev;
484
141k
        if (penum->clip_dev)
485
28.9k
            dev = (gx_device *)penum->clip_dev;
486
141k
        if (penum->rop_dev)
487
0
            dev = (gx_device *)penum->rop_dev;
488
141k
        data.state = penum->tpr_state;
489
141k
        dev_proc(dev, transform_pixel_region)(dev, transform_pixel_region_end, &data);
490
141k
    }
491
    /* release the reference to the target */
492
330k
    if ( penum->rop_dev )
493
0
        gx_device_set_target((gx_device_forward *)penum->rop_dev, NULL);
494
330k
    if ( penum->clip_dev )
495
72.2k
        gx_device_set_target((gx_device_forward *)penum->clip_dev, NULL);
496
    /* it is not clear (to me) why these are freed explicitly instead
497
       of using reference counting */
498
330k
    gs_free_object(mem, penum->rop_dev, "image RasterOp");
499
330k
    gs_free_object(mem, penum->clip_dev, "image clipper");
500
501
330k
    if (scaler != 0) {
502
0
        (*scaler->templat->release) ((stream_state *) scaler);
503
0
        gs_free_object(mem, scaler, "image scaler state");
504
0
    }
505
330k
    if (penum->icc_link != NULL) {
506
236k
        gsicc_release_link(penum->icc_link);
507
236k
    }
508
330k
    if (penum->color_cache != NULL) {
509
67
        gs_free_object(mem, penum->color_cache->device_contone,
510
67
                        "device_contone");
511
67
        gs_free_object(mem, penum->color_cache->is_transparent,
512
67
                       "image is_transparent");
513
67
        gs_free_object(mem, penum->color_cache, "image color cache");
514
67
    }
515
330k
    if (penum->thresh_buffer != NULL) {
516
2.40k
        gs_free_object(mem, penum->thresh_buffer, "image thresh_buffer");
517
2.40k
    }
518
330k
    if (penum->ht_buffer != NULL) {
519
2.40k
        gs_free_object(mem, penum->ht_buffer, "image ht_buffer");
520
2.40k
    }
521
330k
    if (penum->clues != NULL) {
522
93.8k
        gs_free_object(mem,penum->clues, "image clues");
523
93.8k
    }
524
525
    /* decrement this ref that was incremented in gx_image_enum_begin() */
526
330k
    rc_decrement_only(penum->pcs, "pcs");
527
330k
    penum->pcs = NULL;
528
529
330k
    gs_free_object(mem, penum->line, "image line");
530
330k
    gs_free_object(mem, penum->buffer, "image buffer");
531
532
#ifdef WITH_CAL
533
    if (penum->cal_ht != NULL) {
534
        cal_halftone_fin(penum->cal_ht, mem->non_gc_memory);
535
    }
536
#endif
537
330k
    gx_image_free_enum(&info);
538
330k
    return 0;
539
330k
}