cairo-image-surface-jpeg.c 15.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  GThumb
 *
 *  Copyright (C) 2011 Free Software Foundation, Inc.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <config.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <setjmp.h>
#include <jpeglib.h>
28 29 30
#if HAVE_LCMS2
#include <lcms2.h>
#endif
31 32
#include <gthumb.h>
#include <extensions/jpeg_utils/jmemorysrc.h>
Paolo Bacchilega's avatar
Paolo Bacchilega committed
33
#include <extensions/jpeg_utils/jpeg-info.h>
34
#include "cairo-image-surface-jpeg.h"
35 36 37 38


/* error handler data */

39

40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
struct error_handler_data {
	struct jpeg_error_mgr   pub;
	sigjmp_buf              setjmp_buffer;
        GError                **error;
};


static void
fatal_error_handler (j_common_ptr cinfo)
{
	struct error_handler_data *errmgr;
        char buffer[JMSG_LENGTH_MAX];

	errmgr = (struct error_handler_data *) cinfo->err;

        /* Create the message */
        (* cinfo->err->format_message) (cinfo, buffer);

        /* broken check for *error == NULL for robustness against
         * crappy JPEG library
         */
        if (errmgr->error && *errmgr->error == NULL) {
                g_set_error (errmgr->error,
                             GDK_PIXBUF_ERROR,
                             GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
65
			     _("Error interpreting JPEG image file: %s"),
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
                             buffer);
        }

	siglongjmp (errmgr->setjmp_buffer, 1);

        g_assert_not_reached ();
}


static void
output_message_handler (j_common_ptr cinfo)
{
	/* This method keeps libjpeg from dumping crap to stderr */
	/* do nothing */
}


83 84 85 86 87 88 89 90
/* tables with pre-multiplied values */


static unsigned char *CMYK_Tab = NULL;
static int           *YCbCr_R_Cr_Tab = NULL;
static int           *YCbCr_G_Cb_Tab = NULL;
static int           *YCbCr_G_Cr_Tab = NULL;
static int           *YCbCr_B_Cb_Tab = NULL;
91
static GMutex         Tables_Mutex;
92 93 94 95 96 97 98 99 100 101 102


#define SCALE_FACTOR   16
#define SCALE_UP(x)    ((gint32) ((x) * (1L << SCALE_FACTOR) + 0.5))
#define SCALE_DOWN(x)  ((x) >> SCALE_FACTOR)
#define ONE_HALF       ((gint32) (1 << (SCALE_FACTOR - 1)))


static void
CMYK_table_init (void)
{
103
	g_mutex_lock (&Tables_Mutex);
104

105 106 107 108 109 110 111 112 113 114 115 116 117 118
	if (CMYK_Tab == NULL) {
		int    v, k, i;
		double k1;

		/* tab[k * 256 + v] = v * k / 255.0 */

		CMYK_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++)
				CMYK_Tab[i++] = (double) v * k1;
		}
	}
119

120
	g_mutex_unlock (&Tables_Mutex);
121 122 123 124 125 126
}


static void
YCbCr_tables_init (void)
{
127
	g_mutex_lock (&Tables_Mutex);
128

129 130 131 132 133 134 135 136 137
	if (YCbCr_R_Cr_Tab == NULL) {
		int i, v;

		YCbCr_R_Cr_Tab = g_new (int, 256);
		YCbCr_G_Cb_Tab = g_new (int, 256);
		YCbCr_G_Cr_Tab = g_new (int, 256);
		YCbCr_B_Cb_Tab = g_new (int, 256);

		for (i = 0, v = -128; i <= 255; i++, v++) {
138
			YCbCr_R_Cr_Tab[i] = SCALE_DOWN (SCALE_UP (1.402) * v + ONE_HALF);
139 140
			YCbCr_G_Cb_Tab[i] = - SCALE_UP (0.34414) * v;
			YCbCr_G_Cr_Tab[i] = - SCALE_UP (0.71414) * v + ONE_HALF;
141
			YCbCr_B_Cb_Tab[i] = SCALE_DOWN (SCALE_UP (1.77200) * v + ONE_HALF);
142 143
		}
	}
144

145
	g_mutex_unlock (&Tables_Mutex);
146 147 148
}


