Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/base/gximage.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 support */
18
#include "memory_.h"
19
#include "gx.h"
20
#include "gscspace.h"
21
#include "gserrors.h"
22
#include "gsmatrix.h"
23
#include "gsutil.h"
24
#include "gxcolor2.h"   /* for lookup map */
25
#include "gxiparam.h"
26
#include "stream.h"
27
28
/* ---------------- Generic image support ---------------- */
29
30
/* Structure descriptors */
31
public_st_gs_data_image();
32
public_st_gs_pixel_image();
33
34
/* Initialize the common parts of image structures. */
35
void
36
gs_image_common_t_init(gs_image_common_t * pic)
37
267k
{
38
267k
    gs_make_identity(&pic->ImageMatrix);
39
267k
}
40
void
41
gs_data_image_t_init(gs_data_image_t * pim, int num_components)
42
267k
{
43
267k
    int i;
44
45
267k
    gs_image_common_t_init((gs_image_common_t *) pim);
46
267k
    pim->Width = pim->Height = 0;
47
267k
    pim->BitsPerComponent = 1;
48
267k
    if (num_components >= 0) {
49
905k
        for (i = 0; i < num_components * 2; i += 2)
50
637k
            pim->Decode[i] = 0, pim->Decode[i + 1] = 1;
51
267k
    } else {
52
202
        for (i = 0; i < num_components * -2; i += 2)
53
101
            pim->Decode[i] = 1, pim->Decode[i + 1] = 0;
54
101
    }
55
267k
    pim->Interpolate = false;
56
267k
}
57
void
58
gs_pixel_image_t_init(gs_pixel_image_t * pim,
59
                      gs_color_space * color_space)
60
266k
{
61
266k
    int num_components;
62
63
266k
    if (color_space == 0 ||
64
266k
        (num_components =
65
223k
         gs_color_space_num_components(color_space)) < 0
66
266k
        )
67
43.0k
        num_components = 0;
68
266k
    gs_data_image_t_init((gs_data_image_t *) pim, num_components);
69
266k
    pim->format = gs_image_format_chunky;
70
266k
    pim->ColorSpace = color_space;
71
266k
    pim->CombineWithColor = false;
72
266k
    pim->override_in_smask = 0;
73
266k
}
74
75
/* Initialize the common part of an image-processing enumerator. */
76
int
77
gx_image_enum_common_init(gx_image_enum_common_t * piec,
78
                          const gs_data_image_t * pic,
79
                          const gx_image_enum_procs_t * piep,
80
                          gx_device * dev, int num_components,
81
                          gs_image_format_t format)
82
369k
{
83
369k
    int bpc = pic->BitsPerComponent;
84
369k
    int i;
85
86
369k
    piec->image_type = pic->type;
87
369k
    piec->procs = piep;
88
369k
    piec->dev = dev;
89
369k
    piec->id = gs_next_ids(dev->memory, 1);
90
369k
    piec->skipping = false;
91
369k
    switch (format) {
92
363k
        case gs_image_format_chunky:
93
363k
            piec->num_planes = 1;
94
363k
            piec->plane_depths[0] = bpc * num_components;
95
363k
            break;
96
6.34k
        case gs_image_format_component_planar:
97
6.34k
            piec->num_planes = num_components;
98
31.7k
            for (i = 0; i < num_components; ++i)
99
25.3k
                piec->plane_depths[i] = bpc;
100
6.34k
            break;
101
0
        case gs_image_format_bit_planar:
102
0
            piec->num_planes = bpc * num_components;
103
0
            for (i = 0; i < piec->num_planes; ++i)
104
0
                piec->plane_depths[i] = 1;
105
0
            break;
106
0
        default:
107
0
            return_error(gs_error_rangecheck);
108
369k
    }
109
758k
    for (i = 0; i < piec->num_planes; ++i)
110
388k
        piec->plane_widths[i] = pic->Width;
111
369k
    return 0;
112
369k
}
113
114
/* Process the next piece of an image with no source data. */
115
/* This procedure should never be called. */
116
int
117
gx_no_plane_data(gx_image_enum_common_t * info,
118
                 const gx_image_plane_t * planes, int height,
119
                 int *height_used)
