コード例 #1
0
ファイル: load-jxr.c プロジェクト: ccxvii/mupdf
fz_pixmap *
fz_load_jxr(fz_context *ctx, unsigned char *data, size_t size)
{
	struct info info = { 0 };
	fz_pixmap *image = NULL;

	fz_var(image);

	jxr_read_image(ctx, data, size, &info, 0);

	image = fz_new_pixmap(ctx, info.cspace, info.width, info.height, NULL, 1);

	image->xres = info.xres;
	image->yres = info.yres;

	fz_try(ctx)
	{
		fz_unpack_tile(ctx, image, info.samples, fz_colorspace_n(ctx, info.cspace) + 1, 8, info.stride, 0);
		if (info.has_alpha && !info.has_premul)
			fz_premultiply_pixmap(ctx, image);
	}
	fz_always(ctx)
	{
		fz_free(ctx, info.samples);
		fz_drop_colorspace(ctx, info.cspace);
	}
	fz_catch(ctx)
	{
		fz_drop_pixmap(ctx, image);
		fz_rethrow(ctx);
	}

	return image;
}
コード例 #2
0
ファイル: image_jpx.c プロジェクト: plotnick/mupdf
fz_pixmap *
fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs)
{
	fz_pixmap *img;
	opj_event_mgr_t evtmgr;
	opj_dparameters_t params;
	opj_dinfo_t *info;
	opj_cio_t *cio;
	opj_image_t *jpx;
	fz_colorspace *colorspace;
	unsigned char *p;
	int format;
	int a, n, w, h, depth, sgnd;
	int x, y, k, v;

	if (size < 2)
		fz_throw(ctx, "not enough data to determine image format");

	/* Check for SOC marker -- if found we have a bare J2K stream */
	if (data[0] == 0xFF && data[1] == 0x4F)
		format = CODEC_J2K;
	else
		format = CODEC_JP2;

	memset(&evtmgr, 0, sizeof(evtmgr));
	evtmgr.error_handler = fz_opj_error_callback;
	evtmgr.warning_handler = fz_opj_warning_callback;
	evtmgr.info_handler = fz_opj_info_callback;

	opj_set_default_decoder_parameters(&params);

	info = opj_create_decompress(format);
	opj_set_event_mgr((opj_common_ptr)info, &evtmgr, ctx);
	opj_setup_decoder(info, &params);

	cio = opj_cio_open((opj_common_ptr)info, data, size);

	jpx = opj_decode(info, cio);

	opj_cio_close(cio);
	opj_destroy_decompress(info);

	if (!jpx)
		fz_throw(ctx, "opj_decode failed");

	for (k = 1; k < jpx->numcomps; k++)
	{
		if (jpx->comps[k].w != jpx->comps[0].w)
			fz_throw(ctx, "image components have different width");
		if (jpx->comps[k].h != jpx->comps[0].h)
			fz_throw(ctx, "image components have different height");
		if (jpx->comps[k].prec != jpx->comps[0].prec)
			fz_throw(ctx, "image components have different precision");
	}

	n = jpx->numcomps;
	w = jpx->comps[0].w;
	h = jpx->comps[0].h;
	depth = jpx->comps[0].prec;
	sgnd = jpx->comps[0].sgnd;

	if (jpx->color_space == CLRSPC_SRGB && n == 4) { n = 3; a = 1; }
	else if (jpx->color_space == CLRSPC_SYCC && n == 4) { n = 3; a = 1; }
	else if (n == 2) { n = 1; a = 1; }
	else if (n > 4) { n = 4; a = 1; }
	else { a = 0; }

	if (defcs)
	{
		if (defcs->n == n)
		{
			colorspace = defcs;
		}
		else
		{
			fz_warn(ctx, "jpx file and dict colorspaces do not match");
			defcs = NULL;
		}
	}

	if (!defcs)
	{
		switch (n)
		{
		case 1: colorspace = fz_device_gray; break;
		case 3: colorspace = fz_device_rgb; break;
		case 4: colorspace = fz_device_cmyk; break;
		}
	}

	fz_try(ctx)
	{
		img = fz_new_pixmap(ctx, colorspace, w, h);
	}
	fz_catch(ctx)
	{
		opj_image_destroy(jpx);
		fz_throw(ctx, "out of memory");
	}

	p = img->samples;
	for (y = 0; y < h; y++)
	{
		for (x = 0; x < w; x++)
		{
			for (k = 0; k < n + a; k++)
			{
				v = jpx->comps[k].data[y * w + x];
				if (sgnd)
					v = v + (1 << (depth - 1));
				if (depth > 8)
					v = v >> (depth - 8);
				*p++ = v;
			}
			if (!a)
				*p++ = 255;
		}
	}

	if (a)
	{
		if (n == 4)
		{
			fz_pixmap *tmp = fz_new_pixmap(ctx, fz_device_rgb, w, h);
			fz_convert_pixmap(ctx, img, tmp);
			fz_drop_pixmap(ctx, img);
			img = tmp;
		}
		fz_premultiply_pixmap(ctx, img);
	}

	opj_image_destroy(jpx);

	return img;
}
コード例 #3
0
ファイル: load-pnm.c プロジェクト: JorjMcKie/mupdf
static fz_pixmap *
pam_binary_read_image(fz_context *ctx, struct info *pnm, const unsigned char *p, const unsigned char *e, int onlymeta, const unsigned char **out)
{
	fz_pixmap *img = NULL;
	int bitmap = 0;
	int minval = 1;
	int maxval = 65535;

	fz_var(img);

	p = pam_binary_read_header(ctx, pnm, p, e);

	if (pnm->tupletype == PAM_UNKNOWN)
		switch (pnm->depth)
		{
		case 1: pnm->tupletype = pnm->maxval == 1 ? PAM_BW : PAM_GRAY; break;
		case 2: pnm->tupletype = pnm->maxval == 1 ? PAM_BWA : PAM_GRAYA; break;
		case 3: pnm->tupletype = PAM_RGB; break;
		case 4: pnm->tupletype = PAM_CMYK; break;
		case 5: pnm->tupletype = PAM_CMYKA; break;
		default:
			fz_throw(ctx, FZ_ERROR_GENERIC, "cannot guess tuple type based on depth in pnm image");
		}

	if (pnm->tupletype == PAM_BW && pnm->maxval > 1)
		pnm->tupletype = PAM_GRAY;
	else if (pnm->tupletype == PAM_GRAY && pnm->maxval == 1)
		pnm->tupletype = PAM_BW;
	else if (pnm->tupletype == PAM_BWA && pnm->maxval > 1)
		pnm->tupletype = PAM_GRAYA;
	else if (pnm->tupletype == PAM_GRAYA && pnm->maxval == 1)
		pnm->tupletype = PAM_BWA;

	switch (pnm->tupletype)
	{
	case PAM_BWA:
		pnm->alpha = 1;
		/* fallthrough */
	case PAM_BW:
		pnm->cs = fz_device_gray(ctx);
		maxval = 1;
		bitmap = 1;
		break;
	case PAM_GRAYA:
		pnm->alpha = 1;
		/* fallthrough */
	case PAM_GRAY:
		pnm->cs = fz_device_gray(ctx);
		minval = 2;
		break;
	case PAM_RGBA:
		pnm->alpha = 1;
		/* fallthrough */
	case PAM_RGB:
		pnm->cs = fz_device_rgb(ctx);
		break;
	case PAM_CMYKA:
		pnm->alpha = 1;
		/* fallthrough */
	case PAM_CMYK:
		pnm->cs = fz_device_cmyk(ctx);
		break;
	default:
		fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported tuple type");
	}

	if (pnm->depth != fz_colorspace_n(ctx, pnm->cs) + pnm->alpha)
		fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of tuple type range");
	if (pnm->maxval < minval || pnm->maxval > maxval)
		fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range");

	pnm->bitdepth = bitdepth_from_maxval(pnm->maxval);

	if (pnm->height <= 0)
		fz_throw(ctx, FZ_ERROR_GENERIC, "image height must be > 0");
	if (pnm->width <= 0)
		fz_throw(ctx, FZ_ERROR_GENERIC, "image width must be > 0");
	if ((unsigned int)pnm->height > UINT_MAX / pnm->width / fz_colorspace_n(ctx, pnm->cs) / (pnm->bitdepth / 8 + 1))
		fz_throw(ctx, FZ_ERROR_GENERIC, "image too large");

	if (onlymeta)
	{
		int packed;
		int w, h, n;

		w = pnm->width;
		h = pnm->height;
		n = fz_colorspace_n(ctx, pnm->cs) + pnm->alpha;

		/* some encoders incorrectly pack bits into bytes and invert the image */
		packed = 0;
		if (pnm->maxval == 1) {
			const unsigned char *e_packed = p + w * h * n / 8;
			if (e_packed < e - 1 && e_packed[0] == 'P' && e_packed[1] >= '0' && e_packed[1] <= '7')
				e = e_packed;
			if (e - p < w * h * n)
				packed = 1;
		}
		if (packed && e - p < w * h * n / 8)
			fz_throw(ctx, FZ_ERROR_GENERIC, "truncated packed image");
		if (!packed && e - p < w * h * n * (pnm->maxval < 256 ? 1 : 2))
			fz_throw(ctx, FZ_ERROR_GENERIC, "truncated image");

		if (pnm->maxval == 255)
			p += n * w * h;
		else if (bitmap && packed)
			p += ((w + 7) / 8) * h;
		else if (bitmap)
			p += n * w * h;
		else if (pnm->maxval < 255)
			p += n * w * h;
		else
			p += 2 * n * w * h;
	}

	if (!onlymeta)
	{
		unsigned char *dp;
		int x, y, k, packed;
		int w, h, n;

		img = fz_new_pixmap(ctx, pnm->cs, pnm->width, pnm->height, NULL, pnm->alpha);
		fz_try(ctx)
		{
			dp = img->samples;

			w = img->w;
			h = img->h;
			n = img->n;

			/* some encoders incorrectly pack bits into bytes and invert the image */
			packed = 0;
			if (pnm->maxval == 1) {
				const unsigned char *e_packed = p + w * h * n / 8;
				if (e_packed < e - 1 && e_packed[0] == 'P' && e_packed[1] >= '0' && e_packed[1] <= '7')
					e = e_packed;
				if (e - p < w * h * n)
					packed = 1;
			}
			if (packed && e - p < w * h * n / 8)
				fz_throw(ctx, FZ_ERROR_GENERIC, "truncated packed image");
			if (!packed && e - p < w * h * n * (pnm->maxval < 256 ? 1 : 2))
				fz_throw(ctx, FZ_ERROR_GENERIC, "truncated image");

			if (pnm->maxval == 255)
				memcpy(dp, p, w * h * n);
			else if (bitmap && packed)
			{
				for (y = 0; y < h; y++)
					for (x = 0; x < w; x++)
					{
						for (k = 0; k < n; k++)
						{
							*dp++ = (*p & (1 << (7 - (x & 0x7)))) ? 0x00 : 0xff;
							if ((x & 0x7) == 7)
								p++;
						}
						if (w & 0x7)
							p++;
					}
			}
			else if (bitmap)
			{
				for (y = 0; y < h; y++)
					for (x = 0; x < w; x++)
						for (k = 0; k < n; k++)
							*dp++ = *p++ ? 0xff : 0x00;
			}
			else if (pnm->maxval < 255)
			{
				for (y = 0; y < h; y++)
					for (x = 0; x < w; x++)
						for (k = 0; k < n; k++)
							*dp++ = map_color(ctx, *p++, pnm->maxval, 255);
			}
			else
			{
				for (y = 0; y < h; y++)
					for (x = 0; x < w; x++)
						for (k = 0; k < n; k++)
						{
							*dp++ = map_color(ctx, (p[0] << 8) | p[1], pnm->maxval, 255);
							p += 2;
						}
			}

			if (pnm->alpha)
				fz_premultiply_pixmap(ctx, img);
		}
		fz_catch(ctx)
		{
			fz_drop_pixmap(ctx, img);
			fz_rethrow(ctx);
		}
	}
コード例 #4
0
ファイル: load-gif.c プロジェクト: Enzime/mupdf
static fz_pixmap *
gif_read_image(fz_context *ctx, struct info *info, unsigned char *p, size_t total, int only_metadata)
{
	fz_pixmap *pix;
	unsigned char *end = p + total;

	memset(info, 0x00, sizeof (*info));

	/* Read header */
	p = gif_read_header(ctx, info, p, end);

	/* Read logical screen descriptor */
	p = gif_read_lsd(ctx, info, p, end);

	if (only_metadata)
		return NULL;

	pix = fz_new_pixmap(ctx, fz_device_rgb(ctx), info->width, info->height, 1);

	fz_try(ctx)
	{
		info->mask = fz_calloc(ctx, info->width * info->height, 1);

		/* Read optional global color table */
		if (info->has_gct)
		{
			unsigned char *bp, *dp = pix->samples;
			unsigned int x, y, k;

			p = gif_read_gct(ctx, info, p, end);
			bp = &info->gct[info->gct_background * 3];

			memset(info->mask, 0x01, info->width * info->height);

			for (y = 0; y < info->height; y++)
				for (x = 0; x < info->width; x++, dp += 4)
				{
					for (k = 0; k < 3; k++)
						dp[k] = bp[k];
					dp[3] = 255;
				}
		}

		while (1)
		{
			/* Read block indicator */
			if (end - p < 1)
				fz_throw(ctx, FZ_ERROR_GENERIC, "premature end of block indicator in gif image");

			/* Read trailer */
			if (p[0] == 0x3b)
			{
				break;
			}
			/* Read extension */
			else if (p[0] == 0x21)
			{
				/* Read extension label */
				if (end - p < 2)
					fz_throw(ctx, FZ_ERROR_GENERIC, "premature end in extension label in gif image");

				if (p[1] == 0x01 && info->gif89a)
				{
					/* Read plain text extension */
					p = gif_read_pte(ctx, info, p, end);

					/* Graphic control extension applies only to the graphic rendering block following it */
					info->transparent = 0;
					info->has_transparency = 0;
				}
				else if (p[1] == 0xf9 && info->gif89a)
					/* Read graphic control extension */
					p = gif_read_gce(ctx, info, p, end);
				else if (p[1] == 0xfe && info->gif89a)
					/* Read comment extension */
					p = gif_read_ce(ctx, info, p, end);
				else if (p[1] == 0xff && info->gif89a)
					/* Read application extension */
					p = gif_read_ae(ctx, info, p, end);
				else
					fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported extension label %02x in gif image", p[1]);
			}
			/* Read image descriptor */
			else if (p[0] == 0x2c)
			{
				p = gif_read_id(ctx, info, p, end);

				if (info->has_lct)
					/* Read local color table */
					p = gif_read_lct(ctx, info, p, end);

				/* Read table based image data */
				p = gif_read_tbid(ctx, info, pix->samples, p, end);

				/* Graphic control extension applies only to the graphic rendering block following it */
				info->transparent = 0;
				info->has_transparency = 0;

				/* Image descriptor applies only to the table based image data following it */
				info->image_left = info->image_top = 0;
				info->image_width = info->width;
				info->image_height = info->height;
				info->image_interlaced = 0;
				fz_free(ctx, info->lct);
				info->lct = NULL;
				info->has_lct = 0;
			}
			else
				fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported block indicator %02x in gif image", p[0]);
		}

		gif_mask_transparency(ctx, pix, info);
		fz_premultiply_pixmap(ctx, pix);
	}
	fz_always(ctx)
	{
		fz_free(ctx, info->mask);
		fz_free(ctx, info->lct);
		fz_free(ctx, info->gct);
	}
	fz_catch(ctx)
	{
		fz_drop_pixmap(ctx, pix);
		fz_rethrow(ctx);
	}

	return pix;
}
コード例 #5
0
ファイル: load-jpx.c プロジェクト: learnystPDF/learnystPDF
fz_pixmap *
fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs, int indexed)
{
	fz_pixmap *img;
	fz_colorspace *origcs;
	opj_dparameters_t params;
	opj_codec_t *codec;
	opj_image_t *jpx;
	opj_stream_t *stream;
	fz_colorspace *colorspace;
	unsigned char *p;
	OPJ_CODEC_FORMAT format;
	int a, n, w, h, depth, sgnd;
	int x, y, k, v;
	stream_block sb;

	if (size < 2)
		fz_throw(ctx, FZ_ERROR_GENERIC, "not enough data to determine image format");

	/* Check for SOC marker -- if found we have a bare J2K stream */
	if (data[0] == 0xFF && data[1] == 0x4F)
		format = OPJ_CODEC_J2K;
	else
		format = OPJ_CODEC_JP2;

	opj_set_default_decoder_parameters(&params);
	if (indexed)
		params.flags |= OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;

	codec = opj_create_decompress(format);
	opj_set_info_handler(codec, fz_opj_info_callback, ctx);
	opj_set_warning_handler(codec, fz_opj_warning_callback, ctx);
	opj_set_error_handler(codec, fz_opj_error_callback, ctx);
	if (!opj_setup_decoder(codec, &params))
	{
		fz_throw(ctx, FZ_ERROR_GENERIC, "j2k decode failed");
	}

	stream = opj_stream_default_create(OPJ_TRUE);
	sb.data = data;
	sb.pos = 0;
	sb.size = size;

	opj_stream_set_read_function(stream, fz_opj_stream_read);
	opj_stream_set_skip_function(stream, fz_opj_stream_skip);
	opj_stream_set_seek_function(stream, fz_opj_stream_seek);
	opj_stream_set_user_data(stream, &sb);
	/* Set the length to avoid an assert */
	opj_stream_set_user_data_length(stream, size);

	if (!opj_read_header(stream, codec, &jpx))
	{
		opj_stream_destroy(stream);
		opj_destroy_codec(codec);
		fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to read JPX header");
	}

	if (!opj_decode(codec, stream, jpx))
	{
		opj_stream_destroy(stream);
		opj_destroy_codec(codec);
		opj_image_destroy(jpx);
		fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to decode JPX image");
	}

	opj_stream_destroy(stream);
	opj_destroy_codec(codec);

	/* jpx should never be NULL here, but check anyway */
	if (!jpx)
		fz_throw(ctx, FZ_ERROR_GENERIC, "opj_decode failed");

	for (k = 1; k < (int)jpx->numcomps; k++)
	{
		if (!jpx->comps[k].data)
		{
			opj_image_destroy(jpx);
			fz_throw(ctx, FZ_ERROR_GENERIC, "image components are missing data");
		}
		if (jpx->comps[k].w != jpx->comps[0].w)
		{
			opj_image_destroy(jpx);
			fz_throw(ctx, FZ_ERROR_GENERIC, "image components have different width");
		}
		if (jpx->comps[k].h != jpx->comps[0].h)
		{
			opj_image_destroy(jpx);
			fz_throw(ctx, FZ_ERROR_GENERIC, "image components have different height");
		}
		if (jpx->comps[k].prec != jpx->comps[0].prec)
		{
			opj_image_destroy(jpx);
			fz_throw(ctx, FZ_ERROR_GENERIC, "image components have different precision");
		}
	}

	n = jpx->numcomps;
	w = jpx->comps[0].w;
	h = jpx->comps[0].h;
	depth = jpx->comps[0].prec;
	sgnd = jpx->comps[0].sgnd;

	if (jpx->color_space == OPJ_CLRSPC_SRGB && n == 4) { n = 3; a = 1; }
	else if (jpx->color_space == OPJ_CLRSPC_SYCC && n == 4) { n = 3; a = 1; }
	else if (n == 2) { n = 1; a = 1; }
	else if (n > 4) { n = 4; a = 1; }
	else { a = 0; }

	origcs = defcs;
	if (defcs)
	{
		if (defcs->n == n)
		{
			colorspace = defcs;
		}
		else
		{
			fz_warn(ctx, "jpx file and dict colorspaces do not match");
			defcs = NULL;
		}
	}

	if (!defcs)
	{
		switch (n)
		{
		case 1: colorspace = fz_device_gray(ctx); break;
		case 3: colorspace = fz_device_rgb(ctx); break;
		case 4: colorspace = fz_device_cmyk(ctx); break;
		}
	}

	fz_try(ctx)
	{
		img = fz_new_pixmap(ctx, colorspace, w, h);
	}
	fz_catch(ctx)
	{
		opj_image_destroy(jpx);
		fz_rethrow_message(ctx, "out of memory loading jpx");
	}

	p = img->samples;
	for (y = 0; y < h; y++)
	{
		for (x = 0; x < w; x++)
		{
			for (k = 0; k < n + a; k++)
			{
				v = jpx->comps[k].data[y * w + x];
				if (sgnd)
					v = v + (1 << (depth - 1));
				if (depth > 8)
					v = v >> (depth - 8);
				*p++ = v;
			}
			if (!a)
				*p++ = 255;
		}
	}

	opj_image_destroy(jpx);

	if (a)
	{
		if (n == 4)
		{
			fz_pixmap *tmp = fz_new_pixmap(ctx, fz_device_rgb(ctx), w, h);
			fz_convert_pixmap(ctx, tmp, img);
			fz_drop_pixmap(ctx, img);
			img = tmp;
		}
		fz_premultiply_pixmap(ctx, img);
	}

	if (origcs != defcs)
	{
		fz_pixmap *tmp = fz_new_pixmap(ctx, origcs, w, h);
		fz_convert_pixmap(ctx, tmp, img);
		fz_drop_pixmap(ctx, img);
		img = tmp;
	}

	return img;
}