static gboolean gdk_pixbuf__jpeg_image_load_lines (JpegProgContext *context, GError **error) { struct jpeg_decompress_struct *cinfo = &context->cinfo; guchar *lines[4]; guchar **lptr; guchar *rowptr; gint nlines, i; /* keep going until we've done all scanlines */ while (cinfo->output_scanline < cinfo->output_height) { lptr = lines; rowptr = context->dptr; for (i=0; i < cinfo->rec_outbuf_height; i++) { *lptr++ = rowptr; rowptr += context->pixbuf->rowstride; } nlines = jpeg_read_scanlines (cinfo, lines, cinfo->rec_outbuf_height); if (nlines == 0) break; switch (cinfo->out_color_space) { case JCS_GRAYSCALE: explode_gray_into_buf (cinfo, lines); break; case JCS_RGB: /* do nothing */ break; case JCS_CMYK: convert_cmyk_to_rgb (cinfo, lines); break; default: if (error && *error == NULL) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_UNKNOWN_TYPE, _("Unsupported JPEG color space (%s)"), colorspace_name (cinfo->out_color_space)); } return FALSE; } context->dptr += nlines * context->pixbuf->rowstride; /* send updated signal */ if (context->updated_func) (* context->updated_func) (context->pixbuf, 0, cinfo->output_scanline - 1, cinfo->image_width, nlines, context->user_data); } return TRUE; }
static void print_verbose_info_about_header(struct jpeg_decompress_struct const cinfo){ struct jpeg_marker_struct * markerP; pm_message("input color space is %d (%s)\n", cinfo.jpeg_color_space, colorspace_name(cinfo.jpeg_color_space)); /* Note that raw information about marker, including marker type code, was already printed by the jpeg library, due to the jpeg library trace level >= 1. Our job is to interpret it a little bit. */ if (cinfo.marker_list) pm_message("Miscellaneous markers (excluding APP0, APP12) " "in header:"); else pm_message("No miscellaneous markers (excluding APP0, APP12) " "in header"); for (markerP = cinfo.marker_list; markerP; markerP = markerP->next) { if (markerP->marker == JPEG_COM) pm_message("Comment marker (COM):"); else if (markerP->marker >= JPEG_APP0 && markerP->marker <= JPEG_APP0+15) pm_message("Miscellaneous marker type APP%d:", markerP->marker - JPEG_APP0); else pm_message("Miscellaneous marker of unknown type (0x%X):", markerP->marker); print_marker(*markerP); } }
/* Shared library entry point */ static GdkPixbuf * gdk_pixbuf__jpeg_image_load (FILE *f, GError **error) { gint i; int is_otag; char otag_str[5]; GdkPixbuf * volatile pixbuf = NULL; guchar *dptr; guchar *lines[4]; /* Used to expand rows, via rec_outbuf_height, * from the header file: * " Usually rec_outbuf_height will be 1 or 2, * at most 4." */ guchar **lptr; struct jpeg_decompress_struct cinfo; struct error_handler_data jerr; stdio_src_ptr src; /* setup error handler */ cinfo.err = jpeg_std_error (&jerr.pub); jerr.pub.error_exit = fatal_error_handler; jerr.pub.output_message = output_message_handler; jerr.error = error; if (sigsetjmp (jerr.setjmp_buffer, 1)) { /* Whoops there was a jpeg error */ if (pixbuf) g_object_unref (pixbuf); jpeg_destroy_decompress (&cinfo); /* error should have been set by fatal_error_handler () */ return NULL; } /* load header, setup */ jpeg_create_decompress (&cinfo); cinfo.src = (struct jpeg_source_mgr *) (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, sizeof (stdio_source_mgr)); src = (stdio_src_ptr) cinfo.src; src->buffer = (JOCTET *) (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT, JPEG_PROG_BUF_SIZE * sizeof (JOCTET)); src->pub.init_source = stdio_init_source; src->pub.fill_input_buffer = stdio_fill_input_buffer; src->pub.skip_input_data = stdio_skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ src->pub.term_source = stdio_term_source; src->infile = f; src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ src->pub.next_input_byte = NULL; /* until buffer loaded */ jpeg_save_markers (&cinfo, EXIF_JPEG_MARKER, 0xffff); jpeg_read_header (&cinfo, TRUE); /* check for orientation tag */ is_otag = get_orientation (&cinfo); jpeg_start_decompress (&cinfo); cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, cinfo.out_color_components == 4 ? TRUE : FALSE, 8, cinfo.output_width, cinfo.output_height); if (!pixbuf) { jpeg_destroy_decompress (&cinfo); /* broken check for *error == NULL for robustness against * crappy JPEG library */ if (error && *error == NULL) { g_set_error_literal (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Insufficient memory to load image, try exiting some applications to free memory")); } return NULL; } /* if orientation tag was found set an option to remember its value */ if (is_otag) { g_snprintf (otag_str, sizeof (otag_str), "%d", is_otag); gdk_pixbuf_set_option (pixbuf, "orientation", otag_str); } dptr = pixbuf->pixels; /* decompress all the lines, a few at a time */ while (cinfo.output_scanline < cinfo.output_height) { lptr = lines; for (i = 0; i < cinfo.rec_outbuf_height; i++) { *lptr++ = dptr; dptr += pixbuf->rowstride; } jpeg_read_scanlines (&cinfo, lines, cinfo.rec_outbuf_height); switch (cinfo.out_color_space) { case JCS_GRAYSCALE: explode_gray_into_buf (&cinfo, lines); break; case JCS_RGB: /* do nothing */ break; case JCS_CMYK: convert_cmyk_to_rgb (&cinfo, lines); break; default: g_object_unref (pixbuf); if (error && *error == NULL) { g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_UNKNOWN_TYPE, _("Unsupported JPEG color space (%s)"), colorspace_name (cinfo.out_color_space)); } jpeg_destroy_decompress (&cinfo); return NULL; } } jpeg_finish_decompress (&cinfo); jpeg_destroy_decompress (&cinfo); return pixbuf; }