120
0
{
121
0
    return_error(gs_error_Fatal);
122
0
}
123
124
/* Clean up after processing an image with no source data. */
125
/* This procedure may be called, but should do nothing. */
126
int
127
gx_ignore_end_image(gx_image_enum_common_t * info, bool draw_last)
128
0
{
129
0
    return 0;
130
0
}
131
132
/* ---------------- Client procedures ---------------- */
133
134
int
135
gx_image_data(gx_image_enum_common_t * info, const byte ** plane_data,
136
              int data_x, uint raster, int height)
137
0
{
138
0
    int num_planes = info->num_planes;
139
0
    gx_image_plane_t planes[GS_IMAGE_MAX_COMPONENTS];
140
0
    int i;
141
142
#ifdef DEBUG
143
    if (num_planes > GS_IMAGE_MAX_COMPONENTS) {
144
        lprintf2("num_planes=%d > GS_IMAGE_MAX_COMPONENTS=%d!\n",
145
                 num_planes, GS_IMAGE_MAX_COMPONENTS);
146
        return_error(gs_error_Fatal);
147
    }
148
#endif
149
0
    for (i = 0; i < num_planes; ++i) {
150
0
        planes[i].data = plane_data[i];
151
0
        planes[i].data_x = data_x;
152
0
        planes[i].raster = raster;
153
0
    }
154
0
    return gx_image_plane_data(info, planes, height);
155
0
}
156
157
int
158
gx_image_plane_data(gx_image_enum_common_t * info,
159
                    const gx_image_plane_t * planes, int height)
160
637k
{
161
637k
    int ignore_rows_used;
162
163
637k
    return gx_image_plane_data_rows(info, planes, height, &ignore_rows_used);
164
637k
}
165
166
int
167
gx_image_plane_data_rows(gx_image_enum_common_t * info,
168
                         const gx_image_plane_t * planes, int height,
169
                         int *rows_used)
170
4.51M
{
171
4.51M
    return info->procs->plane_data(info, planes, height, rows_used);
172
4.51M
}
173
174
int
175
gx_image_flush(gx_image_enum_common_t * info)
176
420k
{
177
420k
    int (*flush)(gx_image_enum_common_t *) = info->procs->flush;
178
179
420k
    return (flush ? flush(info) : 0);
180
420k
}
181
182
bool
183
gx_image_planes_wanted(const gx_image_enum_common_t *info, byte *wanted)
184
148k
{
185
148k
    bool (*planes_wanted)(const gx_image_enum_common_t *, byte *) =
186
148k
        info->procs->planes_wanted;
187
188
148k
    if (planes_wanted)
189
93.5k
        return planes_wanted(info, wanted);
190
54.7k
    else {
191
54.7k
        memset(wanted, 0xff, info->num_planes);
192
54.7k
        return true;
193
54.7k
    }
194
148k
}
195
196
int
197
gx_image_end(gx_image_enum_common_t * info, bool draw_last)
198
171k
{
199
171k
    return info->procs->end_image(info, draw_last);
200
171k
}
201
202
/* ---------------- Serialization ---------------- */
203
204
/*
205
 * Define dummy sput/sget/release procedures for image types that don't
206
 * implement these functions.
207
 */
208
209
int
210
gx_image_no_sput(const gs_image_common_t *pic, stream *s,
211
                 const gs_color_space **ppcs)
212
0
{
213
0
    return_error(gs_error_rangecheck);
214
0
}
215
216
int
217
gx_image_no_sget(gs_image_common_t *pic, stream *s,
218
                 gs_color_space *pcs)
