[gthumb: 63/129] cairo-io-jpeg: added color space convertion



commit ec6698ab8bf5108a4c2c31435cf7c05f292d9dbe
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sat Apr 23 16:40:02 2011 +0200

    cairo-io-jpeg: added color space convertion

 extensions/cairo_io/cairo-io-jpeg.c |  202 +++++++++++++++++++++++++++++------
 1 files changed, 169 insertions(+), 33 deletions(-)
---
diff --git a/extensions/cairo_io/cairo-io-jpeg.c b/extensions/cairo_io/cairo-io-jpeg.c
index 17c499b..4a2ae06 100644
--- a/extensions/cairo_io/cairo-io-jpeg.c
+++ b/extensions/cairo_io/cairo-io-jpeg.c
@@ -94,14 +94,24 @@ _cairo_image_surface_create_from_jpeg (GthFileData   *file_data,
 	unsigned char                 *surface_row;
 	JSAMPARRAY                     buffer;
 	int                            buffer_stride;
+	JDIMENSION                     n_lines;
 	JSAMPARRAY                     buffer_row;
+	int                            l;
 	unsigned char                 *p_surface;
 	unsigned char                 *p_buffer;
-	JDIMENSION                     nlines;
-	int                            x, l;
+	int                            x;
 
 	image = gth_image_new ();
 
+	if (! g_load_file_in_buffer (file_data->file,
+			      	     &in_buffer,
+			      	     &in_buffer_size,
+			      	     cancellable,
+			      	     error))
+	{
+		return image;
+	}
+
 	srcinfo.err = jpeg_std_error (&(jsrcerr.pub));
 	jsrcerr.pub.error_exit = fatal_error_handler;
 	jsrcerr.pub.output_message = output_message_handler;
@@ -114,27 +124,17 @@ _cairo_image_surface_create_from_jpeg (GthFileData   *file_data,
 		return image;
 	}
 
-	if (! g_load_file_in_buffer (file_data->file,
-			      	     &in_buffer,
-			      	     &in_buffer_size,
-			      	     error))
-	{
-		jpeg_destroy_decompress (&srcinfo);
-		return image;
-	}
-
 	_jpeg_memory_src (&srcinfo, in_buffer, in_buffer_size);
 
 	jpeg_read_header (&srcinfo, TRUE);
 
-	/* FIXME: read the orientation flags and rotate the image */
+	/* FIXME: read the orientation flag and rotate the image */
 
 	if (original_width != NULL)
 		*original_width = srcinfo.image_width;
 	if (original_height != NULL)
 		*original_height = srcinfo.image_height;
 
-	srcinfo.out_color_space = JCS_RGB;
 	/* FIXME
 	if (requested_size > 0) {
 		for (srcinfo.scale_denom = 16; srcinfo.scale_denom >= 1; srcinfo.scale_denom--) {
@@ -159,33 +159,169 @@ _cairo_image_surface_create_from_jpeg (GthFileData   *file_data,
 	buffer_stride = srcinfo.output_width * srcinfo.output_components;
 	buffer = (*srcinfo.mem->alloc_sarray) ((j_common_ptr) &srcinfo, JPOOL_IMAGE, buffer_stride, srcinfo.rec_outbuf_height);
 
-	while (srcinfo.output_scanline < srcinfo.output_height) {
-		nlines = jpeg_read_scanlines (&srcinfo, buffer, srcinfo.rec_outbuf_height);
-		buffer_row = buffer;
-		for (l = 0; l < nlines; l++) {
-			p_surface = surface_row;
-			p_buffer = buffer_row[l];
-			for (x = 0; x < srcinfo.output_width; x++) {
-				p_surface[CAIRO_RED] = p_buffer[0];
-				p_surface[CAIRO_GREEN] = p_buffer[1];
-				p_surface[CAIRO_BLUE] = p_buffer[2];
-				p_surface[CAIRO_ALPHA] = 0xff;
-
-				p_surface += 4;
-				p_buffer += srcinfo.output_components;
+	switch (srcinfo.out_color_space) {
+	case JCS_CMYK:
+		{
+			static unsigned char *tab = NULL; /* table with pre-multiplied values */
+			int                   ki;
+
+			while (srcinfo.output_scanline < srcinfo.output_height) {
+				if (g_cancellable_is_cancelled (cancellable))
+					break;
+
+				n_lines = jpeg_read_scanlines (&srcinfo, buffer, srcinfo.rec_outbuf_height);
+
+				if (tab == NULL) {
+					int    v, k, i;
+					double k1;
+
+					/* tab[k * 256 + v] = v * k / 255.0 */
+
+					tab = g_new (unsigned char, 256 * 256);
+					i = 0;
+					for (k = 0; k <= 255; k++) {
+						k1 = (double) k / 255.0;
+						for (v = 0; v <= 255; v++)
+							tab[i++] = (double) v * k1;
+					}
+				}
+
+				buffer_row = buffer;
+				for (l = 0; l < n_lines; l++) {
+					p_surface = surface_row;
+					p_buffer = buffer_row[l];
+
+					for (x = 0; x < srcinfo.output_width; x++) {
+						ki = p_buffer[3] << 8; /* ki = k * 256 */
+						p_surface[CAIRO_RED]   = tab[ki + p_buffer[0]];
+						p_surface[CAIRO_GREEN] = tab[ki + p_buffer[1]];
+						p_surface[CAIRO_BLUE]  = tab[ki + p_buffer[2]];
+						p_surface[CAIRO_ALPHA] = 0xff;
+
+						p_surface += 4;
+						p_buffer += 4 /*srcinfo.output_components*/;
+					}
+
+					surface_row += surface_stride;
+					buffer_row += buffer_stride;
+				}
 			}
+		}
+		break;
+
+	case JCS_GRAYSCALE:
+		{
+			while (srcinfo.output_scanline < srcinfo.output_height) {
+				if (g_cancellable_is_cancelled (cancellable))
+					break;
+
+				n_lines = jpeg_read_scanlines (&srcinfo, buffer, srcinfo.rec_outbuf_height);
+
+				buffer_row = buffer;
+				for (l = 0; l < n_lines; l++) {
+					p_surface = surface_row;
+					p_buffer = buffer_row[l];
+
+					for (x = 0; x < srcinfo.output_width; x++) {
+						p_surface[CAIRO_RED]   = p_buffer[0];
+						p_surface[CAIRO_GREEN] = p_buffer[0];
+						p_surface[CAIRO_BLUE]  = p_buffer[0];
+						p_surface[CAIRO_ALPHA] = 0xff;
+
+						p_surface += 4;
+						p_buffer += 1 /*srcinfo.output_components*/;
+					}
+
+					surface_row += surface_stride;
+					buffer_row += buffer_stride;
+				}
+			}
+		}
+		break;
+
+	case JCS_RGB:
+		{
+			while (srcinfo.output_scanline < srcinfo.output_height) {
+				if (g_cancellable_is_cancelled (cancellable))
+					break;
+
+				n_lines = jpeg_read_scanlines (&srcinfo, buffer, srcinfo.rec_outbuf_height);
+
+				buffer_row = buffer;
+				for (l = 0; l < n_lines; l++) {
+					p_surface = surface_row;
+					p_buffer = buffer_row[l];
+
+					for (x = 0; x < srcinfo.output_width; x++) {
+						p_surface[CAIRO_RED]   = p_buffer[0];
+						p_surface[CAIRO_GREEN] = p_buffer[1];
+						p_surface[CAIRO_BLUE]  = p_buffer[2];
+						p_surface[CAIRO_ALPHA] = 0xff;
+
+						p_surface += 4;
+						p_buffer += 3 /*srcinfo.output_components*/;
+					}
+
+					surface_row += surface_stride;
+					buffer_row += buffer_stride;
+				}
+			}
+		}
+		break;
+
+	case JCS_YCbCr:
+		{
+			double Y, Cb, Cr;
+
+			while (srcinfo.output_scanline < srcinfo.output_height) {
+				if (g_cancellable_is_cancelled (cancellable))
+					break;
+
+				n_lines = jpeg_read_scanlines (&srcinfo, buffer, srcinfo.rec_outbuf_height);
 
-			surface_row += surface_stride;
-			buffer_row += buffer_stride;
+				buffer_row = buffer;
+				for (l = 0; l < n_lines; l++) {
+					p_surface = surface_row;
+					p_buffer = buffer_row[l];
+
+					for (x = 0; x < srcinfo.output_width; x++) {
+						Y = (double) p_buffer[0];
+						Cb = (double) p_buffer[1];
+						Cr = (double) p_buffer[2];
+
+						p_surface[CAIRO_RED]   = Y + 1.402 * (Cr - 128);
+						p_surface[CAIRO_GREEN] = Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128);
+						p_surface[CAIRO_BLUE]  = Y + 1.772 * (Cb - 128);
+						p_surface[CAIRO_ALPHA] = 0xff;
+
+						p_surface += 4;
+						p_buffer += 3 /*srcinfo.output_components*/;
+					}
+
+					surface_row += surface_stride;
+					buffer_row += buffer_stride;
+				}
+			}
 		}
+		break;
+
+	case JCS_YCCK:
+	case JCS_UNKNOWN:
+	default:
+		/* FIXME: ? */
+		break;
 	}
 
-	jpeg_finish_decompress (&srcinfo);
-	jpeg_destroy_decompress (&srcinfo);
+	if (! g_cancellable_is_cancelled (cancellable)) {
+		jpeg_finish_decompress (&srcinfo);
+		jpeg_destroy_decompress (&srcinfo);
 
-	/* FIXME: scale to the requested size */
+		/* FIXME: scale to the requested size */
 
-	gth_image_set_cairo_surface (image, surface);
+		gth_image_set_cairo_surface (image, surface);
+	}
+	else
+		jpeg_destroy ((j_common_ptr) &srcinfo);
 
 	cairo_surface_destroy (surface);
 	g_free (in_buffer);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]