static fz_error
pdf_load_jpx_image(fz_pixmap **imgp, pdf_xref *xref, fz_obj *dict)
{
	fz_error error;
	fz_buffer *buf;
	fz_colorspace *colorspace;
	fz_pixmap *img;
	fz_obj *obj;

	colorspace = NULL;

	error = pdf_load_stream(&buf, xref, fz_to_num(dict), fz_to_gen(dict));
	if (error)
		return fz_rethrow(error, "cannot load jpx image data");

	obj = fz_dict_gets(dict, "ColorSpace");
	if (obj)
	{
		error = pdf_load_colorspace(&colorspace, xref, obj);
		if (error)
			fz_catch(error, "cannot load image colorspace");
	}

	error = fz_load_jpx_image(&img, buf->data, buf->len, colorspace);
	if (error)
	{
		if (colorspace)
			fz_drop_colorspace(colorspace);
		fz_drop_buffer(buf);
		return fz_rethrow(error, "cannot load jpx image");
	}

	if (colorspace)
		fz_drop_colorspace(colorspace);
	fz_drop_buffer(buf);

	obj = fz_dict_getsa(dict, "SMask", "Mask");
	if (fz_is_dict(obj))
	{
		error = pdf_load_image_imp(&img->mask, xref, NULL, obj, NULL, 1);
		if (error)
		{
			fz_drop_pixmap(img);
			return fz_rethrow(error, "cannot load image mask/softmask");
		}
	}

	*imgp = img;
	return fz_okay;
}
static fz_colorspace *
load_icc_based(pdf_document *doc, pdf_obj *dict)
{
	int n;

	n = pdf_to_int(pdf_dict_gets(dict, "N"));

	/* SumatraPDF: support alternate colorspaces for ICCBased */
	if (pdf_dict_gets(dict, "Alternate"))
	{
		fz_colorspace *cs_alt = pdf_load_colorspace(doc, pdf_dict_gets(dict, "Alternate"));
		if (cs_alt->n != n)
		{
			fz_drop_colorspace(doc->ctx, cs_alt);
			fz_throw(doc->ctx, FZ_ERROR_GENERIC, "ICCBased /Alternate colorspace must have %d components (not %d)", n, cs_alt->n);
		}
		return cs_alt;
	}

	switch (n)
	{
	case 1: return fz_device_gray(doc->ctx);
	case 3: return fz_device_rgb(doc->ctx);
	case 4: return fz_device_cmyk(doc->ctx);
	}

	fz_throw(doc->ctx, FZ_ERROR_GENERIC, "syntaxerror: ICCBased must have 1, 3 or 4 components");
	return NULL; /* Stupid MSVC */
}
Beispiel #3
0
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;
}
Beispiel #4
0
void
fz_set_device_lab(fz_context *ctx, fz_colorspace *cs)
{
	fz_lock(ctx, FZ_LOCK_ALLOC);
	fz_drop_colorspace(ctx, ctx->colorspace->lab);
	ctx->colorspace->lab = fz_keep_colorspace(ctx, cs);
	fz_unlock(ctx, FZ_LOCK_ALLOC);
}
Beispiel #5
0
static void
free_separation(fz_context *ctx, fz_colorspace *cs)
{
	struct separation *sep = cs->data;
	fz_drop_colorspace(ctx, sep->base);
	pdf_drop_function(ctx, sep->tint);
	fz_free(ctx, sep);
}
Beispiel #6
0
static void
free_indexed(fz_context *ctx, fz_colorspace *cs)
{
	struct indexed *idx = cs->data;
	if (idx->base)
		fz_drop_colorspace(ctx, idx->base);
	fz_free(ctx, idx->lookup);
	fz_free(ctx, idx);
}
Beispiel #7
0
static void
fz_drop_image_block(fz_context *ctx, fz_image_block *block)
{
	if (block == NULL)
		return;
	fz_drop_image(ctx, block->image);
	fz_drop_colorspace(ctx, block->cspace);
	fz_free(ctx, block);
}
Beispiel #8
0
void
fz_free_pixmap_imp(fz_context *ctx, fz_storable *pix_)
{
	fz_pixmap *pix = (fz_pixmap *)pix_;

	if (pix->colorspace)
		fz_drop_colorspace(ctx, pix->colorspace);
	if (pix->free_samples)
		fz_free(ctx, pix->samples);
	fz_free(ctx, pix);
}
Beispiel #9
0
static void
pdf_free_xobject_imp(fz_context *ctx, fz_storable *xobj_)
{
	pdf_xobject *xobj = (pdf_xobject *)xobj_;

	if (xobj->colorspace)
		fz_drop_colorspace(ctx, xobj->colorspace);
	pdf_drop_obj(xobj->resources);
	pdf_drop_obj(xobj->contents);
	pdf_drop_obj(xobj->me);
	fz_free(ctx, xobj);
}
Beispiel #10
0
static fz_colorspace *
load_separation(pdf_document *xref, pdf_obj *array)
{
	fz_colorspace *cs;
	struct separation *sep = NULL;
	fz_context *ctx = xref->ctx;
	pdf_obj *nameobj = pdf_array_get(array, 1);
	pdf_obj *baseobj = pdf_array_get(array, 2);
	pdf_obj *tintobj = pdf_array_get(array, 3);
	fz_colorspace *base;
	pdf_function *tint = NULL;
	int n;

	fz_var(tint);
	fz_var(sep);

	if (pdf_is_array(nameobj))
		n = pdf_array_len(nameobj);
	else
		n = 1;

	if (n > FZ_MAX_COLORS)
		fz_throw(ctx, "too many components in colorspace");

	base = pdf_load_colorspace(xref, baseobj);
	/* RJW: "cannot load base colorspace (%d %d R)", pdf_to_num(baseobj), pdf_to_gen(baseobj) */

	fz_try(ctx)
	{
		tint = pdf_load_function(xref, tintobj);
		/* RJW: fz_drop_colorspace(ctx, base);
		 * "cannot load tint function (%d %d R)", pdf_to_num(tintobj), pdf_to_gen(tintobj) */

		sep = fz_malloc_struct(ctx, struct separation);
		sep->base = base;
		sep->tint = tint;

		cs = fz_new_colorspace(ctx, n == 1 ? "Separation" : "DeviceN", n);
		cs->to_rgb = separation_to_rgb;
		cs->free_data = free_separation;
		cs->data = sep;
		cs->size += sizeof(struct separation) + (base ? base->size : 0) + pdf_function_size(tint);
	}
	fz_catch(ctx)
	{
		fz_drop_colorspace(ctx, base);
		pdf_drop_function(ctx, tint);
		fz_free(ctx, sep);
		fz_rethrow(ctx);
	}

	return cs;
}
Beispiel #11
0
void
fz_free_shade_imp(fz_context *ctx, fz_storable *shade_)
{
	fz_shade *shade = (fz_shade *)shade_;

	if (shade->colorspace)
		fz_drop_colorspace(ctx, shade->colorspace);
	if (shade->type == FZ_FUNCTION_BASED)
		fz_free(ctx, shade->u.f.fn_vals);
	fz_free_compressed_buffer(ctx, shade->buffer);
	fz_free(ctx, shade);
}
Beispiel #12
0
void
fz_drop_image_imp(fz_context *ctx, fz_storable *image_)
{
    fz_image *image = (fz_image *)image_;

    if (image == NULL)
        return;
    fz_drop_pixmap(ctx, image->tile);
    fz_drop_compressed_buffer(ctx, image->buffer);
    fz_drop_colorspace(ctx, image->colorspace);
    fz_drop_image(ctx, image->mask);
    fz_free(ctx, image);
}
Beispiel #13
0
static void
pdf_free_image(fz_context *ctx, fz_storable *image_)
{
	pdf_image *image = (pdf_image *)image_;

	if (image == NULL)
		return;
	fz_drop_pixmap(ctx, image->tile);
	fz_free_compressed_buffer(ctx, image->buffer);
	fz_drop_colorspace(ctx, image->base.colorspace);
	fz_drop_image(ctx, image->base.mask);
	fz_free(ctx, image);
}
Beispiel #14
0
fz_pixmap *
fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples)
{
	fz_pixmap *pix;

	pix = fz_malloc_struct(ctx, fz_pixmap);
	FZ_INIT_STORABLE(pix, 1, fz_free_pixmap_imp);
	pix->x = 0;
	pix->y = 0;
	pix->w = w;
	pix->h = h;
	pix->interpolate = 1;
	pix->xres = 96;
	pix->yres = 96;
	pix->colorspace = NULL;
	pix->n = 1;
	pix->has_alpha = 1; /* SumatraPDF: allow optimizing non-alpha pixmaps */
	pix->single_bit = 0; /* SumatraPDF: allow optimizing 1-bit pixmaps */

	if (colorspace)
	{
		pix->colorspace = fz_keep_colorspace(ctx, colorspace);
		pix->n = 1 + colorspace->n;
	}

	pix->samples = samples;
	if (samples)
	{
		pix->free_samples = 0;
	}
	else
	{
		fz_try(ctx)
		{
			if (pix->w + pix->n - 1 > INT_MAX / pix->n)
				fz_throw(ctx, "overly wide image");
			pix->samples = fz_malloc_array(ctx, pix->h, pix->w * pix->n);
		}
		fz_catch(ctx)
		{
			if (colorspace)
				fz_drop_colorspace(ctx, colorspace);
			fz_free(ctx, pix);
			fz_rethrow(ctx);
		}
		pix->free_samples = 1;
	}

	return pix;
}
Beispiel #15
0
static void
fz_free_display_node(fz_context *ctx, fz_display_node *node)
{
	switch (node->cmd)
	{
	case FZ_CMD_FILL_PATH:
	case FZ_CMD_STROKE_PATH:
	case FZ_CMD_CLIP_PATH:
	case FZ_CMD_CLIP_STROKE_PATH:
		fz_free_path(ctx, node->item.path);
		break;
	case FZ_CMD_FILL_TEXT:
	case FZ_CMD_STROKE_TEXT:
	case FZ_CMD_CLIP_TEXT:
	case FZ_CMD_CLIP_STROKE_TEXT:
	case FZ_CMD_IGNORE_TEXT:
		fz_free_text(ctx, node->item.text);
		break;
	case FZ_CMD_FILL_SHADE:
		fz_drop_shade(ctx, node->item.shade);
		break;
	case FZ_CMD_FILL_IMAGE:
	case FZ_CMD_FILL_IMAGE_MASK:
	case FZ_CMD_CLIP_IMAGE_MASK:
		fz_drop_image(ctx, node->item.image);
		break;
	case FZ_CMD_POP_CLIP:
	case FZ_CMD_BEGIN_MASK:
	case FZ_CMD_END_MASK:
	case FZ_CMD_BEGIN_GROUP:
	case FZ_CMD_END_GROUP:
	case FZ_CMD_BEGIN_TILE:
	case FZ_CMD_END_TILE:
	case FZ_CMD_BEGIN_PAGE:
	case FZ_CMD_END_PAGE:
		break;
	/* SumatraPDF: support transfer functions */
	case FZ_CMD_APPLY_TRANSFER_FUNCTION:
		fz_drop_transfer_function(ctx, node->item.tr);
		break;
	}
	if (node->stroke)
		fz_drop_stroke_state(ctx, node->stroke);
	if (node->colorspace)
		fz_drop_colorspace(ctx, node->colorspace);
	fz_free(ctx, node);
}
static fz_error
load_separation(fz_colorspace **csp, pdf_xref *xref, fz_obj *array)
{
	fz_error error;
	fz_colorspace *cs;
	struct separation *sep;
	fz_obj *nameobj = fz_array_get(array, 1);
	fz_obj *baseobj = fz_array_get(array, 2);
	fz_obj *tintobj = fz_array_get(array, 3);
	fz_colorspace *base;
	pdf_function *tint;
	int n;

	if (fz_is_array(nameobj))
		n = fz_array_len(nameobj);
	else
		n = 1;

	if (n > FZ_MAX_COLORS)
		return fz_throw("too many components in colorspace");

	error = pdf_load_colorspace(&base, xref, baseobj);
	if (error)
		return fz_rethrow(error, "cannot load base colorspace (%d %d R)", fz_to_num(baseobj), fz_to_gen(baseobj));

	error = pdf_load_function(&tint, xref, tintobj);
	if (error)
	{
		fz_drop_colorspace(base);
		return fz_rethrow(error, "cannot load tint function (%d %d R)", fz_to_num(tintobj), fz_to_gen(tintobj));
	}

	sep = fz_malloc(sizeof(struct separation));
	sep->base = base;
	sep->tint = tint;

	cs = fz_new_colorspace(n == 1 ? "Separation" : "DeviceN", n);
	cs->to_rgb = separation_to_rgb;
	cs->free_data = free_separation;
	cs->data = sep;

	*csp = cs;
	return fz_okay;
}
static fz_colorspace *
load_icc_based(pdf_document *doc, pdf_obj *dict)
{
	int n;
	pdf_obj *obj;
	fz_context *ctx = doc->ctx;

	n = pdf_to_int(pdf_dict_gets(dict, "N"));
	obj = pdf_dict_gets(dict, "Alternate");

	if (obj)
	{
		fz_colorspace *cs_alt = NULL;

		fz_try(ctx)
		{
			cs_alt = pdf_load_colorspace(doc, obj);
			if (cs_alt->n != n)
			{
				fz_drop_colorspace(ctx, cs_alt);
				fz_throw(ctx, FZ_ERROR_GENERIC, "ICCBased /Alternate colorspace must have %d components", n);
			}
		}
		fz_catch(ctx)
		{
			cs_alt = NULL;
		}

		if (cs_alt)
			return cs_alt;
	}

	switch (n)
	{
	case 1: return fz_device_gray(ctx);
	case 3: return fz_device_rgb(ctx);
	case 4: return fz_device_cmyk(ctx);
	}

	fz_throw(ctx, FZ_ERROR_GENERIC, "syntaxerror: ICCBased must have 1, 3 or 4 components");
}
Beispiel #18
0
static void
fz_free_display_node(fz_display_node *node)
{
	switch (node->cmd)
	{
	case FZ_CMD_FILL_PATH:
	case FZ_CMD_STROKE_PATH:
	case FZ_CMD_CLIP_PATH:
	case FZ_CMD_CLIP_STROKE_PATH:
		fz_free_path(node->item.path);
		break;
	case FZ_CMD_FILL_TEXT:
	case FZ_CMD_STROKE_TEXT:
	case FZ_CMD_CLIP_TEXT:
	case FZ_CMD_CLIP_STROKE_TEXT:
	case FZ_CMD_IGNORE_TEXT:
		fz_free_text(node->item.text);
		break;
	case FZ_CMD_FILL_SHADE:
		fz_drop_shade(node->item.shade);
		break;
	case FZ_CMD_FILL_IMAGE:
	case FZ_CMD_FILL_IMAGE_MASK:
	case FZ_CMD_CLIP_IMAGE_MASK:
		fz_drop_pixmap(node->item.image);
		break;
	case FZ_CMD_POP_CLIP:
	case FZ_CMD_BEGIN_MASK:
	case FZ_CMD_END_MASK:
	case FZ_CMD_BEGIN_GROUP:
	case FZ_CMD_END_GROUP:
	case FZ_CMD_BEGIN_TILE:
	case FZ_CMD_END_TILE:
		break;
	}
	if (node->stroke)
		fz_free(node->stroke);
	if (node->colorspace)
		fz_drop_colorspace(node->colorspace);
	fz_free(node);
}
Beispiel #19
0
static fz_image *
pdf_load_image_imp(pdf_document *xref, pdf_obj *rdb, pdf_obj *dict, fz_stream *cstm, int forcemask)
{
	fz_stream *stm = NULL;
	fz_image *image = NULL;
	pdf_obj *obj, *res;

	int w, h, bpc, n;
	int imagemask;
	int interpolate;
	int indexed;
	fz_image *mask = NULL; /* explicit mask/soft mask image */
	int usecolorkey = 0;
	fz_colorspace *colorspace = NULL;
	float decode[FZ_MAX_COLORS * 2];
	int colorkey[FZ_MAX_COLORS * 2];

	int i;
	fz_context *ctx = xref->ctx;

	fz_var(stm);
	fz_var(mask);
	fz_var(image);
	fz_var(colorspace);

	fz_try(ctx)
	{
		/* special case for JPEG2000 images */
		if (pdf_is_jpx_image(ctx, dict))
		{
			image = pdf_load_jpx(xref, dict, forcemask);

			if (forcemask)
			{
				fz_pixmap *mask_pixmap;
				if (image->n != 2)
				{
					/* SumatraPDF: ignore invalid JPX softmasks */
					fz_warn(ctx, "soft mask must be grayscale");
					mask_pixmap = fz_new_pixmap(ctx, NULL, image->tile->w, image->tile->h);
					fz_clear_pixmap_with_value(ctx, mask_pixmap, 255);
				}
				else
				mask_pixmap = fz_alpha_from_gray(ctx, image->tile, 1);
				fz_drop_pixmap(ctx, image->tile);
				image->tile = mask_pixmap;
			}
			break; /* Out of fz_try */
		}

		w = pdf_to_int(pdf_dict_getsa(dict, "Width", "W"));
		h = pdf_to_int(pdf_dict_getsa(dict, "Height", "H"));
		bpc = pdf_to_int(pdf_dict_getsa(dict, "BitsPerComponent", "BPC"));
		if (bpc == 0)
			bpc = 8;
		imagemask = pdf_to_bool(pdf_dict_getsa(dict, "ImageMask", "IM"));
		interpolate = pdf_to_bool(pdf_dict_getsa(dict, "Interpolate", "I"));

		indexed = 0;
		usecolorkey = 0;
		mask = NULL;

		if (imagemask)
			bpc = 1;

		if (w <= 0)
			fz_throw(ctx, "image width is zero (or less)");
		if (h <= 0)
			fz_throw(ctx, "image height is zero (or less)");
		if (bpc <= 0)
			fz_throw(ctx, "image depth is zero (or less)");
		if (bpc > 16)
			fz_throw(ctx, "image depth is too large: %d", bpc);
		if (w > (1 << 16))
			fz_throw(ctx, "image is too wide");
		if (h > (1 << 16))
			fz_throw(ctx, "image is too high");

		obj = pdf_dict_getsa(dict, "ColorSpace", "CS");
		if (obj && !imagemask && !forcemask)
		{
			/* colorspace resource lookup is only done for inline images */
			if (pdf_is_name(obj))
			{
				res = pdf_dict_get(pdf_dict_gets(rdb, "ColorSpace"), obj);
				if (res)
					obj = res;
			}

			colorspace = pdf_load_colorspace(xref, obj);

			if (!strcmp(colorspace->name, "Indexed"))
				indexed = 1;

			n = colorspace->n;
		}
		else
		{
			n = 1;
		}

		obj = pdf_dict_getsa(dict, "Decode", "D");
		if (obj)
		{
			for (i = 0; i < n * 2; i++)
				decode[i] = pdf_to_real(pdf_array_get(obj, i));
		}
		else
		{
			float maxval = indexed ? (1 << bpc) - 1 : 1;
			for (i = 0; i < n * 2; i++)
				decode[i] = i & 1 ? maxval : 0;
		}

		obj = pdf_dict_getsa(dict, "SMask", "Mask");
		if (pdf_is_dict(obj))
		{
			/* Not allowed for inline images or soft masks */
			if (cstm)
				fz_warn(ctx, "Ignoring invalid inline image soft mask");
			else if (forcemask)
				fz_warn(ctx, "Ignoring recursive image soft mask");
			else
				mask = pdf_load_image_imp(xref, rdb, obj, NULL, 1);
		}
		else if (pdf_is_array(obj))
		{
			usecolorkey = 1;
			for (i = 0; i < n * 2; i++)
			{
				if (!pdf_is_int(pdf_array_get(obj, i)))
				{
					fz_warn(ctx, "invalid value in color key mask");
					usecolorkey = 0;
				}
				colorkey[i] = pdf_to_int(pdf_array_get(obj, i));
			}
		}

		/* Now, do we load a ref, or do we load the actual thing? */
		if (!cstm)
		{
			/* Just load the compressed image data now and we can
			 * decode it on demand. */
			int num = pdf_to_num(dict);
			int gen = pdf_to_gen(dict);
			fz_compressed_buffer *buffer = pdf_load_compressed_stream(xref, num, gen);
			image = fz_new_image(ctx, w, h, bpc, colorspace, 96, 96, interpolate, imagemask, decode, usecolorkey ? colorkey : NULL, buffer, mask);
			break; /* Out of fz_try */
		}

		/* We need to decompress the image now */
		if (cstm)
		{
			int stride = (w * n * bpc + 7) / 8;
			stm = pdf_open_inline_stream(xref, dict, stride * h, cstm, NULL);
		}
		else
		{
			stm = pdf_open_stream(xref, pdf_to_num(dict), pdf_to_gen(dict));
		}

		image = fz_new_image(ctx, w, h, bpc, colorspace, 96, 96, interpolate, imagemask, decode, usecolorkey ? colorkey : NULL, NULL, mask);
		image->tile = fz_decomp_image_from_stream(ctx, stm, image, cstm != NULL, indexed, 0, 0);
	}
	fz_catch(ctx)
	{
		/* SumatraPDF: fix memory leak */
		if (!image)
			fz_drop_colorspace(ctx, colorspace);
		else
		fz_drop_image(ctx, image);
		fz_rethrow(ctx);
	}

	/* cf. http://bugs.ghostscript.com/show_bug.cgi?id=693517 */
	fz_try(ctx)
	{
		obj = pdf_dict_getp(dict, "SMask/Matte");
		if (pdf_is_array(obj) && image->mask)
		{
			assert(!image->usecolorkey);
			image->usecolorkey = 2;
			for (i = 0; i < n; i++)
				image->colorkey[i] = pdf_to_int(pdf_array_get(obj, i));
		}
	}
	fz_catch(ctx)
	{
		fz_drop_image(ctx, image);
		fz_rethrow(ctx);
	}

	return image;
}
static fz_error
pdf_load_image_imp(fz_pixmap **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, fz_stream *cstm, int forcemask)
{
	fz_stream *stm;
	fz_pixmap *tile;
	fz_obj *obj, *res;
	fz_error error;

	int w, h, bpc, n;
	int imagemask;
	int interpolate;
	int indexed;
	fz_colorspace *colorspace;
	fz_pixmap *mask; /* explicit mask/softmask image */
	int usecolorkey;
	int colorkey[FZ_MAX_COLORS * 2];
	float decode[FZ_MAX_COLORS * 2];

	int stride;
	unsigned char *samples;
	int i, len;

	/* special case for JPEG2000 images */
	if (pdf_is_jpx_image(dict))
	{
		tile = NULL;
		error = pdf_load_jpx_image(&tile, xref, dict);
		if (error)
			return fz_rethrow(error, "cannot load jpx image");
		if (forcemask)
		{
			if (tile->n != 2)
			{
				fz_drop_pixmap(tile);
				return fz_throw("softmask must be grayscale");
			}
			mask = fz_alpha_from_gray(tile, 1);
			fz_drop_pixmap(tile);
			*imgp = mask;
			return fz_okay;
		}
		*imgp = tile;
		return fz_okay;
	}

	w = fz_to_int(fz_dict_getsa(dict, "Width", "W"));
	h = fz_to_int(fz_dict_getsa(dict, "Height", "H"));
	bpc = fz_to_int(fz_dict_getsa(dict, "BitsPerComponent", "BPC"));
	imagemask = fz_to_bool(fz_dict_getsa(dict, "ImageMask", "IM"));
	interpolate = fz_to_bool(fz_dict_getsa(dict, "Interpolate", "I"));

	indexed = 0;
	usecolorkey = 0;
	colorspace = NULL;
	mask = NULL;

	if (imagemask)
		bpc = 1;

	if (w == 0)
		return fz_throw("image width is zero");
	if (h == 0)
		return fz_throw("image height is zero");
	if (bpc == 0)
		return fz_throw("image depth is zero");
	if (w > (1 << 16))
		return fz_throw("image is too wide");
	if (h > (1 << 16))
		return fz_throw("image is too high");

	obj = fz_dict_getsa(dict, "ColorSpace", "CS");
	if (obj && !imagemask && !forcemask)
	{
		/* colorspace resource lookup is only done for inline images */
		if (fz_is_name(obj))
		{
			res = fz_dict_get(fz_dict_gets(rdb, "ColorSpace"), obj);
			if (res)
				obj = res;
		}

		error = pdf_load_colorspace(&colorspace, xref, obj);
		if (error)
			return fz_rethrow(error, "cannot load image colorspace");

		if (!strcmp(colorspace->name, "Indexed"))
			indexed = 1;

		n = colorspace->n;
	}
	else
	{
		n = 1;
	}

	obj = fz_dict_getsa(dict, "Decode", "D");
	if (obj)
	{
		for (i = 0; i < n * 2; i++)
			decode[i] = fz_to_real(fz_array_get(obj, i));
	}
	else
	{
		float maxval = indexed ? (1 << bpc) - 1 : 1;
		for (i = 0; i < n * 2; i++)
			decode[i] = i & 1 ? maxval : 0;
	}

	obj = fz_dict_getsa(dict, "SMask", "Mask");
	if (fz_is_dict(obj))
	{
		/* Not allowed for inline images */
		if (!cstm)
		{
			error = pdf_load_image_imp(&mask, xref, rdb, obj, NULL, 1);
			if (error)
			{
				if (colorspace)
					fz_drop_colorspace(colorspace);
				return fz_rethrow(error, "cannot load image mask/softmask");
			}
		}
	}
	else if (fz_is_array(obj))
	{
		usecolorkey = 1;
		for (i = 0; i < n * 2; i++)
			colorkey[i] = fz_to_int(fz_array_get(obj, i));
	}

	/* Allocate now, to fail early if we run out of memory */
	tile = fz_new_pixmap_with_limit(colorspace, w, h);
	if (!tile)
	{
		if (colorspace)
			fz_drop_colorspace(colorspace);
		if (mask)
			fz_drop_pixmap(mask);
		return fz_throw("out of memory");
	}

	if (colorspace)
		fz_drop_colorspace(colorspace);

	tile->mask = mask;
	tile->interpolate = interpolate;

	stride = (w * n * bpc + 7) / 8;

	if (cstm)
	{
		stm = pdf_open_inline_stream(cstm, xref, dict, stride * h);
	}
	else
	{
		error = pdf_open_stream(&stm, xref, fz_to_num(dict), fz_to_gen(dict));
		if (error)
		{
			fz_drop_pixmap(tile);
			return fz_rethrow(error, "cannot open image data stream (%d 0 R)", fz_to_num(dict));
		}
	}

	samples = fz_calloc(h, stride);

	len = fz_read(stm, samples, h * stride);
	if (len < 0)
	{
		fz_close(stm);
		fz_free(samples);
		fz_drop_pixmap(tile);
		return fz_rethrow(len, "cannot read image data");
	}

	/* Make sure we read the EOF marker (for inline images only) */
	if (cstm)
	{
		unsigned char tbuf[512];
		int tlen = fz_read(stm, tbuf, sizeof tbuf);
		if (tlen < 0)
			fz_catch(tlen, "ignoring error at end of image");
		if (tlen > 0)
			fz_warn("ignoring garbage at end of image");
	}

	fz_close(stm);

	/* Pad truncated images */
	if (len < stride * h)
	{
		fz_warn("padding truncated image (%d 0 R)", fz_to_num(dict));
		memset(samples + len, 0, stride * h - len);
	}

	/* Invert 1-bit image masks */
	if (imagemask)
	{
		/* 0=opaque and 1=transparent so we need to invert */
		unsigned char *p = samples;
		len = h * stride;
		for (i = 0; i < len; i++)
			p[i] = ~p[i];
	}

	fz_unpack_tile(tile, samples, n, bpc, stride, indexed);

	fz_free(samples);

	if (usecolorkey)
		pdf_mask_color_key(tile, n, colorkey);

	if (indexed)
	{
		fz_pixmap *conv;
		fz_decode_indexed_tile(tile, decode, (1 << bpc) - 1);
		conv = pdf_expand_indexed_pixmap(tile);
		fz_drop_pixmap(tile);
		tile = conv;
	}
	else
	{
		fz_decode_tile(tile, decode);
	}

	*imgp = tile;
	return fz_okay;
}
Beispiel #21
0
static void
pdf_run_page_contents_with_usage(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_device *dev, const fz_matrix *ctm, const char *usage, fz_cookie *cookie)
{
	fz_matrix local_ctm, page_ctm;
	pdf_obj *resources;
	pdf_obj *contents;
	fz_rect mediabox;
	pdf_processor *proc = NULL;
	fz_default_colorspaces *default_cs;

	fz_var(proc);

	default_cs = pdf_load_default_colorspaces(ctx, doc, page);
	if (default_cs)
		fz_set_default_colorspaces(ctx, dev, default_cs);

	fz_try(ctx)
	{
		pdf_page_transform(ctx, page, &mediabox, &page_ctm);
		fz_concat(&local_ctm, &page_ctm, ctm);

		resources = pdf_page_resources(ctx, page);
		contents = pdf_page_contents(ctx, page);

		if (page->transparency)
		{
			fz_colorspace *colorspace = NULL;
			pdf_obj *group = pdf_page_group(ctx, page);

			if (group)
			{
				pdf_obj *cs = pdf_dict_get(ctx, group, PDF_NAME_CS);
				if (cs)
				{
					fz_try(ctx)
						colorspace = pdf_load_colorspace(ctx, cs);
					fz_catch(ctx)
						colorspace = NULL;
				}
			}
			else
				colorspace = fz_keep_colorspace(ctx, fz_default_output_intent(ctx, default_cs));

			fz_begin_group(ctx, dev, fz_transform_rect(&mediabox, &local_ctm), colorspace, 1, 0, 0, 1);
			fz_drop_colorspace(ctx, colorspace);
		}

		proc = pdf_new_run_processor(ctx, dev, &local_ctm, usage, NULL, 0);
		pdf_process_contents(ctx, proc, doc, resources, contents, cookie);
		pdf_close_processor(ctx, proc);
	}
	fz_always(ctx)
	{
		fz_drop_default_colorspaces(ctx, default_cs);
		pdf_drop_processor(ctx, proc);
	}
	fz_catch(ctx)
		fz_rethrow(ctx);

	if (page->transparency)
		fz_end_group(ctx, dev);
}
Beispiel #22
0
static fz_image *
pdf_load_jpx(pdf_document *doc, pdf_obj *dict, int forcemask)
{
	fz_buffer *buf = NULL;
	fz_colorspace *colorspace = NULL;
	fz_pixmap *img = NULL;
	pdf_obj *obj;
	fz_context *ctx = doc->ctx;
	int indexed = 0;
	fz_image *mask = NULL;

	fz_var(img);
	fz_var(buf);
	fz_var(colorspace);
	fz_var(mask);

	buf = pdf_load_stream(doc, pdf_to_num(dict), pdf_to_gen(dict));

	/* FIXME: We can't handle decode arrays for indexed images currently */
	fz_try(ctx)
	{
		obj = pdf_dict_gets(dict, "ColorSpace");
		if (obj)
		{
			colorspace = pdf_load_colorspace(doc, obj);
			indexed = fz_colorspace_is_indexed(colorspace);
		}

		img = fz_load_jpx(ctx, buf->data, buf->len, colorspace, indexed);

		obj = pdf_dict_getsa(dict, "SMask", "Mask");
		if (pdf_is_dict(obj))
		{
			if (forcemask)
				fz_warn(ctx, "Ignoring recursive JPX soft mask");
			else
				mask = pdf_load_image_imp(doc, NULL, obj, NULL, 1);
		}

		obj = pdf_dict_getsa(dict, "Decode", "D");
		if (obj && !indexed)
		{
			float decode[FZ_MAX_COLORS * 2];
			int i;

			for (i = 0; i < img->n * 2; i++)
				decode[i] = pdf_to_real(pdf_array_get(obj, i));

			fz_decode_tile(img, decode);
		}
	}
	fz_always(ctx)
	{
		fz_drop_colorspace(ctx, colorspace);
		fz_drop_buffer(ctx, buf);
	}
	fz_catch(ctx)
	{
		fz_drop_pixmap(ctx, img);
		fz_rethrow(ctx);
	}

	return fz_new_image_from_pixmap(ctx, img, mask);
}
Beispiel #23
0
static void
pdf_process_extgstate(fz_context *ctx, pdf_processor *proc, pdf_csi *csi, pdf_obj *dict)
{
	pdf_obj *obj;

	obj = pdf_dict_get(ctx, dict, PDF_NAME_LW);
	if (pdf_is_number(ctx, obj) && proc->op_w)
		proc->op_w(ctx, proc, pdf_to_real(ctx, obj));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_LC);
	if (pdf_is_int(ctx, obj) && proc->op_J)
		proc->op_J(ctx, proc, fz_clampi(pdf_to_int(ctx, obj), 0, 2));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_LJ);
	if (pdf_is_int(ctx, obj) && proc->op_j)
		proc->op_j(ctx, proc, fz_clampi(pdf_to_int(ctx, obj), 0, 2));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_ML);
	if (pdf_is_number(ctx, obj) && proc->op_M)
		proc->op_M(ctx, proc, pdf_to_real(ctx, obj));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_D);
	if (pdf_is_array(ctx, obj) && proc->op_d)
	{
		pdf_obj *dash_array = pdf_array_get(ctx, obj, 0);
		pdf_obj *dash_phase = pdf_array_get(ctx, obj, 1);
		proc->op_d(ctx, proc, dash_array, pdf_to_real(ctx, dash_phase));
	}

	obj = pdf_dict_get(ctx, dict, PDF_NAME_RI);
	if (pdf_is_name(ctx, obj) && proc->op_ri)
		proc->op_ri(ctx, proc, pdf_to_name(ctx, obj));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_FL);
	if (pdf_is_number(ctx, obj) && proc->op_i)
		proc->op_i(ctx, proc, pdf_to_real(ctx, obj));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_Font);
	if (pdf_is_array(ctx, obj) && proc->op_Tf)
	{
		pdf_obj *font_ref = pdf_array_get(ctx, obj, 0);
		pdf_obj *font_size = pdf_array_get(ctx, obj, 1);
		pdf_font_desc *font = load_font_or_hail_mary(ctx, csi->doc, csi->rdb, font_ref, 0, csi->cookie);
		fz_try(ctx)
			proc->op_Tf(ctx, proc, "ExtGState", font, pdf_to_real(ctx, font_size));
		fz_always(ctx)
			pdf_drop_font(ctx, font);
		fz_catch(ctx)
			fz_rethrow(ctx);
	}

	/* transfer functions */

	obj = pdf_dict_get(ctx, dict, PDF_NAME_TR2);
	if (pdf_is_name(ctx, obj))
		if (!pdf_name_eq(ctx, obj, PDF_NAME_Identity) && !pdf_name_eq(ctx, obj, PDF_NAME_Default))
			fz_warn(ctx, "ignoring transfer function");
	if (!obj) /* TR is ignored in the presence of TR2 */
	{
		pdf_obj *tr = pdf_dict_get(ctx, dict, PDF_NAME_TR);
		if (pdf_is_name(ctx, tr))
			if (!pdf_name_eq(ctx, tr, PDF_NAME_Identity))
				fz_warn(ctx, "ignoring transfer function");
	}

	/* transparency state */

	obj = pdf_dict_get(ctx, dict, PDF_NAME_CA);
	if (pdf_is_number(ctx, obj) && proc->op_gs_CA)
		proc->op_gs_CA(ctx, proc, pdf_to_real(ctx, obj));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_ca);
	if (pdf_is_number(ctx, obj) && proc->op_gs_ca)
		proc->op_gs_ca(ctx, proc, pdf_to_real(ctx, obj));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_BM);
	if (pdf_is_array(ctx, obj))
		obj = pdf_array_get(ctx, obj, 0);
	if (pdf_is_name(ctx, obj) && proc->op_gs_BM)
		proc->op_gs_BM(ctx, proc, pdf_to_name(ctx, obj));

	obj = pdf_dict_get(ctx, dict, PDF_NAME_SMask);
	if (proc->op_gs_SMask)
	{
		if (pdf_is_dict(ctx, obj))
		{
			pdf_xobject *xobj;
			pdf_obj *group, *s, *bc, *tr;
			float softmask_bc[FZ_MAX_COLORS];
			fz_colorspace *colorspace;
			int colorspace_n = 1;
			int k, luminosity;

			fz_var(xobj);

			group = pdf_dict_get(ctx, obj, PDF_NAME_G);
			if (!group)
				fz_throw(ctx, FZ_ERROR_GENERIC, "cannot load softmask xobject (%d 0 R)", pdf_to_num(ctx, obj));
			xobj = pdf_load_xobject(ctx, csi->doc, group);

			fz_try(ctx)
			{
				colorspace = pdf_xobject_colorspace(ctx, xobj);
				if (colorspace)
				{
					colorspace_n = fz_colorspace_n(ctx, colorspace);
					fz_drop_colorspace(ctx, colorspace);
				}

				/* Default background color is black. */
				for (k = 0; k < colorspace_n; k++)
					softmask_bc[k] = 0;
				/* Which in CMYK means not all zeros! This should really be
				 * a test for subtractive color spaces, but this will have
				 * to do for now. */
				if (colorspace == fz_device_cmyk(ctx))
					softmask_bc[3] = 1.0;

				bc = pdf_dict_get(ctx, obj, PDF_NAME_BC);
				if (pdf_is_array(ctx, bc))
				{
					for (k = 0; k < colorspace_n; k++)
						softmask_bc[k] = pdf_to_real(ctx, pdf_array_get(ctx, bc, k));
				}

				s = pdf_dict_get(ctx, obj, PDF_NAME_S);
				if (pdf_name_eq(ctx, s, PDF_NAME_Luminosity))
					luminosity = 1;
				else
					luminosity = 0;

				tr = pdf_dict_get(ctx, obj, PDF_NAME_TR);
				if (tr && !pdf_name_eq(ctx, tr, PDF_NAME_Identity))
					fz_warn(ctx, "ignoring transfer function");

				proc->op_gs_SMask(ctx, proc, xobj, csi->rdb, softmask_bc, luminosity);
			}
			fz_always(ctx)
			{
				pdf_drop_xobject(ctx, xobj);
			}
			fz_catch(ctx)
			{
				fz_rethrow(ctx);
			}
		}
		else if (pdf_is_name(ctx, obj) && pdf_name_eq(ctx, obj, PDF_NAME_None))
		{
			proc->op_gs_SMask(ctx, proc, NULL, NULL, NULL, 0);
		}
	}
