Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gximage4.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 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
/* ImageType 4 image implementation */
18
#include "memory_.h"
19
#include "gx.h"
20
#include "gserrors.h"
21
#include "gscspace.h"
22
#include "gsiparm4.h"
23
#include "gxiparam.h"
24
#include "gximage.h"
25
#include "stream.h"
26
27
/* Forward references */
28
static dev_proc_begin_typed_image(gx_begin_image4);
29
30
/* Structure descriptor */
31
private_st_gs_image4();
32
33
/* Define the image type for ImageType 4 images. */
34
static image_proc_sput(gx_image4_sput);
35
static image_proc_sget(gx_image4_sget);
36
static image_proc_release(gx_image4_release);
37
const gx_image_type_t gs_image_type_4 = {
38
    &st_gs_image4, gx_begin_image4,
39
    gx_image4_sput, gx_image4_sget, gx_image4_release, 4
40
};
41
/*
42
 * The implementation is shared with ImageType 1, so we don't need our own
43
 * enum_procs.
44
 */
45
/*
46
  static const gx_image_enum_procs_t image4_enum_procs = {
47
    gx_image1_plane_data, gx_image1_end_image
48
  };
49
*/
50
51
/* Initialize an ImageType 4 image. */
52
void
53
gs_image4_t_init(gs_image4_t * pim, gs_color_space * color_space)
54
181
{
55
181
    gs_pixel_image_t_init((gs_pixel_image_t *) pim, color_space);
56
181
    pim->type = &gs_image_type_4;
57
181
    pim->MaskColor_is_range = false;
58
181
    pim->image_parent_type = gs_image_type4;
59
181
}
60
61
/* Start processing an ImageType 4 image. */
62
static int
63
gx_begin_image4(gx_device * dev,
64
                const gs_gstate * pgs, const gs_matrix * pmat,
65
                const gs_image_common_t * pic, const gs_int_rect * prect,
66
                const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
67
                gs_memory_t * mem, gx_image_enum_common_t ** pinfo)
68
174
{
69
174
    gx_image_enum *penum = NULL;
70
174
    const gs_image4_t *pim = (const gs_image4_t *)pic;
71
174
    int code = gx_image_enum_alloc(pic, prect, mem, &penum);
72
73
174
    if (code < 0)
74
0
        return code;
75
174
    penum->alpha = gs_image_alpha_none;
76
174
    penum->masked = false;
77
174
    penum->adjust = fixed_0;
78
174
    penum->image_parent_type = gs_image_type4;
79
    /* Check that MaskColor values are within the valid range. */
80
174
    {
81
174
        bool opaque = false;
82
174
        uint max_value = (1 << pim->BitsPerComponent) - 1;
83
174
        int spp = cs_num_components(pim->ColorSpace);
84
174
        int i;
85
86
674
        for (i = 0; i < spp * 2; i += 2) {
87
500
            uint c0, c1;
88
89
500
            if (pim->MaskColor_is_range)
90
500
                c0 = pim->MaskColor[i], c1 = pim->MaskColor[i + 1];
91
0
            else
92
0
                c0 = c1 = pim->MaskColor[i >> 1];
93
94
500
            if ((c0 | c1) > max_value) {
95
0
                gs_free_object(mem, penum, "gx_begin_image4");
96
0
                return_error(gs_error_rangecheck);
97
0
            }
98
500
            if (c0 > c1) {
99
0
                opaque = true; /* pixel can never match mask color */
100
0
                break;
101
0
            }
102
500
            penum->mask_color.values[i] = c0;
103
500
            penum->mask_color.values[i + 1] = c1;
104
500
        }
105
174
        penum->use_mask_color = !opaque;
106
174
    }
107
0
    code = gx_image_enum_begin(dev, pgs, pmat, pic, pdcolor, pcpath, mem,
108
174
                               penum);
109
174
    if (code >= 0)
110
174
        *pinfo = (gx_image_enum_common_t *)penum;
111
0
    else {
112
        /* penum is freed in by gx_image_enum_begin */
113
0
        *pinfo = NULL;
114
0
    }
115
174
    return code;
116
174
}
117
118
/* Serialization */
119
120
static int
121
gx_image4_sput(const gs_image_common_t *pic, stream *s,
122
               const gs_color_space **ppcs)
123
0
{
124
0
    const gs_image4_t *pim = (const gs_image4_t *)pic;
125
0
    bool is_range = pim->MaskColor_is_range;
126
0
    int code = gx_pixel_image_sput((const gs_pixel_image_t *)pim, s, ppcs,
127
0
                                   is_range);
128
0
    int num_values =
129
0
        gs_color_space_num_components(pim->ColorSpace) * (is_range ? 2 : 1);
130
0
    int i;
131
132
0
    if (code < 0)
133
0
        return code;
134
0
    for (i = 0; i < num_values; ++i)
135
0
        sput_variable_uint(s, pim->MaskColor[i]);
136
0
    *ppcs = pim->ColorSpace;
137
0
    return 0;
138
0
}
139
140
static int
141
gx_image4_sget(gs_image_common_t *pic, stream *s,
142
               gs_color_space *pcs)
143
0
{
144
0
    gs_image4_t *const pim = (gs_image4_t *)pic;
145
0
    int num_values;
146
0
    int i;
147
0
    int code = gx_pixel_image_sget((gs_pixel_image_t *)pim, s, pcs);
148
149
0
    if (code < 0)
150
0
        return code;
151
0
    pim->type = &gs_image_type_4;
152
0
    pim->MaskColor_is_range = code;
153
0
    num_values =
154
0
        gs_color_space_num_components(pcs) *
155
0
        (pim->MaskColor_is_range ? 2 : 1);
156
0
    for (i = 0; i < num_values; ++i) {
157
0
        code = sget_variable_uint(s, &pim->MaskColor[i]);
158
0
        if (code < 0)
159
0
            return code;
160
0
    }
161
0
    pim->image_parent_type = gs_image_type4;
162
0
    return 0;
163
0
}
164
165
static void
166
gx_image4_release(gs_image_common_t *pic, gs_memory_t *mem)
167
0
{
168
0
    gx_pixel_image_release((gs_pixel_image_t *)pic, mem);
169
0
}