219
0
{
220
0
    return_error(gs_error_rangecheck);
221
0
}
222
223
void
224
gx_image_default_release(gs_image_common_t *pic, gs_memory_t *mem)
225
0
{
226
0
    gs_free_object(mem, pic, "gx_image_default_release");
227
0
}
228
229
#ifdef DEBUG
230
static void
231
debug_b_print_matrix(const gs_pixel_image_t *pim)
232
{
233
    if_debug6('b', "      ImageMatrix=[%g %g %g %g %g %g]\n",
234
              pim->ImageMatrix.xx, pim->ImageMatrix.xy,
235
              pim->ImageMatrix.yx, pim->ImageMatrix.yy,
236
              pim->ImageMatrix.tx, pim->ImageMatrix.ty);
237
}
238
static void
239
debug_b_print_decode(const gs_pixel_image_t *pim, int num_decode)
240
{
241
    if (gs_debug_c('b')) {
242
        const char *str = "      Decode=[";
243
        int i;
244
245
        for (i = 0; i < num_decode; str = " ", ++i)
246
            dprintf2("%s%g", str, pim->Decode[i]);
247
        dputs("]\n");
248
    }
249
}
250
#else
251
916
#  define debug_b_print_matrix(pim) DO_NOTHING
252
329
#  define debug_b_print_decode(pim, num_decode) DO_NOTHING
253
#endif
254
255
/* Test whether an image has a default ImageMatrix. */
256
bool
257
gx_image_matrix_is_default(const gs_data_image_t *pid)
258
15.8k
{
259
15.8k
    return (is_xxyy(&pid->ImageMatrix) &&
260
15.8k
            pid->ImageMatrix.xx == pid->Width &&
261
15.8k
            pid->ImageMatrix.yy == -pid->Height &&
262
15.8k
            is_fzero(pid->ImageMatrix.tx) &&
263
15.8k
            pid->ImageMatrix.ty == pid->Height);
264
15.8k
}
265
266
/* Put a variable-length uint on a stream. */
267
void
268
sput_variable_uint(stream *s, uint w)
269
47.5k
{
270
56.0k
    for (; w > 0x7f; w >>= 7)
271
8.54k
        sputc(s, (byte)(w | 0x80));
272
47.5k
    sputc(s, (byte)w);
273
47.5k
}
274
275
/*
276
 * Write generic pixel image parameters.  The format is the following,
277
 * encoded as a variable-length uint in the usual way:
278
 *  xxxFEDCCBBBBA
279
 *      A = 0 if standard ImageMatrix, 1 if explicit ImageMatrix
280
 *      BBBB = BitsPerComponent - 1
281
 *      CC = format
282
 *      D = 0 if standard (0..1) Decode, 1 if explicit Decode
283
 *      E = Interpolate
284
 *      F = CombineWithColor
285
 *      xxx = extra information from caller
286
 */
287
130k
#define PI_ImageMatrix 0x001
288
130k
#define PI_BPC_SHIFT 1
289
114k
#define PI_BPC_MASK 0xf
290
130k
#define PI_FORMAT_SHIFT 5
291
114k
#define PI_FORMAT_MASK 0x3
292
130k
#define PI_Decode 0x080
293
114k
#define PI_Interpolate 0x100
294
114k
#define PI_CombineWithColor 0x200
295
130k
#define PI_BITS 10
296
/*
297
 *  Width, encoded as a variable-length uint
298
 *  Height, encoded ditto
299
 *  ImageMatrix (if A = 1), per gs_matrix_store/fetch
300
 *  Decode (if D = 1): blocks of up to 4 components
301
 *      aabbccdd, where each xx is decoded as:
302
 *    00 = default, 01 = swapped default,
303
 *    10 = (0,V), 11 = (U,V)
304
 *      non-defaulted components (up to 8 floats)
305
 */
306
int
307
gx_pixel_image_sput(const gs_pixel_image_t *pim, stream *s,
308
                    const gs_color_space **ppcs, int extra)
