Coverage Report

Created: 2025-06-24 07:01

/src/ghostpdl/base/gximage1.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 1 initialization */
18
#include "gx.h"
19
#include "gserrors.h"
20
#include "gxiparam.h"
21
#include "gximage.h"
22
#include "stream.h"
23
#include "memory_.h"
24
25
/* Structure descriptor */
26
public_st_gs_image1();
27
28
/*
29
 * Define the image types for ImageType 1 images.
30
 * Note that opaque images and masks have different types, although
31
 * they have the same ImageType.
32
 */
33
static image_proc_sput(gx_image1_sput);
34
static image_proc_sget(gx_image1_sget);
35
static image_proc_release(gx_image1_release);
36
const gx_image_type_t gs_image_type_1 = {
37
    &st_gs_image1, gx_begin_image1,
38
    gx_image1_sput, gx_image1_sget, gx_image1_release, 1
39
};
40
static image_proc_sput(gx_image1_mask_sput);
41
static image_proc_sget(gx_image1_mask_sget);
42
/*
43
 * Image masks are not actually pixel images, so they don't need to
44
 * worry about releasing the color space.
45
 */
46
const gx_image_type_t gs_image_type_mask1 = {
47
    &st_gs_image1, gx_begin_image1,
48
    gx_image1_mask_sput, gx_image1_mask_sget, gx_image_default_release, 1
49
};
50
51
/* Define the procedures for initializing gs_image_ts to default values. */
52
void
53
gs_image_t_init_adjust(gs_image_t * pim, gs_color_space * color_space,
54
                       bool adjust)
55
2.50M
{
56
2.50M
    gs_pixel_image_t_init((gs_pixel_image_t *) pim, color_space);
57
2.50M
    pim->ImageMask = (color_space == NULL);
58
2.50M
    pim->adjust = adjust;
59
2.50M
    pim->type = (pim->ImageMask ? &gs_image_type_mask1 : &gs_image_type_1);
60
2.50M
    pim->Alpha = gs_image_alpha_none;
61
2.50M
    pim->image_parent_type = gs_image_type1;
62
2.50M
    pim->imagematrices_are_untrustworthy = 0;
63
2.50M
}
64
void
65
gs_image_t_init_mask_adjust(gs_image_t * pim, bool write_1s, bool adjust)
66
963k
{
67
963k
    gs_image_t_init(pim, NULL);
68
963k
    if (write_1s)
69
235k
        pim->Decode[0] = 1, pim->Decode[1] = 0;
70
728k
    else
71
728k
        pim->Decode[0] = 0, pim->Decode[1] = 1;
72
963k
    pim->adjust = adjust;
73
963k
}
74
75
/* Start processing an ImageType 1 image. */
76
int
77
gx_begin_image1(gx_device * dev,
78
                const gs_gstate * pgs, const gs_matrix * pmat,
79
                const gs_image_common_t * pic, const gs_int_rect * prect,
80
                const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
81
                gs_memory_t * mem, gx_image_enum_common_t ** pinfo)
82
2.28M
{
83
2.28M
    gx_image_enum *penum;
84
2.28M
    const gs_image_t *pim = (const gs_image_t *)pic;
85
2.28M
    int code = gx_image_enum_alloc(pic, prect, mem, &penum);
86
87
2.28M
    if (code < 0)
88
2
        return code;
89
2.28M
    penum->alpha = pim->Alpha;
90
2.28M
    penum->use_mask_color = false;
91
2.28M
    penum->image_parent_type = pim->image_parent_type;
92
2.28M
    penum->masked = pim->ImageMask;
93
2.28M
    penum->adjust =
94
2.28M
        (pim->ImageMask && pim->adjust ? float2fixed(0.25) : fixed_0);
95
2.28M
    code = gx_image_enum_begin(dev, pgs, pmat, pic, pdcolor, pcpath, mem,
96
2.28M
                               penum);
97
2.28M
    if (code >= 0)
98
2.28M
        *pinfo = (gx_image_enum_common_t *)penum;
99
166
    else {
100
        /* penum is freed in by gx_image_enum_begin */
101
166
        *pinfo = NULL;
102
166
    }
103
2.28M
    return code;
104
2.28M
}
105
106
/* Serialization */
107
108
/*
109
 * We add the Alpha value to the control word.
110
 */
111
112
static int
113
gx_image1_sput(const gs_image_common_t *pic, stream *s,
114
               const gs_color_space **ppcs)
115
63.1k
{
116
63.1k
    const gs_image_t *const pim = (const gs_image_t *)pic;
117
118
63.1k
    return gx_pixel_image_sput((const gs_pixel_image_t *)pic, s, ppcs,
119
63.1k
                               (int)pim->Alpha);
120
63.1k
}
121
122
static int
123
gx_image1_sget(gs_image_common_t *pic, stream *s,
124
               gs_color_space *pcs)
