xref: /plan9/sys/src/cmd/gs/src/sjpegc.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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