[gegl] operations: Support CMYK in jpg-load
- From: Jon Nordby <jonnor src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] operations: Support CMYK in jpg-load
- Date: Tue, 12 Aug 2014 00:06:10 +0000 (UTC)
commit a7a2f129560ec6e1746ca0dd47b46d8699094495
Author: Jon Nordby <jononor gmail com>
Date: Mon Aug 11 22:06:34 2014 +0200
operations: Support CMYK in jpg-load
Before would fail with "attempted to load unsupported JPEG (components=4)"
Also changes the format selection logic to be based on the out_color_space
in JPEG, instead of deducing it from the number of channels.
Note: uses the 'naive' CMYK support in BABL, which looks to
match what other viewer programs like Firefox and Eye of Gnome does.
operations/external/jpg-load.c | 106 +++++++++++++++++++++++++++++++---------
1 files changed, 82 insertions(+), 24 deletions(-)
---
diff --git a/operations/external/jpg-load.c b/operations/external/jpg-load.c
index e05d059..68a137e 100644
--- a/operations/external/jpg-load.c
+++ b/operations/external/jpg-load.c
@@ -34,15 +34,66 @@ property_file_path (path, _("File"), "")
#include <stdio.h>
#include <jpeglib.h>
+static const gchar *
+jpeg_colorspace_name(J_COLOR_SPACE space)
+{
+ static const gchar * const names[] = {
+ "Unknown",
+ "Grayscale",
+ "RGB",
+ "YCbCr",
+ "CMYK",
+ "YCCK"
+ };
+ const gint n_valid_names = G_N_ELEMENTS(names);
+ const gint idx = (space > 0 && space < n_valid_names) ? (gint)space : 0;
+ return names[idx];
+}
+
+static const Babl *
+babl_from_jpeg_colorspace(J_COLOR_SPACE space)
+{
+ // XXX: assumes bitdepth == 8
+ const Babl *format = NULL;
+ if (space == JCS_GRAYSCALE)
+ format = babl_format ("Y' u8");
+ else if (space == JCS_RGB)
+ format = babl_format ("R'G'B' u8");
+ else if (space == JCS_CMYK) {
+ static gboolean reg = FALSE;
+ if (!reg) {
+ // TODO: move into babl?
+ reg = TRUE;
+ babl_format_new (
+ "name", "CMYK u8",
+ babl_model ("CMYK"),
+ babl_type ("u8"),
+ babl_component ("cyan"),
+ babl_component ("magenta"),
+ babl_component ("yellow"),
+ babl_component ("key"),
+ NULL
+ );
+ }
+ format = babl_format("CMYK u8");
+ g_assert(format);
+ }
+
+ return format;
+}
+
+
static gint
gegl_jpg_load_query_jpg (const gchar *path,
gint *width,
gint *height,
- gint *components)
+ const Babl **out_format)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *infile;
+ gint status = 0;
+ const Babl *format = NULL;
if ((infile = fopen (path, "rb")) == NULL)
{
@@ -56,17 +107,24 @@ gegl_jpg_load_query_jpg (const gchar *path,
(void) jpeg_read_header (&cinfo, TRUE);
+ format = babl_from_jpeg_colorspace(cinfo.out_color_space);
if (width)
*width = cinfo.image_width;
if (height)
*height = cinfo.image_height;
- if (components)
- *components = cinfo.num_components;
+ if (out_format)
+ *out_format = format;
+ if (!format)
+ {
+ g_warning ("attempted to load JPEG with unsupported color space: '%s'",
+ jpeg_colorspace_name(cinfo.out_color_space));
+ status = -1;
+ }
jpeg_destroy_decompress (&cinfo);
fclose (infile);
- return 0;
+ return status;
}
static gint
@@ -96,14 +154,11 @@ gegl_jpg_load_buffer_import_jpg (GeglBuffer *gegl_buffer,
(void) jpeg_read_header (&cinfo, TRUE);
(void) jpeg_start_decompress (&cinfo);
- if (cinfo.output_components == 1)
- format = babl_format ("Y' u8");
- else if (cinfo.output_components == 3)
- format = babl_format ("R'G'B' u8");
- else
+ format = babl_from_jpeg_colorspace(cinfo.out_color_space);
+ if (!format)
{
- g_warning ("attempted to load unsupported JPEG (components=%d)",
- cinfo.output_components);
+ g_warning ("attempted to load JPEG with unsupported color space: '%s'",
+ jpeg_colorspace_name(cinfo.out_color_space));
jpeg_destroy_decompress (&cinfo);
return -1;
}
@@ -122,10 +177,20 @@ gegl_jpg_load_buffer_import_jpg (GeglBuffer *gegl_buffer,
write_rect.width = cinfo.output_width;
write_rect.height = 1;
+ // Most CMYK JPEG files are produced by Adobe Photoshop. Each component is stored where 0 means 100% ink
+ // However this might not be case for all. Gory details:
https://bugzilla.mozilla.org/show_bug.cgi?id=674619
+ const gboolean is_inverted_cmyk = (format == babl_format("CMYK u8"));
+
while (cinfo.output_scanline < cinfo.output_height)
{
jpeg_read_scanlines (&cinfo, buffer, 1);
+ if (is_inverted_cmyk) {
+ for (int i=0; i<row_stride; i++) {
+ buffer[0][i] = 255-buffer[0][i];
+ }
+ }
+
gegl_buffer_set (gegl_buffer, &write_rect, 0,
format, buffer[0],
GEGL_AUTO_ROWSTRIDE);
@@ -142,20 +207,13 @@ gegl_jpg_load_buffer_import_jpg (GeglBuffer *gegl_buffer,
static GeglRectangle
gegl_jpg_load_get_bounding_box (GeglOperation *operation)
{
+ gint width, height;
GeglProperties *o = GEGL_PROPERTIES (operation);
- gint width, height, components;
- gint status;
- status = gegl_jpg_load_query_jpg (o->path, &width, &height, &components);
-
- if (components == 1)
- gegl_operation_set_format (operation, "output", babl_format ("Y' u8"));
- else if (components == 3)
- gegl_operation_set_format (operation, "output", babl_format ("R'G'B' u8"));
- else
- {
- g_warning ("attempted to load unsupported JPEG (components=%d)", components);
- status = -1;
- }
+ const Babl *format = NULL;
+ const gint status = gegl_jpg_load_query_jpg (o->path, &width, &height, &format);
+
+ if (format)
+ gegl_operation_set_format (operation, "output", format);
if (status)
return (GeglRectangle) {0, 0, 0, 0};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]