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 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 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 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 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 * 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 * 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 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 * 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 * 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 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 * 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 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 * 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 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 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 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 276 jpeg_mem_init(j_common_ptr cinfo) 277 { 278 return 0; /* just set max_memory_to_use to 0 */ 279 } 280 281 void 282 jpeg_mem_term(j_common_ptr cinfo) 283 { 284 /* no work */ 285 } 286