149
GthImage *
150 151
_cairo_image_surface_create_from_jpeg (GInputStream  *istream,
				       GthFileData   *file_data,
152
				       int            requested_size,
153 154
				       int           *original_width_p,
				       int           *original_height_p,
155
				       gboolean      *loaded_original_p,
156 157 158 159 160
				       gpointer       user_data,
				       GCancellable  *cancellable,
				       GError       **error)
{
	GthImage                      *image;
161
	JpegInfoFlags		       info_flags;
162
	gboolean                       load_scaled;
163 164 165 166 167 168
	GthTransform                   orientation;
	int                            destination_width;
	int                            destination_height;
	int                            line_start;
	int                            line_step;
	int                            pixel_step;
169 170
	void                          *in_buffer;
	gsize                          in_buffer_size;
171
	JpegInfoData                   jpeg_info;
172 173 174
	struct error_handler_data      jsrcerr;
	struct jpeg_decompress_struct  srcinfo;
	cairo_surface_t               *surface;
175
	cairo_surface_metadata_t      *metadata;
176
	unsigned char                 *surface_data;
177 178 179
	unsigned char                 *surface_row;
	JSAMPARRAY                     buffer;
	int                            buffer_stride;
180
	JDIMENSION                     n_lines;
181
	JSAMPARRAY                     buffer_row;
182
	int                            l;
183
	unsigned char                 *p_surface;
184 185
	guchar                         r, g, b;
	guint32                        pixel;
186
	unsigned char                 *p_buffer;
187
	int                            x;
188 189 190

	image = gth_image_new ();

191 192 193 194 195
	if (! _g_input_stream_read_all (istream,
			      	        &in_buffer,
			      	        &in_buffer_size,
			      	        cancellable,
			      	        error))
196 197 198 199
	{
		return image;
	}

200
	_jpeg_info_data_init (&jpeg_info);
201 202 203 204 205
	info_flags = _JPEG_INFO_EXIF_ORIENTATION;
#if HAVE_LCMS2
	info_flags |= _JPEG_INFO_ICC_PROFILE;
#endif
	_jpeg_info_get_from_buffer (in_buffer, in_buffer_size, info_flags, &jpeg_info);
206 207 208 209
	if (jpeg_info.valid & _JPEG_INFO_EXIF_ORIENTATION)
		orientation = jpeg_info.orientation;
	else
		orientation = GTH_TRANSFORM_NONE;
210
#if HAVE_LCMS2
211 212 213 214 215
	if (jpeg_info.valid & _JPEG_INFO_ICC_PROFILE) {
		GthICCData *profile = gth_icc_data_new (NULL, cmsOpenProfileFromMem (jpeg_info.icc_data, jpeg_info.icc_data_size));
		gth_image_set_icc_profile (image, profile);
		g_object_unref (profile);
	}
216
#endif
217 218
	_jpeg_info_data_dispose (&jpeg_info);

219 220 221 222 223 224 225 226
	srcinfo.err = jpeg_std_error (&(jsrcerr.pub));
	jsrcerr.pub.error_exit = fatal_error_handler;
	jsrcerr.pub.output_message = output_message_handler;
	jsrcerr.error = error;

	jpeg_create_decompress (&srcinfo);

	if (sigsetjmp (jsrcerr.setjmp_buffer, 1)) {
Paolo Bacchilega's avatar
Paolo Bacchilega committed
227
		g_free (in_buffer);
228 229 230 231 232 233 234 235
		jpeg_destroy_decompress (&srcinfo);
		return image;
	}

	_jpeg_memory_src (&srcinfo, in_buffer, in_buffer_size);

	jpeg_read_header (&srcinfo, TRUE);

236 237
	srcinfo.out_color_space = srcinfo.jpeg_color_space; /* make all the color space conversions manually */

238 239 240
	load_scaled = (requested_size > 0) && (requested_size < srcinfo.image_width) && (requested_size < srcinfo.image_height);
	if (load_scaled) {
		for (srcinfo.scale_denom = 1; srcinfo.scale_denom <= 16; srcinfo.scale_denom++) {
241 242
			jpeg_calc_output_dimensions (&srcinfo);
			if ((srcinfo.output_width < requested_size) || (srcinfo.output_height < requested_size)) {
243
				srcinfo.scale_denom -= 1;
244 245 246 247
				break;
			}
		}

248
		if (srcinfo.scale_denom <= 0) {
249
			srcinfo.scale_denom = srcinfo.scale_num;
250 251
			load_scaled = FALSE;
		}
252 253
	}

254 255 256 257 258
	jpeg_calc_output_dimensions (&srcinfo);

	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);

