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