309
15.5k
{
310
15.5k
    const gs_color_space *pcs = pim->ColorSpace;
311
15.5k
    int bpc = pim->BitsPerComponent;
312
15.5k
    int num_components = gs_color_space_num_components(pcs);
313
15.5k
    int num_decode;
314
15.5k
    uint control = extra << PI_BITS;
315
15.5k
    float decode_default_1 = 1;
316
15.5k
    int i;
317
15.5k
    uint ignore;
318
319
    /* Construct the control word. */
320
321
15.5k
    if (!gx_image_matrix_is_default((const gs_data_image_t *)pim))
322
335
        control |= PI_ImageMatrix;
323
15.5k
    switch (pim->format) {
324
15.5k
    case gs_image_format_chunky:
325
15.5k
    case gs_image_format_component_planar:
326
15.5k
        switch (bpc) {
327
15.5k
        case 1: case 2: case 4: case 8: case 12: case 16: break;
328
1
        default: return_error(gs_error_rangecheck);
329
15.5k
        }
330
15.5k
        break;
331
15.5k
    case gs_image_format_bit_planar:
332
0
        if (bpc < 1 || bpc > 8)
333
0
            return_error(gs_error_rangecheck);
334
15.5k
    }
335
15.5k
    control |= (bpc - 1) << PI_BPC_SHIFT;
336
15.5k
    control |= pim->format << PI_FORMAT_SHIFT;
337
15.5k
    num_decode = num_components * 2;
338
15.5k
    if (gs_color_space_get_index(pcs) == gs_color_space_index_Indexed)
339
1.19k
        decode_default_1 = (float)pcs->params.indexed.hival;
340
79.0k
    for (i = 0; i < num_decode; ++i)
341
63.7k
        if (pim->Decode[i] != DECODE_DEFAULT(i, decode_default_1)) {
342
211
            control |= PI_Decode;
343
211
            break;
344
211
        }
345
15.5k
    if (pim->Interpolate)
346
0
        control |= PI_Interpolate;
347
15.5k
    if (pim->CombineWithColor)
348
0
        control |= PI_CombineWithColor;
349
350
    /* Write the encoding on the stream. */
351
352
15.5k
    if_debug3('b', "[b]put control=0x%x, Width=%d, Height=%d\n",
353
15.5k
              control, pim->Width, pim->Height);
354
15.5k
    sput_variable_uint(s, control);
355
15.5k
    sput_variable_uint(s, (uint)pim->Width);
356
15.5k
    sput_variable_uint(s, (uint)pim->Height);
357
15.5k
    if (control & PI_ImageMatrix) {
358
334
        debug_b_print_matrix(pim);
359
334
        sput_matrix(s, &pim->ImageMatrix);
360
334
    }
361
15.5k
    if (control & PI_Decode) {
362
211
        int i;
363
211
        uint dflags = 1;
364
211
        float decode[8];
365
211
        int di = 0;
366
367
211
        debug_b_print_decode(pim, num_decode);
368
446
        for (i = 0; i < num_decode; i += 2) {
369
235
            float u = pim->Decode[i], v = pim->Decode[i + 1];
370
235
            float dv = DECODE_DEFAULT(i + 1, decode_default_1);
371
372
235
            if (dflags >= 0x100) {
373
0
                sputc(s, (byte)(dflags & 0xff));
374
0
                sputs(s, (const byte *)decode, di * sizeof(float), &ignore);
375
0
                dflags = 1;
376
0
                di = 0;
377
0
            }
378
235
            dflags <<= 2;
379
235
            if (u == 0 && v == dv)
380
235
                DO_NOTHING;
381
235
            else if (u == dv && v == 0)
382
49
                dflags += 1;
383
186
            else {
384
186
                if (u != 0) {
385
0
                    dflags++;
386
0
                    decode[di++] = u;
387
0
                }
388
186
                dflags += 2;
389
186
                decode[di++] = v;
390
186
            }
391
235
        }
392
211
        sputc(s, (byte)((dflags << (8 - num_decode)) & 0xff));
393
211
        sputs(s, (const byte *)decode, di * sizeof(float), &ignore);
394
211
    }
395
15.5k
    *ppcs = pcs;
396
15.5k
    return 0;
397
15.5k
}
398
399
/* Set an image's ImageMatrix to the default. */
400
void
401
gx_image_matrix_set_default(gs_data_image_t *pid)
402
114k
{
403
114k
    pid->ImageMatrix.xx = (float)pid->Width;
404
114k
    pid->ImageMatrix.xy = 0;
405
114k
    pid->ImageMatrix.yx = 0;
406
114k
    pid->ImageMatrix.yy = (float)-pid->Height;
407
114k
    pid->ImageMatrix.tx = 0;
408
114k
    pid->ImageMatrix.ty = (float)pid->Height;
409
114k
}
410
411
/* Get a variable-length uint from a stream. */
412
int
413
sget_variable_uint(stream *s, uint *pw)
414
344k
{
415
344k
    uint w = 0;
416
344k
    int shift = 0;
417
344k
    int ch;
418
419
451k
    for (; (ch = sgetc(s)) >= 0x80; shift += 7)
420
106k
        w += (ch & 0x7f) << shift;
421
344k
    if (ch < 0)
422
0
        return_error(gs_error_ioerror);
423
344k
    *pw = w + (ch << shift);
424
344k
    return 0;
425
344k
}
426
427
/*
428
 * Read generic pixel image parameters.
429
 */