259 260
	jpeg_start_decompress (&srcinfo);

261
	_cairo_image_surface_transform_get_steps (CAIRO_FORMAT_ARGB32,
262 263
						  MIN (srcinfo.output_width, CAIRO_MAX_IMAGE_SIZE),
						  MIN (srcinfo.output_height, CAIRO_MAX_IMAGE_SIZE),
264 265 266 267 268 269 270
						  orientation,
						  &destination_width,
						  &destination_height,
						  &line_start,
						  &line_step,
						  &pixel_step);

271 272 273 274 275 276 277 278 279
#if 0
	g_print ("requested: %d, original [%d, %d] ==> load at [%d, %d]\n",
			requested_size,
			srcinfo.image_width,
			srcinfo.image_height,
			destination_width,
			destination_height);
#endif

280 281 282
	surface = _cairo_image_surface_create (CAIRO_FORMAT_ARGB32, destination_width, destination_height);
	if (surface == NULL) {
		jpeg_destroy_decompress (&srcinfo);
283 284 285 286
		g_free (in_buffer);

		return image;
	}
287

288
	metadata = _cairo_image_surface_get_metadata (surface);
289
	_cairo_metadata_set_has_alpha (metadata, FALSE);
290 291
	surface_data = _cairo_image_surface_flush_and_get_data (surface);
	surface_row = surface_data + line_start;
292

293 294 295
	switch (srcinfo.out_color_space) {
	case JCS_CMYK:
		{
296 297 298 299 300
			register unsigned char *cmyk_tab;
			int c, m, y, k, ki;

			CMYK_table_init ();
			cmyk_tab = CMYK_Tab;
301 302 303

			while (srcinfo.output_scanline < srcinfo.output_height) {
				if (g_cancellable_is_cancelled (cancellable))
304
					goto stop_loading;
305 306 307 308 309 310 311 312

				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];

313 314 315
					if (g_cancellable_is_cancelled (cancellable))
						goto stop_loading;

316
					for (x = 0; x < srcinfo.output_width; x++) {
317 318 319 320 321 322 323 324 325 326 327 328 329 330
						if (srcinfo.saw_Adobe_marker) {
							c = p_buffer[0];
							m = p_buffer[1];
							y = p_buffer[2];
							k = p_buffer[3];
						}
						else {
							c = 255 - p_buffer[0];
							m = 255 - p_buffer[1];
							y = 255 - p_buffer[2];
							k = 255 - p_buffer[3];
						}

						ki = k << 8; /* ki = k * 256 */
331 332 333
						r = cmyk_tab[ki + c];
						g = cmyk_tab[ki + m];
						b = cmyk_tab[ki + y];
334
						pixel = CAIRO_RGBA_TO_UINT32 (r, g, b, 0xff);
335
						memcpy (p_surface, &pixel, sizeof (guint32));
336

337
						p_surface += pixel_step;
338 339 340
						p_buffer += 4 /*srcinfo.output_components*/;
					}

341
					surface_row += line_step;
342 343
					buffer_row += buffer_stride;
				}
344
			}
