1 /* Copyright (C) 1994, 1997, 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: sjpegc.c,v 1.7 2002/03/30 23:55:15 giles Exp $ */
18 /* Interface routines for IJG code, common to encode/decode. */
19 #include "stdio_.h"
20 #include "string_.h"
21 #include "jpeglib_.h"
22 #include "jerror_.h"
23 #include "gx.h"
24 #include "gserrors.h"
25 #include "strimpl.h"
26 #include "sdct.h"
27 #include "sjpeg.h"
28
29 /*
30 Ghostscript uses a non-public interface to libjpeg in order to
31 override the library's default memory manager implementation.
32 Since many users will want to compile Ghostscript using the
33 shared jpeg library, we provide these prototypes so that a copy
34 of the libjpeg source distribution is not needed.
35
36 The presence of the jmemsys.h header file is detected in
37 unix-aux.mak, and written to gconfig_.h
38 */
39
40 #include "gconfig_.h"
41 #ifdef DONT_HAVE_JMEMSYS_H
42
43 void *
44 jpeg_get_small(j_common_ptr cinfo, size_t size);
45
46 void
47 jpeg_free_small(j_common_ptr cinfo, void *object, size_t size);
48
49 void FAR *
50 jpeg_get_large(j_common_ptr cinfo, size_t size);
51
52 void
53 jpeg_free_large(j_common_ptr cinfo, void FAR * object, size_t size);
54 typedef void *backing_store_ptr;
55
56 long
57 jpeg_mem_available(j_common_ptr cinfo, long min_bytes_needed,
58 long max_bytes_needed, long already_allocated);
59
60 void
61 jpeg_open_backing_store(j_common_ptr cinfo, backing_store_ptr info,
62 long total_bytes_needed);
63
64 long
65 jpeg_mem_init(j_common_ptr cinfo);
66
67 void
68 jpeg_mem_term(j_common_ptr cinfo);
69
70 #else
71 #include "jmemsys.h" /* for prototypes */
72 #endif
73
74 private_st_jpeg_block();
75
76 /*
77 * Error handling routines (these replace corresponding IJG routines from
78 * jpeg/jerror.c). These are used for both compression and decompression.
79 * We assume
80 * offset_of(jpeg_compress_data, cinfo)==offset_of(jpeg_decompress_data, dinfo)
81 */
82
83 private void
gs_jpeg_error_exit(j_common_ptr cinfo)84 gs_jpeg_error_exit(j_common_ptr cinfo)
85 {
86 jpeg_stream_data *jcomdp =
87 (jpeg_stream_data *) ((char *)cinfo -
88 offset_of(jpeg_compress_data, cinfo));
89
90 longjmp(jcomdp->exit_jmpbuf, 1);
91 }
92
93 private void
gs_jpeg_emit_message(j_common_ptr cinfo,int msg_level)94 gs_jpeg_emit_message(j_common_ptr cinfo, int msg_level)
95 {
96 if (msg_level < 0) { /* GS policy is to ignore IJG warnings when Picky=0,
97 * treat them as errors when Picky=1.
98 */
99 jpeg_stream_data *jcomdp =
100 (jpeg_stream_data *) ((char *)cinfo -
101 offset_of(jpeg_compress_data, cinfo));
102
103 if (jcomdp->Picky)
104 gs_jpeg_error_exit(cinfo);
105 }
106 /* Trace messages are always ignored. */
107 }
108
109 /*
110 * This routine initializes the error manager fields in the JPEG object.
111 * It is based on jpeg_std_error from jpeg/jerror.c.
112 */
113
114 void
gs_jpeg_error_setup(stream_DCT_state * st)115 gs_jpeg_error_setup(stream_DCT_state * st)
116 {
117 struct jpeg_error_mgr *err = &st->data.common->err;
118
119 /* Initialize the JPEG compression object with default error handling */
120 jpeg_std_error(err);
121
122 /* Replace some methods with our own versions */
123 err->error_exit = gs_jpeg_error_exit;
124 err->emit_message = gs_jpeg_emit_message;
125
126 st->data.compress->cinfo.err = err; /* works for decompress case too */
127 }
128
129 /* Stuff the IJG error message into errorinfo after an error exit. */
130
131 int
gs_jpeg_log_error(stream_DCT_state * st)132 gs_jpeg_log_error(stream_DCT_state * st)
133 {
134 j_common_ptr cinfo = (j_common_ptr) & st->data.compress->cinfo;
135 char buffer[JMSG_LENGTH_MAX];
136
137 /* Format the error message */
138 (*cinfo->err->format_message) (cinfo, buffer);
139 (*st->report_error) ((stream_state *) st, buffer);
140 return gs_error_ioerror; /* caller will do return_error() */
141 }
142
143
144 /*
145 * Interface routines. This layer of routines exists solely to limit
146 * side-effects from using setjmp.
147 */
148
149
150 JQUANT_TBL *
gs_jpeg_alloc_quant_table(stream_DCT_state * st)151 gs_jpeg_alloc_quant_table(stream_DCT_state * st)
152 {
153 if (setjmp(st->data.common->exit_jmpbuf)) {
154 gs_jpeg_log_error(st);
155 return NULL;
156 }
157 return jpeg_alloc_quant_table((j_common_ptr)
158 & st->data.compress->cinfo);
159 }
160
161 JHUFF_TBL *
gs_jpeg_alloc_huff_table(stream_DCT_state * st)162 gs_jpeg_alloc_huff_table(stream_DCT_state * st)
163 {
164 if (setjmp(st->data.common->exit_jmpbuf)) {
165 gs_jpeg_log_error(st);
166 return NULL;
167 }
168 return jpeg_alloc_huff_table((j_common_ptr)
169 & st->data.compress->cinfo);
170 }
171
172 int
gs_jpeg_destroy(stream_DCT_state * st)173 gs_jpeg_destroy(stream_DCT_state * st)
174 {
175 if (setjmp(st->data.common->exit_jmpbuf))
176 return_error(gs_jpeg_log_error(st));
177 jpeg_destroy((j_common_ptr) & st->data.compress->cinfo);
178 return 0;
179 }
180
181
182 /*
183 * These routines replace the low-level memory manager of the IJG library.
184 * They pass malloc/free calls to the Ghostscript memory manager.
185 * Note we do not need these to be declared in any GS header file.
186 */
187
188 private inline jpeg_compress_data *
cinfo2jcd(j_common_ptr cinfo)189 cinfo2jcd(j_common_ptr cinfo)
190 { /* We use the offset of cinfo in jpeg_compress data here, but we */
191 /* could equally well have used jpeg_decompress_data. */
192 return (jpeg_compress_data *)
193 ((byte *)cinfo - offset_of(jpeg_compress_data, cinfo));
194 }
195
196 private void *
jpeg_alloc(j_common_ptr cinfo,size_t size,const char * info)197 jpeg_alloc(j_common_ptr cinfo, size_t size, const char *info)
198 {
199 jpeg_compress_data *jcd = cinfo2jcd(cinfo);
200 gs_memory_t *mem = jcd->memory;
201
202 jpeg_block_t *p = gs_alloc_struct_immovable(mem, jpeg_block_t,
203 &st_jpeg_block, "jpeg_alloc(block)");
204 void *data = gs_alloc_bytes_immovable(mem, size, info);
205
206 if (p == 0 || data == 0) {
207 gs_free_object(mem, data, info);
208 gs_free_object(mem, p, "jpeg_alloc(block)");
209 return 0;
210 }
211 p->data = data;
212 p->next = jcd->blocks;
213 jcd->blocks = p;
214 return data;
215 }
216
217 private void
jpeg_free(j_common_ptr cinfo,void * data,const char * info)218 jpeg_free(j_common_ptr cinfo, void *data, const char *info)
219 {
220 jpeg_compress_data *jcd = cinfo2jcd(cinfo);
221 gs_memory_t *mem = jcd->memory;
222 jpeg_block_t *p = jcd->blocks;
223 jpeg_block_t **pp = &jcd->blocks;
224
225 gs_free_object(mem, data, info);
226 while(p && p->data != data)
227 { pp = &p->next;
228 p = p->next;
229 }
230 if(p == 0)
231 lprintf1("Freeing unrecorded JPEG data 0x%lx!\n", (ulong)data);
232 else
233 *pp = p->next;
234 gs_free_object(mem, p, "jpeg_free(block)");
235 }
236
237 void *
jpeg_get_small(j_common_ptr cinfo,size_t size)238 jpeg_get_small(j_common_ptr cinfo, size_t size)
239 {
240 return jpeg_alloc(cinfo, size, "JPEG small internal data allocation");
241 }
242
243 void
jpeg_free_small(j_common_ptr cinfo,void * object,size_t size)244 jpeg_free_small(j_common_ptr cinfo, void *object, size_t size)
245 {
246 jpeg_free(cinfo, object, "Freeing JPEG small internal data");
247 }
248
249 void FAR *
jpeg_get_large(j_common_ptr cinfo,size_t size)250 jpeg_get_large(j_common_ptr cinfo, size_t size)
251 {
252 return jpeg_alloc(cinfo, size, "JPEG large internal data allocation");
253 }
254
255 void
jpeg_free_large(j_common_ptr cinfo,void FAR * object,size_t size)256 jpeg_free_large(j_common_ptr cinfo, void FAR * object, size_t size)
257 {
258 jpeg_free(cinfo, object, "Freeing JPEG large internal data");
259 }
260
261 long
jpeg_mem_available(j_common_ptr cinfo,long min_bytes_needed,long max_bytes_needed,long already_allocated)262 jpeg_mem_available(j_common_ptr cinfo, long min_bytes_needed,
263 long max_bytes_needed, long already_allocated)
264 {
265 return max_bytes_needed;
266 }
267
268 void
jpeg_open_backing_store(j_common_ptr cinfo,backing_store_ptr info,long total_bytes_needed)269 jpeg_open_backing_store(j_common_ptr cinfo, backing_store_ptr info,
270 long total_bytes_needed)
271 {
272 ERREXIT(cinfo, JERR_NO_BACKING_STORE);
273 }
274
275 long
jpeg_mem_init(j_common_ptr cinfo)276 jpeg_mem_init(j_common_ptr cinfo)
277 {
278 return 0; /* just set max_memory_to_use to 0 */
279 }
280
281 void
jpeg_mem_term(j_common_ptr cinfo)282 jpeg_mem_term(j_common_ptr cinfo)
283 {
284 /* no work */
285 }
286