Пример #1
0
fz_pixmap *
fz_load_jpeg(fz_context *ctx, unsigned char *rbuf, int rlen)
{
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr_jmp err;
	struct jpeg_source_mgr src;
	unsigned char *row[1], *sp, *dp;
	fz_colorspace *colorspace;
	unsigned int x;
	int k;

	fz_pixmap *image = NULL;
	fz_var(image);

	if (setjmp(err.env))
	{
		/* SumatraPDF: prevent memory leak */
		if (image)
		{
			fz_drop_pixmap(ctx, image);
			image = NULL;
			jpeg_finish_decompress(&cinfo);
		}
		jpeg_destroy_decompress(&cinfo);
		fz_throw(ctx, "jpeg error: %s", err.msg);
	}

	cinfo.err = jpeg_std_error(&err.super);
	err.super.error_exit = error_exit;

	jpeg_create_decompress(&cinfo);

	cinfo.src = &src;
	src.init_source = init_source;
	src.fill_input_buffer = fill_input_buffer;
	src.skip_input_data = skip_input_data;
	src.resync_to_restart = jpeg_resync_to_restart;
	src.term_source = term_source;
	src.next_input_byte = rbuf;
	src.bytes_in_buffer = rlen;

	jpeg_read_header(&cinfo, 1);

	jpeg_start_decompress(&cinfo);

	if (cinfo.output_components == 1)
		colorspace = fz_device_gray;
	else if (cinfo.output_components == 3)
		colorspace = fz_device_rgb;
	else if (cinfo.output_components == 4)
		colorspace = fz_device_cmyk;
	else
	{
		/* SumatraPDF: prevent memory leak */
		jpeg_finish_decompress(&cinfo);
		jpeg_destroy_decompress(&cinfo);
		fz_throw(ctx, "bad number of components in jpeg: %d", cinfo.output_components);
	}

	fz_try(ctx)
	{
		image = fz_new_pixmap(ctx, colorspace, cinfo.output_width, cinfo.output_height);
	}
	fz_catch(ctx)
	{
		jpeg_finish_decompress(&cinfo);
		jpeg_destroy_decompress(&cinfo);
		fz_throw(ctx, "out of memory");
	}

	if (cinfo.density_unit == 1)
	{
		image->xres = cinfo.X_density;
		image->yres = cinfo.Y_density;
	}
	else if (cinfo.density_unit == 2)
	{
		image->xres = cinfo.X_density * 254 / 100;
		image->yres = cinfo.Y_density * 254 / 100;
	}
	/* cf. http://code.google.com/p/sumatrapdf/issues/detail?id=1963 */
	else if (cinfo.density_unit == 0)
	{
		extract_exif_resolution(rbuf, rlen, &image->xres, &image->yres);
	}

	if (image->xres <= 0) image->xres = 72;
	if (image->yres <= 0) image->yres = 72;

	fz_clear_pixmap(ctx, image);

	row[0] = fz_malloc(ctx, cinfo.output_components * cinfo.output_width);
	dp = image->samples;
	while (cinfo.output_scanline < cinfo.output_height)
	{
		jpeg_read_scanlines(&cinfo, row, 1);
		sp = row[0];
		for (x = 0; x < cinfo.output_width; x++)
		{
			for (k = 0; k < cinfo.output_components; k++)
				*dp++ = *sp++;
			*dp++ = 255;
		}
	}
	fz_free(ctx, row[0]);

	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);

	image->has_alpha = 0; /* SumatraPDF: allow optimizing non-alpha pixmaps */

	return image;
}
Пример #2
0
void
fz_load_jpeg_info(fz_context *ctx, unsigned char *rbuf, int rlen, int *xp, int *yp, int *xresp, int *yresp, fz_colorspace **cspacep)
{
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr err;
	struct jpeg_source_mgr src;

	fz_try(ctx)
	{
		cinfo.client_data = ctx;
		cinfo.err = jpeg_std_error(&err);
		err.error_exit = error_exit;

		fz_jpg_mem_init(ctx, &cinfo);

		jpeg_create_decompress(&cinfo);

		cinfo.src = &src;
		src.init_source = init_source;
		src.fill_input_buffer = fill_input_buffer;
		src.skip_input_data = skip_input_data;
		src.resync_to_restart = jpeg_resync_to_restart;
		src.term_source = term_source;
		src.next_input_byte = rbuf;
		src.bytes_in_buffer = rlen;

		jpeg_save_markers(&cinfo, JPEG_APP0+1, 0xffff);
		jpeg_save_markers(&cinfo, JPEG_APP0+13, 0xffff);

		jpeg_read_header(&cinfo, 1);

		if (cinfo.num_components == 1)
			*cspacep = fz_device_gray(ctx);
		else if (cinfo.num_components == 3)
			*cspacep = fz_device_rgb(ctx);
		else if (cinfo.num_components == 4)
			*cspacep = fz_device_cmyk(ctx);
		else
			fz_throw(ctx, FZ_ERROR_GENERIC, "bad number of components in jpeg: %d", cinfo.num_components);

		*xp = cinfo.image_width;
		*yp = cinfo.image_height;

		if (extract_exif_resolution(cinfo.marker_list, xresp, yresp))
			/* XPS prefers EXIF resolution to JFIF density */;
		else if (extract_app13_resolution(cinfo.marker_list, xresp, yresp))
			/* XPS prefers APP13 resolution to JFIF density */;
		else if (cinfo.density_unit == 1)
		{
			*xresp = cinfo.X_density;
			*yresp = cinfo.Y_density;
		}
		else if (cinfo.density_unit == 2)
		{
			*xresp = cinfo.X_density * 254 / 100;
			*yresp = cinfo.Y_density * 254 / 100;
		}
		else
		{
			*xresp = 0;
			*yresp = 0;
		}

		if (*xresp <= 0) *xresp = 96;
		if (*yresp <= 0) *yresp = 96;
	}
	fz_always(ctx)
	{
		jpeg_destroy_decompress(&cinfo);
		fz_jpg_mem_term(&cinfo);
	}
	fz_catch(ctx)
	{
		fz_rethrow(ctx);
	}
}