| | 200 | // |
| | 201 | // JPEG handling code |
| | 202 | // |
| | 203 | struct shoes_jpeg_file_src { |
| | 204 | struct jpeg_source_mgr pub; /* public fields */ |
| | 205 | |
| | 206 | FILE *infile; /* source stream */ |
| | 207 | JOCTET *buffer; /* start of buffer */ |
| | 208 | boolean start_of_file; /* have we gotten any data yet? */ |
| | 209 | }; |
| | 210 | |
| | 211 | typedef struct shoes_jpeg_file_src *shoes_jpeg_file; |
| | 212 | |
| | 213 | #define JPEG_INPUT_BUF_SIZE 4096 |
| | 214 | |
| | 215 | static void |
| | 216 | shoes_jpeg_term_source(j_decompress_ptr cinfo) |
| | 217 | { |
| | 218 | } |
| | 219 | |
| | 220 | static void |
| | 221 | shoes_jpeg_init_source(j_decompress_ptr cinfo) |
| | 222 | { |
| | 223 | shoes_jpeg_file src = (shoes_jpeg_file) cinfo->src; |
| | 224 | src->start_of_file = 1; |
| | 225 | } |
| | 226 | |
| | 227 | |
| | 228 | static boolean |
| | 229 | shoes_jpeg_fill_input_buffer(j_decompress_ptr cinfo) |
| | 230 | { |
| | 231 | shoes_jpeg_file src = (shoes_jpeg_file)cinfo->src; |
| | 232 | size_t nbytes; |
| | 233 | |
| | 234 | nbytes = fread(src->buffer, 1, JPEG_INPUT_BUF_SIZE, src->infile); |
| | 235 | |
| | 236 | if (nbytes <= 0) { |
| | 237 | if (src->start_of_file) /* Treat empty input file as fatal error */ |
| | 238 | ERREXIT(cinfo, JERR_INPUT_EMPTY); |
| | 239 | WARNMS(cinfo, JWRN_JPEG_EOF); |
| | 240 | src->buffer[0] = (JOCTET) 0xFF; |
| | 241 | src->buffer[1] = (JOCTET) JPEG_EOI; |
| | 242 | nbytes = 2; |
| | 243 | } |
| | 244 | |
| | 245 | src->pub.next_input_byte = src->buffer; |
| | 246 | src->pub.bytes_in_buffer = nbytes; |
| | 247 | src->start_of_file = 0; |
| | 248 | |
| | 249 | return 1; |
| | 250 | } |
| | 251 | |
| | 252 | static void |
| | 253 | shoes_jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes) |
| | 254 | { |
| | 255 | shoes_jpeg_file src = (shoes_jpeg_file)cinfo->src; |
| | 256 | |
| | 257 | if (num_bytes > 0) |
| | 258 | { |
| | 259 | while (num_bytes > (long)src->pub.bytes_in_buffer) |
| | 260 | { |
| | 261 | num_bytes -= (long)src->pub.bytes_in_buffer; |
| | 262 | (void)shoes_jpeg_fill_input_buffer(cinfo); |
| | 263 | } |
| | 264 | src->pub.next_input_byte += (size_t)num_bytes; |
| | 265 | src->pub.bytes_in_buffer -= (size_t)num_bytes; |
| | 266 | } |
| | 267 | } |
| | 268 | |
| | 269 | static void |
| | 270 | jpeg_file_src(j_decompress_ptr cinfo, FILE *infile) |
| | 271 | { |
| | 272 | shoes_jpeg_file src; |
| | 273 | |
| | 274 | if (cinfo->src == NULL) |
| | 275 | { |
| | 276 | /* first time for this JPEG object? */ |
| | 277 | cinfo->src = (struct jpeg_source_mgr *) |
| | 278 | (*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT, |
| | 279 | sizeof(struct shoes_jpeg_file_src)); |
| | 280 | src = (shoes_jpeg_file) cinfo->src; |
| | 281 | src->buffer = (JOCTET *) |
| | 282 | (*cinfo->mem->alloc_small)((j_common_ptr) cinfo, JPOOL_PERMANENT, |
| | 283 | JPEG_INPUT_BUF_SIZE * sizeof(JOCTET)); |
| | 284 | } |
| | 285 | |
| | 286 | src = (shoes_jpeg_file)cinfo->src; |
| | 287 | src->pub.init_source = shoes_jpeg_init_source; |
| | 288 | src->pub.fill_input_buffer = shoes_jpeg_fill_input_buffer; |
| | 289 | src->pub.skip_input_data = shoes_jpeg_skip_input_data; |
| | 290 | src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ |
| | 291 | src->pub.term_source = shoes_jpeg_term_source; |
| | 292 | src->infile = infile; |
| | 293 | src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ |
| | 294 | src->pub.next_input_byte = NULL; /* until buffer loaded */ |
| | 295 | } |
| | 296 | |