430
int
431
gx_pixel_image_sget(gs_pixel_image_t *pim, stream *s,
432
                    gs_color_space *pcs)
433
114k
{
434
114k
    uint control;
435
114k
    float decode_default_1 = 1;
436
114k
    int num_components, num_decode;
437
114k
    int i;
438
114k
    int code;
439
114k
    uint ignore;
440
441
114k
    if ((code = sget_variable_uint(s, &control)) < 0 ||
442
114k
        (code = sget_variable_uint(s, (uint *)&pim->Width)) < 0 ||
443
114k
        (code = sget_variable_uint(s, (uint *)&pim->Height)) < 0
444
114k
        )
445
0
        return code;
446
114k
    if_debug3('b', "[b]get control=0x%x, Width=%d, Height=%d\n",
447
114k
              control, pim->Width, pim->Height);
448
114k
    if (control & PI_ImageMatrix) {
449
582
        if ((code = sget_matrix(s, &pim->ImageMatrix)) < 0)
450
0
            return code;
451
582
        debug_b_print_matrix(pim);
452
582
    } else
453
114k
        gx_image_matrix_set_default((gs_data_image_t *)pim);
454
114k
    pim->BitsPerComponent = ((control >> PI_BPC_SHIFT) & PI_BPC_MASK) + 1;
455
114k
    pim->format = (control >> PI_FORMAT_SHIFT) & PI_FORMAT_MASK;
456
114k
    pim->ColorSpace = pcs;
457
114k
    num_components = gs_color_space_num_components(pcs);
458
114k
    num_decode = num_components * 2;
459
114k
    if (gs_color_space_get_index(pcs) == gs_color_space_index_Indexed)
460
948
        decode_default_1 = (float)pcs->params.indexed.hival;
461
114k
    if (control & PI_Decode) {
462
118
        uint dflags = 0x10000;
463
118
        float *dp = pim->Decode;
464
465
260
        for (i = 0; i < num_decode; i += 2, dp += 2, dflags <<= 2) {
466
142
            if (dflags >= 0x10000) {
467
118
                dflags = sgetc(s) + 0x100;
468
118
                if (dflags < 0x100)
469
0
                    return_error(gs_error_ioerror);
470
118
            }
471
142
            switch (dflags & 0xc0) {
472
0
            case 0x00:
473
0
                dp[0] = 0, dp[1] = DECODE_DEFAULT(i + 1, decode_default_1);
474
0
                break;
475
44
            case 0x40:
476
44
                dp[0] = DECODE_DEFAULT(i + 1, decode_default_1), dp[1] = 0;
477
44
                break;
478
98
            case 0x80:
479
98
                dp[0] = 0;
480
98
                if (sgets(s, (byte *)(dp + 1), sizeof(float), &ignore) < 0)
481
0
                    return_error(gs_error_ioerror);
482
98
                break;
483
98
            case 0xc0:
484
0
                if (sgets(s, (byte *)dp, sizeof(float) * 2, &ignore) < 0)
485
0
                    return_error(gs_error_ioerror);
486
0
                break;
487
142
            }
488
142
        }
489
118
        debug_b_print_decode(pim, num_decode);
490
114k
    } else {
491
546k
        for (i = 0; i < num_decode; ++i)
492
431k
            pim->Decode[i] = DECODE_DEFAULT(i, decode_default_1);
493
114k
    }
494
114k
    pim->Interpolate = (control & PI_Interpolate) != 0;
495
114k
    pim->CombineWithColor = (control & PI_CombineWithColor) != 0;
496
114k
    return control >> PI_BITS;
497
114k
}
498
499
/*
500
 * Release a pixel image object.  Currently this just frees the object.
501
 */
502
void
503
gx_pixel_image_release(gs_pixel_image_t *pic, gs_memory_t *mem)
504
0
{
505
0
    gx_image_default_release((gs_image_common_t *)pic, mem);
506
0
}