13 unsigned char fake_eoi[]={(JOCTET) 0xFF,(JOCTET) JPEG_EOI};
15 /* Handlers to read from memory */
18 struct jpeg_source_mgr pub; /* public fields */
21 JOCTET * buffer; /* start of buffer */
22 boolean start_of_file; /* have we gotten any data yet? */
25 typedef scalar_source_mgr *scalar_src_ptr;
36 scalar_init_source (j_decompress_ptr cinfo) {
37 scalar_src_ptr src = (scalar_src_ptr) cinfo->src;
39 /* We reset the empty-input-file flag for each image,
40 * but we don't clear the input buffer.
41 * This is correct behavior for reading a series of images from one source.
43 src->start_of_file = TRUE;
47 scalar_fill_input_buffer (j_decompress_ptr cinfo) {
48 scalar_src_ptr src = (scalar_src_ptr) cinfo->src;
51 if (src->start_of_file) {
53 src->buffer=src->data;
55 /* Insert a fake EOI marker */
56 src->buffer = fake_eoi;
60 src->pub.next_input_byte = src->buffer;
61 src->pub.bytes_in_buffer = nbytes;
62 src->start_of_file = FALSE;
67 scalar_skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
68 scalar_src_ptr src = (scalar_src_ptr) cinfo->src;
70 /* Just a dumb implementation for now. Could use fseek() except
71 * it doesn't work on pipes. Not clear that being smart is worth
72 * any trouble anyway --- large skips are infrequent.
76 while (num_bytes > (long) src->pub.bytes_in_buffer) {
77 num_bytes -= (long) src->pub.bytes_in_buffer;
78 (void) scalar_fill_input_buffer(cinfo);
79 /* note we assume that fill_input_buffer will never return FALSE,
80 * so suspension need not be handled.
83 src->pub.next_input_byte += (size_t) num_bytes;
84 src->pub.bytes_in_buffer -= (size_t) num_bytes;
89 scalar_term_source (j_decompress_ptr cinfo) { /* no work necessary here */ }
92 jpeg_scalar_src(j_decompress_ptr cinfo, char *data, int length) {
95 if (cinfo->src == NULL) { /* first time for this JPEG object? */
96 cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,sizeof(scalar_source_mgr));
97 src = (scalar_src_ptr) cinfo->src;
100 src = (scalar_src_ptr) cinfo->src;
102 src->length = length;
103 src->pub.init_source = scalar_init_source;
104 src->pub.fill_input_buffer = scalar_fill_input_buffer;
105 src->pub.skip_input_data = scalar_skip_input_data;
106 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
107 src->pub.term_source = scalar_term_source;
108 src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
109 src->pub.next_input_byte = NULL; /* until buffer loaded */
116 i_writejpeg(i_img *im,int fd,int qfactor) {
118 JSAMPLE *image_buffer;
121 struct jpeg_compress_struct cinfo;
122 struct jpeg_error_mgr jerr;
124 FILE *outfile; /* target file */
125 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
126 int row_stride; /* physical row width in image buffer */
128 mm_log((1,"i_writejpeg(0x%x,fd %d,qfactor %d)\n",im,fd,qfactor));
130 if (!(im->channels==1 || im->channels==3)) { fprintf(stderr,"Unable to write JPEG, improper colorspace.\n"); exit(3); }
133 image_buffer=im->data;
135 /* Step 1: allocate and initialize JPEG compression object */
137 /* We have to set up the error handler first, in case the initialization
138 * step fails. (Unlikely, but it could happen if you are out of memory.)
139 * This routine fills in the contents of struct jerr, and returns jerr's
140 * address which we place into the link field in cinfo.
142 cinfo.err = jpeg_std_error(&jerr);
143 /* Now we can initialize the JPEG compression object. */
144 jpeg_create_compress(&cinfo);
146 /* Step 2: specify data destination (eg, a file) */
147 /* Note: steps 2 and 3 can be done in either order. */
149 /* Here we use the library-supplied code to send compressed data to a
150 * stdio stream. You can also write your own code to do something else.
151 * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
152 * requires it in order to write binary files.
155 if (fstat(fd,&stbuf)<0) { fprintf(stderr,"Unable to stat fd.\n"); exit(1); }
157 if ((outfile = fdopen(fd,"w")) == NULL) {
158 fprintf(stderr, "can't fdopen.\n");
162 jpeg_stdio_dest(&cinfo, outfile);
164 /* Step 3: set parameters for compression */
166 /* First we supply a description of the input image.
167 * Four fields of the cinfo struct must be filled in:
169 cinfo.image_width = im->xsize; /* image width and height, in pixels */
170 cinfo.image_height = im->ysize;
172 if (im->channels==3) {
173 cinfo.input_components = 3; /* # of color components per pixel */
174 cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
177 if (im->channels==1) {
178 cinfo.input_components = 1; /* # of color components per pixel */
179 cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */
182 /* Now use the library's routine to set default compression parameters.
183 * (You must set at least cinfo.in_color_space before calling this,
184 * since the defaults depend on the source color space.)
186 jpeg_set_defaults(&cinfo);
187 /* Now you can set any non-default parameters you wish to.
188 * Here we just illustrate the use of quality (quantization table) scaling:
191 jpeg_set_quality(&cinfo, quality, TRUE); /* limit to baseline-JPEG values */
193 /* Step 4: Start compressor */
195 /* TRUE ensures that we will write a complete interchange-JPEG file.
196 * Pass TRUE unless you are very sure of what you're doing.
198 jpeg_start_compress(&cinfo, TRUE);
200 /* Step 5: while (scan lines remain to be written) */
201 /* jpeg_write_scanlines(...); */
203 /* Here we use the library's state variable cinfo.next_scanline as the
204 * loop counter, so that we don't have to keep track ourselves.
205 * To keep things simple, we pass one scanline per call; you can pass
206 * more if you wish, though.
208 row_stride = im->xsize * im->channels; /* JSAMPLEs per row in image_buffer */
210 while (cinfo.next_scanline < cinfo.image_height) {
211 /* jpeg_write_scanlines expects an array of pointers to scanlines.
212 * Here the array is only one element long, but you could pass
213 * more than one scanline at a time if that's more convenient.
215 row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
216 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
219 /* Step 6: Finish compression */
221 jpeg_finish_compress(&cinfo);
222 /* After finish_compress, we can close the output file. */
225 /* Step 7: release JPEG compression object */
227 /* This is an important step since it will release a good deal of memory. */
228 jpeg_destroy_compress(&cinfo);
234 static int tlength=0;
235 static char **iptc_text=NULL;
237 #define JPEG_APP13 0xED /* APP13 marker code */
240 jpeg_getc (j_decompress_ptr cinfo)
243 struct jpeg_source_mgr * datasrc = cinfo->src;
245 if (datasrc->bytes_in_buffer == 0) {
246 if (! (*datasrc->fill_input_buffer) (cinfo))
247 { fprintf(stderr,"Jpeglib: cant suspend.\n"); exit(3); }
248 /* ERREXIT(cinfo, JERR_CANT_SUSPEND);*/
250 datasrc->bytes_in_buffer--;
251 return GETJOCTET(*datasrc->next_input_byte++);
255 APP13_handler (j_decompress_ptr cinfo) {
259 length = jpeg_getc(cinfo) << 8;
260 length += jpeg_getc(cinfo);
261 length -= 2; /* discount the length word itself */
265 if ( ((*iptc_text)=mymalloc(length)) == NULL ) return FALSE;
266 while (--length >= 0) (*iptc_text)[cnt++] = jpeg_getc(cinfo);
283 my_output_message (j_common_ptr cinfo)
285 char buffer[JMSG_LENGTH_MAX];
287 /* Create the message */
288 (*cinfo->err->format_message) (cinfo, buffer);
290 /* Send it to stderr, adding a newline */
291 mm_log((1, "%s\n", buffer));
299 struct my_error_mgr {
300 struct jpeg_error_mgr pub; /* "public" fields */
301 jmp_buf setjmp_buffer; /* for return to caller */
304 typedef struct my_error_mgr * my_error_ptr;
306 /* Here's the routine that will replace the standard error_exit method */
309 my_error_exit (j_common_ptr cinfo) {
310 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
311 my_error_ptr myerr = (my_error_ptr) cinfo->err;
313 /* Always display the message. */
314 /* We could postpone this until after returning, if we chose. */
315 (*cinfo->err->output_message) (cinfo);
317 /* Return control to the setjmp point */
318 longjmp(myerr->setjmp_buffer, 1);
327 i_readjpeg(int fd,char** iptc_itext,int *itlength) {
330 struct jpeg_decompress_struct cinfo;
331 /* We use our private extension JPEG error handler.
332 * Note that this struct must live as long as the main JPEG parameter
333 * struct, to avoid dangling-pointer problems.
336 /* struct jpeg_error_mgr jerr;*/
337 struct my_error_mgr jerr;
338 FILE * infile; /* source file */
339 JSAMPARRAY buffer; /* Output row buffer */
340 int row_stride; /* physical row width in output buffer */
342 mm_log((1,"i_readjpeg(fd %d,iptc_itext 0x%x)\n",fd,iptc_itext));
344 iptc_text=iptc_itext;
346 if ((infile = fdopen(fd,"r")) == NULL) {
347 fprintf(stderr, "can't fdopen.\n");
351 /* Step 1: allocate and initialize JPEG decompression object */
353 /* We set up the normal JPEG error routines, then override error_exit. */
354 cinfo.err = jpeg_std_error(&jerr.pub);
355 jerr.pub.error_exit = my_error_exit;
356 jerr.pub.output_message = my_output_message;
357 /* Establish the setjmp return context for my_error_exit to use. */
358 if (setjmp(jerr.setjmp_buffer)) {
359 /* If we get here, the JPEG code has signaled an error.
360 * We need to clean up the JPEG object, close the input file, and return.
362 jpeg_destroy_decompress(&cinfo);
369 /* Now we can initialize the JPEG decompression object. */
370 jpeg_create_decompress(&cinfo);
371 jpeg_set_marker_processor(&cinfo, JPEG_APP13, APP13_handler);
372 /* Step 2: specify data source (eg, a file) */
374 jpeg_stdio_src(&cinfo, infile);
376 /* Step 3: read file parameters with jpeg_read_header() */
378 (void) jpeg_read_header(&cinfo, TRUE);
380 /* We can ignore the return value from jpeg_read_header since
381 * (a) suspension is not possible with the stdio data source, and
382 * (b) we passed TRUE to reject a tables-only JPEG file as an error.
383 * See libjpeg.doc for more info.
386 /* Step 4: set parameters for decompression */
388 /* In this example, we don't need to change any of the defaults set by
389 * jpeg_read_header(), so we do nothing here.
392 /* Step 5: Start decompressor */
394 (void) jpeg_start_decompress(&cinfo);
395 /* We can ignore the return value since suspension is not possible
396 * with the stdio data source.
399 /* We may need to do some setup of our own at this point before reading
400 * the data. After jpeg_start_decompress() we have the correct scaled
401 * output image dimensions available, as well as the output colormap
402 * if we asked for color quantization.
403 * In this example, we need to make an output work buffer of the right size.
406 im=i_img_empty_ch(NULL,cinfo.output_width,cinfo.output_height,cinfo.output_components);
408 /* fprintf(stderr,"JPEG info:\n xsize:%d\n ysize:%d\n channels:%d.\n",xsize,ysize,channels);*/
410 /* JSAMPLEs per row in output buffer */
411 row_stride = cinfo.output_width * cinfo.output_components;
412 /* Make a one-row-high sample array that will go away when done with image */
413 buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
415 /* Step 6: while (scan lines remain to be read) */
416 /* jpeg_read_scanlines(...); */
418 /* Here we use the library's state variable cinfo.output_scanline as the
419 * loop counter, so that we don't have to keep track ourselves.
422 while (cinfo.output_scanline < cinfo.output_height) {
423 /* jpeg_read_scanlines expects an array of pointers to scanlines.
424 * Here the array is only one element long, but you could ask for
425 * more than one scanline at a time if that's more convenient.
427 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
428 /* Assume put_scanline_someplace wants a pointer and sample count. */
429 memcpy(im->data+im->channels*im->xsize*(cinfo.output_scanline-1),buffer[0],row_stride);
432 /* Step 7: Finish decompression */
434 (void) jpeg_finish_decompress(&cinfo);
435 /* We can ignore the return value since suspension is not possible
436 * with the stdio data source.
439 /* Step 8: Release JPEG decompression object */
441 /* This is an important step since it will release a good deal of memory. */
442 jpeg_destroy_decompress(&cinfo);
444 /* After finish_decompress, we can close the input file.
445 * Here we postpone it until after no more JPEG errors are possible,
446 * so as to simplify the setjmp error logic above. (Actually, I don't
447 * think that jpeg_destroy can do an error exit, but why assume anything...)
450 /* fclose(infile); DO NOT fclose() BECAUSE THEN close() WILL FAIL*/
452 /* At this point you may want to check to see whether any corrupt-data
453 * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
456 /* And we're done! */
459 mm_log((1,"i_readjpeg -> (0x%x)\n",im));
466 i_readjpeg_scalar(char *data, int length,char** iptc_itext,int *itlength) {
469 struct jpeg_decompress_struct cinfo;
470 struct my_error_mgr jerr;
471 JSAMPARRAY buffer; /* Output row buffer */
472 int row_stride; /* physical row width in output buffer */
474 mm_log((1,"i_readjpeg_scalar(data 0x%08x, length %d,iptc_itext 0x%x)\n",data,length,iptc_itext));
475 iptc_text=iptc_itext;
477 cinfo.err = jpeg_std_error(&jerr.pub);
478 jerr.pub.error_exit = my_error_exit;
479 jerr.pub.output_message = my_output_message;
480 if (setjmp(jerr.setjmp_buffer)) {
481 jpeg_destroy_decompress(&cinfo);
487 jpeg_create_decompress(&cinfo);
488 jpeg_set_marker_processor(&cinfo, JPEG_APP13, APP13_handler);
489 jpeg_scalar_src(&cinfo, data, length );
490 (void) jpeg_read_header(&cinfo, TRUE);
491 (void) jpeg_start_decompress(&cinfo);
492 im=i_img_empty_ch(NULL,cinfo.output_width,cinfo.output_height,cinfo.output_components);
493 row_stride = cinfo.output_width * cinfo.output_components;
494 buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
495 while (cinfo.output_scanline < cinfo.output_height) {
496 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
497 memcpy(im->data+im->channels*im->xsize*(cinfo.output_scanline-1),buffer[0],row_stride);
499 (void) jpeg_finish_decompress(&cinfo);
500 jpeg_destroy_decompress(&cinfo);
502 mm_log((1,"i_readjpeg_scalar -> (0x%x)\n",im));
563 struct jpeg_source_mgr pub; /* public fields */
565 JOCTET *buffer; /* start of buffer */
566 int length; /* Do I need this? */
567 boolean start_of_file; /* have we gotten any data yet? */
570 typedef wiol_source_mgr *wiol_src_ptr;
573 wiol_init_source (j_decompress_ptr cinfo) {
574 wiol_src_ptr src = (wiol_src_ptr) cinfo->src;
576 /* We reset the empty-input-file flag for each image,
577 * but we don't clear the input buffer.
578 * This is correct behavior for reading a series of images from one source.
580 src->start_of_file = TRUE;
584 wiol_fill_input_buffer(j_decompress_ptr cinfo) {
585 wiol_src_ptr src = (wiol_src_ptr) cinfo->src;
586 ssize_t nbytes; /* We assume that reads are "small" */
588 mm_log((1,"wiol_fill_input_buffer(cinfo 0x%p)\n"));
590 nbytes = src->data->readcb(src->data, src->buffer, JPGS);
592 if (nbytes <= 0) { /* Insert a fake EOI marker */
593 src->pub.next_input_byte = fake_eoi;
594 src->pub.bytes_in_buffer = 2;
596 src->pub.next_input_byte = src->buffer;
597 src->pub.bytes_in_buffer = nbytes;
599 src->start_of_file = FALSE;
604 wiol_skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
605 wiol_src_ptr src = (wiol_src_ptr) cinfo->src;
607 /* Just a dumb implementation for now. Could use fseek() except
608 * it doesn't work on pipes. Not clear that being smart is worth
609 * any trouble anyway --- large skips are infrequent.
613 while (num_bytes > (long) src->pub.bytes_in_buffer) {
614 num_bytes -= (long) src->pub.bytes_in_buffer;
615 (void) wiol_fill_input_buffer(cinfo);
616 /* note we assume that fill_input_buffer will never return FALSE,
617 * so suspension need not be handled.
620 src->pub.next_input_byte += (size_t) num_bytes;
621 src->pub.bytes_in_buffer -= (size_t) num_bytes;
626 wiol_term_source (j_decompress_ptr cinfo) {
627 /* no work necessary here */
629 if (cinfo->src != NULL) {
630 src = (wiol_src_ptr) cinfo->src;
636 jpeg_wiol_src(j_decompress_ptr cinfo, io_glue *ig, int length) {
639 if (cinfo->src == NULL) { /* first time for this JPEG object? */
640 cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)
641 ((j_common_ptr) cinfo, JPOOL_PERMANENT,sizeof(wiol_source_mgr));
642 src = (wiol_src_ptr) cinfo->src;
645 /* put the request method call in here later */
646 io_glue_commit_types(ig);
648 src = (wiol_src_ptr) cinfo->src;
650 src->buffer = mymalloc( JPGS );
651 src->length = length;
653 src->pub.init_source = wiol_init_source;
654 src->pub.fill_input_buffer = wiol_fill_input_buffer;
655 src->pub.skip_input_data = wiol_skip_input_data;
656 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
657 src->pub.term_source = wiol_term_source;
658 src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
659 src->pub.next_input_byte = NULL; /* until buffer loaded */
674 i_readjpeg_wiol(io_glue *data, int length, char** iptc_itext, int *itlength) {
677 struct jpeg_decompress_struct cinfo;
678 struct my_error_mgr jerr;
679 JSAMPARRAY buffer; /* Output row buffer */
680 int row_stride; /* physical row width in output buffer */
682 mm_log((1,"i_readjpeg_wiol(data 0x%p, length %d,iptc_itext 0x%p)\n", data, iptc_itext));
684 iptc_text = iptc_itext;
685 cinfo.err = jpeg_std_error(&jerr.pub);
686 jerr.pub.error_exit = my_error_exit;
687 jerr.pub.output_message = my_output_message;
689 /* Set error handler */
690 if (setjmp(jerr.setjmp_buffer)) {
691 jpeg_destroy_decompress(&cinfo);
697 jpeg_create_decompress(&cinfo);
698 jpeg_set_marker_processor(&cinfo, JPEG_APP13, APP13_handler);
699 jpeg_wiol_src(&cinfo, data, length);
701 (void) jpeg_read_header(&cinfo, TRUE);
702 (void) jpeg_start_decompress(&cinfo);
703 im=i_img_empty_ch(NULL,cinfo.output_width,cinfo.output_height,cinfo.output_components);
704 row_stride = cinfo.output_width * cinfo.output_components;
705 buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
706 while (cinfo.output_scanline < cinfo.output_height) {
707 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
708 memcpy(im->data+im->channels*im->xsize*(cinfo.output_scanline-1),buffer[0],row_stride);
710 (void) jpeg_finish_decompress(&cinfo);
711 jpeg_destroy_decompress(&cinfo);
713 mm_log((1,"i_readjpeg_wiol -> (0x%x)\n",im));