345 346 347 348 349 350 351
		}
		break;

	case JCS_GRAYSCALE:
		{
			while (srcinfo.output_scanline < srcinfo.output_height) {
				if (g_cancellable_is_cancelled (cancellable))
352
					goto stop_loading;
353 354 355 356 357 358 359 360

				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];

361 362 363
					if (g_cancellable_is_cancelled (cancellable))
						goto stop_loading;

364
					for (x = 0; x < srcinfo.output_width; x++) {
365
						r = g = b = p_buffer[0];
366
						pixel = CAIRO_RGBA_TO_UINT32 (r, g, b, 0xff);
367
						memcpy (p_surface, &pixel, sizeof (guint32));
368

369
						p_surface += pixel_step;
370 371 372
						p_buffer += 1 /*srcinfo.output_components*/;
					}

373
					surface_row += line_step;
374 375 376 377 378 379 380 381 382 383
					buffer_row += buffer_stride;
				}
			}
		}
		break;

	case JCS_RGB:
		{
			while (srcinfo.output_scanline < srcinfo.output_height) {
				if (g_cancellable_is_cancelled (cancellable))
384
					goto stop_loading;
385 386 387 388 389 390 391 392

				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];

393 394 395
					if (g_cancellable_is_cancelled (cancellable))
						goto stop_loading;

396
					for (x = 0; x < srcinfo.output_width; x++) {
397 398 399
						r = p_buffer[0];
						g = p_buffer[1];
						b = p_buffer[2];
400
						pixel = CAIRO_RGBA_TO_UINT32 (r, g, b, 0xff);
401
						memcpy (p_surface, &pixel, sizeof (guint32));
402

403
						p_surface += pixel_step;
404 405 406
						p_buffer += 3 /*srcinfo.output_components*/;
					}

407
					surface_row += line_step;
408 409 410 411 412 413 414 415
					buffer_row += buffer_stride;
				}
			}
		}
		break;

	case JCS_YCbCr:
		{
416 417 418 419 420 421 422 423 424 425 426 427
			register JSAMPLE *range_limit = srcinfo.sample_range_limit;
			register int     *r_cr_tab;
			register int     *g_cb_tab;
			register int     *g_cr_tab;
			register int     *b_cb_tab;
			int               Y, Cb, Cr;

			YCbCr_tables_init ();
			r_cr_tab = YCbCr_R_Cr_Tab;
			g_cb_tab = YCbCr_G_Cb_Tab;
			g_cr_tab = YCbCr_G_Cr_Tab;
			b_cb_tab = YCbCr_B_Cb_Tab;
428 429 430

			while (srcinfo.output_scanline < srcinfo.output_height) {
				if (g_cancellable_is_cancelled (cancellable))
431
					goto stop_loading;
432 433

				n_lines = jpeg_read_scanlines (&srcinfo, buffer, srcinfo.rec_outbuf_height);
434

435 436 437 438 439
				buffer_row = buffer;
				for (l = 0; l < n_lines; l++) {
					p_surface = surface_row;
					p_buffer = buffer_row[l];

440 441 442
					if (g_cancellable_is_cancelled (cancellable))
						goto stop_loading;

443
					for (x = 0; x < srcinfo.output_width; x++) {
444 445 446
						Y = p_buffer[0];
						Cb = p_buffer[1];
						Cr = p_buffer[2];
447

448 449 450
						r = range_limit[Y + r_cr_tab[Cr]];
						g = range_limit[Y + SCALE_DOWN (g_cb_tab[Cb] + g_cr_tab[Cr])];
						b = range_limit[Y + b_cb_tab[Cb]];
451
						pixel = CAIRO_RGBA_TO_UINT32 (r, g, b, 0xff);
452
						memcpy (p_surface, &pixel, sizeof (guint32));
453

454
						p_surface += pixel_step;
455 456 457
						p_buffer += 3 /*srcinfo.output_components*/;
					}

458
					surface_row += line_step;
459 460 461
					buffer_row += buffer_stride;
				}
			}
462
		}
