Beispiel #1
0
static void
pdf_filter_k(fz_context *ctx, pdf_processor *proc, float c, float m, float y, float k)
{
	float color[4] = { c, m, y, k };
	pdf_filter_cs(ctx, proc, "DeviceCMYK", fz_device_cmyk(ctx));
	pdf_filter_sc_color(ctx, proc, 4, color);
}
Beispiel #2
0
fz_document_writer *
fz_new_pixmap_writer(fz_context *ctx, const char *path, const char *options,
	const char *default_path, int n,
	void (*save)(fz_context *ctx, fz_pixmap *pix, const char *filename))
{
	fz_pixmap_writer *wri = fz_new_derived_document_writer(ctx, fz_pixmap_writer, pixmap_begin_page, pixmap_end_page, NULL, pixmap_drop_writer);

	fz_try(ctx)
	{
		fz_parse_draw_options(ctx, &wri->options, options);
		wri->path = fz_strdup(ctx, path ? path : default_path);
		wri->save = save;
		switch (n)
		{
		case 1: wri->options.colorspace = fz_device_gray(ctx); break;
		case 3: wri->options.colorspace = fz_device_rgb(ctx); break;
		case 4: wri->options.colorspace = fz_device_cmyk(ctx); break;
		}
	}
	fz_catch(ctx)
	{
		fz_free(ctx, wri);
		fz_rethrow(ctx);
	}

	return (fz_document_writer*)wri;
}
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 */
}
static fz_colorspace *
load_icc_based(pdf_document *xref, pdf_obj *dict)
{
	int n;

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

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

	fz_throw(xref->ctx, "syntaxerror: ICCBased must have 1, 3 or 4 components");
	return NULL; /* Stupid MSVC */
}
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 #6
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 #7
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);
		}
	}
