Commit ec6698ab authored by Paolo Bacchilega's avatar Paolo Bacchilega
Browse files

cairo-io-jpeg: added color space convertion

parent 9e5d74c3
......@@ -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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment