xref: /plan9-contrib/sys/src/cmd/gs/src/sjpegc.c (revision d46c239f8612929b7dbade67d0d071633df3a15d)
1 /* Copyright (C) 1994, 1997, 1999 Aladdin Enterprises.  All rights reserved.
2 
3   This file is part of AFPL Ghostscript.
4 
5   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
6   distributor accepts any responsibility for the consequences of using it, or
7   for whether it serves any particular purpose or works at all, unless he or
8   she says so in writing.  Refer to the Aladdin Free Public License (the
9   "License") for full details.
10 
11   Every copy of AFPL Ghostscript must include a copy of the License, normally
12   in a plain ASCII text file named PUBLIC.  The License grants you the right
13   to copy, modify and redistribute AFPL Ghostscript, but only under certain
14   conditions described in the License.  Among other things, the License
15   requires that the copyright notice and this notice be preserved on all
16   copies.
17 */
18 
19 /*$Id: sjpegc.c,v 1.4 2001/04/07 00:33:22 rayjj Exp $ */
20 /* Interface routines for IJG code, common to encode/decode. */
21 #include "stdio_.h"
22 #include "string_.h"
23 #include "jpeglib_.h"
24 #include "jerror_.h"
25 #include "jmemsys.h"		/* for prototypes */
26 #include "gx.h"
27 #include "gserrors.h"
28 #include "strimpl.h"
29 #include "sdct.h"
30 #include "sjpeg.h"
31 
32 private_st_jpeg_block();
33 
34 /*
35  * Error handling routines (these replace corresponding IJG routines from
36  * jpeg/jerror.c).  These are used for both compression and decompression.
37  * We assume
38  * offset_of(jpeg_compress_data, cinfo)==offset_of(jpeg_decompress_data, dinfo)
39  */
40 
41 private void
42 gs_jpeg_error_exit(j_common_ptr cinfo)
43 {
44     jpeg_stream_data *jcomdp =
45     (jpeg_stream_data *) ((char *)cinfo -
46 			  offset_of(jpeg_compress_data, cinfo));
47 
48     longjmp(jcomdp->exit_jmpbuf, 1);
49 }
50 
51 private void
52 gs_jpeg_emit_message(j_common_ptr cinfo, int msg_level)
53 {
54     if (msg_level < 0) {	/* GS policy is to ignore IJG warnings when Picky=0,
55 				 * treat them as errors when Picky=1.
56 				 */
57 	jpeg_stream_data *jcomdp =
58 	(jpeg_stream_data *) ((char *)cinfo -
59 			      offset_of(jpeg_compress_data, cinfo));
60 
61 	if (jcomdp->Picky)
62 	    gs_jpeg_error_exit(cinfo);
63     }
64     /* Trace messages are always ignored. */
65 }
66 
67 /*
68  * This routine initializes the error manager fields in the JPEG object.
69  * It is based on jpeg_std_error from jpeg/jerror.c.
70  */
71 
72 void
73 gs_jpeg_error_setup(stream_DCT_state * st)
74 {
75     struct jpeg_error_mgr *err = &st->data.common->err;
76 
77     /* Initialize the JPEG compression object with default error handling */
78     jpeg_std_error(err);
79 
80     /* Replace some methods with our own versions */
81     err->error_exit = gs_jpeg_error_exit;
82     err->emit_message = gs_jpeg_emit_message;
83 
84     st->data.compress->cinfo.err = err;		/* works for decompress case too */
85 }
86 
87 /* Stuff the IJG error message into errorinfo after an error exit. */
88 
89 int
90 gs_jpeg_log_error(stream_DCT_state * st)
91 {
92     j_common_ptr cinfo = (j_common_ptr) & st->data.compress->cinfo;
93     char buffer[JMSG_LENGTH_MAX];
94 
95     /* Format the error message */
96     (*cinfo->err->format_message) (cinfo, buffer);
97     (*st->report_error) ((stream_state *) st, buffer);
98     return gs_error_ioerror;	/* caller will do return_error() */
99 }
100 
101 
102 /*
103  * Interface routines.  This layer of routines exists solely to limit
104  * side-effects from using setjmp.
105  */
106 
107 
108 JQUANT_TBL *
109 gs_jpeg_alloc_quant_table(stream_DCT_state * st)
110 {
111     if (setjmp(st->data.common->exit_jmpbuf)) {
112 	gs_jpeg_log_error(st);
113 	return NULL;
114     }
115     return jpeg_alloc_quant_table((j_common_ptr)
116 				  & st->data.compress->cinfo);
117 }
118 
119 JHUFF_TBL *
120 gs_jpeg_alloc_huff_table(stream_DCT_state * st)
121 {
122     if (setjmp(st->data.common->exit_jmpbuf)) {
123 	gs_jpeg_log_error(st);
124 	return NULL;
125     }
126     return jpeg_alloc_huff_table((j_common_ptr)
127 				 & st->data.compress->cinfo);
128 }
129 
130 int
131 gs_jpeg_destroy(stream_DCT_state * st)
132 {
133     if (setjmp(st->data.common->exit_jmpbuf))
134 	return_error(gs_jpeg_log_error(st));
135     jpeg_destroy((j_common_ptr) & st->data.compress->cinfo);
136     return 0;
137 }
138 
139 
140 /*
141  * These routines replace the low-level memory manager of the IJG library.
142  * They pass malloc/free calls to the Ghostscript memory manager.
143  * Note we do not need these to be declared in any GS header file.
144  */
145 
146 private inline jpeg_compress_data *
147 cinfo2jcd(j_common_ptr cinfo)
148 {   /* We use the offset of cinfo in jpeg_compress data here, but we */
149     /* could equally well have used jpeg_decompress_data.            */
150     return (jpeg_compress_data *)
151       ((byte *)cinfo - offset_of(jpeg_compress_data, cinfo));
152 }
153 
154 private void *
155 jpeg_alloc(j_common_ptr cinfo, size_t size, const char *info)
156 {
157     jpeg_compress_data *jcd = cinfo2jcd(cinfo);
158     gs_memory_t *mem = jcd->memory;
159 
160     jpeg_block_t *p = gs_alloc_struct_immovable(mem, jpeg_block_t,
161     			&st_jpeg_block, "jpeg_alloc(block)");
162     void *data = gs_alloc_bytes_immovable(mem, size, info);
163 
164     if (p == 0 || data == 0) {
165 	gs_free_object(mem, data, info);
166 	gs_free_object(mem, p, "jpeg_alloc(block)");
167 	return 0;
168     }
169     p->data = data;
170     p->next = jcd->blocks;
171     jcd->blocks = p;
172     return data;
173 }
174 
175 private void
176 jpeg_free(j_common_ptr cinfo, void *data, const char *info)
177 {
178     jpeg_compress_data *jcd = cinfo2jcd(cinfo);
179     gs_memory_t *mem = jcd->memory;
180     jpeg_block_t  *p  =  jcd->blocks;
181     jpeg_block_t **pp = &jcd->blocks;
182 
183     gs_free_object(mem, data, info);
184     while(p && p->data != data)
185       { pp = &p->next;
186         p = p->next;
187       }
188     if(p == 0)
189       lprintf1("Freeing unrecorded JPEG data 0x%lx!\n", (ulong)data);
190     else
191       *pp = p->next;
192     gs_free_object(mem, p, "jpeg_free(block)");
193 }
194 
195 void *
196 jpeg_get_small(j_common_ptr cinfo, size_t size)
197 {
198     return jpeg_alloc(cinfo, size, "JPEG small internal data allocation");
199 }
200 
201 void
202 jpeg_free_small(j_common_ptr cinfo, void *object, size_t size)
203 {
204     jpeg_free(cinfo, object, "Freeing JPEG small internal data");
205 }
206 
207 void FAR *
208 jpeg_get_large(j_common_ptr cinfo, size_t size)
209 {
210     return jpeg_alloc(cinfo, size, "JPEG large internal data allocation");
211 }
212 
213 void
214 jpeg_free_large(j_common_ptr cinfo, void FAR * object, size_t size)
215 {
216     jpeg_free(cinfo, object, "Freeing JPEG large internal data");
217 }
218 
219 long
220 jpeg_mem_available(j_common_ptr cinfo, long min_bytes_needed,
221 		   long max_bytes_needed, long already_allocated)
222 {
223     return max_bytes_needed;
224 }
225 
226 void
227 jpeg_open_backing_store(j_common_ptr cinfo, backing_store_ptr info,
228 			long total_bytes_needed)
229 {
230     ERREXIT(cinfo, JERR_NO_BACKING_STORE);
231 }
232 
233 long
234 jpeg_mem_init(j_common_ptr cinfo)
235 {
236     return 0;			/* just set max_memory_to_use to 0 */
237 }
238 
239 void
240 jpeg_mem_term(j_common_ptr cinfo)
241 {
242     /* no work */
243 }
244