/src/ghostpdl/base/sjpegc.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 | | /* Interface routines for IJG code, common to encode/decode. */ |
18 | | #include "stdio_.h" |
19 | | #include "string_.h" |
20 | | #include "jpeglib_.h" |
21 | | #include "jerror_.h" |
22 | | #include "gx.h" |
23 | | #include "gserrors.h" |
24 | | #include "strimpl.h" |
25 | | #include "sdct.h" |
26 | | #include "sjpeg.h" |
27 | | #include "gsmchunk.h" |
28 | | |
29 | | #if !defined(SHARE_JPEG) || SHARE_JPEG==0 |
30 | | #include "jmemcust.h" |
31 | | #endif |
32 | | |
33 | | /* |
34 | | Ghostscript uses a non-public interface to libjpeg in order to |
35 | | override the library's default memory manager implementation. |
36 | | Since many users will want to compile Ghostscript using the |
37 | | shared jpeg library, we provide these prototypes so that a copy |
38 | | of the libjpeg source distribution is not needed. |
39 | | |
40 | | The presence of the jmemsys.h header file is detected in |
41 | | unix-aux.mak, and written to gconfig_.h |
42 | | */ |
43 | | |
44 | | #include "gconfig_.h" |
45 | | |
46 | | /* |
47 | | * Error handling routines (these replace corresponding IJG routines from |
48 | | * jpeg/jerror.c). These are used for both compression and decompression. |
49 | | * We assume |
50 | | * offset_of(jpeg_compress_data, cinfo)==offset_of(jpeg_decompress_data, dinfo) |
51 | | */ |
52 | | |
53 | | static void |
54 | | gs_jpeg_error_exit(j_common_ptr cinfo) |
55 | 1.40k | { |
56 | 1.40k | jpeg_stream_data *jcomdp = |
57 | 1.40k | (jpeg_stream_data *) ((char *)cinfo - |
58 | 1.40k | offset_of(jpeg_compress_data, cinfo)); |
59 | | |
60 | 1.40k | longjmp(find_jmp_buf(jcomdp->exit_jmpbuf), 1); |
61 | 1.40k | } |
62 | | |
63 | | static void |
64 | | gs_jpeg_emit_message(j_common_ptr cinfo, int msg_level) |
65 | 199k | { |
66 | 199k | if (msg_level < 0) { /* GS policy is to ignore IJG warnings when Picky=0, |
67 | | * treat them as errors when Picky=1. |
68 | | */ |
69 | 13.0k | jpeg_stream_data *jcomdp = |
70 | 13.0k | (jpeg_stream_data *) ((char *)cinfo - |
71 | 13.0k | offset_of(jpeg_compress_data, cinfo)); |
72 | | |
73 | 13.0k | if (jcomdp->Picky) |
74 | 0 | gs_jpeg_error_exit(cinfo); |
75 | 13.0k | } |
76 | | /* Trace messages are always ignored. */ |
77 | 199k | } |
78 | | |
79 | | /* |
80 | | * This routine initializes the error manager fields in the JPEG object. |
81 | | * It is based on jpeg_std_error from jpeg/jerror.c. |
82 | | */ |
83 | | |
84 | | void |
85 | | gs_jpeg_error_setup(stream_DCT_state * st) |
86 | 384k | { |
87 | 384k | struct jpeg_error_mgr *err = &st->data.common->err; |
88 | | |
89 | | /* Initialize the JPEG compression object with default error handling */ |
90 | 384k | jpeg_std_error(err); |
91 | | |
92 | | /* Replace some methods with our own versions */ |
93 | 384k | err->error_exit = gs_jpeg_error_exit; |
94 | 384k | err->emit_message = gs_jpeg_emit_message; |
95 | | |
96 | 384k | st->data.compress->cinfo.err = err; /* works for decompress case too */ |
97 | 384k | } |
98 | | |
99 | | /* Stuff the IJG error message into errorinfo after an error exit. */ |
100 | | |
101 | | int |
102 | | gs_jpeg_log_error(stream_DCT_state * st) |
103 | 1.40k | { |
104 | 1.40k | j_common_ptr cinfo = (j_common_ptr) & st->data.compress->cinfo; |
105 | 1.40k | char buffer[JMSG_LENGTH_MAX]; |
106 | | |
107 | | /* Format the error message */ |
108 | 1.40k | (*cinfo->err->format_message) (cinfo, buffer); |
109 | 1.40k | (*st->report_error) ((stream_state *) st, buffer); |
110 | 1.40k | return_error(gs_error_ioerror); /* caller will do return_error() */ |
111 | 1.40k | } |
112 | | |
113 | | /* |
114 | | * Interface routines. This layer of routines exists solely to limit |
115 | | * side-effects from using setjmp. |
116 | | */ |
117 | | |
118 | | JQUANT_TBL * |
119 | | gs_jpeg_alloc_quant_table(stream_DCT_state * st) |
120 | 0 | { |
121 | 0 | if (setjmp(find_jmp_buf(st->data.common->exit_jmpbuf))) { |
122 | 0 | gs_jpeg_log_error(st); |
123 | 0 | return NULL; |
124 | 0 | } |
125 | 0 | return jpeg_alloc_quant_table((j_common_ptr) |
126 | 0 | & st->data.compress->cinfo); |
127 | 0 | } |
128 | | |
129 | | JHUFF_TBL * |
130 | | gs_jpeg_alloc_huff_table(stream_DCT_state * st) |
131 | 0 | { |
132 | 0 | if (setjmp(find_jmp_buf(st->data.common->exit_jmpbuf))) { |
133 | 0 | gs_jpeg_log_error(st); |
134 | 0 | return NULL; |
135 | 0 | } |
136 | 0 | return jpeg_alloc_huff_table((j_common_ptr) |
137 | 0 | & st->data.compress->cinfo); |
138 | 0 | } |
139 | | |
140 | | int |
141 | | gs_jpeg_destroy(stream_DCT_state * st) |
142 | 384k | { |
143 | 384k | if (st->data.common && setjmp(find_jmp_buf(st->data.common->exit_jmpbuf))) |
144 | 0 | return_error(gs_jpeg_log_error(st)); |
145 | | |
146 | 384k | if (st->data.compress){ |
147 | 384k | jpeg_destroy((j_common_ptr) & st->data.compress->cinfo); |
148 | 384k | gs_jpeg_mem_term((j_common_ptr) & st->data.compress->cinfo); |
149 | 384k | } |
150 | 384k | return 0; |
151 | 384k | } |
152 | | |
153 | | #if !defined(SHARE_JPEG) || SHARE_JPEG==0 |
154 | | static void *gs_j_mem_alloc(j_common_ptr cinfo, size_t size) |
155 | 809k | { |
156 | 809k | gs_memory_t *mem = (gs_memory_t *)(GET_CUST_MEM_DATA(cinfo)->priv); |
157 | | |
158 | 809k | return(gs_alloc_bytes(mem, size, "JPEG allocation")); |
159 | 809k | } |
160 | | |
161 | | static void gs_j_mem_free(j_common_ptr cinfo, void *object, size_t size) |
162 | 809k | { |
163 | 809k | gs_memory_t *mem = (gs_memory_t *)(GET_CUST_MEM_DATA(cinfo)->priv); |
164 | | |
165 | 809k | gs_free_object(mem, object, "JPEG free"); |
166 | 809k | } |
167 | | |
168 | | static long gs_j_mem_init (j_common_ptr cinfo) |
169 | 384k | { |
170 | 384k | gs_memory_t *mem = (gs_memory_t *)(GET_CUST_MEM_DATA(cinfo)->priv); |
171 | 384k | gs_memory_t *cmem = NULL; |
172 | | |
173 | 384k | if (gs_memory_chunk_wrap(&(cmem), mem) < 0) { |
174 | 0 | return (-1); |
175 | 0 | } |
176 | | |
177 | 384k | (void)jpeg_cust_mem_set_private(GET_CUST_MEM_DATA(cinfo), cmem); |
178 | | |
179 | 384k | return 0; |
180 | 384k | } |
181 | | |
182 | | static void gs_j_mem_term (j_common_ptr cinfo) |
183 | 384k | { |
184 | 384k | gs_memory_t *cmem = (gs_memory_t *)(GET_CUST_MEM_DATA(cinfo)->priv); |
185 | 384k | gs_memory_t *mem = gs_memory_chunk_unwrap(cmem); |
186 | | |
187 | 384k | if (mem == cmem) |
188 | 0 | return; |
189 | | |
190 | 384k | (void)jpeg_cust_mem_set_private(GET_CUST_MEM_DATA(cinfo), mem); |
191 | 384k | } |
192 | | #endif /* SHAREJPEG == 0 */ |
193 | | |
194 | | |
195 | | int gs_jpeg_mem_init (gs_memory_t *mem, j_common_ptr cinfo) |
196 | 384k | { |
197 | 384k | int code = 0; |
198 | 384k | #if !defined(SHARE_JPEG) || SHARE_JPEG==0 |
199 | 384k | jpeg_cust_mem_data custm, *custmptr; |
200 | | |
201 | 384k | memset(&custm, 0x00, sizeof(custm)); |
202 | | |
203 | | /* JPEG allocated chunks don't need to be subject to gc. */ |
204 | 384k | mem = mem->non_gc_memory; |
205 | | |
206 | 384k | if (!jpeg_cust_mem_init(&custm, (void *) mem, gs_j_mem_init, gs_j_mem_term, NULL, |
207 | 384k | gs_j_mem_alloc, gs_j_mem_free, |
208 | 384k | gs_j_mem_alloc, gs_j_mem_free, NULL)) { |
209 | 0 | code = gs_note_error(gs_error_VMerror); |
210 | 0 | } |
211 | 384k | if (code == 0) { |
212 | 384k | custmptr = (jpeg_cust_mem_data *)gs_alloc_bytes(mem, sizeof(custm) + sizeof(void *), "JPEG custom memory descriptor"); |
213 | 384k | if (!custmptr) { |
214 | 0 | code = gs_note_error(gs_error_VMerror); |
215 | 0 | } |
216 | 384k | else { |
217 | 384k | memcpy(custmptr, &custm, sizeof(custm)); |
218 | 384k | cinfo->client_data = custmptr; |
219 | 384k | } |
220 | 384k | } |
221 | 384k | #endif /* SHAREJPEG == 0 */ |
222 | 384k | return code; |
223 | 384k | } |
224 | | |
225 | | void |
226 | | gs_jpeg_mem_term(j_common_ptr cinfo) |
227 | 384k | { |
228 | 384k | #if !defined(SHARE_JPEG) || SHARE_JPEG==0 |
229 | 384k | if (cinfo->client_data) { |
230 | 384k | jpeg_cust_mem_data *custmptr = (jpeg_cust_mem_data *)cinfo->client_data; |
231 | 384k | gs_memory_t *mem = (gs_memory_t *)(GET_CUST_MEM_DATA(cinfo)->priv); |
232 | | |
233 | 384k | gs_free_object(mem, custmptr, "gs_jpeg_mem_term"); |
234 | 384k | cinfo->client_data = NULL; |
235 | 384k | } |
236 | 384k | #endif /* SHAREJPEG == 0 */ |
237 | 384k | } |