Exemple #1
0
/*
 * Open a stream for reading the raw (compressed but decrypted) data. 
 * Using xref->file while this is open is a bad idea.
 */
fz_error *
pdf_openrawstream(fz_stream **stmp, pdf_xref *xref, int oid, int gen)
{
	pdf_xrefentry *x;
	fz_error *error;
	fz_filter *filter;

	if (oid < 0 || oid >= xref->len)
		return fz_throw("object id out of range (%d)", oid);

	x = xref->table + oid;

	error = pdf_cacheobject(xref, oid, gen);
	if (error)
		return fz_rethrow(error, "cannot load stream object (%d)", oid);

	if (x->stmbuf)
	{
		error = fz_openrbuffer(stmp, x->stmbuf);
		if (error)
			return fz_rethrow(error, "cannot open stream from buffer");
		return fz_okay;
	}

	if (x->stmofs)
	{
		error = buildrawfilter(&filter, xref, x->obj, oid, gen);
		if (error)
			return fz_rethrow(error, "cannot create raw filter");

		error = fz_seek(xref->file, x->stmofs, 0);
		if (error)
		{
			fz_dropfilter(filter);
			return fz_rethrow(error, "cannot seek to stream");
		}

		error = fz_openrfilter(stmp, filter, xref->file);

		fz_dropfilter(filter);

		if (error)
			return fz_rethrow(error, "cannot open filter stream");

		return fz_okay;
	}

	return fz_throw("object is not a stream");
}
static fz_error *
writestream(fz_stream *out, pdf_xref *xref, pdf_crypt *encrypt, int oid, int gen)
{
	fz_error *error;
	fz_stream *dststm;
	fz_stream *srcstm;
	unsigned char buf[4096];
	fz_filter *ef;
	int n;

	fz_print(out, "stream\n");

	if (encrypt)
	{
		error = pdf_cryptstream(&ef, encrypt, oid, gen);
		if (error)
			return error;

		error = fz_openrfilter(&dststm, ef, out);
		fz_dropfilter(ef);
		if (error)
			return error;
	}
	else
	{
		dststm = fz_keepstream(out);
	}

	error = pdf_openrawstream(&srcstm, xref, oid, gen);
	if (error)
		goto cleanupdst;

	while (1)
	{
		n = fz_read(srcstm, buf, sizeof buf);
		if (n == 0)
			break;
		if (n < 0)
		{
			error = fz_ioerror(srcstm);
			goto cleanupsrc;
		}

		n = fz_write(dststm, buf, n);
		if (n < 0)
		{
			error = fz_ioerror(dststm);
			goto cleanupsrc;
		}
	}

	fz_dropstream(srcstm);
	fz_dropstream(dststm);

	fz_print(out, "endstream\n");

	return nil;

cleanupsrc:
	fz_dropstream(srcstm);
cleanupdst:
	fz_dropstream(dststm);
	return error;
}
fz_error *
pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref,
		fz_obj *rdb, fz_obj *dict, fz_stream *file)
{
	fz_error *error;
	pdf_image *img;
	fz_filter *filter;
	fz_obj *f;
	fz_obj *cs;
	fz_obj *d;
	int ismask;
	int i;

	img = fz_malloc(sizeof(pdf_image));
	if (!img)
		return fz_outofmem;

	pdf_logimage("load inline image %p {\n", img);

	img->super.loadtile = pdf_loadtile;
	img->super.drop = pdf_dropimage;
	img->super.n = 0;
	img->super.a = 0;
	img->super.refs = 0;
	img->indexed = nil;
	img->usecolorkey = 0;
	img->mask = nil;

	img->super.w = fz_toint(fz_dictgetsa(dict, "Width", "W"));
	img->super.h = fz_toint(fz_dictgetsa(dict, "Height", "H"));
	img->bpc = fz_toint(fz_dictgetsa(dict, "BitsPerComponent", "BPC"));
	ismask = fz_tobool(fz_dictgetsa(dict, "ImageMask", "IM"));
	d = fz_dictgetsa(dict, "Decode", "D");
	cs = fz_dictgetsa(dict, "ColorSpace", "CS");

	pdf_logimage("size %dx%d %d\n", img->super.w, img->super.h, img->bpc);

	if (ismask)
	{
		pdf_logimage("is mask\n");
		img->super.cs = nil;
		img->super.n = 0;
		img->super.a = 1;
		img->bpc = 1;
	}

	if (cs)
	{
		img->super.cs = nil;

		if (fz_isname(cs))
		{
			fz_obj *csd = fz_dictgets(rdb, "ColorSpace");
			if (csd)
			{
				fz_obj *cso = fz_dictget(csd, cs);
				img->super.cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, cso);
				if (img->super.cs)
					fz_keepcolorspace(img->super.cs);
			}
		}

		if (!img->super.cs)
		{
			/* XXX danger! danger! does this resolve? */
			error = pdf_loadcolorspace(&img->super.cs, xref, cs);
			if (error)
				return error;
		}

		if (!strcmp(img->super.cs->name, "Indexed"))
		{
			pdf_logimage("indexed\n");
			img->indexed = (pdf_indexed*)img->super.cs;
			img->super.cs = img->indexed->base;
		}

		pdf_logimage("colorspace %s\n", img->super.cs->name);

		img->super.n = img->super.cs->n;
		img->super.a = 0;
	}

	if (fz_isarray(d))
	{
		pdf_logimage("decode array\n");
		if (img->indexed)
			for (i = 0; i < 2; i++)
				img->decode[i] = fz_toreal(fz_arrayget(d, i));
		else
			for (i = 0; i < (img->super.n + img->super.a) * 2; i++)
				img->decode[i] = fz_toreal(fz_arrayget(d, i));
	}
	else
	{
		if (img->indexed)
			for (i = 0; i < 2; i++)
				img->decode[i] = i & 1 ? (1 << img->bpc) - 1 : 0;
		else
			for (i = 0; i < (img->super.n + img->super.a) * 2; i++)
				img->decode[i] = i & 1;
	}

	if (img->indexed)
		img->stride = (img->super.w * img->bpc + 7) / 8;
	else
		img->stride = (img->super.w * (img->super.n + img->super.a) * img->bpc + 7) / 8;

	/* load image data */

	f = fz_dictgetsa(dict, "Filter", "F");
	if (f)
	{
		fz_stream *tempfile;

		error = pdf_buildinlinefilter(&filter, dict);
		if (error)
			return error;

		error = fz_openrfilter(&tempfile, filter, file);
		if (error)
			return error;

		i = fz_readall(&img->samples, tempfile);
		if (i < 0)
			return fz_ioerror(tempfile);

		fz_dropfilter(filter);
		fz_dropstream(tempfile);
	}
	else
	{
		error = fz_newbuffer(&img->samples, img->super.h * img->stride);
		if (error)
			return error;

		i = fz_read(file, img->samples->bp, img->super.h * img->stride);
		if (i < 0)
			return fz_ioerror(file);

		img->samples->wp += img->super.h * img->stride;
	}

	/* 0 means opaque and 1 means transparent, so we invert to get alpha */
	if (ismask)
	{
		unsigned char *p;
		for (p = img->samples->bp; p < img->samples->ep; p++)
			*p = ~*p;
	}

	pdf_logimage("}\n");

	*imgp = img;
	return nil;
}