11 unsigned char fake_eoi[]={(JOCTET) 0xFF,(JOCTET) JPEG_EOI};
13 /* Handlers to read from memory */
16 struct jpeg_source_mgr pub; /* public fields */
19 JOCTET * buffer; /* start of buffer */
20 boolean start_of_file; /* have we gotten any data yet? */
23 typedef scalar_source_mgr *scalar_src_ptr;
34 scalar_init_source (j_decompress_ptr cinfo) {
35 scalar_src_ptr src = (scalar_src_ptr) cinfo->src;
37 /* We reset the empty-input-file flag for each image,
38 * but we don't clear the input buffer.
39 * This is correct behavior for reading a series of images from one source.
41 src->start_of_file = TRUE;
45 scalar_fill_input_buffer (j_decompress_ptr cinfo) {
46 scalar_src_ptr src = (scalar_src_ptr) cinfo->src;
49 if (src->start_of_file) {
51 src->buffer=src->data;
53 /* Insert a fake EOI marker */
54 src->buffer = fake_eoi;
58 src->pub.next_input_byte = src->buffer;
59 src->pub.bytes_in_buffer = nbytes;
60 src->start_of_file = FALSE;
65 scalar_skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
66 scalar_src_ptr src = (scalar_src_ptr) cinfo->src;
68 /* Just a dumb implementation for now. Could use fseek() except
69 * it doesn't work on pipes. Not clear that being smart is worth
70 * any trouble anyway --- large skips are infrequent.
74 while (num_bytes > (long) src->pub.bytes_in_buffer) {
75 num_bytes -= (long) src->pub.bytes_in_buffer;
76 (void) scalar_fill_input_buffer(cinfo);
77 /* note we assume that fill_input_buffer will never return FALSE,
78 * so suspension need not be handled.
81 src->pub.next_input_byte += (size_t) num_bytes;
82 src->pub.bytes_in_buffer -= (size_t) num_bytes;
87 scalar_term_source (j_decompress_ptr cinfo) { /* no work necessary here */ }
90 jpeg_scalar_src(j_decompress_ptr cinfo, char *data, int length) {
93 if (cinfo->src == NULL) { /* first time for this JPEG object? */
94 cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,sizeof(scalar_source_mgr));
95 src = (scalar_src_ptr) cinfo->src;
98 src = (scalar_src_ptr) cinfo->src;
100 src->length = length;
101 src->pub.init_source = scalar_init_source;
102 src->pub.fill_input_buffer = scalar_fill_input_buffer;
103 src->pub.skip_input_data = scalar_skip_input_data;
104 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
105 src->pub.term_source = scalar_term_source;
106 src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
107 src->pub.next_input_byte = NULL; /* until buffer loaded */
114 i_writejpeg(i_img *im,int fd,int qfactor) {
116 JSAMPLE *image_buffer;
119 struct jpeg_compress_struct cinfo;
120 struct jpeg_error_mgr jerr;
122 FILE *outfile; /* target file */
123 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
124 int row_stride; /* physical row width in image buffer */
126 mm_log((1,"i_writejpeg(0x%x,fd %d,qfactor %d)\n",im,fd,qfactor));
128 if (!(im->channels==1 || im->channels==3)) { fprintf(stderr,"Unable to write JPEG, improper colorspace.\n"); exit(3); }
131 image_buffer=im->data;
133 /* Step 1: allocate and initialize JPEG compression object */
135 /* We have to set up the error handler first, in case the initialization
136 * step fails. (Unlikely, but it could happen if you are out of memory.)
137 * This routine fills in the contents of struct jerr, and returns jerr's
138 * address which we place into the link field in cinfo.
140 cinfo.err = jpeg_std_error(&jerr);
141 /* Now we can initialize the JPEG compression object. */
142 jpeg_create_compress(&cinfo);
144 /* Step 2: specify data destination (eg, a file) */
145 /* Note: steps 2 and 3 can be done in either order. */
147 /* Here we use the library-supplied code to send compressed data to a
148 * stdio stream. You can also write your own code to do something else.
149 * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
150 * requires it in order to write binary files.
153 if (fstat(fd,&stbuf)<0) { fprintf(stderr,"Unable to stat fd.\n"); exit(1); }
155 if ((outfile = fdopen(fd,"w")) == NULL) {
156 fprintf(stderr, "can't fdopen.\n");
160 jpeg_stdio_dest(&cinfo, outfile);
162 /* Step 3: set parameters for compression */
164 /* First we supply a description of the input image.
165 * Four fields of the cinfo struct must be filled in:
167 cinfo.image_width = im->xsize; /* image width and height, in pixels */
168 cinfo.image_height = im->ysize;
170 if (im->channels==3) {
171 cinfo.input_components = 3; /* # of color components per pixel */
172 cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
175 if (im->channels==1) {
176 cinfo.input_components = 1; /* # of color components per pixel */
177 cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */
180 /* Now use the library's routine to set default compression parameters.
181 * (You must set at least cinfo.in_color_space before calling this,
182 * since the defaults depend on the source color space.)
184 jpeg_set_defaults(&cinfo);
185 /* Now you can set any non-default parameters you wish to.
186 * Here we just illustrate the use of quality (quantization table) scaling:
189 jpeg_set_quality(&cinfo, quality, TRUE); /* limit to baseline-JPEG values */
191 /* Step 4: Start compressor */
193 /* TRUE ensures that we will write a complete interchange-JPEG file.
194 * Pass TRUE unless you are very sure of what you're doing.
196 jpeg_start_compress(&cinfo, TRUE);
198 /* Step 5: while (scan lines remain to be written) */
199 /* jpeg_write_scanlines(...); */
201 /* Here we use the library's state variable cinfo.next_scanline as the
202 * loop counter, so that we don't have to keep track ourselves.
203 * To keep things simple, we pass one scanline per call; you can pass
204 * more if you wish, though.
206 row_stride = im->xsize * im->channels; /* JSAMPLEs per row in image_buffer */
208 while (cinfo.next_scanline < cinfo.image_height) {
209 /* jpeg_write_scanlines expects an array of pointers to scanlines.
210 * Here the array is only one element long, but you could pass
211 * more than one scanline at a time if that's more convenient.
213 row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
214 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
217 /* Step 6: Finish compression */
219 jpeg_finish_compress(&cinfo);
220 /* After finish_compress, we can close the output file. */
223 /* Step 7: release JPEG compression object */
225 /* This is an important step since it will release a good deal of memory. */
226 jpeg_destroy_compress(&cinfo);
232 static int tlength=0;
233 static char **iptc_text=NULL;
235 #define JPEG_APP13 0xED /* APP13 marker code */
238 jpeg_getc (j_decompress_ptr cinfo)
241 struct jpeg_source_mgr * datasrc = cinfo->src;
243 if (datasrc->bytes_in_buffer == 0) {
244 if (! (*datasrc->fill_input_buffer) (cinfo))
245 { fprintf(stderr,"Jpeglib: cant suspend.\n"); exit(3); }
246 /* ERREXIT(cinfo, JERR_CANT_SUSPEND);*/
248 datasrc->bytes_in_buffer--;
249 return GETJOCTET(*datasrc->next_input_byte++);
253 APP13_handler (j_decompress_ptr cinfo) {
257 length = jpeg_getc(cinfo) << 8;
258 length += jpeg_getc(cinfo);
259 length -= 2; /* discount the length word itself */
263 if ( ((*iptc_text)=mymalloc(length)) == NULL ) return FALSE;
264 while (--length >= 0) (*iptc_text)[cnt++] = jpeg_getc(cinfo);
281 my_output_message (j_common_ptr cinfo)
283 char buffer[JMSG_LENGTH_MAX];
285 /* Create the message */
286 (*cinfo->err->format_message) (cinfo, buffer);
288 /* Send it to stderr, adding a newline */
289 mm_log((1, "%s\n", buffer));
297 struct my_error_mgr {
298 struct jpeg_error_mgr pub; /* "public" fields */
299 jmp_buf setjmp_buffer; /* for return to caller */
302 typedef struct my_error_mgr * my_error_ptr;
304 /* Here's the routine that will replace the standard error_exit method */
307 my_error_exit (j_common_ptr cinfo) {
308 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
309 my_error_ptr myerr = (my_error_ptr) cinfo->err;
311 /* Always display the message. */
312 /* We could postpone this until after returning, if we chose. */
313 (*cinfo->err->output_message) (cinfo);
315 /* Return control to the setjmp point */
316 longjmp(myerr->setjmp_buffer, 1);
325 i_readjpeg(int fd,char** iptc_itext,int *itlength) {
328 struct jpeg_decompress_struct cinfo;
329 /* We use our private extension JPEG error handler.
330 * Note that this struct must live as long as the main JPEG parameter
331 * struct, to avoid dangling-pointer problems.
334 /* struct jpeg_error_mgr jerr;*/
335 struct my_error_mgr jerr;
336 FILE * infile; /* source file */
337 JSAMPARRAY buffer; /* Output row buffer */
338 int row_stride; /* physical row width in output buffer */
340 mm_log((1,"i_readjpeg(fd %d,iptc_itext 0x%x)\n",fd,iptc_itext));
342 iptc_text=iptc_itext;
344 if ((infile = fdopen(fd,"r")) == NULL) {
345 fprintf(stderr, "can't fdopen.\n");
349 /* Step 1: allocate and initialize JPEG decompression object */
351 /* We set up the normal JPEG error routines, then override error_exit. */
352 cinfo.err = jpeg_std_error(&jerr.pub);
353 jerr.pub.error_exit = my_error_exit;
354 jerr.pub.output_message = my_output_message;
355 /* Establish the setjmp return context for my_error_exit to use. */
356 if (setjmp(jerr.setjmp_buffer)) {
357 /* If we get here, the JPEG code has signaled an error.
358 * We need to clean up the JPEG object, close the input file, and return.
360 jpeg_destroy_decompress(&cinfo);
367 /* Now we can initialize the JPEG decompression object. */
368 jpeg_create_decompress(&cinfo);
369 jpeg_set_marker_processor(&cinfo, JPEG_APP13, APP13_handler);
370 /* Step 2: specify data source (eg, a file) */
372 jpeg_stdio_src(&cinfo, infile);
374 /* Step 3: read file parameters with jpeg_read_header() */
376 (void) jpeg_read_header(&cinfo, TRUE);
378 /* We can ignore the return value from jpeg_read_header since
379 * (a) suspension is not possible with the stdio data source, and
380 * (b) we passed TRUE to reject a tables-only JPEG file as an error.
381 * See libjpeg.doc for more info.
384 /* Step 4: set parameters for decompression */
386 /* In this example, we don't need to change any of the defaults set by
387 * jpeg_read_header(), so we do nothing here.
390 /* Step 5: Start decompressor */
392 (void) jpeg_start_decompress(&cinfo);
393 /* We can ignore the return value since suspension is not possible
394 * with the stdio data source.
397 /* We may need to do some setup of our own at this point before reading
398 * the data. After jpeg_start_decompress() we have the correct scaled
399 * output image dimensions available, as well as the output colormap
400 * if we asked for color quantization.
401 * In this example, we need to make an output work buffer of the right size.
404 im=i_img_empty_ch(NULL,cinfo.output_width,cinfo.output_height,cinfo.output_components);
406 /* fprintf(stderr,"JPEG info:\n xsize:%d\n ysize:%d\n channels:%d.\n",xsize,ysize,channels);*/
408 /* JSAMPLEs per row in output buffer */
409 row_stride = cinfo.output_width * cinfo.output_components;
410 /* Make a one-row-high sample array that will go away when done with image */
411 buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
413 /* Step 6: while (scan lines remain to be read) */
414 /* jpeg_read_scanlines(...); */
416 /* Here we use the library's state variable cinfo.output_scanline as the
417 * loop counter, so that we don't have to keep track ourselves.
420 while (cinfo.output_scanline < cinfo.output_height) {
421 /* jpeg_read_scanlines expects an array of pointers to scanlines.
422 * Here the array is only one element long, but you could ask for
423 * more than one scanline at a time if that's more convenient.
425 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
426 /* Assume put_scanline_someplace wants a pointer and sample count. */
427 memcpy(im->data+im->channels*im->xsize*(cinfo.output_scanline-1),buffer[0],row_stride);
430 /* Step 7: Finish decompression */
432 (void) jpeg_finish_decompress(&cinfo);
433 /* We can ignore the return value since suspension is not possible
434 * with the stdio data source.
437 /* Step 8: Release JPEG decompression object */
439 /* This is an important step since it will release a good deal of memory. */
440 jpeg_destroy_decompress(&cinfo);
442 /* After finish_decompress, we can close the input file.
443 * Here we postpone it until after no more JPEG errors are possible,
444 * so as to simplify the setjmp error logic above. (Actually, I don't
445 * think that jpeg_destroy can do an error exit, but why assume anything...)
448 /* fclose(infile); DO NOT fclose() BECAUSE THEN close() WILL FAIL*/
450 /* At this point you may want to check to see whether any corrupt-data
451 * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
454 /* And we're done! */
457 mm_log((1,"i_readjpeg -> (0x%x)\n",im));
464 i_readjpeg_scalar(char *data, int length,char** iptc_itext,int *itlength) {
467 struct jpeg_decompress_struct cinfo;
468 struct my_error_mgr jerr;
469 JSAMPARRAY buffer; /* Output row buffer */
470 int row_stride; /* physical row width in output buffer */
472 mm_log((1,"i_readjpeg_scalar(data 0x%08x, length %d,iptc_itext 0x%x)\n",data,length,iptc_itext));
473 iptc_text=iptc_itext;
475 cinfo.err = jpeg_std_error(&jerr.pub);
476 jerr.pub.error_exit = my_error_exit;
477 jerr.pub.output_message = my_output_message;
478 if (setjmp(jerr.setjmp_buffer)) {
479 jpeg_destroy_decompress(&cinfo);
485 jpeg_create_decompress(&cinfo);
486 jpeg_set_marker_processor(&cinfo, JPEG_APP13, APP13_handler);
487 jpeg_scalar_src(&cinfo, data, length );
488 (void) jpeg_read_header(&cinfo, TRUE);
489 (void) jpeg_start_decompress(&cinfo);
490 im=i_img_empty_ch(NULL,cinfo.output_width,cinfo.output_height,cinfo.output_components);
491 row_stride = cinfo.output_width * cinfo.output_components;
492 buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
493 while (cinfo.output_scanline < cinfo.output_height) {
494 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
495 memcpy(im->data+im->channels*im->xsize*(cinfo.output_scanline-1),buffer[0],row_stride);
497 (void) jpeg_finish_decompress(&cinfo);
498 jpeg_destroy_decompress(&cinfo);
500 mm_log((1,"i_readjpeg_scalar -> (0x%x)\n",im));
561 struct jpeg_source_mgr pub; /* public fields */
563 JOCTET *buffer; /* start of buffer */
564 int length; /* Do I need this? */
565 boolean start_of_file; /* have we gotten any data yet? */
568 typedef wiol_source_mgr *wiol_src_ptr;
571 wiol_init_source (j_decompress_ptr cinfo) {
572 wiol_src_ptr src = (wiol_src_ptr) cinfo->src;
574 /* We reset the empty-input-file flag for each image,
575 * but we don't clear the input buffer.
576 * This is correct behavior for reading a series of images from one source.
578 src->start_of_file = TRUE;
582 wiol_fill_input_buffer(j_decompress_ptr cinfo) {
583 wiol_src_ptr src = (wiol_src_ptr) cinfo->src;
584 ssize_t nbytes; /* We assume that reads are "small" */
586 mm_log((1,"wiol_fill_input_buffer(cinfo 0x%p)\n"));
588 nbytes = src->data->readcb(src->data, src->buffer, JPGS);
590 if (nbytes <= 0) { /* Insert a fake EOI marker */
591 src->pub.next_input_byte = fake_eoi;
592 src->pub.bytes_in_buffer = 2;
594 src->pub.next_input_byte = src->buffer;
595 src->pub.bytes_in_buffer = nbytes;
597 src->start_of_file = FALSE;
602 wiol_skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
603 wiol_src_ptr src = (wiol_src_ptr) cinfo->src;
605 /* Just a dumb implementation for now. Could use fseek() except
606 * it doesn't work on pipes. Not clear that being smart is worth
607 * any trouble anyway --- large skips are infrequent.
611 while (num_bytes > (long) src->pub.bytes_in_buffer) {
612 num_bytes -= (long) src->pub.bytes_in_buffer;
613 (void) wiol_fill_input_buffer(cinfo);
614 /* note we assume that fill_input_buffer will never return FALSE,
615 * so suspension need not be handled.
618 src->pub.next_input_byte += (size_t) num_bytes;
619 src->pub.bytes_in_buffer -= (size_t) num_bytes;
624 wiol_term_source (j_decompress_ptr cinfo) {
625 /* no work necessary here */
627 if (cinfo->src != NULL) {
628 src = (wiol_src_ptr) cinfo->src;
634 jpeg_wiol_src(j_decompress_ptr cinfo, io_glue *ig, int length) {
637 if (cinfo->src == NULL) { /* first time for this JPEG object? */
638 cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)
639 ((j_common_ptr) cinfo, JPOOL_PERMANENT,sizeof(wiol_source_mgr));
640 src = (wiol_src_ptr) cinfo->src;
643 /* put the request method call in here later */
644 io_glue_commit_types(ig);
646 src = (wiol_src_ptr) cinfo->src;
648 src->buffer = mymalloc( JPGS );
649 src->length = length;
651 src->pub.init_source = wiol_init_source;
652 src->pub.fill_input_buffer = wiol_fill_input_buffer;
653 src->pub.skip_input_data = wiol_skip_input_data;
654 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
655 src->pub.term_source = wiol_term_source;
656 src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
657 src->pub.next_input_byte = NULL; /* until buffer loaded */
672 i_readjpeg_wiol(io_glue *data, int length, char** iptc_itext, int *itlength) {
675 struct jpeg_decompress_struct cinfo;
676 struct my_error_mgr jerr;
677 JSAMPARRAY buffer; /* Output row buffer */
678 int row_stride; /* physical row width in output buffer */
680 mm_log((1,"i_readjpeg_wiol(data 0x%p, length %d,iptc_itext 0x%p)\n", data, iptc_itext));
682 iptc_text = iptc_itext;
683 cinfo.err = jpeg_std_error(&jerr.pub);
684 jerr.pub.error_exit = my_error_exit;
685 jerr.pub.output_message = my_output_message;
687 /* Set error handler */
688 if (setjmp(jerr.setjmp_buffer)) {
689 jpeg_destroy_decompress(&cinfo);
695 jpeg_create_decompress(&cinfo);
696 jpeg_set_marker_processor(&cinfo, JPEG_APP13, APP13_handler);
697 jpeg_wiol_src(&cinfo, data, length);
699 (void) jpeg_read_header(&cinfo, TRUE);
700 (void) jpeg_start_decompress(&cinfo);
701 im=i_img_empty_ch(NULL,cinfo.output_width,cinfo.output_height,cinfo.output_components);
702 row_stride = cinfo.output_width * cinfo.output_components;
703 buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
704 while (cinfo.output_scanline < cinfo.output_height) {
705 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
706 memcpy(im->data+im->channels*im->xsize*(cinfo.output_scanline-1),buffer[0],row_stride);
708 (void) jpeg_finish_decompress(&cinfo);
709 jpeg_destroy_decompress(&cinfo);
711 mm_log((1,"i_readjpeg_wiol -> (0x%x)\n",im));