1 /* -*- mode: C; c-file-style: "linux" -*- */
2 /* GdkPixbuf library - JPEG image loader
4 * Copyright (C) 1999 Michael Zucchi
5 * Copyright (C) 1999 The Free Software Foundation
7 * Progressive loading code Copyright (C) 1999 Red Hat, Inc.
9 * Authors: Michael Zucchi <zucchi@zedzone.mmc.com.au>
10 * Federico Mena-Quintero <federico@gimp.org>
11 * Michael Fulbright <drmike@redhat.com>
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2 of the License, or (at your option) any later version.
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the
25 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 * Boston, MA 02111-1307, USA.
37 #include "gdk-pixbuf-private.h"
38 #include "gdk-pixbuf-io.h"
40 #ifndef HAVE_SIGSETJMP
41 #define sigjmp_buf jmp_buf
42 #define sigsetjmp(jb, x) setjmp(jb)
43 #define siglongjmp longjmp
47 /* we are a "source manager" as far as libjpeg is concerned */
48 #define JPEG_PROG_BUF_SIZE 65536
51 struct jpeg_source_mgr pub; /* public fields */
53 JOCTET buffer[JPEG_PROG_BUF_SIZE]; /* start of buffer */
54 long skip_next; /* number of bytes to skip next read */
58 typedef my_source_mgr * my_src_ptr;
60 /* error handler data */
61 struct error_handler_data {
62 struct jpeg_error_mgr pub;
63 sigjmp_buf setjmp_buffer;
67 /* progressive loader context */
69 GdkPixbufModuleSizeFunc size_func;
70 GdkPixbufModuleUpdatedFunc updated_func;
71 GdkPixbufModulePreparedFunc prepared_func;
75 guchar *dptr; /* current position in pixbuf */
77 gboolean did_prescan; /* are we in image data yet? */
78 gboolean got_header; /* have we loaded jpeg header? */
79 gboolean src_initialized;/* TRUE when jpeg lib initialized */
80 gboolean in_output; /* did we get suspended in an output pass? */
81 struct jpeg_decompress_struct cinfo;
82 struct error_handler_data jerr;
85 static GdkPixbuf *gdk_pixbuf__jpeg_image_load (FILE *f, GError **error);
86 static gpointer gdk_pixbuf__jpeg_image_begin_load (GdkPixbufModuleSizeFunc func0,
87 GdkPixbufModulePreparedFunc func1,
88 GdkPixbufModuleUpdatedFunc func2,
91 static gboolean gdk_pixbuf__jpeg_image_stop_load (gpointer context, GError **error);
92 static gboolean gdk_pixbuf__jpeg_image_load_increment(gpointer context,
93 const guchar *buf, guint size,
98 fatal_error_handler (j_common_ptr cinfo)
100 struct error_handler_data *errmgr;
101 char buffer[JMSG_LENGTH_MAX];
103 errmgr = (struct error_handler_data *) cinfo->err;
105 /* Create the message */
106 (* cinfo->err->format_message) (cinfo, buffer);
108 /* broken check for *error == NULL for robustness against
109 * crappy JPEG library
111 if (errmgr->error && *errmgr->error == NULL) {
112 g_set_error (errmgr->error,
114 cinfo->err->msg_code == JERR_OUT_OF_MEMORY
115 ? GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY
116 : GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
117 _("Error interpreting JPEG image file (%s)"),
121 siglongjmp (errmgr->setjmp_buffer, 1);
123 g_assert_not_reached ();
127 output_message_handler (j_common_ptr cinfo)
129 /* This method keeps libjpeg from dumping crap to stderr */
134 /* explode gray image data from jpeg library into rgb components in pixbuf */
136 explode_gray_into_buf (struct jpeg_decompress_struct *cinfo,
142 g_return_if_fail (cinfo != NULL);
143 g_return_if_fail (cinfo->output_components == 1);
144 g_return_if_fail (cinfo->out_color_space == JCS_GRAYSCALE);
146 /* Expand grey->colour. Expand from the end of the
147 * memory down, so we can use the same buffer.
149 w = cinfo->output_width;
150 for (i = cinfo->rec_outbuf_height - 1; i >= 0; i--) {
153 from = lines[i] + w - 1;
154 to = lines[i] + (w - 1) * 3;
155 for (j = w - 1; j >= 0; j--) {
167 convert_cmyk_to_rgb (struct jpeg_decompress_struct *cinfo,
172 g_return_if_fail (cinfo != NULL);
173 g_return_if_fail (cinfo->output_components == 4);
174 g_return_if_fail (cinfo->out_color_space == JCS_CMYK);
176 for (i = cinfo->rec_outbuf_height - 1; i >= 0; i--) {
180 for (j = 0; j < cinfo->output_width; j++) {
186 if (cinfo->saw_Adobe_marker) {
192 p[0] = (255 - k)*(255 - c) / 255;
193 p[1] = (255 - k)*(255 - m) / 255;
194 p[2] = (255 - k)*(255 - y) / 255;
203 struct jpeg_source_mgr pub; /* public fields */
205 FILE * infile; /* source stream */
206 JOCTET * buffer; /* start of buffer */
207 boolean start_of_file; /* have we gotten any data yet? */
210 typedef stdio_source_mgr * stdio_src_ptr;
213 stdio_init_source (j_decompress_ptr cinfo)
215 stdio_src_ptr src = (stdio_src_ptr)cinfo->src;
216 src->start_of_file = FALSE;
220 stdio_fill_input_buffer (j_decompress_ptr cinfo)
222 stdio_src_ptr src = (stdio_src_ptr) cinfo->src;
225 nbytes = fread (src->buffer, 1, JPEG_PROG_BUF_SIZE, src->infile);
229 if (src->start_of_file) /* Treat empty input file as fatal error */
230 ERREXIT(cinfo, JERR_INPUT_EMPTY);
231 WARNMS(cinfo, JWRN_JPEG_EOF);
233 /* Insert a fake EOI marker */
234 src->buffer[0] = (JOCTET) 0xFF;
235 src->buffer[1] = (JOCTET) JPEG_EOI;
239 src->pub.next_input_byte = src->buffer;
240 src->pub.bytes_in_buffer = nbytes;
241 src->start_of_file = FALSE;
247 stdio_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
249 stdio_src_ptr src = (stdio_src_ptr) cinfo->src;
252 while (num_bytes > (long) src->pub.bytes_in_buffer) {
253 num_bytes -= (long) src->pub.bytes_in_buffer;
254 (void)stdio_fill_input_buffer(cinfo);
256 src->pub.next_input_byte += (size_t) num_bytes;
257 src->pub.bytes_in_buffer -= (size_t) num_bytes;
262 stdio_term_source (j_decompress_ptr cinfo)
267 colorspace_name (const J_COLOR_SPACE jpeg_color_space)
269 switch (jpeg_color_space) {
270 case JCS_UNKNOWN: return "UNKNOWN";
271 case JCS_GRAYSCALE: return "GRAYSCALE";
272 case JCS_RGB: return "RGB";
273 case JCS_YCbCr: return "YCbCr";
274 case JCS_CMYK: return "CMYK";
275 case JCS_YCCK: return "YCCK";
276 default: return "invalid";
281 const char leth[] = {0x49, 0x49, 0x2a, 0x00}; // Little endian TIFF header
282 const char beth[] = {0x4d, 0x4d, 0x00, 0x2a}; // Big endian TIFF header
283 const char types[] = {0x00, 0x01, 0x01, 0x02, 0x04, 0x08, 0x00,
284 0x08, 0x00, 0x04, 0x08}; // size in bytes for EXIF types
286 #define DE_ENDIAN16(val) endian == G_BIG_ENDIAN ? GUINT16_FROM_BE(val) : GUINT16_FROM_LE(val)
287 #define DE_ENDIAN32(val) endian == G_BIG_ENDIAN ? GUINT32_FROM_BE(val) : GUINT32_FROM_LE(val)
289 #define ENDIAN16_IT(val) endian == G_BIG_ENDIAN ? GUINT16_TO_BE(val) : GUINT16_TO_LE(val)
290 #define ENDIAN32_IT(val) endian == G_BIG_ENDIAN ? GUINT32_TO_BE(val) : GUINT32_TO_LE(val)
292 #define EXIF_JPEG_MARKER JPEG_APP0+1
293 #define EXIF_IDENT_STRING "Exif\000\000"
295 static unsigned short de_get16(void *ptr, guint endian)
299 memcpy(&val, ptr, sizeof(val));
300 val = DE_ENDIAN16(val);
305 static unsigned int de_get32(void *ptr, guint endian)
309 memcpy(&val, ptr, sizeof(val));
310 val = DE_ENDIAN32(val);
316 get_orientation (j_decompress_ptr cinfo)
318 /* This function looks through the meta data in the libjpeg decompress structure to
319 determine if an EXIF Orientation tag is present and if so return its value (1-8).
320 If no EXIF Orientation tag is found 0 (zero) is returned. */
322 guint i; /* index into working buffer */
323 guint orient_tag_id; /* endianed version of orientation tag ID */
324 guint ret; /* Return value */
325 guint offset; /* de-endianed offset in various situations */
326 guint tags; /* number of tags in current ifd */
327 guint type; /* de-endianed type of tag used as index into types[] */
328 guint count; /* de-endianed count of elements in a tag */
329 guint tiff = 0; /* offset to active tiff header */
330 guint endian = 0; /* detected endian of data */
332 jpeg_saved_marker_ptr exif_marker; /* Location of the Exif APP1 marker */
333 jpeg_saved_marker_ptr cmarker; /* Location to check for Exif APP1 marker */
335 /* check for Exif marker (also called the APP1 marker) */
337 cmarker = cinfo->marker_list;
339 if (cmarker->marker == EXIF_JPEG_MARKER) {
340 /* The Exif APP1 marker should contain a unique
341 identification string ("Exif\0\0"). Check for it. */
342 if (!memcmp (cmarker->data, EXIF_IDENT_STRING, 6)) {
343 exif_marker = cmarker;
346 cmarker = cmarker->next;
349 /* Did we find the Exif APP1 marker? */
350 if (exif_marker == NULL)
353 /* Do we have enough data? */
354 if (exif_marker->data_length < 32)
357 /* Check for TIFF header and catch endianess */
360 /* Just skip data until TIFF header - it should be within 16 bytes from marker start.
361 Normal structure relative to APP1 marker -
362 0x0000: APP1 marker entry = 2 bytes
363 0x0002: APP1 length entry = 2 bytes
364 0x0004: Exif Identifier entry = 6 bytes
365 0x000A: Start of TIFF header (Byte order entry) - 4 bytes
366 - This is what we look for, to determine endianess.
367 0x000E: 0th IFD offset pointer - 4 bytes
369 exif_marker->data points to the first data after the APP1 marker
370 and length entries, which is the exif identification string.
371 The TIFF header should thus normally be found at i=6, below,
372 and the pointer to IFD0 will be at 6+4 = 10.
377 /* Little endian TIFF header */
378 if (memcmp (&exif_marker->data[i], leth, 4) == 0){
379 endian = G_LITTLE_ENDIAN;
382 /* Big endian TIFF header */
383 else if (memcmp (&exif_marker->data[i], beth, 4) == 0){
384 endian = G_BIG_ENDIAN;
387 /* Keep looking through buffer */
392 /* We have found either big or little endian TIFF header */
397 /* So did we find a TIFF header or did we just hit end of buffer? */
401 /* Endian the orientation tag ID, to locate it more easily */
402 orient_tag_id = ENDIAN16_IT(0x112);
404 /* Read out the offset pointer to IFD0 */
405 offset = de_get32(&exif_marker->data[i] + 4, endian);
408 /* Check that we still are within the buffer and can read the tag count */
409 if ((i + 2) > exif_marker->data_length)
412 /* Find out how many tags we have in IFD0. As per the TIFF spec, the first
413 two bytes of the IFD contain a count of the number of tags. */
414 tags = de_get16(&exif_marker->data[i], endian);
417 /* Check that we still have enough data for all tags to check. The tags
418 are listed in consecutive 12-byte blocks. The tag ID, type, size, and
419 a pointer to the actual value, are packed into these 12 byte entries. */
420 if ((i + tags * 12) > exif_marker->data_length)
423 /* Check through IFD0 for tags of interest */
425 type = de_get16(&exif_marker->data[i + 2], endian);
426 count = de_get32(&exif_marker->data[i + 4], endian);
428 /* Is this the orientation tag? */
429 if (memcmp (&exif_marker->data[i], (char *) &orient_tag_id, 2) == 0){
431 /* Check that type and count fields are OK. The orientation field
432 will consist of a single (count=1) 2-byte integer (type=3). */
433 if (type != 3 || count != 1) return 0;
435 /* Return the orientation value. Within the 12-byte block, the
436 pointer to the actual data is at offset 8. */
437 ret = de_get16(&exif_marker->data[i + 8], endian);
438 return ret <= 8 ? ret : 0;
440 /* move the pointer to the next 12-byte tag field. */
444 return 0; /* No EXIF Orientation tag found */
448 /* Shared library entry point */
450 gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
455 GdkPixbuf * volatile pixbuf = NULL;
457 guchar *lines[4]; /* Used to expand rows, via rec_outbuf_height,
458 * from the header file:
459 * " Usually rec_outbuf_height will be 1 or 2,
463 struct jpeg_decompress_struct cinfo;
464 struct error_handler_data jerr;
467 /* setup error handler */
468 cinfo.err = jpeg_std_error (&jerr.pub);
469 jerr.pub.error_exit = fatal_error_handler;
470 jerr.pub.output_message = output_message_handler;
474 if (sigsetjmp (jerr.setjmp_buffer, 1)) {
475 /* Whoops there was a jpeg error */
477 g_object_unref (pixbuf);
479 jpeg_destroy_decompress (&cinfo);
481 /* error should have been set by fatal_error_handler () */
485 /* load header, setup */
486 jpeg_create_decompress (&cinfo);
488 cinfo.src = (struct jpeg_source_mgr *)
489 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
490 sizeof (stdio_source_mgr));
491 src = (stdio_src_ptr) cinfo.src;
492 src->buffer = (JOCTET *)
493 (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
494 JPEG_PROG_BUF_SIZE * sizeof (JOCTET));
496 src->pub.init_source = stdio_init_source;
497 src->pub.fill_input_buffer = stdio_fill_input_buffer;
498 src->pub.skip_input_data = stdio_skip_input_data;
499 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
500 src->pub.term_source = stdio_term_source;
502 src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
503 src->pub.next_input_byte = NULL; /* until buffer loaded */
505 jpeg_save_markers (&cinfo, EXIF_JPEG_MARKER, 0xffff);
506 jpeg_read_header (&cinfo, TRUE);
508 /* check for orientation tag */
509 is_otag = get_orientation (&cinfo);
511 jpeg_start_decompress (&cinfo);
512 cinfo.do_fancy_upsampling = FALSE;
513 cinfo.do_block_smoothing = FALSE;
515 pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
516 cinfo.out_color_components == 4 ? TRUE : FALSE,
517 8, cinfo.output_width, cinfo.output_height);
520 jpeg_destroy_decompress (&cinfo);
522 /* broken check for *error == NULL for robustness against
523 * crappy JPEG library
525 if (error && *error == NULL) {
526 g_set_error_literal (error,
528 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
529 _("Insufficient memory to load image, try exiting some applications to free memory"));
535 /* if orientation tag was found set an option to remember its value */
537 g_snprintf (otag_str, sizeof (otag_str), "%d", is_otag);
538 gdk_pixbuf_set_option (pixbuf, "orientation", otag_str);
542 dptr = pixbuf->pixels;
544 /* decompress all the lines, a few at a time */
545 while (cinfo.output_scanline < cinfo.output_height) {
547 for (i = 0; i < cinfo.rec_outbuf_height; i++) {
549 dptr += pixbuf->rowstride;
552 jpeg_read_scanlines (&cinfo, lines, cinfo.rec_outbuf_height);
554 switch (cinfo.out_color_space) {
556 explode_gray_into_buf (&cinfo, lines);
562 convert_cmyk_to_rgb (&cinfo, lines);
565 g_object_unref (pixbuf);
566 if (error && *error == NULL) {
569 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
570 _("Unsupported JPEG color space (%s)"),
571 colorspace_name (cinfo.out_color_space));
574 jpeg_destroy_decompress (&cinfo);
579 jpeg_finish_decompress (&cinfo);
580 jpeg_destroy_decompress (&cinfo);
586 /**** Progressive image loading handling *****/
588 /* these routines required because we are acting as a source manager for */
591 init_source (j_decompress_ptr cinfo)
593 my_src_ptr src = (my_src_ptr) cinfo->src;
600 term_source (j_decompress_ptr cinfo)
602 /* XXXX - probably should scream something has happened */
606 /* for progressive loading (called "I/O Suspension" by libjpeg docs) */
607 /* we do nothing except return "FALSE" */
609 fill_input_buffer (j_decompress_ptr cinfo)
616 skip_input_data (j_decompress_ptr cinfo, long num_bytes)
618 my_src_ptr src = (my_src_ptr) cinfo->src;
621 /* move as far as we can into current buffer */
622 /* then set skip_next to catch the rest */
624 num_can_do = MIN (src->pub.bytes_in_buffer, num_bytes);
625 src->pub.next_input_byte += (size_t) num_can_do;
626 src->pub.bytes_in_buffer -= (size_t) num_can_do;
628 src->skip_next = num_bytes - num_can_do;
634 * func - called when we have pixmap created (but no image data)
635 * user_data - passed as arg 1 to func
636 * return context (opaque to user)
640 gdk_pixbuf__jpeg_image_begin_load (GdkPixbufModuleSizeFunc size_func,
641 GdkPixbufModulePreparedFunc prepared_func,
642 GdkPixbufModuleUpdatedFunc updated_func,
646 JpegProgContext *context;
649 context = g_new0 (JpegProgContext, 1);
650 context->size_func = size_func;
651 context->prepared_func = prepared_func;
652 context->updated_func = updated_func;
653 context->user_data = user_data;
654 context->pixbuf = NULL;
655 context->got_header = FALSE;
656 context->did_prescan = FALSE;
657 context->src_initialized = FALSE;
658 context->in_output = FALSE;
660 /* create libjpeg structures */
661 jpeg_create_decompress (&context->cinfo);
663 context->cinfo.src = (struct jpeg_source_mgr *) g_try_malloc (sizeof (my_source_mgr));
664 if (!context->cinfo.src) {
665 g_set_error_literal (error,
667 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
668 _("Couldn't allocate memory for loading JPEG file"));
671 memset (context->cinfo.src, 0, sizeof (my_source_mgr));
673 src = (my_src_ptr) context->cinfo.src;
675 context->cinfo.err = jpeg_std_error (&context->jerr.pub);
676 context->jerr.pub.error_exit = fatal_error_handler;
677 context->jerr.pub.output_message = output_message_handler;
678 context->jerr.error = error;
680 src = (my_src_ptr) context->cinfo.src;
681 src->pub.init_source = init_source;
682 src->pub.fill_input_buffer = fill_input_buffer;
683 src->pub.skip_input_data = skip_input_data;
684 src->pub.resync_to_restart = jpeg_resync_to_restart;
685 src->pub.term_source = term_source;
686 src->pub.bytes_in_buffer = 0;
687 src->pub.next_input_byte = NULL;
689 context->jerr.error = NULL;
691 return (gpointer) context;
695 * context - returned from image_begin_load
697 * free context, unref gdk_pixbuf
700 gdk_pixbuf__jpeg_image_stop_load (gpointer data, GError **error)
702 JpegProgContext *context = (JpegProgContext *) data;
705 g_return_val_if_fail (context != NULL, TRUE);
707 /* FIXME this thing needs to report errors if
708 * we have unused image data
712 g_object_unref (context->pixbuf);
714 /* if we have an error? */
715 context->jerr.error = error;
716 if (sigsetjmp (context->jerr.setjmp_buffer, 1)) {
719 jpeg_finish_decompress (&context->cinfo);
723 jpeg_destroy_decompress (&context->cinfo);
725 if (context->cinfo.src) {
726 my_src_ptr src = (my_src_ptr) context->cinfo.src;
738 gdk_pixbuf__jpeg_image_load_lines (JpegProgContext *context,
741 struct jpeg_decompress_struct *cinfo = &context->cinfo;
747 /* keep going until we've done all scanlines */
748 while (cinfo->output_scanline < cinfo->output_height) {
750 rowptr = context->dptr;
751 for (i=0; i < cinfo->rec_outbuf_height; i++) {
753 rowptr += context->pixbuf->rowstride;
756 nlines = jpeg_read_scanlines (cinfo, lines,
757 cinfo->rec_outbuf_height);
761 switch (cinfo->out_color_space) {
763 explode_gray_into_buf (cinfo, lines);
769 convert_cmyk_to_rgb (cinfo, lines);
772 if (error && *error == NULL) {
775 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
776 _("Unsupported JPEG color space (%s)"),
777 colorspace_name (cinfo->out_color_space));
783 context->dptr += nlines * context->pixbuf->rowstride;
785 /* send updated signal */
786 if (context->updated_func)
787 (* context->updated_func) (context->pixbuf,
789 cinfo->output_scanline - 1,
800 * context - from image_begin_load
801 * buf - new image data
802 * size - length of new image data
804 * append image data onto inrecrementally built output image
807 gdk_pixbuf__jpeg_image_load_increment (gpointer data,
808 const guchar *buf, guint size,
811 JpegProgContext *context = (JpegProgContext *)data;
812 struct jpeg_decompress_struct *cinfo;
814 guint num_left, num_copy;
815 guint last_num_left, last_bytes_left;
823 g_return_val_if_fail (context != NULL, FALSE);
824 g_return_val_if_fail (buf != NULL, FALSE);
826 src = (my_src_ptr) context->cinfo.src;
828 cinfo = &context->cinfo;
830 context->jerr.error = error;
832 /* check for fatal error */
833 if (sigsetjmp (context->jerr.setjmp_buffer, 1)) {
837 /* skip over data if requested, handle unsigned int sizes cleanly */
838 /* only can happen if we've already called jpeg_get_header once */
839 if (context->src_initialized && src->skip_next) {
840 if (src->skip_next > size) {
841 src->skip_next -= size;
844 num_left = size - src->skip_next;
845 bufhd = buf + src->skip_next;
856 last_num_left = num_left;
862 /* handle any data from caller we haven't processed yet */
864 if(src->pub.bytes_in_buffer &&
865 src->pub.next_input_byte != src->buffer)
866 memmove(src->buffer, src->pub.next_input_byte,
867 src->pub.bytes_in_buffer);
870 num_copy = MIN (JPEG_PROG_BUF_SIZE - src->pub.bytes_in_buffer,
873 memcpy(src->buffer + src->pub.bytes_in_buffer, bufhd,num_copy);
874 src->pub.next_input_byte = src->buffer;
875 src->pub.bytes_in_buffer += num_copy;
877 num_left -= num_copy;
880 /* did anything change from last pass, if not return */
882 last_bytes_left = src->pub.bytes_in_buffer;
884 } else if (src->pub.bytes_in_buffer == last_bytes_left
885 && num_left == last_num_left) {
888 last_bytes_left = src->pub.bytes_in_buffer;
889 last_num_left = num_left;
892 /* should not go through twice and not pull bytes out of buf */
896 /* try to load jpeg header */
897 if (!context->got_header) {
900 jpeg_save_markers (cinfo, EXIF_JPEG_MARKER, 0xffff);
901 rc = jpeg_read_header (cinfo, TRUE);
902 context->src_initialized = TRUE;
904 if (rc == JPEG_SUSPENDED)
907 context->got_header = TRUE;
909 /* check for orientation tag */
910 is_otag = get_orientation (cinfo);
912 width = cinfo->image_width;
913 height = cinfo->image_height;
914 if (context->size_func) {
915 (* context->size_func) (&width, &height, context->user_data);
916 if (width == 0 || height == 0) {
917 g_set_error_literal (error,
919 GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
920 _("Transformed JPEG has zero width or height."));
925 for (cinfo->scale_denom = 2; cinfo->scale_denom <= 8; cinfo->scale_denom *= 2) {
926 jpeg_calc_output_dimensions (cinfo);
927 if (cinfo->output_width < width || cinfo->output_height < height) {
928 cinfo->scale_denom /= 2;
932 jpeg_calc_output_dimensions (cinfo);
934 context->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
935 cinfo->output_components == 4 ? TRUE : FALSE,
938 cinfo->output_height);
940 if (context->pixbuf == NULL) {
941 g_set_error_literal (error,
943 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
944 _("Couldn't allocate memory for loading JPEG file"));
948 /* if orientation tag was found set an option to remember its value */
950 g_snprintf (otag_str, sizeof (otag_str), "%d", is_otag);
951 gdk_pixbuf_set_option (context->pixbuf, "orientation", otag_str);
954 /* Use pixbuf buffer to store decompressed data */
955 context->dptr = context->pixbuf->pixels;
957 /* Notify the client that we are ready to go */
958 if (context->prepared_func)
959 (* context->prepared_func) (context->pixbuf,
963 } else if (!context->did_prescan) {
966 /* start decompression */
967 cinfo->buffered_image = cinfo->progressive_mode;
968 rc = jpeg_start_decompress (cinfo);
969 cinfo->do_fancy_upsampling = FALSE;
970 cinfo->do_block_smoothing = FALSE;
972 if (rc == JPEG_SUSPENDED)
975 context->did_prescan = TRUE;
976 } else if (!cinfo->buffered_image) {
977 /* we're decompressing unbuffered so
978 * simply get scanline by scanline from jpeg lib
980 if (! gdk_pixbuf__jpeg_image_load_lines (context,
984 if (cinfo->output_scanline >= cinfo->output_height)
987 /* we're decompressing buffered (progressive)
988 * so feed jpeg lib scanlines
991 /* keep going until we've done all passes */
992 while (!jpeg_input_complete (cinfo)) {
993 if (!context->in_output) {
994 if (jpeg_start_output (cinfo, cinfo->input_scan_number)) {
995 context->in_output = TRUE;
996 context->dptr = context->pixbuf->pixels;
1002 /* get scanlines from jpeg lib */
1003 if (! gdk_pixbuf__jpeg_image_load_lines (context,
1007 if (cinfo->output_scanline >= cinfo->output_height &&
1008 jpeg_finish_output (cinfo))
1009 context->in_output = FALSE;
1013 if (jpeg_input_complete (cinfo))
1014 /* did entire image */
1024 #define TO_FUNCTION_BUF_SIZE 4096
1027 struct jpeg_destination_mgr pub;
1029 GdkPixbufSaveFunc save_func;
1032 } ToFunctionDestinationManager;
1035 to_callback_init (j_compress_ptr cinfo)
1037 ToFunctionDestinationManager *destmgr;
1039 destmgr = (ToFunctionDestinationManager*) cinfo->dest;
1040 destmgr->pub.next_output_byte = destmgr->buffer;
1041 destmgr->pub.free_in_buffer = TO_FUNCTION_BUF_SIZE;
1045 to_callback_do_write (j_compress_ptr cinfo, gsize length)
1047 ToFunctionDestinationManager *destmgr;
1049 destmgr = (ToFunctionDestinationManager*) cinfo->dest;
1050 if (!destmgr->save_func (destmgr->buffer,
1053 destmgr->user_data)) {
1054 struct error_handler_data *errmgr;
1056 errmgr = (struct error_handler_data *) cinfo->err;
1057 /* Use a default error message if the callback didn't set one,
1058 * which it should have.
1060 if (errmgr->error && *errmgr->error == NULL) {
1061 g_set_error_literal (errmgr->error,
1063 GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
1064 "write function failed");
1066 siglongjmp (errmgr->setjmp_buffer, 1);
1067 g_assert_not_reached ();
1072 to_callback_empty_output_buffer (j_compress_ptr cinfo)
1074 ToFunctionDestinationManager *destmgr;
1076 destmgr = (ToFunctionDestinationManager*) cinfo->dest;
1077 to_callback_do_write (cinfo, TO_FUNCTION_BUF_SIZE);
1078 destmgr->pub.next_output_byte = destmgr->buffer;
1079 destmgr->pub.free_in_buffer = TO_FUNCTION_BUF_SIZE;
1084 to_callback_terminate (j_compress_ptr cinfo)
1086 ToFunctionDestinationManager *destmgr;
1088 destmgr = (ToFunctionDestinationManager*) cinfo->dest;
1089 to_callback_do_write (cinfo, TO_FUNCTION_BUF_SIZE - destmgr->pub.free_in_buffer);
1093 real_save_jpeg (GdkPixbuf *pixbuf,
1097 gboolean to_callback,
1099 GdkPixbufSaveFunc save_func,
1102 /* FIXME error handling is broken */
1104 struct jpeg_compress_struct cinfo;
1107 guchar *pixels = NULL;
1110 volatile int quality = 75; /* default; must be between 0 and 100 */
1115 struct error_handler_data jerr;
1116 ToFunctionDestinationManager to_callback_destmgr;
1118 to_callback_destmgr.buffer = NULL;
1120 if (keys && *keys) {
1121 gchar **kiter = keys;
1122 gchar **viter = values;
1125 if (strcmp (*kiter, "quality") == 0) {
1126 char *endptr = NULL;
1127 quality = strtol (*viter, &endptr, 10);
1129 if (endptr == *viter) {
1132 GDK_PIXBUF_ERROR_BAD_OPTION,
1133 _("JPEG quality must be a value between 0 and 100; value '%s' could not be parsed."),
1141 /* This is a user-visible error;
1142 * lets people skip the range-checking
1147 GDK_PIXBUF_ERROR_BAD_OPTION,
1148 _("JPEG quality must be a value between 0 and 100; value '%d' is not allowed."),
1154 g_warning ("Unrecognized parameter (%s) passed to JPEG saver.", *kiter);
1162 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
1163 n_channels = gdk_pixbuf_get_n_channels (pixbuf);
1165 w = gdk_pixbuf_get_width (pixbuf);
1166 h = gdk_pixbuf_get_height (pixbuf);
1167 pixels = gdk_pixbuf_get_pixels (pixbuf);
1169 /* Allocate a small buffer to convert image data,
1170 * and a larger buffer if doing to_callback save.
1172 buf = g_try_malloc (w * 3 * sizeof (guchar));
1174 g_set_error_literal (error,
1176 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
1177 _("Couldn't allocate memory for loading JPEG file"));
1181 to_callback_destmgr.buffer = g_try_malloc (TO_FUNCTION_BUF_SIZE);
1182 if (!to_callback_destmgr.buffer) {
1183 g_set_error_literal (error,
1185 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
1186 _("Couldn't allocate memory for loading JPEG file"));
1191 /* set up error handling */
1192 jerr.pub.error_exit = fatal_error_handler;
1193 jerr.pub.output_message = output_message_handler;
1196 cinfo.err = jpeg_std_error (&(jerr.pub));
1197 if (sigsetjmp (jerr.setjmp_buffer, 1)) {
1198 jpeg_destroy_compress (&cinfo);
1200 g_free (to_callback_destmgr.buffer);
1204 /* setup compress params */
1205 jpeg_create_compress (&cinfo);
1207 to_callback_destmgr.pub.init_destination = to_callback_init;
1208 to_callback_destmgr.pub.empty_output_buffer = to_callback_empty_output_buffer;
1209 to_callback_destmgr.pub.term_destination = to_callback_terminate;
1210 to_callback_destmgr.error = error;
1211 to_callback_destmgr.save_func = save_func;
1212 to_callback_destmgr.user_data = user_data;
1213 cinfo.dest = (struct jpeg_destination_mgr*) &to_callback_destmgr;
1215 jpeg_stdio_dest (&cinfo, f);
1217 cinfo.image_width = w;
1218 cinfo.image_height = h;
1219 cinfo.input_components = 3;
1220 cinfo.in_color_space = JCS_RGB;
1222 /* set up jepg compression parameters */
1223 jpeg_set_defaults (&cinfo);
1224 jpeg_set_quality (&cinfo, quality, TRUE);
1225 jpeg_start_compress (&cinfo, TRUE);
1226 /* get the start pointer */
1228 /* go one scanline at a time... and save */
1230 while (cinfo.next_scanline < cinfo.image_height) {
1231 /* convert scanline from ARGB to RGB packed */
1232 for (j = 0; j < w; j++)
1233 memcpy (&(buf[j*3]), &(ptr[i*rowstride + j*n_channels]), 3);
1235 /* write scanline */
1236 jbuf = (JSAMPROW *)(&buf);
1237 jpeg_write_scanlines (&cinfo, jbuf, 1);
1244 jpeg_finish_compress (&cinfo);
1245 jpeg_destroy_compress(&cinfo);
1247 g_free (to_callback_destmgr.buffer);
1252 gdk_pixbuf__jpeg_image_save (FILE *f,
1258 return real_save_jpeg (pixbuf, keys, values, error,
1259 FALSE, f, NULL, NULL);
1263 gdk_pixbuf__jpeg_image_save_to_callback (GdkPixbufSaveFunc save_func,
1270 return real_save_jpeg (pixbuf, keys, values, error,
1271 TRUE, NULL, save_func, user_data);
1274 #ifndef INCLUDE_jpeg
1275 #define MODULE_ENTRY(function) G_MODULE_EXPORT void function
1277 #define MODULE_ENTRY(function) void _gdk_pixbuf__jpeg_ ## function
1280 MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
1282 module->load = gdk_pixbuf__jpeg_image_load;
1283 module->begin_load = gdk_pixbuf__jpeg_image_begin_load;
1284 module->stop_load = gdk_pixbuf__jpeg_image_stop_load;
1285 module->load_increment = gdk_pixbuf__jpeg_image_load_increment;
1286 module->save = gdk_pixbuf__jpeg_image_save;
1287 module->save_to_callback = gdk_pixbuf__jpeg_image_save_to_callback;
1290 MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
1292 static GdkPixbufModulePattern signature[] = {
1293 { "\xff\xd8", NULL, 100 },
1296 static gchar * mime_types[] = {
1300 static gchar * extensions[] = {
1307 info->name = "jpeg";
1308 info->signature = signature;
1309 info->description = N_("The JPEG image format");
1310 info->mime_types = mime_types;
1311 info->extensions = extensions;
1312 info->flags = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE;
1313 info->license = "LGPL";