Beispiel #1
0
static fz_pixmap *
pdf_image_get_pixmap(fz_context *ctx, fz_image *image_, int w, int h)
{
	pdf_image *image = (pdf_image *)image_;
	fz_pixmap *tile;
	fz_stream *stm;
	int l2factor;
	pdf_image_key key;
	int native_l2factor;
	int indexed;

	/* Check for 'simple' images which are just pixmaps */
	if (image->buffer == NULL)
	{
		tile = image->tile;
		if (!tile)
			return NULL;
		return fz_keep_pixmap(ctx, tile); /* That's all we can give you! */
	}

	/* Ensure our expectations for tile size are reasonable */
	if (w > image->base.w)
		w = image->base.w;
	if (h > image->base.h)
		h = image->base.h;

	/* What is our ideal factor? */
	if (w == 0 || h == 0)
		l2factor = 0;
	else
		for (l2factor=0; image->base.w>>(l2factor+1) >= w && image->base.h>>(l2factor+1) >= h && l2factor < 8; l2factor++);

	/* Can we find any suitable tiles in the cache? */
	key.refs = 1;
	key.image = &image->base;
	key.l2factor = l2factor;
	do
	{
		tile = fz_find_item(ctx, fz_free_pixmap_imp, &key, &pdf_image_store_type);
		if (tile)
			return tile;
		key.l2factor--;
	}
	while (key.l2factor >= 0);

	/* We need to make a new one. */
	native_l2factor = l2factor;
	stm = fz_open_image_decomp_stream(ctx, image->buffer, &native_l2factor);

	indexed = fz_colorspace_is_indexed(image->base.colorspace);
	return decomp_image_from_stream(ctx, stm, image, 0, indexed, l2factor, native_l2factor, 1);
}
Beispiel #2
0
fz_image *
fz_new_image(fz_context *ctx, int w, int h, int bpc, fz_colorspace *colorspace,
	int xres, int yres, int interpolate, int imagemask, float *decode,
	int *colorkey, fz_compressed_buffer *buffer, fz_image *mask)
{
	fz_image *image;

	assert(mask == NULL || mask->mask == NULL);

	fz_try(ctx)
	{
		image = fz_malloc_struct(ctx, fz_image);
		FZ_INIT_STORABLE(image, 1, fz_free_image);
		image->get_pixmap = fz_image_get_pixmap;
		image->w = w;
		image->h = h;
		image->xres = xres;
		image->yres = yres;
		image->bpc = bpc;
		image->n = (colorspace ? colorspace->n : 1);
		image->colorspace = colorspace;
		image->interpolate = interpolate;
		image->imagemask = imagemask;
		image->usecolorkey = (colorkey != NULL);
		if (colorkey)
			memcpy(image->colorkey, colorkey, sizeof(int)*image->n*2);
		if (decode)
			memcpy(image->decode, decode, sizeof(float)*image->n*2);
		else
		{
			float maxval = fz_colorspace_is_indexed(colorspace) ? (1 << bpc) - 1 : 1;
			int i;
			for (i = 0; i < image->n; i++)
			{
				image->decode[2*i] = 0;
				image->decode[2*i+1] = maxval;
			}
		}
		image->mask = mask;
		image->buffer = buffer;
	}
	fz_catch(ctx)
	{
		fz_free_compressed_buffer(ctx, buffer);
		fz_rethrow(ctx);
	}

	return image;
}
Beispiel #3
0
static fz_pixmap *
standard_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h, int *l2factor)
{
    int native_l2factor;
    fz_stream *stm;
    int indexed;
    fz_pixmap *tile;

    /* We need to make a new one. */
    /* First check for ones that we can't decode using streams */
    switch (image->buffer->params.type)
    {
    case FZ_IMAGE_PNG:
        tile = fz_load_png(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
        break;
    case FZ_IMAGE_GIF:
        tile = fz_load_gif(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
        break;
    case FZ_IMAGE_TIFF:
        tile = fz_load_tiff(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
        break;
    case FZ_IMAGE_JXR:
        tile = fz_load_jxr(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
        break;
    case FZ_IMAGE_JPEG:
        /* Scan JPEG stream and patch missing height values in header */
    {
        unsigned char *s = image->buffer->buffer->data;
        unsigned char *e = s + image->buffer->buffer->len;
        unsigned char *d;
        for (d = s + 2; s < d && d < e - 9 && d[0] == 0xFF; d += (d[2] << 8 | d[3]) + 2)
        {
            if (d[1] < 0xC0 || (0xC3 < d[1] && d[1] < 0xC9) || 0xCB < d[1])
                continue;
            if ((d[5] == 0 && d[6] == 0) || ((d[5] << 8) | d[6]) > image->h)
            {
                d[5] = (image->h >> 8) & 0xFF;
                d[6] = image->h & 0xFF;
            }
        }
    }
    /* fall through */

    default:
        native_l2factor = l2factor ? *l2factor : 0;
        stm = fz_open_image_decomp_stream_from_buffer(ctx, image->buffer, l2factor);
        if (l2factor)
            native_l2factor -= *l2factor;

        indexed = fz_colorspace_is_indexed(ctx, image->colorspace);
        tile = fz_decomp_image_from_stream(ctx, stm, image, indexed, native_l2factor);

        /* CMYK JPEGs in XPS documents have to be inverted */
        if (image->invert_cmyk_jpeg &&
                image->buffer->params.type == FZ_IMAGE_JPEG &&
                image->colorspace == fz_device_cmyk(ctx) &&
                image->buffer->params.u.jpeg.color_transform)
        {
            fz_invert_pixmap(ctx, tile);
        }

        break;
    }
Beispiel #4
0
fz_pixmap *
fz_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h)
{
	fz_pixmap *tile;
	fz_stream *stm;
	int l2factor;
	fz_image_key key;
	int native_l2factor;
	int indexed;
	fz_image_key *keyp;

	/* Check for 'simple' images which are just pixmaps */
	if (image->buffer == NULL)
	{
		tile = image->tile;
		if (!tile)
			return NULL;
		return fz_keep_pixmap(ctx, tile); /* That's all we can give you! */
	}

	/* Ensure our expectations for tile size are reasonable */
	if (w > image->w)
		w = image->w;
	if (h > image->h)
		h = image->h;

	/* What is our ideal factor? */
	if (w == 0 || h == 0)
		l2factor = 0;
	else
		for (l2factor=0; image->w>>(l2factor+1) >= w && image->h>>(l2factor+1) >= h && l2factor < 8; l2factor++);

	/* Can we find any suitable tiles in the cache? */
	key.refs = 1;
	key.image = image;
	key.l2factor = l2factor;
	do
	{
		tile = fz_find_item(ctx, fz_free_pixmap_imp, &key, &fz_image_store_type);
		if (tile)
			return tile;
		key.l2factor--;
	}
	while (key.l2factor >= 0);

	/* We need to make a new one. */
	/* First check for ones that we can't decode using streams */
	switch (image->buffer->params.type)
	{
	case FZ_IMAGE_PNG:
		tile = fz_load_png(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
		break;
	case FZ_IMAGE_TIFF:
		tile = fz_load_tiff(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
		break;
	default:
		native_l2factor = l2factor;
		stm = fz_open_image_decomp_stream(ctx, image->buffer, &native_l2factor);

		indexed = fz_colorspace_is_indexed(image->colorspace);
		tile = fz_decomp_image_from_stream(ctx, stm, image, 0, indexed, l2factor, native_l2factor);
		break;
	}

	/* Now we try to cache the pixmap. Any failure here will just result
	 * in us not caching. */
	fz_var(keyp);
	fz_try(ctx)
	{
		fz_pixmap *existing_tile;

		keyp = fz_malloc_struct(ctx, fz_image_key);
		keyp->refs = 1;
		keyp->image = fz_keep_image(ctx, image);
		keyp->l2factor = l2factor;
		existing_tile = fz_store_item(ctx, keyp, tile, fz_pixmap_size(ctx, tile), &fz_image_store_type);
		if (existing_tile)
		{
			/* We already have a tile. This must have been produced by a
			 * racing thread. We'll throw away ours and use that one. */
			fz_drop_pixmap(ctx, tile);
			tile = existing_tile;
		}
	}
	fz_always(ctx)
	{
		fz_drop_image_key(ctx, keyp);
	}
	fz_catch(ctx)
	{
		/* Do nothing */
	}

	return tile;
}
Beispiel #5
0
static void
pdf_out_BI(fz_context *ctx, pdf_processor *proc, fz_image *img)
{
	fz_output *out = ((pdf_output_processor*)proc)->out;
	int ahx = ((pdf_output_processor*)proc)->ahxencode;
	fz_compressed_buffer *cbuf;
	fz_buffer *buf;
	int i;

	if (img == NULL)
		return;
	cbuf = fz_compressed_image_buffer(ctx, img);
	if (cbuf == NULL)
		return;
	buf = cbuf->buffer;
	if (buf == NULL)
		return;

	fz_printf(ctx, out, "BI\n");
	fz_printf(ctx, out, "/W %d\n", img->w);
	fz_printf(ctx, out, "/H %d\n", img->h);
	fz_printf(ctx, out, "/BPC %d\n", img->bpc);
	if (img->imagemask)
		fz_printf(ctx, out, "/IM true\n");
	else if (img->colorspace == fz_device_gray(ctx))
		fz_printf(ctx, out, "/CS/G\n");
	else if (img->colorspace == fz_device_rgb(ctx))
		fz_printf(ctx, out, "/CS/RGB\n");
	else if (img->colorspace == fz_device_cmyk(ctx))
		fz_printf(ctx, out, "/CS/CMYK\n");
	else if (fz_colorspace_is_indexed(ctx, img->colorspace))
		fz_printf(ctx, out, "/CS/I\n");
	if (img->interpolate)
		fz_printf(ctx, out, "/I true\n");
	fz_printf(ctx, out, "/D[");
	for (i = 0; i < img->n * 2; ++i)
	{
		if (i > 0)
			fz_putc(ctx, out, ' ');
		fz_printf(ctx, out, "%g", img->decode[i]);
	}
	fz_printf(ctx, out, "]\n");

	switch (cbuf->params.type)
	{
	default:
		fz_throw(ctx, FZ_ERROR_GENERIC, "unknown compressed buffer type");
		break;

	case FZ_IMAGE_JPEG:
		fz_printf(ctx, out, ahx ? "/F[/AHx/DCT]\n" : "/F/DCT\n");
		if (cbuf->params.u.jpeg.color_transform != -1)
			fz_printf(ctx, out, "/DP<</ColorTransform %d>>\n",
				cbuf->params.u.jpeg.color_transform);
		break;

	case FZ_IMAGE_FAX:
		fz_printf(ctx, out, ahx ? "/F[/AHx/CCF]\n/DP[null<<\n" : "/F/CCF\n/DP<<\n");
		fz_printf(ctx, out, "/K %d\n", cbuf->params.u.fax.k);
		if (cbuf->params.u.fax.columns != 1728)
			fz_printf(ctx, out, "/Columns %d\n", cbuf->params.u.fax.columns);
		if (cbuf->params.u.fax.rows > 0)
			fz_printf(ctx, out, "/Rows %d\n", cbuf->params.u.fax.rows);
		if (cbuf->params.u.fax.end_of_line)
			fz_printf(ctx, out, "/EndOfLine true\n");
		if (cbuf->params.u.fax.encoded_byte_align)
			fz_printf(ctx, out, "/EncodedByteAlign true\n");
		if (!cbuf->params.u.fax.end_of_block)
			fz_printf(ctx, out, "/EndOfBlock false\n");
		if (cbuf->params.u.fax.black_is_1)
			fz_printf(ctx, out, "/BlackIs1 true\n");
		if (cbuf->params.u.fax.damaged_rows_before_error > 0)
			fz_printf(ctx, out, "/DamagedRowsBeforeError %d\n",
				cbuf->params.u.fax.damaged_rows_before_error);
		fz_printf(ctx, out, ahx ? ">>]\n" : ">>\n");
		break;

	case FZ_IMAGE_RAW:
		if (ahx)
			fz_printf(ctx, out, "/F/AHx\n");
		break;

	case FZ_IMAGE_RLD:
		fz_printf(ctx, out, ahx ? "/F[/AHx/RL]\n" : "/F/RL\n");
		break;

	case FZ_IMAGE_FLATE:
		fz_printf(ctx, out, ahx ? "/F[/AHx/Fl]\n" : "/F/Fl\n");
		if (cbuf->params.u.flate.predictor > 1)
		{
			fz_printf(ctx, out, ahx ? "/DP[null<<\n" : "/DP<<\n");
			fz_printf(ctx, out, "/Predictor %d\n", cbuf->params.u.flate.predictor);
			if (cbuf->params.u.flate.columns != 1)
				fz_printf(ctx, out, "/Columns %d\n", cbuf->params.u.flate.columns);
			if (cbuf->params.u.flate.colors != 1)
				fz_printf(ctx, out, "/Colors %d\n", cbuf->params.u.flate.colors);
			if (cbuf->params.u.flate.bpc != 8)
				fz_printf(ctx, out, "/BitsPerComponent %d\n", cbuf->params.u.flate.bpc);
			fz_printf(ctx, out, ahx ? ">>]\n" : ">>\n");
		}
		break;

	case FZ_IMAGE_LZW:
		fz_printf(ctx, out, ahx ? "/F[/AHx/LZW]\n" : "/F/LZW\n");
		if (cbuf->params.u.lzw.predictor > 1)
		{
			fz_printf(ctx, out, ahx ? "/DP[<<null\n" : "/DP<<\n");
			fz_printf(ctx, out, "/Predictor %d\n", cbuf->params.u.lzw.predictor);
			if (cbuf->params.u.lzw.columns != 1)
				fz_printf(ctx, out, "/Columns %d\n", cbuf->params.u.lzw.columns);
			if (cbuf->params.u.lzw.colors != 1)
				fz_printf(ctx, out, "/Colors %d\n", cbuf->params.u.lzw.colors);
			if (cbuf->params.u.lzw.bpc != 8)
				fz_printf(ctx, out, "/BitsPerComponent %d\n", cbuf->params.u.lzw.bpc);
			if (cbuf->params.u.lzw.early_change != 1)
				fz_printf(ctx, out, "/EarlyChange %d\n", cbuf->params.u.lzw.early_change);
			fz_printf(ctx, out, ahx ? ">>]\n" : ">>\n");
		}
		break;
	}

	fz_printf(ctx, out, "ID\n");
	if (ahx)
	{
		size_t z;
		for (z = 0; z < buf->len; ++z)
		{
			int c = buf->data[z];
			fz_putc(ctx, out, "0123456789abcdef"[(c >> 4) & 0xf]);
			fz_putc(ctx, out, "0123456789abcdef"[c & 0xf]);
			if ((z & 31) == 31)
				fz_putc(ctx, out, '\n');
		}
		fz_putc(ctx, out, '>');
	}
	else
	{
Beispiel #6
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 #7
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 #8
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 #9
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;
}