Example #1
0
fz_error *
pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *cs)
{
	pdf_gstate *gs = csi->gstate + csi->gtop;
	fz_error *error;
	pdf_material *mat;

	error = pdf_flushtext(csi);
	if (error)
		return fz_rethrow(error, "cannot finish text node (state change)");

	mat = what == PDF_MFILL ? &gs->fill : &gs->stroke;

	fz_dropcolorspace(mat->cs);

	mat->kind = PDF_MCOLOR;
	mat->cs = fz_keepcolorspace(cs);

	mat->v[0] = 0;	/* FIXME: default color */
	mat->v[1] = 0;	/* FIXME: default color */
	mat->v[2] = 0;	/* FIXME: default color */
	mat->v[3] = 1;	/* FIXME: default color */

	if (!strcmp(cs->name, "Indexed"))
	{
		mat->kind = PDF_MINDEXED;
		mat->indexed = (pdf_indexed*)cs;
		mat->cs = mat->indexed->base;
	}

	if (!strcmp(cs->name, "Lab"))
		mat->kind = PDF_MLAB;

	return fz_okay;
}
Example #2
0
void
pdf_initgstate(pdf_gstate *gs, fz_matrix ctm)
{
	gs->ctm = ctm;
	gs->clipdepth = 0;

	gs->strokestate.linewidth = 1;
	gs->strokestate.linecap = 0;
	gs->strokestate.linejoin = 0;
	gs->strokestate.miterlimit = 10;
	gs->strokestate.dashphase = 0;
	gs->strokestate.dashlen = 0;
	memset(gs->strokestate.dashlist, 0, sizeof(gs->strokestate.dashlist));

	gs->stroke.kind = PDF_MCOLOR;
	gs->stroke.colorspace = fz_keepcolorspace(fz_devicegray);
	gs->stroke.v[0] = 0;
	gs->stroke.pattern = nil;
	gs->stroke.shade = nil;
	gs->stroke.alpha = 1;

	gs->fill.kind = PDF_MCOLOR;
	gs->fill.colorspace = fz_keepcolorspace(fz_devicegray);
	gs->fill.v[0] = 0;
	gs->fill.pattern = nil;
	gs->fill.shade = nil;
	gs->fill.alpha = 1;

	gs->charspace = 0;
	gs->wordspace = 0;
	gs->scale = 1;
	gs->leading = 0;
	gs->font = nil;
	gs->size = -1;
	gs->render = 0;
	gs->rise = 0;

	gs->blendmode = FZ_BNORMAL;
	gs->softmask = nil;
	gs->softmaskctm = fz_identity;
	gs->luminosity = 0;
}
Example #3
0
void
pdf_initgstate(pdf_gstate *gs)
{
	gs->linewidth = 1.0;
	gs->linecap = 0;
	gs->linejoin = 0;
	gs->miterlimit = 10;
	gs->dashphase = 0;
	gs->dashlen = 0;
	memset(gs->dashlist, 0, sizeof(gs->dashlist));

	gs->stroke.kind = PDF_MCOLOR;
	gs->stroke.cs = fz_keepcolorspace(pdf_devicegray);
	gs->stroke.v[0] = 0;
	gs->stroke.indexed = nil;
	gs->stroke.pattern = nil;
	gs->stroke.shade = nil;
	gs->stroke.alpha = 1.0;

	gs->fill.kind = PDF_MCOLOR;
	gs->fill.cs = fz_keepcolorspace(pdf_devicegray);
	gs->fill.v[0] = 0;
	gs->fill.indexed = nil;
	gs->fill.pattern = nil;
	gs->fill.shade = nil;
	gs->fill.alpha = 1.0;

	gs->blendmode = FZ_BNORMAL;

	gs->charspace = 0;
	gs->wordspace = 0;
	gs->scale = 1;
	gs->leading = 0;
	gs->font = nil;
	gs->size = -1;
	gs->render = 0;
	gs->rise = 0;

	gs->head = nil;
}
Example #4
0
static fz_error
loadseparation(fz_colorspace **csp, pdf_xref *xref, fz_obj *array)
{
	fz_error error;
	struct separation *cs;
	fz_obj *nameobj = fz_arrayget(array, 1);
	fz_obj *baseobj = fz_arrayget(array, 2);
	fz_obj *tintobj = fz_arrayget(array, 3);
	fz_colorspace *base;
	pdf_function *tint;
	int n;

	pdf_logrsrc("load Separation {\n");

	if (fz_isarray(nameobj))
		n = fz_arraylen(nameobj);
	else
		n = 1;

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

	pdf_logrsrc("n = %d\n", n);

	error = pdf_loadcolorspace(&base, xref, baseobj);
	if (error)
		return fz_rethrow(error, "cannot load base colorspace");

	error = pdf_loadfunction(&tint, xref, tintobj);
	if (error)
	{
		fz_dropcolorspace(base);
		return fz_rethrow(error, "cannot load tint function");
	}

	cs = fz_malloc(sizeof(struct separation));

	initcs((fz_colorspace*)cs,
		n == 1 ? "Separation" : "DeviceN", n,
		separationtoxyz, nil, freeseparation);

	cs->base = fz_keepcolorspace(base);
	cs->tint = pdf_keepfunction(tint);

	fz_dropcolorspace(base);
	pdf_dropfunction(tint);

	pdf_logrsrc("}\n");

	*csp = (fz_colorspace*)cs;
	return fz_okay;
}
Example #5
0
fz_error *
pdf_storeitem(pdf_store *store, pdf_itemkind kind, fz_obj *key, void *val)
{
	fz_error *error;

	switch (kind)
	{
	case PDF_KCOLORSPACE: fz_keepcolorspace(val); break;
	case PDF_KFUNCTION: pdf_keepfunction(val); break;
	case PDF_KXOBJECT: pdf_keepxobject(val); break;
	case PDF_KIMAGE: fz_keepimage(val); break;
	case PDF_KPATTERN: pdf_keeppattern(val); break;
	case PDF_KSHADE: fz_keepshade(val); break;
	case PDF_KCMAP: pdf_keepcmap(val); break;
	case PDF_KFONT: fz_keepfont(val); break;
	}

	if (fz_isindirect(key))
	{
		struct refkey item;

		pdf_logrsrc("store item %d: %d %d R = %p\n", kind, fz_tonum(key), fz_togen(key), val);

		item.kind = kind;
		item.oid = fz_tonum(key);
		item.gen = fz_togen(key);

		error = fz_hashinsert(store->hash, &item, val);
		if (error)
			return error;
	}

	else
	{
		pdf_item *item;

		item = fz_malloc(sizeof(pdf_item));
		if (!item)
			return fz_outofmem;

		pdf_logrsrc("store item %d: ... = %p\n", kind, val);

		item->kind = kind;
		item->key = fz_keepobj(key);
		item->val = val;

		item->next = store->root;
		store->root = item;
	}

	return nil;
}
Example #6
0
static void keepitem(pdf_itemkind kind, void *val)
{
	switch (kind)
	{
	case PDF_KCOLORSPACE: fz_keepcolorspace(val); break;
	case PDF_KFUNCTION: pdf_keepfunction(val); break;
	case PDF_KXOBJECT: pdf_keepxobject(val); break;
	case PDF_KIMAGE: fz_keepimage(val); break;
	case PDF_KPATTERN: pdf_keeppattern(val); break;
	case PDF_KSHADE: fz_keepshade(val); break;
	case PDF_KCMAP: pdf_keepcmap(val); break;
	case PDF_KFONT: pdf_keepfont(val); break;
	}
}
Example #7
0
fz_error
pdf_loadcolorspace(fz_colorspace **csp, pdf_xref *xref, fz_obj *obj)
{
	fz_error error;

	if ((*csp = pdf_finditem(xref->store, PDF_KCOLORSPACE, obj)))
	{
		fz_keepcolorspace(*csp);
		return fz_okay;
	}

	error = pdf_loadcolorspaceimp(csp, xref, obj);
	if (error)
		return fz_rethrow(error, "cannot load colorspace");

	pdf_storeitem(xref->store, PDF_KCOLORSPACE, obj, *csp);

	return fz_okay;
}
Example #8
0
fz_error
fz_newsolidnode(fz_node **nodep, float a, fz_colorspace *cs, int n, float *v)
{
	fz_solidnode *node;
	int i;

	node = fz_malloc(sizeof(fz_solidnode) + sizeof(float) * n);
	if (!node)
		return fz_rethrow(-1, "out of memory");
	*nodep = (fz_node*)node;

	fz_initnode((fz_node*)node, FZ_NCOLOR);
	node->a = a;
	node->cs = fz_keepcolorspace(cs);
	node->n = n;
	for (i = 0; i < n; i++)
		node->samples[i] = v[i];

	return fz_okay;
}
Example #9
0
void
pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *colorspace)
{
	pdf_gstate *gs = csi->gstate + csi->gtop;
	pdf_material *mat;

	pdf_flushtext(csi);

	mat = what == PDF_MFILL ? &gs->fill : &gs->stroke;

	fz_dropcolorspace(mat->colorspace);

	mat->kind = PDF_MCOLOR;
	mat->colorspace = fz_keepcolorspace(colorspace);

	mat->v[0] = 0;
	mat->v[1] = 0;
	mat->v[2] = 0;
	mat->v[3] = 1;
}
Example #10
0
static fz_error *
loadshadedict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_matrix matrix)
{
	fz_error *error;
	fz_shade *shade;
	fz_obj *obj;
	int type;
	int i;

	pdf_logshade("load shade dict %d %d {\n", fz_tonum(ref), fz_togen(ref));

	shade = fz_malloc(sizeof(fz_shade));
	if (!shade)
		return fz_outofmem;

	shade->refs = 1;
	shade->usebackground = 0;
	shade->usefunction = 0;
	shade->matrix = matrix;
	shade->bbox = fz_infiniterect;

	shade->meshlen = 0;
	shade->meshcap = 0;
	shade->mesh = nil;

	obj = fz_dictgets(dict, "ShadingType");
	type = fz_toint(obj);
	pdf_logshade("type %d\n", type);

	/* TODO: flatten indexed... */
	obj = fz_dictgets(dict, "ColorSpace");
	if (obj)
	{
		shade->cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, obj);
		if (shade->cs)
			fz_keepcolorspace(shade->cs);
		else
		{
			error = pdf_resolve(&obj, xref);
			if (error)
				return error;
			error = pdf_loadcolorspace(&shade->cs, xref, obj);
			if (error)
				return error;
			fz_dropobj(obj);
		}
	}
	pdf_logshade("colorspace %s\n", shade->cs->name);

	obj = fz_dictgets(dict, "Background");
	if (obj)
	{
		pdf_logshade("background\n");
		shade->usebackground = 1;
		for (i = 0; i < shade->cs->n; i++)
			shade->background[i] = fz_toreal(fz_arrayget(obj, i));
	}

	obj = fz_dictgets(dict, "BBox");
	if (fz_isarray(obj))
	{
		shade->bbox = pdf_torect(obj);
		pdf_logshade("bbox [%g %g %g %g]\n",
			shade->bbox.x0, shade->bbox.y0,
			shade->bbox.x1, shade->bbox.y1);
	}

	switch(type)
	{
	case 1:
		error = pdf_loadtype1shade(shade, xref, dict, ref);
		if (error) goto cleanup;
		break;
	case 2:
		error = pdf_loadtype2shade(shade, xref, dict, ref);
		if (error) goto cleanup;
		break;
	case 3:
		error = pdf_loadtype3shade(shade, xref, dict, ref);
		if (error) goto cleanup;
		break;
	case 4:
		error = pdf_loadtype4shade(shade, xref, dict, ref);
		if (error) goto cleanup;
		break;
	case 5:
		error = pdf_loadtype5shade(shade, xref, dict, ref);
		if (error) goto cleanup;
		break;
	case 6:
		error = pdf_loadtype6shade(shade, xref, dict, ref);
		if (error) goto cleanup;
		break;
	case 7:
		error = pdf_loadtype7shade(shade, xref, dict, ref);
		if (error) goto cleanup;
		break;
	default:
		fz_warn("syntaxerror: unknown shading type: %d", type);
		break;
	};

	pdf_logshade("}\n");

	*shadep = shade;
	return nil;