Beispiel #8
0
static void
jxr_read_image(fz_context *ctx, unsigned char *data, int size, struct info *info, int only_metadata)
{
	jxr_container_t container;
	jxr_image_t image = NULL;
	jxr_image_t alpha = NULL;
	int rc, i;

	fz_try(ctx)
	{
		container = jxr_create_container();

		rc = jxr_read_image_container_memory(container, data, size);
		if (rc < 0)
			fz_throw(ctx, FZ_ERROR_GENERIC, "cannot read jxr image container: %s", jxr_error_string(rc));

		info->xres = jxrc_width_resolution(container, 0);
		info->yres = jxrc_height_resolution(container, 0);
		info->width = jxrc_image_width(container, 0);
		info->height = jxrc_image_height(container, 0);

		info->format = jxrc_image_pixelformat(container, 0);

		for (i = 0; i < nelem(pixelformats); i++)
			if (pixelformats[i].format == info->format)
			{
				info->comps = pixelformats[i].comps;
				break;
			}
		if (i == nelem(pixelformats))
			fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported pixel format: %u", info->format);

		if (info->comps == 1)
			info->cspace = fz_device_gray(ctx);
		else if (info->comps == 3)
			info->cspace = fz_device_rgb(ctx);
		else if (info->comps >= 4)
			info->cspace = fz_device_cmyk(ctx);

		info->stride = info->width * (fz_colorspace_n(ctx, info->cspace) + 1);

		if (!only_metadata)
		{
			unsigned long image_offset;
			unsigned char image_band;
			unsigned long alpha_offset;
			unsigned char alpha_band;

			info->ctx = ctx;
			info->samples = fz_malloc(ctx, info->stride * info->height);
			memset(info->samples, 0xff, info->stride * info->height);

			image_offset = jxrc_image_offset(container, 0);
			image_band = jxrc_image_band_presence(container, 0);
			alpha_offset = jxrc_alpha_offset(container, 0);
			alpha_band = jxrc_alpha_band_presence(container, 0);

			image = jxr_create_input();

			jxr_set_PROFILE_IDC(image, 111);
			jxr_set_LEVEL_IDC(image, 255);
			jxr_set_pixel_format(image, info->format);
			jxr_set_container_parameters(image, info->format,
				info->width, info->height, alpha_offset,
				image_band, alpha_band, 0);

			jxr_set_user_data(image, info);
			jxr_set_block_output(image, jxr_decode_block);

			rc = jxr_read_image_bitstream_memory(image, data + image_offset, size - image_offset);
			if (rc < 0)
				fz_throw(ctx, FZ_ERROR_GENERIC, "cannot read jxr image: %s", jxr_error_string(rc));

			if (info->format == JXRC_FMT_32bppPBGRA ||
					info->format == JXRC_FMT_64bppPRGBA ||
					info->format == JXRC_FMT_128bppPRGBAFloat)
				info->has_premul = 1;

			if (jxr_get_ALPHACHANNEL_FLAG(image))
				info->has_alpha = 1;

			if (alpha_offset > 0)
			{
				info->has_alpha = 1;

				alpha = jxr_create_input();

				jxr_set_PROFILE_IDC(alpha, 111);
				jxr_set_LEVEL_IDC(alpha, 255);
				jxr_set_pixel_format(alpha, info->format);
				jxr_set_container_parameters(alpha, info->format,
					info->width, info->height, alpha_offset,
					image_band, alpha_band, 1);

				jxr_set_user_data(alpha, info);
				jxr_set_block_output(alpha, jxr_decode_block_alpha);

				rc = jxr_read_image_bitstream_memory(alpha, data + alpha_offset, size - alpha_offset);
				if (rc < 0)
					fz_throw(ctx, FZ_ERROR_GENERIC, "cannot read jxr image: %s", jxr_error_string(rc));
			}
		}
	}
	fz_always(ctx)
	{
		if (alpha)
			jxr_destroy(alpha);
		if (image)
			jxr_destroy(image);
		jxr_destroy_container(container);
	}
	fz_catch(ctx)
	{
		fz_rethrow(ctx);
	}
}
Beispiel #9
0
static void
pdf_dev_color(fz_context *ctx, pdf_device *pdev, fz_colorspace *colorspace, const float *color, int stroke, const fz_color_params *color_params)
{
	int diff = 0;
	int i;
	int cspace = 0;
	float rgb[FZ_MAX_COLORS];
	gstate *gs = CURRENT_GSTATE(pdev);

	if (colorspace == fz_device_gray(ctx))
		cspace = 1;
	else if (colorspace == fz_device_rgb(ctx))
		cspace = 3;
	else if (colorspace == fz_device_cmyk(ctx))
		cspace = 4;

	if (cspace == 0)
	{
		/* If it's an unknown colorspace, fallback to rgb */
		fz_convert_color(ctx, color_params, NULL, fz_device_rgb(ctx), rgb, colorspace, color);
		color = rgb;
		colorspace = fz_device_rgb(ctx);
		cspace = 3;
	}

	if (gs->colorspace[stroke] != colorspace)
	{
		gs->colorspace[stroke] = colorspace;
		diff = 1;
	}

	for (i=0; i < cspace; i++)
		if (gs->color[stroke][i] != color[i])
		{
			gs->color[stroke][i] = color[i];
			diff = 1;
		}

	if (diff == 0)
		return;

	switch (cspace + stroke*8)
	{
		case 1:
			fz_append_printf(ctx, gs->buf, "%g g\n", color[0]);
			break;
		case 3:
			fz_append_printf(ctx, gs->buf, "%g %g %g rg\n", color[0], color[1], color[2]);
			break;
		case 4:
			fz_append_printf(ctx, gs->buf, "%g %g %g %g k\n", color[0], color[1], color[2], color[3]);
			break;
		case 1+8:
			fz_append_printf(ctx, gs->buf, "%g G\n", color[0]);
			break;
		case 3+8:
			fz_append_printf(ctx, gs->buf, "%g %g %g RG\n", color[0], color[1], color[2]);
			break;
		case 4+8:
			fz_append_printf(ctx, gs->buf, "%g %g %g %g K\n", color[0], color[1], color[2], color[3]);
			break;
	}
}
Beispiel #10
0
static fz_pixmap *
pam_binary_read_image(fz_context *ctx, struct info *pnm, unsigned char *p, unsigned char *e, int onlymeta)
{
	fz_pixmap *img = NULL;
	int bitmap = 0;

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

	if (pnm->tupletype == NULL)
		switch (pnm->depth)
		{
		case 1: pnm->tupletype = fz_strdup(ctx, "BLACKANDWHITE"); break;
		case 2: pnm->tupletype = fz_strdup(ctx, "GRAYSCALE_ALPHA"); break;
		case 3: pnm->tupletype = fz_strdup(ctx, "RGB"); break;
		case 4: pnm->tupletype = fz_strdup(ctx, "CMYK"); break;
		case 5: pnm->tupletype = fz_strdup(ctx, "CMYK_ALPHA"); break;
		default:
			fz_throw(ctx, FZ_ERROR_GENERIC, "cannot guess tupletype based on depth in pnm image");
		}

	if (!strcmp(pnm->tupletype, "BLACKANDWHITE"))
	{
		if (pnm->depth != 1)
			fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of range for b/w pnm image");
		if (pnm->maxval == 1)
			bitmap = 1;
		else if (pnm->maxval < 2 || pnm->maxval > 65535)
			fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range for grayscale pnm image");

		pnm->cs = fz_device_gray(ctx);
	}
	else if (!strcmp(pnm->tupletype, "GRAYSCALE"))
	{
		if (pnm->maxval < 2 || pnm->maxval > 65535)
			fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range for grayscale pnm image");
		if (pnm->depth != 1)
			fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of range for grayscale pnm image");
		pnm->cs = fz_device_gray(ctx);
	}
	else if (!strcmp(pnm->tupletype, "GRAYSCALE_ALPHA"))
	{
		if (pnm->maxval < 2 || pnm->maxval > 65535)
			fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range for grayscale pnm image with alpha");
		if (pnm->depth != 2)
			fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of range for grayscale pnm image with alpha");
		pnm->cs = fz_device_gray(ctx);
		pnm->alpha = 1;
	}
	else if (!strcmp(pnm->tupletype, "RGB"))
	{
		if (pnm->maxval < 1 || pnm->maxval > 65535)
			fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range for rgb pnm image");
		if (pnm->depth != 3)
			fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of range for rgb pnm image");
		pnm->cs = fz_device_rgb(ctx);
	}
	else if (!strcmp(pnm->tupletype, "RGB_ALPHA"))
	{
		if (pnm->maxval < 1 || pnm->maxval > 65535)
			fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range for rgb pnm image with alpha");
		if (pnm->depth != 4)
			fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of range for rgb pnm image with alpha");
		pnm->cs = fz_device_rgb(ctx);
		pnm->alpha = 1;
	}
	else if (!strcmp(pnm->tupletype, "CMYK"))
	{
		if (pnm->maxval < 1 || pnm->maxval > 65535)
			fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range for cmyk pnm image");
		if (pnm->depth != 4)
			fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of range for cmyk pnm image");
		pnm->cs = fz_device_cmyk(ctx);
	}
	else if (!strcmp(pnm->tupletype, "CMYK_ALPHA"))
	{
		if (pnm->maxval < 1 || pnm->maxval > 65535)
			fz_throw(ctx, FZ_ERROR_GENERIC, "maxval out of range for cmyk pnm image with alpha");
		if (pnm->depth != 5)
			fz_throw(ctx, FZ_ERROR_GENERIC, "depth out of range for cmyk pnm image with alpha");
		pnm->cs = fz_device_cmyk(ctx);
		pnm->alpha = 1;
	}
	else
	{
		fz_free(ctx, pnm->tupletype);
		fz_throw(ctx, FZ_ERROR_GENERIC, "unsupported tupletype");
	}

	fz_free(ctx, pnm->tupletype);

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

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

		if (bitmap)
		{
			if (e - p < pnm->height * pnm->width * img->n)
				fz_throw(ctx, FZ_ERROR_GENERIC, "truncated image");

			for (y = 0; y < pnm->height; y++)
				for (x = 0; x < pnm->width; x++)
					for (k = 0; k < img->colorspace->n; k++)
					{
						if (*p)
							*dp = 0x00;
						else
							*dp = 0xff;
						dp++;
						p++;
					}
		}
		else
		{
			if (pnm->maxval == 255)
			{
				if (e - p < pnm->height * pnm->width * img->n)
					fz_throw(ctx, FZ_ERROR_GENERIC, "truncated image");

				for (y = 0; y < pnm->height; y++)
					for (x = 0; x < pnm->width; x++)
						for (k = 0; k < img->n; k++)
							*dp++ = *p++;
			}
			else if (pnm->maxval < 256)
			{
				if (e - p < pnm->height * pnm->width * img->n)
					fz_throw(ctx, FZ_ERROR_GENERIC, "truncated image");

				for (y = 0; y < pnm->height; y++)
					for (x = 0; x < pnm->width; x++)
						for (k = 0; k < img->n; k++)
							*dp++ = map_color(ctx, *p++, pnm->maxval, 255);
			}
			else
			{
				if (e - p < pnm->height * pnm->width * img->n * 2)
					fz_throw(ctx, FZ_ERROR_GENERIC, "truncated image");

				for (y = 0; y < pnm->height; y++)
					for (x = 0; x < pnm->width; x++)
						for (k = 0; k < img->n; k++)
						{
							*dp++ = map_color(ctx, (p[0] << 8) | p[1], pnm->maxval, 255);
							p += 2;
						}
			}
		}
	}

	return img;
}
Beispiel #11
0
static void filter_flush(fz_context *ctx, pdf_filter_processor *p, int flush)
{
	filter_gstate *gstate = gstate_to_update(ctx, p);
	int i;

	if (gstate->pushed == 0)
	{
		gstate->pushed = 1;
		if (p->chain->op_q)
			p->chain->op_q(ctx, p->chain);
	}

	if (flush & FLUSH_CTM)
	{
		if (gstate->ctm.a != 1 || gstate->ctm.b != 0 ||
			gstate->ctm.c != 0 || gstate->ctm.d != 1 ||
			gstate->ctm.e != 0 || gstate->ctm.f != 0)
		{
			fz_matrix current = gstate->current_ctm;

			if (p->chain->op_cm)
				p->chain->op_cm(ctx, p->chain,
					gstate->ctm.a,
					gstate->ctm.b,
					gstate->ctm.c,
					gstate->ctm.d,
					gstate->ctm.e,
					gstate->ctm.f);

			fz_concat(&gstate->current_ctm, &current, &gstate->ctm);
			gstate->ctm.a = 1;
			gstate->ctm.b = 0;
			gstate->ctm.c = 0;
			gstate->ctm.d = 1;
			gstate->ctm.e = 0;
			gstate->ctm.f = 0;
		}
	}

	if (flush & FLUSH_COLOR_F)
	{
		if (gstate->cs.cs == fz_device_gray(ctx) && !gstate->sc.pat && !gstate->sc.shd && gstate->sc.n == 1)
		{
			if (p->chain->op_g)
				p->chain->op_g(ctx, p->chain, gstate->sc.c[0]);
			goto done_sc;
		}
		if (gstate->cs.cs == fz_device_rgb(ctx) && !gstate->sc.pat && !gstate->sc.shd && gstate->sc.n == 3)
		{
			if (p->chain->op_rg)
				p->chain->op_rg(ctx, p->chain, gstate->sc.c[0], gstate->sc.c[1], gstate->sc.c[2]);
			goto done_sc;
		}
		if (gstate->cs.cs == fz_device_cmyk(ctx) && !gstate->sc.pat && !gstate->sc.shd && gstate->sc.n == 4)
		{
			if (p->chain->op_k)
				p->chain->op_k(ctx, p->chain, gstate->sc.c[0], gstate->sc.c[1], gstate->sc.c[2], gstate->sc.c[3]);
			goto done_sc;
		}

		if (strcmp(gstate->cs.name, gstate->current_cs.name))
		{
			if (p->chain->op_cs)
				p->chain->op_cs(ctx, p->chain, gstate->cs.name, gstate->cs.cs);
		}

		/* pattern or shading */
		if (gstate->sc.name[0])
		{
			int emit = 0;
			if (strcmp(gstate->sc.name, gstate->current_sc.name))
				emit = 1;
			if (gstate->sc.n != gstate->current_sc.n)
				emit = 1;
			else
				for (i = 0; i < gstate->sc.n; ++i)
					if (gstate->sc.c[i] != gstate->current_sc.c[i])
						emit = 1;
			if (emit)
			{
				if (gstate->sc.pat)
					if (p->chain->op_sc_pattern)
						p->chain->op_sc_pattern(ctx, p->chain, gstate->sc.name, gstate->sc.pat, gstate->sc.n, gstate->sc.c);
				if (gstate->sc.shd)
					if (p->chain->op_sc_shade)
						p->chain->op_sc_shade(ctx, p->chain, gstate->sc.name, gstate->sc.shd);
			}
		}

		/* plain color */
		else
		{
			int emit = 0;
			if (gstate->sc.n != gstate->current_sc.n)
				emit = 1;
			else
				for (i = 0; i < gstate->sc.n; ++i)
					if (gstate->sc.c[i] != gstate->current_sc.c[i])
						emit = 1;
			if (emit)
			{
				if (p->chain->op_sc_color)
					p->chain->op_sc_color(ctx, p->chain, gstate->sc.n, gstate->sc.c);
			}
		}

done_sc:
		gstate->current_cs = gstate->cs;
		gstate->current_sc = gstate->sc;
	}

	if (flush & FLUSH_COLOR_S)
	{
		if (gstate->CS.cs == fz_device_gray(ctx) && !gstate->SC.pat && !gstate->SC.shd && gstate->SC.n == 1)
		{
			if (p->chain->op_G)
				p->chain->op_G(ctx, p->chain, gstate->SC.c[0]);
			goto done_SC;
		}
		if (gstate->CS.cs == fz_device_rgb(ctx) && !gstate->SC.pat && !gstate->SC.shd && gstate->SC.n == 3)
		{
			if (p->chain->op_RG)
				p->chain->op_RG(ctx, p->chain, gstate->SC.c[0], gstate->SC.c[1], gstate->SC.c[2]);
			goto done_SC;
		}
		if (gstate->CS.cs == fz_device_cmyk(ctx) && !gstate->SC.pat && !gstate->SC.shd && gstate->SC.n == 4)
		{
			if (p->chain->op_K)
				p->chain->op_K(ctx, p->chain, gstate->SC.c[0], gstate->SC.c[1], gstate->SC.c[2], gstate->SC.c[3]);
			goto done_SC;
		}

		if (strcmp(gstate->CS.name, gstate->current_CS.name))
		{
			if (p->chain->op_CS)
				p->chain->op_CS(ctx, p->chain, gstate->CS.name, gstate->CS.cs);
		}

		/* pattern or shading */
		if (gstate->SC.name[0])
		{
			int emit = 0;
			if (strcmp(gstate->SC.name, gstate->current_SC.name))
				emit = 1;
			if (gstate->SC.n != gstate->current_SC.n)
				emit = 1;
			else
				for (i = 0; i < gstate->SC.n; ++i)
					if (gstate->SC.c[i] != gstate->current_SC.c[i])
						emit = 1;
			if (emit)
			{
				if (gstate->SC.pat)
					if (p->chain->op_SC_pattern)
						p->chain->op_SC_pattern(ctx, p->chain, gstate->SC.name, gstate->SC.pat, gstate->SC.n, gstate->SC.c);
				if (gstate->SC.shd)
					if (p->chain->op_SC_shade)
						p->chain->op_SC_shade(ctx, p->chain, gstate->SC.name, gstate->SC.shd);
			}
		}

		/* plain color */
		else
		{
			int emit = 0;
			if (gstate->SC.n != gstate->current_SC.n)
				emit = 1;
			else
				for (i = 0; i < gstate->SC.n; ++i)
					if (gstate->SC.c[i] != gstate->current_SC.c[i])
						emit = 1;
			if (emit)
			{
				if (p->chain->op_SC_color)
					p->chain->op_SC_color(ctx, p->chain, gstate->SC.n, gstate->SC.c);
			}
		}

done_SC:
		gstate->current_CS = gstate->CS;
		gstate->current_SC = gstate->SC;
	}

	if (flush & FLUSH_STROKE)
	{
		if (gstate->stroke.linecap != gstate->current_stroke.linecap)
		{
			if (p->chain->op_J)
				p->chain->op_J(ctx, p->chain, gstate->stroke.linecap);
		}
		if (gstate->stroke.linejoin != gstate->current_stroke.linejoin)
		{
			if (p->chain->op_j)
				p->chain->op_j(ctx, p->chain, gstate->stroke.linejoin);
		}
		if (gstate->stroke.linewidth != gstate->current_stroke.linewidth)
		{
			if (p->chain->op_w)
				p->chain->op_w(ctx, p->chain, gstate->stroke.linewidth);
		}
		if (gstate->stroke.miterlimit != gstate->current_stroke.miterlimit)
		{
			if (p->chain->op_M)
				p->chain->op_M(ctx, p->chain, gstate->stroke.linewidth);
		}
		gstate->current_stroke = gstate->stroke;
	}
}
void
fz_load_jpeg_info(fz_context *ctx, unsigned char *rbuf, int rlen, int *xp, int *yp, int *xresp, int *yresp, fz_colorspace **cspacep)
{
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr err;
	struct jpeg_source_mgr src;

	fz_try(ctx)
	{
		cinfo.client_data = ctx;
		cinfo.err = jpeg_std_error(&err);
		err.error_exit = error_exit;

		jpeg_create_decompress(&cinfo);

		cinfo.src = &src;
		src.init_source = init_source;
		src.fill_input_buffer = fill_input_buffer;
		src.skip_input_data = skip_input_data;
		src.resync_to_restart = jpeg_resync_to_restart;
		src.term_source = term_source;
		src.next_input_byte = rbuf;
		src.bytes_in_buffer = rlen;

		jpeg_read_header(&cinfo, 1);

		if (cinfo.num_components == 1)
			*cspacep = fz_device_gray(ctx);
		else if (cinfo.num_components == 3)
			*cspacep = fz_device_rgb(ctx);
		else if (cinfo.num_components == 4)
			*cspacep = fz_device_cmyk(ctx);
		else
			fz_throw(ctx, "bad number of components in jpeg: %d", cinfo.num_components);

		*xp = cinfo.image_width;
		*yp = cinfo.image_height;

		if (cinfo.density_unit == 1)
		{
			*xresp = cinfo.X_density;
			*yresp = cinfo.Y_density;
		}
		else if (cinfo.density_unit == 2)
		{
			*xresp = cinfo.X_density * 254 / 100;
			*yresp = cinfo.Y_density * 254 / 100;
		}
		else
		{
			*xresp = 0;
			*yresp = 0;
		}

		if (*xresp <= 0) *xresp = 72;
		if (*yresp <= 0) *yresp = 72;
	}
	fz_always(ctx)
	{
		jpeg_destroy_decompress(&cinfo);
	}
	fz_catch(ctx)
	{
		fz_rethrow(ctx);
	}
}
Beispiel #13
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 #14
0
void
fz_load_jpeg_info(fz_context *ctx, unsigned char *rbuf, int rlen, int *xp, int *yp, int *xresp, int *yresp, fz_colorspace **cspacep)
{
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr err;
	struct jpeg_source_mgr src;

	fz_try(ctx)
	{
		cinfo.client_data = ctx;
		cinfo.err = jpeg_std_error(&err);
		err.error_exit = error_exit;

		fz_jpg_mem_init(ctx, &cinfo);

		jpeg_create_decompress(&cinfo);

		cinfo.src = &src;
		src.init_source = init_source;
		src.fill_input_buffer = fill_input_buffer;
		src.skip_input_data = skip_input_data;
		src.resync_to_restart = jpeg_resync_to_restart;
		src.term_source = term_source;
		src.next_input_byte = rbuf;
		src.bytes_in_buffer = rlen;

		jpeg_save_markers(&cinfo, JPEG_APP0+1, 0xffff);
		jpeg_save_markers(&cinfo, JPEG_APP0+13, 0xffff);

		jpeg_read_header(&cinfo, 1);

		if (cinfo.num_components == 1)
			*cspacep = fz_device_gray(ctx);
		else if (cinfo.num_components == 3)
			*cspacep = fz_device_rgb(ctx);
		else if (cinfo.num_components == 4)
			*cspacep = fz_device_cmyk(ctx);
		else
			fz_throw(ctx, FZ_ERROR_GENERIC, "bad number of components in jpeg: %d", cinfo.num_components);

		*xp = cinfo.image_width;
		*yp = cinfo.image_height;

		if (extract_exif_resolution(cinfo.marker_list, xresp, yresp))
			/* XPS prefers EXIF resolution to JFIF density */;
		else if (extract_app13_resolution(cinfo.marker_list, xresp, yresp))
			/* XPS prefers APP13 resolution to JFIF density */;
		else if (cinfo.density_unit == 1)
		{
			*xresp = cinfo.X_density;
			*yresp = cinfo.Y_density;
		}
		else if (cinfo.density_unit == 2)
		{
			*xresp = cinfo.X_density * 254 / 100;
			*yresp = cinfo.Y_density * 254 / 100;
		}
		else
		{
			*xresp = 0;
			*yresp = 0;
		}

		if (*xresp <= 0) *xresp = 96;
		if (*yresp <= 0) *yresp = 96;
	}
	fz_always(ctx)
	{
		jpeg_destroy_decompress(&cinfo);
		fz_jpg_mem_term(&cinfo);
	}
	fz_catch(ctx)
	{
		fz_rethrow(ctx);
	}
}
Beispiel #15
0
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);
		}
	}