463 464 465
		break;

	case JCS_YCCK:
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
		{
			register JSAMPLE *range_limit = srcinfo.sample_range_limit;
			register int     *r_cr_tab;
			register int     *g_cb_tab;
			register int     *g_cr_tab;
			register int     *b_cb_tab;
			register guchar  *cmyk_tab;
			int               Y, Cb, Cr, K, Ki, c, m , y;

			YCbCr_tables_init ();
			r_cr_tab = YCbCr_R_Cr_Tab;
			g_cb_tab = YCbCr_G_Cb_Tab;
			g_cr_tab = YCbCr_G_Cr_Tab;
			b_cb_tab = YCbCr_B_Cb_Tab;

			CMYK_table_init ();
			cmyk_tab = CMYK_Tab;

			while (srcinfo.output_scanline < srcinfo.output_height) {
				if (g_cancellable_is_cancelled (cancellable))
486
					goto stop_loading;
487 488 489 490 491 492 493 494

				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];

495 496 497
					if (g_cancellable_is_cancelled (cancellable))
						goto stop_loading;

498 499 500 501 502 503 504 505 506 507 508
					for (x = 0; x < srcinfo.output_width; x++) {
						Y = p_buffer[0];
						Cb = p_buffer[1];
						Cr = p_buffer[2];
						K = p_buffer[3];

						c = range_limit[255 - (Y + r_cr_tab[Cr])];
						m = range_limit[255 - (Y + SCALE_DOWN (g_cb_tab[Cb] + g_cr_tab[Cr]))];
						y = range_limit[255 - (Y + b_cb_tab[Cb])];

						Ki = K << 8; /* ki = K * 256 */
509 510 511 512

						r = cmyk_tab[Ki + c];
						g = cmyk_tab[Ki + m];
						b = cmyk_tab[Ki + y];
513
						pixel = CAIRO_RGBA_TO_UINT32 (r, g, b, 0xff);
514
						memcpy (p_surface, &pixel, sizeof (guint32));
515

516
						p_surface += pixel_step;
517 518 519
						p_buffer += 4 /*srcinfo.output_components*/;
					}

520
					surface_row += line_step;
521 522 523 524 525 526
					buffer_row += buffer_stride;
				}
			}
		}
		break;

527 528
	case JCS_UNKNOWN:
	default:
529 530 531 532 533
		g_set_error (error,
                             GDK_PIXBUF_ERROR,
                             GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
                             _("Unknown JPEG color space (%d)"),
                             srcinfo.out_color_space);
534
		break;
535 536
	}

537
	stop_loading:
538

539
	cairo_surface_mark_dirty (surface);
540

541
	if (! g_cancellable_is_cancelled (cancellable)) {
542 543
		int original_width;
		int original_height;
544

545 546 547 548 549 550 551
		/* Set the original dimensions */

		if ((orientation == GTH_TRANSFORM_ROTATE_90)
		     ||	(orientation == GTH_TRANSFORM_ROTATE_270)
		     ||	(orientation == GTH_TRANSFORM_TRANSPOSE)
		     ||	(orientation == GTH_TRANSFORM_TRANSVERSE))
		{
552 553
			original_width = srcinfo.image_height;
			original_height = srcinfo.image_width;
554 555
		}
		else {
556 557
			original_width = srcinfo.image_width;
			original_height = srcinfo.image_height;
558
		}
559

560
		_cairo_metadata_set_original_size (metadata, original_width, original_height);
561

562 563 564 565
		if (original_width_p != NULL)
			*original_width_p = original_width;
		if (original_height_p != NULL)
			*original_height_p = original_height;
566 567
		if (loaded_original_p != NULL)
			*loaded_original_p = ! load_scaled;
568

569 570
		jpeg_finish_decompress (&srcinfo);
		jpeg_destroy_decompress (&srcinfo);
571 572 573

		/*_cairo_image_surface_set_attribute_int (surface, "Image::Rotation", rotation); FIXME*/
		/* FIXME _cairo_image_surface_set_attribute (surface, "Jpeg::ColorSpace", jpeg_color_space_name (srcinfo.jpeg_color_space)); */
574

575 576
		gth_image_set_cairo_surface (image, surface);
	}
577
	else {
578
		jpeg_destroy_decompress (&srcinfo);
579 580
		g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "");
	}
581 582 583 584 585 586

	cairo_surface_destroy (surface);
	g_free (in_buffer);

	return image;
}
587 588 589 590 591 592


#undef SCALE_FACTOR
#undef SCALE_UP
#undef SCALE_DOWN
#undef ONE_HALF