diff options
author | Matthias Clasen <matthiasc@src.gnome.org> | 2002-07-01 22:20:20 +0000 |
---|---|---|
committer | Matthias Clasen <matthiasc@src.gnome.org> | 2002-07-01 22:20:20 +0000 |
commit | 155aa55bedfb06b0f065934edcf3ab93e8e42f1c (patch) | |
tree | 8c9eefe69078e39f1eab651e527355bd336bc508 /gdk-pixbuf | |
parent | 3778b86c2e2fe91fc668234f66bf6b88de48c084 (diff) | |
download | gtk+-155aa55bedfb06b0f065934edcf3ab93e8e42f1c.tar.gz |
Better colorspace support for the jpeg loader (#61211):
* io-jpeg.c (convert_cmyk_to_rgb): New function.
(gdk_pixbuf__jpeg_image_load,
gdk_pixbuf__jpeg_image_load_increment): Allocate a pixbuf with
alpha for 4-channel jpegs and call convert_cmyk_to_rgb for these.
Diffstat (limited to 'gdk-pixbuf')
-rw-r--r-- | gdk-pixbuf/ChangeLog | 9 | ||||
-rw-r--r-- | gdk-pixbuf/io-jpeg.c | 128 |
2 files changed, 119 insertions, 18 deletions
diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index 301487f16c..078d646785 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,3 +1,12 @@ +2002-07-02 Matthias Clasen <maclas@gmx.de> + + Better colorspace support for the jpeg loader (#61211): + + * io-jpeg.c (convert_cmyk_to_rgb): New function. + (gdk_pixbuf__jpeg_image_load, + gdk_pixbuf__jpeg_image_load_increment): Allocate a pixbuf with + alpha for 4-channel jpegs and call convert_cmyk_to_rgb for these. + 2002-06-28 Sven Neumann <sven@gimp.org> * gdk-pixbuf-csource.c (print_blurb): converted a Tab to spaces. diff --git a/gdk-pixbuf/io-jpeg.c b/gdk-pixbuf/io-jpeg.c index 9e7aed2472..0081402e83 100644 --- a/gdk-pixbuf/io-jpeg.c +++ b/gdk-pixbuf/io-jpeg.c @@ -135,6 +135,7 @@ explode_gray_into_buf (struct jpeg_decompress_struct *cinfo, g_return_if_fail (cinfo != NULL); g_return_if_fail (cinfo->output_components == 1); + g_return_if_fail (cinfo->out_color_space == JCS_GRAYSCALE); /* Expand grey->colour. Expand from the end of the * memory down, so we can use the same buffer. @@ -155,6 +156,43 @@ explode_gray_into_buf (struct jpeg_decompress_struct *cinfo, } } + +static void +convert_cmyk_to_rgb (struct jpeg_decompress_struct *cinfo, + guchar **lines) +{ + gint i, j; + + g_return_if_fail (cinfo != NULL); + g_return_if_fail (cinfo->output_components == 4); + g_return_if_fail (cinfo->out_color_space == JCS_CMYK); + + for (i = cinfo->rec_outbuf_height - 1; i >= 0; i--) { + guchar *p; + + p = lines[i]; + for (j = 0; j < cinfo->image_width; j++) { + int c, m, y, k; + c = p[0]; + m = p[1]; + y = p[2]; + k = p[3]; + if (cinfo->saw_Adobe_marker) { + p[0] = k*c / 255; + p[1] = k*m / 255; + p[2] = k*y / 255; + } + else { + p[0] = (255 - k)*(255 - c) / 255; + p[1] = (255 - k)*(255 - m) / 255; + p[2] = (255 - k)*(255 - y) / 255; + } + p[3] = 255; + p += 4; + } + } +} + typedef struct { struct jpeg_source_mgr pub; /* public fields */ @@ -219,6 +257,20 @@ stdio_term_source (j_decompress_ptr cinfo) { } +static gchar * +colorspace_name (const J_COLOR_SPACE jpeg_color_space) +{ + switch (jpeg_color_space) { + case JCS_UNKNOWN: return "UNKNOWN"; + case JCS_GRAYSCALE: return "GRAYSCALE"; + case JCS_RGB: return "RGB"; + case JCS_YCbCr: return "YCbCr"; + case JCS_CMYK: return "CMYK"; + case JCS_YCCK: return "YCCK"; + default: return "invalid"; + } +} + /* Shared library entry point */ static GdkPixbuf * gdk_pixbuf__jpeg_image_load (FILE *f, GError **error) @@ -277,8 +329,10 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error) cinfo.do_fancy_upsampling = FALSE; cinfo.do_block_smoothing = FALSE; - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, cinfo.output_width, cinfo.output_height); - + 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); @@ -298,7 +352,6 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error) 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++) { @@ -308,8 +361,28 @@ gdk_pixbuf__jpeg_image_load (FILE *f, GError **error) jpeg_read_scanlines (&cinfo, lines, cinfo.rec_outbuf_height); - if (cinfo.output_components == 1) - explode_gray_into_buf (&cinfo, lines); + 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)); + } + + jpeg_destroy_decompress (&cinfo); + return NULL; + } } jpeg_finish_decompress (&cinfo); @@ -572,8 +645,17 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data, context->got_header = TRUE; + } else if (!context->did_prescan) { + int rc; + + /* start decompression */ + cinfo->buffered_image = TRUE; + rc = jpeg_start_decompress (cinfo); + cinfo->do_fancy_upsampling = FALSE; + cinfo->do_block_smoothing = FALSE; + context->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, - FALSE, + cinfo->output_components == 4 ? TRUE : FALSE, 8, cinfo->image_width, cinfo->image_height); @@ -594,14 +676,6 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data, NULL, context->user_data); - } else if (!context->did_prescan) { - int rc; - - /* start decompression */ - cinfo->buffered_image = TRUE; - rc = jpeg_start_decompress (cinfo); - cinfo->do_fancy_upsampling = FALSE; - cinfo->do_block_smoothing = FALSE; if (rc == JPEG_SUSPENDED) continue; @@ -638,10 +712,28 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data, if (nlines == 0) break; - /* handle gray */ - if (cinfo->output_components == 1) - explode_gray_into_buf (cinfo, lines); - + 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 */ |