cleanup:
	fz_dropshade(shade);
	return error;
}
Example #11
0
static fz_error
loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array)
{
	fz_error error;
	pdf_indexed *cs;
	fz_obj *baseobj = fz_arrayget(array, 1);
	fz_obj *highobj = fz_arrayget(array, 2);
	fz_obj *lookup = fz_arrayget(array, 3);
	fz_colorspace *base;
	int n;

	pdf_logrsrc("load Indexed {\n");

	error = pdf_loadcolorspace(&base, xref, baseobj);
	if (error)
		return fz_rethrow(error, "cannot load base colorspace");

	pdf_logrsrc("base %s\n", base->name);

	cs = fz_malloc(sizeof(pdf_indexed));

	initcs((fz_colorspace*)cs, "Indexed", 1, nil, nil, freeindexed);

	cs->base = fz_keepcolorspace(base);
	cs->high = fz_toint(highobj);

	fz_dropcolorspace(base);

	n = base->n * (cs->high + 1);
	cs->lookup = fz_malloc(n);

	if (fz_isstring(lookup) && fz_tostrlen(lookup) == n)
	{
		unsigned char *buf;
		int i;

		pdf_logrsrc("string lookup\n");

		buf = (unsigned char *) fz_tostrbuf(lookup);
		for (i = 0; i < n; i++)
			cs->lookup[i] = buf[i];
	}
	else if (fz_isindirect(lookup))
	{
		fz_buffer *buf;
		int i;

		pdf_logrsrc("stream lookup\n");

		error = pdf_loadstream(&buf, xref, fz_tonum(lookup), fz_togen(lookup));
		if (error)
		{
			fz_dropcolorspace((fz_colorspace*)cs);
			return fz_rethrow(error, "cannot load colorpsace lookup table");
		}

		for (i = 0; i < n && i < (buf->wp - buf->rp); i++)
			cs->lookup[i] = buf->rp[i];

		fz_dropbuffer(buf);
	}
	else
		return fz_throw("cannot parse colorspace lookup table");

	pdf_logrsrc("}\n");

	*csp = (fz_colorspace*)cs;
	return fz_okay;
}
Example #12
0
/* TODO error cleanup */
fz_error *
pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_obj *ref)
{
	fz_error *error;
	pdf_image *img;
	pdf_image *mask;
	int ismask;
	fz_obj *obj;
	fz_obj *sub;
	int i;

	int w, h, bpc;
	int n = 0;
	int a = 0;
	int usecolorkey = 0;
	fz_colorspace *cs = nil;
	pdf_indexed *indexed = nil;
	int stride;
#ifndef PSP
	printf("LI\n");
#endif
	if ((*imgp = pdf_finditem(xref->store, PDF_KIMAGE, ref)))
	{
		fz_keepimage((fz_image*)*imgp);
		return nil;
	}

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

	img->super.refs = 0;

	pdf_logimage("load image %d %d (%p) {\n", fz_tonum(ref), fz_togen(ref), img);

	/*
	 * Dimensions, BPC and ColorSpace
	 */

	w = fz_toint(fz_dictgets(dict, "Width"));
	h = fz_toint(fz_dictgets(dict, "Height"));
	bpc = fz_toint(fz_dictgets(dict, "BitsPerComponent"));

	pdf_logimage("size %dx%d %d\n", w, h, bpc);

	cs = nil;
	obj = fz_dictgets(dict, "ColorSpace");
	if (obj)
	{
		cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, obj);
		if (cs)
			fz_keepcolorspace(cs);
		else
		{
			error = pdf_resolve(&obj, xref);
			if (error)
				return error;

			error = pdf_loadcolorspace(&cs, xref, obj);
			if (error)
				return error;

			fz_dropobj(obj);
		}

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

		pdf_logimage("colorspace %s\n", cs->name);
	}

	/*
	 * ImageMask, Mask and SoftMask
	 */

	mask = nil;

	ismask = fz_tobool(fz_dictgets(dict, "ImageMask"));
	if (ismask)
	{
		pdf_logimage("is mask\n");
		bpc = 1;
		n = 0;
		a = 1;
	}

	obj = fz_dictgets(dict, "SMask");
	if (fz_isindirect(obj))
	{
		pdf_logimage("has soft mask\n");

		error = pdf_loadindirect(&sub, xref, obj);
		if (error)
			return error;

		error = pdf_loadimage(&mask, xref, sub, obj);
		if (error)
			return error;

		if (mask->super.cs != pdf_devicegray)
			return fz_throw("syntaxerror: SMask must be DeviceGray");

		mask->super.cs = 0;
		mask->super.n = 0;
		mask->super.a = 1;

		fz_dropobj(sub);
	}

	obj = fz_dictgets(dict, "Mask");
	if (fz_isindirect(obj))
	{
		error = pdf_loadindirect(&sub, xref, obj);
		if (error)
			return error;
		if (fz_isarray(sub))
		{
			usecolorkey = 1;
			loadcolorkey(img->colorkey, bpc, indexed != nil, sub);
		}
		else
		{
			pdf_logimage("has mask\n");
			error = pdf_loadimage(&mask, xref, sub, obj);
			if (error)
				return error;
		}
		fz_dropobj(sub);
	}
	else if (fz_isarray(obj))
	{
		usecolorkey = 1;
		loadcolorkey(img->colorkey, bpc, indexed != nil, obj);
	}

	/*
	 * Decode
	 */

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

	/*
	 * Load samples
	 */

	if (indexed)
		stride = (w * bpc + 7) / 8;
	else
		stride = (w * (n + a) * bpc + 7) / 8;

	// ccm
	// do not load images larger than 2MB uncompressed
	int early_reject = 0;
	if (h * stride <= 2*1024*1024) {
		error = pdf_loadstream(&img->samples, xref, fz_tonum(ref), fz_togen(ref));
		if (error)
		{
			/* TODO: colorspace? */
			fz_free(img);
			return error;
		}
	
		if (img->samples->wp - img->samples->bp < stride * h)
		{
			/* TODO: colorspace? */
			fz_dropbuffer(img->samples);
			fz_free(img);
			return fz_throw("syntaxerror: truncated image data");
		}
	
		/* 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;
		}
	} else {
#ifndef PSP
		printf("LI - %p - early reject\n", img);
#endif
		img->samples = nil;
		early_reject = 1;
	}

	/*
	 * Create image object
	 */

	img->super.loadtile = pdf_loadtile;
	img->super.drop = pdf_dropimage;
	img->super.cs = cs;
	img->super.w = w;
	img->super.h = h;
	img->super.n = n;
	img->super.a = a;
	img->indexed = indexed;
	img->stride = stride;
	img->bpc = bpc;
	img->mask = (fz_image*)mask;
	img->usecolorkey = usecolorkey;
	if (img->mask)
		fz_keepimage(img->mask);

	// ccm
	#if 1
	int bs = 0;
	if (img->samples)
		bs = (int)(img->samples->wp) - (int)(img->samples->rp);
	if (early_reject || (image_buffers_size + bs >= image_buffers_size_max)) {
#ifndef PSP
		printf("LI - %p - optimized out\n", img);
#endif
		if (img->samples)
			fz_dropbuffer(img->samples);
		if (img->mask)
			fz_dropimage(img->mask);
		fz_newbuffer(&img->samples, 8);
		img->super.w = 1;
		img->super.h = 1;
		img->super.n = 3;
		img->super.a = 0;
		img->super.refs = 0;
		unsigned char *p;
		for (p = img->samples->bp; p < img->samples->ep; p++)
			*p = 0x7f;
		img->indexed = 0;
		img->stride = (1 * (3 + 0) * 8 + 7) / 8; //(w * (n + a) * bpc + 7) / 8;
		img->super.cs = cs;
		img->super.loadtile = fakeImageTile;
		img->bpc = 8;
		img->mask = NULL;
		img->usecolorkey = 0;
	} else {
		image_buffers_size += bs;
	}
	#endif

	pdf_logimage("}\n");

	error = pdf_storeitem(xref->store, PDF_KIMAGE, ref, img);
	if (error)
	{
		fz_dropimage((fz_image*)img);
		return error;
	}

	*imgp = img;
	return nil;
}
Example #13
0
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;
}