Beispiel #16
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 < 0 || w > image->w)
		w = image->w;
	if (h < 0 || 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;
	case FZ_IMAGE_JXR:
		tile = fz_load_jxr(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, indexed, l2factor, 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;
	}

	/* 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 #17
0
static void
pdf_dev_color(fz_context *ctx, pdf_device *pdev, fz_colorspace *colorspace, const float *color, int stroke)
{
	int diff = 0;
	int i;
	int cspace = 0;
	float rgb[FZ_MAX_COLORS];
	gstate *gs = CURRENT_GSTATE(pdev);

	if (colorspace == fz_device_gray(ctx))
		cspace = 1;
	else if (colorspace == fz_device_rgb(ctx))
		cspace = 3;
	else if (colorspace == fz_device_cmyk(ctx))
		cspace = 4;

	if (cspace == 0)
	{
		/* If it's an unknown colorspace, fallback to rgb */
		colorspace->to_rgb(ctx, colorspace, color, rgb);
		color = rgb;
		colorspace = fz_device_rgb(ctx);
	}

	if (gs->colorspace[stroke] != colorspace)
	{
		gs->colorspace[stroke] = colorspace;
		diff = 1;
	}

	for (i=0; i < colorspace->n; i++)
		if (gs->color[stroke][i] != color[i])
		{
			gs->color[stroke][i] = color[i];
			diff = 1;
		}

	if (diff == 0)
		return;

	switch (cspace + stroke*8)
	{
		case 1:
			fz_buffer_printf(ctx, gs->buf, "%f g\n", color[0]);
			break;
		case 3:
			fz_buffer_printf(ctx, gs->buf, "%f %f %f rg\n", color[0], color[1], color[2]);
			break;
		case 4:
			fz_buffer_printf(ctx, gs->buf, "%f %f %f %f k\n", color[0], color[1], color[2], color[3]);
			break;
		case 1+8:
			fz_buffer_printf(ctx, gs->buf, "%f G\n", color[0]);
			break;
		case 3+8:
			fz_buffer_printf(ctx, gs->buf, "%f %f %f RG\n", color[0], color[1], color[2]);
			break;
		case 4+8:
			fz_buffer_printf(ctx, gs->buf, "%f %f %f %f K\n", color[0], color[1], color[2], color[3]);
			break;
	}
}
Beispiel #18
0
void
xps_parse_color(fz_context *ctx, xps_document *doc, char *base_uri, char *string,
		fz_colorspace **csp, float *samples)
{
	char *p;
	int i, n;
	char buf[1024];
	char *profile;

	*csp = fz_device_rgb(ctx);

	samples[0] = 1;
	samples[1] = 0;
	samples[2] = 0;
	samples[3] = 0;

	if (string[0] == '#')
	{
		if (strlen(string) == 9)
		{
			samples[0] = unhex(string[1]) * 16 + unhex(string[2]);
			samples[1] = unhex(string[3]) * 16 + unhex(string[4]);
			samples[2] = unhex(string[5]) * 16 + unhex(string[6]);
			samples[3] = unhex(string[7]) * 16 + unhex(string[8]);
		}
		else
		{
			samples[0] = 255;
			samples[1] = unhex(string[1]) * 16 + unhex(string[2]);
			samples[2] = unhex(string[3]) * 16 + unhex(string[4]);
			samples[3] = unhex(string[5]) * 16 + unhex(string[6]);
		}

		samples[0] /= 255;
		samples[1] /= 255;
		samples[2] /= 255;
		samples[3] /= 255;
	}

	else if (string[0] == 's' && string[1] == 'c' && string[2] == '#')
	{
		if (count_commas(string) == 2)
			sscanf(string, "sc#%g,%g,%g", samples + 1, samples + 2, samples + 3);
		if (count_commas(string) == 3)
			sscanf(string, "sc#%g,%g,%g,%g", samples, samples + 1, samples + 2, samples + 3);
	}

	else if (strstr(string, "ContextColor ") == string)
	{
		/* Crack the string for profile name and sample values */
		fz_strlcpy(buf, string, sizeof buf);

		profile = strchr(buf, ' ');
		if (!profile)
		{
			fz_warn(ctx, "cannot find icc profile uri in '%s'", string);
			return;
		}

		*profile++ = 0;
		p = strchr(profile, ' ');
		if (!p)
		{
			fz_warn(ctx, "cannot find component values in '%s'", profile);
			return;
		}

		*p++ = 0;
		n = count_commas(p) + 1;
		if (n > FZ_MAX_COLORS)
		{
			fz_warn(ctx, "ignoring %d color components (max %d allowed)", n - FZ_MAX_COLORS, FZ_MAX_COLORS);
			n = FZ_MAX_COLORS;
		}
		i = 0;
		while (i < n)
		{
			samples[i++] = fz_atof(p);
			p = strchr(p, ',');
			if (!p)
				break;
			p ++;
			if (*p == ' ')
				p ++;
		}
		while (i < n)
		{
			samples[i++] = 0;
		}

		/* TODO: load ICC profile */
		switch (n)
		{
		case 2: *csp = fz_device_gray(ctx); break;
		case 4: *csp = fz_device_rgb(ctx); break;
		case 5: *csp = fz_device_cmyk(ctx); break;
		default: *csp = fz_device_gray(ctx); break;
		}
	}
}
Beispiel #19
0
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;
}