125
627k
{
126
627k
    gs_image1_t *const pim = (gs_image1_t *)pic;
127
627k
    int code = gx_pixel_image_sget((gs_pixel_image_t *)pim, s, pcs);
128
129
627k
    if (code < 0)
130
0
        return code;
131
627k
    pim->type = &gs_image_type_1;
132
627k
    pim->ImageMask = false;
133
627k
    pim->Alpha = code;
134
627k
    pim->image_parent_type = gs_image_type1;
135
627k
    return 0;
136
627k
}
137
138
/*
139
 * Masks have different parameters, so we use a different encoding:
140
 *  FFFFEEDCBA
141
 *      A = 0 if standard ImageMatrix, 1 if explicit ImageMatrix
142
 *      B = 0 if Decode=[0 1], 1 if Decode=[1 0]
143
 *      C = Interpolate
144
 *      D = adjust
145
 *      EE = Alpha
146
 *      FFFF = BitsPerComponent - 1 (only needed for soft masks)
147
 *  Width, encoded as a variable-length uint
148
 *  Height, encoded like Width
149
 *  ImageMatrix (if A = 1), per gs_matrix_store/fetch
150
 */
151
690k
#define MI_ImageMatrix 0x01
152
393k
#define MI_Decode 0x02
153
104k
#define MI_Interpolate 0x04
154
399k
#define MI_adjust 0x08
155
498k
#define MI_Alpha_SHIFT 4
156
104k
#define MI_Alpha_MASK 0x3
157
498k
#define MI_BPC_SHIFT 6
158
104k
#define MI_BPC_MASK 0xf
159
#define MI_BITS 10
160
161
static int
162
gx_image1_mask_sput(const gs_image_common_t *pic, stream *s,
163
                    const gs_color_space **ignore_ppcs)
164
393k
{
165
393k
    const gs_image_t *pim = (const gs_image_t *)pic;
166
393k
    uint control =
167
393k
        (gx_image_matrix_is_default((const gs_data_image_t *)pim) ? 0 :
168
393k
         MI_ImageMatrix) |
169
393k
        (pim->Decode[0] != 0 ? MI_Decode : 0) |
170
393k
        (pim->Interpolate ? MI_Interpolate : 0) |
171
393k
        (pim->adjust ? MI_adjust : 0) |
172
393k
        (pim->Alpha << MI_Alpha_SHIFT) |
173
393k
        ((pim->BitsPerComponent - 1) << MI_BPC_SHIFT);
174
175
393k
    sput_variable_uint(s, control);
176
393k
    sput_variable_uint(s, (uint)pim->Width);
177
393k
    sput_variable_uint(s, (uint)pim->Height);
178
393k
    if (control & MI_ImageMatrix)
179
192k
        sput_matrix(s, &pim->ImageMatrix);
180
393k
    return 0;
181
393k
}
182
183
static int
184
gx_image1_mask_sget(gs_image_common_t *pic, stream *s,
185
                    gs_color_space *ignore_pcs)
186
104k
{
187
104k
    gs_image1_t *const pim = (gs_image1_t *)pic;
188
104k
    int code;
189
104k
    uint control;
190
191
104k
    if ((code = sget_variable_uint(s, &control)) < 0)
192
0
        return code;
193
104k
    gs_image_t_init_mask(pim, (control & MI_Decode) != 0);
194
104k
    if ((code = sget_variable_uint(s, (uint *)&pim->Width)) < 0 ||
195
104k
        (code = sget_variable_uint(s, (uint *)&pim->Height)) < 0
196
104k
        )
197
0
        return code;
198
104k
    if (control & MI_ImageMatrix) {
199
1.94k
        if ((code = sget_matrix(s, &pim->ImageMatrix)) < 0)
200
0
            return code;
201
1.94k
    } else
202
102k
        gx_image_matrix_set_default((gs_data_image_t *)pim);
203
104k
    pim->Interpolate = (control & MI_Interpolate) != 0;
204
104k
    pim->adjust = (control & MI_adjust) != 0;
205
104k
    pim->Alpha = (control >> MI_Alpha_SHIFT) & MI_Alpha_MASK;
206
104k
    pim->BitsPerComponent = ((control >> MI_BPC_SHIFT) & MI_BPC_MASK) + 1;
207
104k
    return 0;
208
104k
}
209
210
static void
211
gx_image1_release(gs_image_common_t *pic, gs_memory_t *mem)
212
0
{
213
0
    gx_pixel_image_release((gs_pixel_image_t *)pic, mem);
214
0
}
215
216
/* Free the image enumerator. */
217
void
218
gx_image_free_enum(gx_image_enum_common_t **ppenum)
219
2.99M
{
220
2.99M
    gx_image_enum_common_t  * penum = *ppenum;
221
2.99M
    gs_memory_t *mem = penum->memory;
222
223
     /* Bug 688845 comment #38 :
224
        Adobe Illustrator creates a Postscript document,
225
        in which an image data procedure executes 'save',
226
        and the corresponding 'restore' appears after the image end.
227
        It causes this procedure is called at a higher save level than
228
        at which the enumerator was allocated, so that gs_free_object below
229
        works idle. Nevertheless we can't leave pointers in the structure,
230
        because they may point to blocks already released
231
        by the client's subclass method for end_image.
232
        Leaving them uncleaned caused a real crash in the garbager - see bug 688845.
233
        So we clean the entire subclassed enumerator here,
234
        rather this is a generic function for base class.
235
        Note the cleaning is neccessaryfor Postscript only,
236
        because other languaged don't implement save-restore.
237
     */
238
2.99M
    memset(penum, 0, gs_object_size(mem, penum));
239
2.99M
    gs_free_object(mem, penum, "gx_image_free_enum");
240
2.99M
    *ppenum = NULL;
241
2.99M
}