/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 | } |