static fz_error
load_indexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array)
{
	fz_error error;
	fz_colorspace *cs;
	struct indexed *idx;
	fz_obj *baseobj = fz_array_get(array, 1);
	fz_obj *highobj = fz_array_get(array, 2);
	fz_obj *lookup = fz_array_get(array, 3);
	fz_colorspace *base;
	int i, n;

	error = pdf_load_colorspace(&base, xref, baseobj);
	if (error)
		return fz_rethrow(error, "cannot load base colorspace (%d %d R)", fz_to_num(baseobj), fz_to_gen(baseobj));

	idx = fz_malloc(sizeof(struct indexed));
	idx->base = base;
	idx->high = fz_to_int(highobj);
	idx->high = CLAMP(idx->high, 0, 255);
	n = base->n * (idx->high + 1);
	idx->lookup = fz_malloc(n);
	memset(idx->lookup, 0, n);

	cs = fz_new_colorspace("Indexed", 1);
	cs->to_rgb = indexed_to_rgb;
	cs->free_data = free_indexed;
	cs->data = idx;

	if (fz_is_string(lookup) && fz_to_str_len(lookup) == n)
	{
		unsigned char *buf = (unsigned char *) fz_to_str_buf(lookup);
		for (i = 0; i < n; i++)
			idx->lookup[i] = buf[i];
	}
	else if (fz_is_indirect(lookup))
	{
		fz_stream *file;

		error = pdf_open_stream(&file, xref, fz_to_num(lookup), fz_to_gen(lookup));
		if (error)
		{
			fz_drop_colorspace(cs);
			return fz_rethrow(error, "cannot open colorspace lookup table (%d 0 R)", fz_to_num(lookup));
		}

		i = fz_read(file, idx->lookup, n);
		if (i < 0)
		{
			fz_drop_colorspace(cs);
			return fz_throw("cannot read colorspace lookup table (%d 0 R)", fz_to_num(lookup));
		}

		fz_close(file);
	}
	else
	{
		fz_drop_colorspace(cs);
		return fz_throw("cannot parse colorspace lookup table");
	}

	*csp = cs;
	return fz_okay;
}
Beispiel #25
0
static fz_image *
pdf_load_image_imp(fz_context *ctx, pdf_document *doc, pdf_obj *rdb, pdf_obj *dict, fz_stream *cstm, int forcemask)
{
	fz_image *image = NULL;
	pdf_obj *obj, *res;

	int w, h, bpc, n;
	int imagemask;
	int interpolate;
	int indexed;
	fz_image *mask = NULL; /* explicit mask/soft mask image */
	int use_colorkey = 0;
	fz_colorspace *colorspace = NULL;
	float decode[FZ_MAX_COLORS * 2];
	int colorkey[FZ_MAX_COLORS * 2];
	int stride;

	int i;
	fz_compressed_buffer *buffer;

	/* special case for JPEG2000 images */
	if (pdf_is_jpx_image(ctx, dict))
		return pdf_load_jpx_imp(ctx, doc, rdb, dict, cstm, forcemask);

	w = pdf_to_int(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(Width), PDF_NAME(W)));
	h = pdf_to_int(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(Height), PDF_NAME(H)));
	bpc = pdf_to_int(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(BitsPerComponent), PDF_NAME(BPC)));
	if (bpc == 0)
		bpc = 8;
	imagemask = pdf_to_bool(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(ImageMask), PDF_NAME(IM)));
	interpolate = pdf_to_bool(ctx, pdf_dict_geta(ctx, dict, PDF_NAME(Interpolate), PDF_NAME(I)));

	indexed = 0;
	use_colorkey = 0;

	if (imagemask)
		bpc = 1;

	if (w <= 0)
		fz_throw(ctx, FZ_ERROR_GENERIC, "image width is zero (or less)");
	if (h <= 0)
		fz_throw(ctx, FZ_ERROR_GENERIC, "image height is zero (or less)");
	if (bpc <= 0)
		fz_throw(ctx, FZ_ERROR_GENERIC, "image depth is zero (or less)");
	if (bpc > 16)
		fz_throw(ctx, FZ_ERROR_GENERIC, "image depth is too large: %d", bpc);
	if (w > (1 << 16))
		fz_throw(ctx, FZ_ERROR_GENERIC, "image is too wide");
	if (h > (1 << 16))
		fz_throw(ctx, FZ_ERROR_GENERIC, "image is too high");

	fz_var(mask);
	fz_var(image);
	fz_var(colorspace);

	fz_try(ctx)
	{
		obj = pdf_dict_geta(ctx, dict, PDF_NAME(ColorSpace), PDF_NAME(CS));
		if (obj && !imagemask && !forcemask)
		{
			/* colorspace resource lookup is only done for inline images */
			if (pdf_is_name(ctx, obj))
			{
				res = pdf_dict_get(ctx, pdf_dict_get(ctx, rdb, PDF_NAME(ColorSpace)), obj);
				if (res)
					obj = res;
			}

			colorspace = pdf_load_colorspace(ctx, obj);
			indexed = fz_colorspace_is_indexed(ctx, colorspace);

			n = fz_colorspace_n(ctx, colorspace);
		}
		else
		{
			n = 1;
		}

		obj = pdf_dict_geta(ctx, dict, PDF_NAME(Decode), PDF_NAME(D));
		if (obj)
		{
			for (i = 0; i < n * 2; i++)
				decode[i] = pdf_array_get_real(ctx, obj, i);
		}
		else if (fz_colorspace_is_lab(ctx, colorspace) || fz_colorspace_is_lab_icc(ctx, colorspace))
		{
			decode[0] = 0;
			decode[1] = 100;
			decode[2] = -128;
			decode[3] = 127;
			decode[4] = -128;
			decode[5] = 127;
		}
		else
		{
			float maxval = indexed ? (1 << bpc) - 1 : 1;
			for (i = 0; i < n * 2; i++)
				decode[i] = i & 1 ? maxval : 0;
		}

		obj = pdf_dict_geta(ctx, dict, PDF_NAME(SMask), PDF_NAME(Mask));
		if (pdf_is_dict(ctx, obj))
		{
			/* Not allowed for inline images or soft masks */
			if (cstm)
				fz_warn(ctx, "Ignoring invalid inline image soft mask");
			else if (forcemask)
				fz_warn(ctx, "Ignoring recursive image soft mask");
			else
			{
				mask = pdf_load_image_imp(ctx, doc, rdb, obj, NULL, 1);
				obj = pdf_dict_get(ctx, obj, PDF_NAME(Matte));
				if (pdf_is_array(ctx, obj))
				{
					use_colorkey = 1;
					for (i = 0; i < n; i++)
						colorkey[i] = pdf_array_get_real(ctx, obj, i) * 255;
				}
			}
		}
		else if (pdf_is_array(ctx, obj))
		{
			use_colorkey = 1;
			for (i = 0; i < n * 2; i++)
			{
				if (!pdf_is_int(ctx, pdf_array_get(ctx, obj, i)))
				{
					fz_warn(ctx, "invalid value in color key mask");
					use_colorkey = 0;
				}
				colorkey[i] = pdf_array_get_int(ctx, obj, i);
			}
		}

		/* Do we load from a ref, or do we load an inline stream? */
		if (cstm == NULL)
		{
			/* Just load the compressed image data now and we can decode it on demand. */
			buffer = pdf_load_compressed_stream(ctx, doc, pdf_to_num(ctx, dict));
			image = fz_new_image_from_compressed_buffer(ctx, w, h, bpc, colorspace, 96, 96, interpolate, imagemask, decode, use_colorkey ? colorkey : NULL, buffer, mask);
			image->invert_cmyk_jpeg = 0;
		}
		else
		{
			/* Inline stream */
			stride = (w * n * bpc + 7) / 8;
			image = fz_new_image_from_compressed_buffer(ctx, w, h, bpc, colorspace, 96, 96, interpolate, imagemask, decode, use_colorkey ? colorkey : NULL, NULL, mask);
			image->invert_cmyk_jpeg = 0;
			pdf_load_compressed_inline_image(ctx, doc, dict, stride * h, cstm, indexed, (fz_compressed_image *)image);
		}
	}
	fz_always(ctx)
	{
		fz_drop_colorspace(ctx, colorspace);
		fz_drop_image(ctx, mask);
	}
	fz_catch(ctx)
	{
		fz_drop_image(ctx, image);
		fz_rethrow(ctx);
	}
	return image;
}
Beispiel #26
0
static fz_image *
pdf_load_image_imp(pdf_document *doc, pdf_obj *rdb, pdf_obj *dict, fz_stream *cstm, int forcemask)
{
	fz_stream *stm = NULL;
	fz_image *image = NULL;
	pdf_obj *obj, *res;

	int w, h, bpc, n;
	int imagemask;
	int interpolate;
	int indexed;
	fz_image *mask = NULL; /* explicit mask/soft mask image */
	int usecolorkey = 0;
	fz_colorspace *colorspace = NULL;
	float decode[FZ_MAX_COLORS * 2];
	int colorkey[FZ_MAX_COLORS * 2];
	int stride;

	int i;
	fz_context *ctx = doc->ctx;
	fz_compressed_buffer *buffer;

	fz_var(stm);
	fz_var(mask);
	fz_var(image);
	fz_var(colorspace);

	fz_try(ctx)
	{
		/* special case for JPEG2000 images */
		if (pdf_is_jpx_image(ctx, dict))
		{
//			image = pdf_load_jpx(doc, dict, forcemask);
//
//			if (forcemask)
//			{
//				fz_pixmap *mask_pixmap;
//				if (image->n != 2)
//				{
//					fz_pixmap *gray;
//					fz_irect bbox;
//					fz_warn(ctx, "soft mask should be grayscale");
//					gray = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), fz_pixmap_bbox(ctx, image->tile, &bbox));
//					fz_convert_pixmap(ctx, gray, image->tile);
//					fz_drop_pixmap(ctx, image->tile);
//					image->tile = gray;
//				}
//				mask_pixmap = fz_alpha_from_gray(ctx, image->tile, 1);
//				fz_drop_pixmap(ctx, image->tile);
//				image->tile = mask_pixmap;
//			}
			break; /* Out of fz_try */
		}

		w = pdf_to_int(pdf_dict_getsa(dict, "Width", "W"));
		h = pdf_to_int(pdf_dict_getsa(dict, "Height", "H"));
		bpc = pdf_to_int(pdf_dict_getsa(dict, "BitsPerComponent", "BPC"));
		if (bpc == 0)
			bpc = 8;
		imagemask = pdf_to_bool(pdf_dict_getsa(dict, "ImageMask", "IM"));
		interpolate = pdf_to_bool(pdf_dict_getsa(dict, "Interpolate", "I"));

		indexed = 0;
		usecolorkey = 0;

		if (imagemask)
			bpc = 1;

		if (w <= 0)
			fz_throw(ctx, FZ_ERROR_GENERIC, "image width is zero (or less)");
		if (h <= 0)
			fz_throw(ctx, FZ_ERROR_GENERIC, "image height is zero (or less)");
		if (bpc <= 0)
			fz_throw(ctx, FZ_ERROR_GENERIC, "image depth is zero (or less)");
		if (bpc > 16)
			fz_throw(ctx, FZ_ERROR_GENERIC, "image depth is too large: %d", bpc);
		if (w > (1 << 16))
			fz_throw(ctx, FZ_ERROR_GENERIC, "image is too wide");
		if (h > (1 << 16))
			fz_throw(ctx, FZ_ERROR_GENERIC, "image is too high");

		obj = pdf_dict_getsa(dict, "ColorSpace", "CS");
		if (obj && !imagemask && !forcemask)
		{
			/* colorspace resource lookup is only done for inline images */
			if (pdf_is_name(obj))
			{
				res = pdf_dict_get(pdf_dict_gets(rdb, "ColorSpace"), obj);
				if (res)
					obj = res;
			}

			colorspace = pdf_load_colorspace(doc, obj);
			indexed = fz_colorspace_is_indexed(colorspace);

			n = colorspace->n;
		}
		else
		{
			n = 1;
		}

		obj = pdf_dict_getsa(dict, "Decode", "D");
		if (obj)
		{
			for (i = 0; i < n * 2; i++)
				decode[i] = pdf_to_real(pdf_array_get(obj, i));
		}
		else
		{
			float maxval = indexed ? (1 << bpc) - 1 : 1;
			for (i = 0; i < n * 2; i++)
				decode[i] = i & 1 ? maxval : 0;
		}

		obj = pdf_dict_getsa(dict, "SMask", "Mask");
		if (pdf_is_dict(obj))
		{
			/* Not allowed for inline images or soft masks */
			if (cstm)
				fz_warn(ctx, "Ignoring invalid inline image soft mask");
			else if (forcemask)
				fz_warn(ctx, "Ignoring recursive image soft mask");
			else
			{
				mask = pdf_load_image_imp(doc, rdb, obj, NULL, 1);
				obj = pdf_dict_gets(obj, "Matte");
				if (pdf_is_array(obj))
				{
					usecolorkey = 1;
					for (i = 0; i < n; i++)
						colorkey[i] = pdf_to_real(pdf_array_get(obj, i)) * 255;
				}
			}
		}
		else if (pdf_is_array(obj))
		{
			usecolorkey = 1;
			for (i = 0; i < n * 2; i++)
			{
				if (!pdf_is_int(pdf_array_get(obj, i)))
				{
					fz_warn(ctx, "invalid value in color key mask");
					usecolorkey = 0;
				}
				colorkey[i] = pdf_to_int(pdf_array_get(obj, i));
			}
		}

		/* Do we load from a ref, or do we load an inline stream? */
		if (cstm == NULL)
		{
			/* Just load the compressed image data now and we can
			 * decode it on demand. */
			int num = pdf_to_num(dict);
			int gen = pdf_to_gen(dict);
			buffer = pdf_load_compressed_stream(doc, num, gen);
			image = fz_new_image(ctx, w, h, bpc, colorspace, 96, 96, interpolate, imagemask, decode, usecolorkey ? colorkey : NULL, buffer, mask);
		}
		else
		{
			/* Inline stream */
			stride = (w * n * bpc + 7) / 8;
			image = fz_new_image(ctx, w, h, bpc, colorspace, 96, 96, interpolate, imagemask, decode, usecolorkey ? colorkey : NULL, NULL, mask);
			pdf_load_compressed_inline_image(doc, dict, stride * h, cstm, indexed, image);
		}

	}
	fz_catch(ctx)
	{
		fz_drop_colorspace(ctx, colorspace);
		fz_drop_image(ctx, mask);
		fz_drop_image(ctx, image);
		fz_rethrow(ctx);
	}
	return image;
}
Beispiel #27
0
static void
pdf_load_jpx(pdf_document *xref, pdf_obj *dict, pdf_image *image, int forcemask)
{
	fz_buffer *buf = NULL;
	fz_colorspace *colorspace = NULL;
	fz_pixmap *img = NULL;
	pdf_obj *obj;
	fz_context *ctx = xref->ctx;
	int indexed = 0;

	fz_var(img);
	fz_var(buf);
	fz_var(colorspace);

	buf = pdf_load_stream(xref, pdf_to_num(dict), pdf_to_gen(dict));

	/* FIXME: We can't handle decode arrays for indexed images currently */
	fz_try(ctx)
	{
		obj = pdf_dict_gets(dict, "ColorSpace");
		if (obj)
		{
			colorspace = pdf_load_colorspace(xref, obj);
			indexed = !strcmp(colorspace->name, "Indexed");
		}

		img = fz_load_jpx(ctx, buf->data, buf->len, colorspace, indexed);

		if (img && colorspace == NULL)
			colorspace = fz_keep_colorspace(ctx, img->colorspace);

		fz_drop_buffer(ctx, buf);
		buf = NULL;

		obj = pdf_dict_getsa(dict, "SMask", "Mask");
		if (pdf_is_dict(obj))
		{
			if (forcemask)
				fz_warn(ctx, "Ignoring recursive JPX soft mask");
			else
				image->base.mask = (fz_image *)pdf_load_image_imp(xref, NULL, obj, NULL, 1);
		}

		obj = pdf_dict_getsa(dict, "Decode", "D");
		if (obj && !indexed)
		{
			float decode[FZ_MAX_COLORS * 2];
			int i;

			for (i = 0; i < img->n * 2; i++)
				decode[i] = pdf_to_real(pdf_array_get(obj, i));

			fz_decode_tile(img, decode);
		}
	}
	fz_catch(ctx)
	{
		if (colorspace)
			fz_drop_colorspace(ctx, colorspace);
		fz_drop_buffer(ctx, buf);
		fz_drop_pixmap(ctx, img);
		fz_rethrow(ctx);
	}
	FZ_INIT_STORABLE(&image->base, 1, pdf_free_image);
	image->base.get_pixmap = pdf_image_get_pixmap;
	image->base.w = img->w;
	image->base.h = img->h;
	image->base.bpc = 8;
	image->base.colorspace = colorspace;
	image->buffer = NULL;
	image->tile = img;
	image->n = img->n;
	image->interpolate = 0;
	image->imagemask = 0;
	image->usecolorkey = 0;
}
Beispiel #28
0
static fz_image *
pdf_load_jpx(fz_context *ctx, pdf_document *doc, pdf_obj *dict, int forcemask)
{
	fz_buffer *buf = NULL;
	fz_colorspace *colorspace = NULL;
	fz_pixmap *pix = NULL;
	pdf_obj *obj;
	fz_image *mask = NULL;
	fz_image *img = NULL;

	fz_var(pix);
	fz_var(buf);
	fz_var(colorspace);
	fz_var(mask);

	buf = pdf_load_stream(ctx, dict);

	/* FIXME: We can't handle decode arrays for indexed images currently */
	fz_try(ctx)
	{
		unsigned char *data;
		size_t len;

		obj = pdf_dict_get(ctx, dict, PDF_NAME(ColorSpace));
		if (obj)
			colorspace = pdf_load_colorspace(ctx, obj);

		len = fz_buffer_storage(ctx, buf, &data);
		pix = fz_load_jpx(ctx, data, len, colorspace);

		obj = pdf_dict_geta(ctx, dict, PDF_NAME(SMask), PDF_NAME(Mask));
		if (pdf_is_dict(ctx, obj))
		{
			if (forcemask)
				fz_warn(ctx, "Ignoring recursive JPX soft mask");
			else
				mask = pdf_load_image_imp(ctx, doc, NULL, obj, NULL, 1);
		}

		obj = pdf_dict_geta(ctx, dict, PDF_NAME(Decode), PDF_NAME(D));
		if (obj && !fz_colorspace_is_indexed(ctx, colorspace))
		{
			float decode[FZ_MAX_COLORS * 2];
			int i;

			for (i = 0; i < pix->n * 2; i++)
				decode[i] = pdf_array_get_real(ctx, obj, i);

			fz_decode_tile(ctx, pix, decode);
		}

		img = fz_new_image_from_pixmap(ctx, pix, mask);
	}
	fz_always(ctx)
	{
		fz_drop_image(ctx, mask);
		fz_drop_pixmap(ctx, pix);
		fz_drop_colorspace(ctx, colorspace);
		fz_drop_buffer(ctx, buf);
	}
	fz_catch(ctx)
	{
		fz_rethrow(ctx);
	}

	return img;
}