Ejemplo n.º 1
0
static fz_image *pack_jp2(fz_context *ctx, const char *data, size_t len, SizeI size)
{
    fz_compressed_buffer *buf = nullptr;
    fz_var(buf);

    fz_try(ctx) {
        buf = fz_malloc_struct(ctx, fz_compressed_buffer);
        buf->buffer = fz_new_buffer(ctx, (int)len);
        memcpy(buf->buffer->data, data, (buf->buffer->len = (int)len));
        buf->params.type = FZ_IMAGE_JPX;
    }
    fz_catch(ctx) {
        fz_free_compressed_buffer(ctx, buf);
        fz_rethrow(ctx);
    }

    return fz_new_image(ctx, size.dx, size.dy, 8, fz_device_rgb(ctx), 96, 96, 0, 0, nullptr, nullptr, buf, nullptr);
}
Ejemplo n.º 2
0
static void
svg_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
{
	svg_device *sdev = (svg_device*)dev;
	fz_output *out = sdev->out;

	fz_rect rect;
	fz_irect bbox;
	fz_pixmap *pix;
	fz_buffer *buf = NULL;

	fz_var(buf);

	if (dev->container_len == 0)
		return;

	fz_round_rect(&bbox, fz_intersect_rect(fz_bound_shade(ctx, shade, ctm, &rect), &dev->container[dev->container_len-1].scissor));
	if (fz_is_empty_irect(&bbox))
		return;
	pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &bbox);
	fz_clear_pixmap(ctx, pix);

	fz_try(ctx)
	{
		fz_paint_shade(ctx, shade, ctm, pix, &bbox);
		buf = fz_new_buffer_from_pixmap_as_png(ctx, pix);
		if (alpha != 1.0f)
			fz_printf(ctx, out, "<g opacity=\"%g\">", alpha);
		fz_printf(ctx, out, "<image x=\"%dpx\" y=\"%dpx\" width=\"%dpx\" height=\"%dpx\" xlink:href=\"data:image/png;base64,", pix->x, pix->y, pix->w, pix->h);
		send_data_base64(ctx, out, buf);
		fz_printf(ctx, out, "\"/>\n");
		if (alpha != 1.0f)
			fz_printf(ctx, out, "</g>");
	}
	fz_always(ctx)
	{
		fz_drop_buffer(ctx, buf);
		fz_drop_pixmap(ctx, pix);
	}
	fz_catch(ctx)
	{
		fz_rethrow(ctx);
	}
}
Ejemplo n.º 3
0
void PDFDocument::Render(
    Document::PixelWriter* pw, int page, float zoom, int rotation) {
  assert((page >= 0) && (page < GetNumPages()));

  std::unique_lock<std::mutex> lock(_render_mutex);

  // 1. Init MuPDF structures.
  const fz_matrix& m = Transform(zoom, rotation);
  pdf_page* page_struct = GetPage(page);
  const fz_irect& bbox = GetBoundingBox(page_struct, m);
  fz_pixmap* pixmap = fz_new_pixmap_with_bbox(
      _fz_context, fz_device_rgb(_fz_context), &bbox, 1);
  fz_device* dev = fz_new_draw_device(_fz_context, &fz_identity, pixmap);

  // 2. Render page.
  fz_clear_pixmap_with_value(_fz_context, pixmap, 0xff);
  pdf_run_page(_fz_context, _pdf_document, page_struct, dev, &m, nullptr);

  // 3. Write pixmap to buffer. The page is vertically divided into n equal
  // stripes, each copied to pw by one thread.
  assert(fz_pixmap_components(_fz_context, pixmap) == 4);
  uint8_t* buffer = reinterpret_cast<uint8_t*>(
      fz_pixmap_samples(_fz_context, pixmap));
  const int num_cols = fz_pixmap_width(_fz_context, pixmap);
  const int num_rows = fz_pixmap_height(_fz_context, pixmap);
  ExecuteInParallel([=](int num_threads, int i) {
    const int num_rows_per_thread = num_rows / num_threads;
    const int y_begin = i * num_rows_per_thread;
    const int y_end = (i == num_threads - 1) ?
                          num_rows :
                          (i + 1) * num_rows_per_thread;
    uint8_t* p = buffer + y_begin * num_cols * 4;
    for (int y = y_begin; y < y_end; ++y) {
      for (int x = 0; x < num_cols; ++x) {
        pw->Write(x, y, p[0], p[1], p[2]);
        p += 4;
      }
    }
  });

  // 4. Clean up.
  fz_drop_device(_fz_context, dev);
  fz_drop_pixmap(_fz_context, pixmap);
}
Ejemplo n.º 4
0
static void
svg_dev_clip_text(fz_device *dev, fz_text *text, const fz_matrix *ctm, int accumulate)
{
	svg_device *sdev = dev->user;
	fz_output *out = sdev->out;
	fz_context *ctx = dev->ctx;
	fz_rect bounds;
	int num = sdev->id++;
	float white[3] = { 255, 255, 255 };

	fz_bound_text(ctx, text, NULL, ctm, &bounds);

	fz_printf(out, "<mask id=\"ma%d\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" maskUnits=\"userSpaceOnUse\" maskContentUnits=\"userSpaceOnUse\">\n",
		num, bounds.x0, bounds.y0, bounds.x1 - bounds.x0, bounds.y1 - bounds.y0);
	fz_printf(out, "<text");
	svg_dev_fill_color(sdev, fz_device_rgb(ctx), white, 1.0f);
	svg_dev_text(sdev, ctm, text);
	fz_printf(out, "</mask>\n<g mask=\"url(#ma%d)\">\n", num);
}
Ejemplo n.º 5
0
static fz_image *pack_jpeg(fz_context *ctx, const char *data, size_t len, SizeI size)
{
    fz_compressed_buffer *buf = NULL;
    fz_var(buf);

    fz_try(ctx) {
        buf = fz_malloc_struct(ctx, fz_compressed_buffer);
        buf->buffer = fz_new_buffer(ctx, (int)len);
        memcpy(buf->buffer->data, data, (buf->buffer->len = (int)len));
        buf->params.type = FZ_IMAGE_JPEG;
        buf->params.u.jpeg.color_transform = -1;
    }
    fz_catch(ctx) {
        fz_free_compressed_buffer(ctx, buf);
        fz_rethrow(ctx);
    }

    return fz_new_image(ctx, size.dx, size.dy, 8, fz_device_rgb(ctx), 96, 96, 0, 0, NULL, NULL, buf, NULL);
}
Ejemplo n.º 6
0
void j_mu_render_page(void* p_ctx, void* p_page)
{
	fz_context* ctx = (fz_context*) p_ctx;
	pdf_page* page = (pdf_page*)p_page;

	fz_matrix transform;
	fz_rotate(&transform, 0);

	fz_pre_scale(&transform, 100 / 100.0f, 100 / 100.0f);
	fz_rect bounds;
	pdf_bound_page(ctx, page, &bounds);
	fz_transform_rect(&bounds, &transform);

	fz_irect bbox;
	fz_round_rect(&bbox, &bounds);
	fz_pixmap *pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &bbox);
	fz_pixmap_set_resolution(pix, 300);
	fz_clear_pixmap_with_value(ctx, pix, 0xff);
}
Ejemplo n.º 7
0
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");
}
Ejemplo n.º 8
0
static void
svg_dev_clip_stroke_path(fz_device *dev, fz_path *path, const fz_rect *rect, fz_stroke_state *stroke, const fz_matrix *ctm)
{
	svg_device *sdev = dev->user;
	fz_output *out = sdev->out;
	fz_context *ctx = dev->ctx;
	fz_rect bounds;
	int num = sdev->id++;
	float white[3] = { 255, 255, 255 };

	fz_bound_path(ctx, path, stroke, ctm, &bounds);

	fz_printf(out, "<mask id=\"ma%d\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" maskUnits=\"userSpaceOnUse\" maskContentUnits=\"userSpaceOnUse\">\n",
		num, bounds.x0, bounds.y0, bounds.x1 - bounds.x0, bounds.y1 - bounds.y0);
	fz_printf(out, "<path");
	svg_dev_ctm(sdev, ctm);
	svg_dev_stroke_state(sdev, stroke);
	svg_dev_stroke_color(sdev, fz_device_rgb(ctx), white, 1);
	svg_dev_path(sdev, path);
	fz_printf(out, "/>\n</mask>\n<g mask=\"url(#ma%d)\">\n", num);
}
Ejemplo n.º 9
0
static void
svg_dev_fill_color(fz_context *ctx, svg_device *sdev, fz_colorspace *colorspace, float *color, float alpha)
{
	fz_output *out = sdev->out;
	float rgb[FZ_MAX_COLORS];

	if (colorspace != fz_device_rgb(ctx))
	{
		/* If it's not rgb, make it rgb */
		colorspace->to_rgb(ctx, colorspace, color, rgb);
		color = rgb;
	}

	if (color[0] == 0 && color[1] == 0 && color[2] == 0)
	{
		/* don't send a fill, as it will be assumed to be black */
	}
	else
		fz_printf(ctx, out, " fill=\"rgb(%d,%d,%d)\"", (int)(255*color[0] + 0.5), (int)(255*color[1] + 0.5), (int)(255*color[2]+0.5));
	if (alpha != 1)
		fz_printf(ctx, out, " fill-opacity=\"%g\"", alpha);
}
Ejemplo n.º 10
0
static void draw_rect(fz_context *ctx, fz_device *dev, const fz_matrix *ctm, fz_css_color color, float x0, float y0, float x1, float y1)
{
    if (color.a > 0)
    {
        float rgb[3];

        fz_path *path = fz_new_path(ctx);

        fz_moveto(ctx, path, x0, y0);
        fz_lineto(ctx, path, x1, y0);
        fz_lineto(ctx, path, x1, y1);
        fz_lineto(ctx, path, x0, y1);
        fz_closepath(ctx, path);

        rgb[0] = color.r / 255.0f;
        rgb[1] = color.g / 255.0f;
        rgb[2] = color.b / 255.0f;

        fz_fill_path(ctx, dev, path, 0, ctm, fz_device_rgb(ctx), rgb, color.a / 255.0f);

        fz_drop_path(ctx, path);
    }
}
Ejemplo n.º 11
0
void pdfapp_init(fz_context *ctx, pdfapp_t *app)
{
	memset(app, 0, sizeof(pdfapp_t));
	app->scrw = 640;
	app->scrh = 480;
	app->resolution = 72;
	app->ctx = ctx;

	app->layout_w = 450;
	app->layout_h = 600;
	app->layout_em = 12;

	app->transition.duration = 0.25;
	app->transition.type = FZ_TRANSITION_FADE;
#if defined(_WIN32) || defined(_WIN64)
	app->colorspace = fz_device_bgr(ctx);
#else
	app->colorspace = fz_device_rgb(ctx);
#endif
	app->tint_r = 255;
	app->tint_g = 250;
	app->tint_b = 240;
}
Ejemplo n.º 12
0
static void
svg_dev_clip_stroke_path(fz_context *ctx, fz_device *dev, const fz_path *path, const fz_rect *rect, const fz_stroke_state *stroke, const fz_matrix *ctm)
{
	svg_device *sdev = (svg_device*)dev;

	fz_output *out;
	fz_rect bounds;
	int num = sdev->id++;
	float white[3] = { 1, 1, 1 };

	fz_bound_path(ctx, path, stroke, ctm, &bounds);

	out = start_def(ctx, sdev);
	fz_printf(ctx, out, "<mask id=\"ma%d\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" maskUnits=\"userSpaceOnUse\" maskContentUnits=\"userSpaceOnUse\">\n",
		num, bounds.x0, bounds.y0, bounds.x1 - bounds.x0, bounds.y1 - bounds.y0);
	fz_printf(ctx, out, "<path");
	svg_dev_ctm(ctx, sdev, ctm);
	svg_dev_stroke_state(ctx, sdev, stroke, &fz_identity);
	svg_dev_stroke_color(ctx, sdev, fz_device_rgb(ctx), white, 1);
	svg_dev_path(ctx, sdev, path);
	fz_printf(ctx, out, "/>\n</mask>\n");
	out = end_def(ctx, sdev);
	fz_printf(ctx, out, "<g mask=\"url(#ma%d)\">\n", num);
}
Ejemplo n.º 13
0
void render(char *filename, int pagenumber, int zoom, int rotation)
{
	// Create a context to hold the exception stack and various caches.

	fz_context *ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);

	// Open the PDF, XPS or CBZ document.

	fz_document *doc = fz_open_document(ctx, filename);

	// Retrieve the number of pages (not used in this example).

	int pagecount = fz_count_pages(doc);

	// Load the page we want. Page numbering starts from zero.

	fz_page *page = fz_load_page(doc, pagenumber - 1);

	// Calculate a transform to use when rendering. This transform
	// contains the scale and rotation. Convert zoom percentage to a
	// scaling factor. Without scaling the resolution is 72 dpi.

	fz_matrix transform;
	fz_rotate(&transform, rotation);
	fz_pre_scale(&transform, zoom / 100.0f, zoom / 100.0f);

	// Take the page bounds and transform them by the same matrix that
	// we will use to render the page.

	fz_rect bounds;
	fz_bound_page(doc, page, &bounds);
	fz_transform_rect(&bounds, &transform);

	// Create a blank pixmap to hold the result of rendering. The
	// pixmap bounds used here are the same as the transformed page
	// bounds, so it will contain the entire page. The page coordinate
	// space has the origin at the top left corner and the x axis
	// extends to the right and the y axis extends down.

	fz_irect bbox;
	fz_round_rect(&bbox, &bounds);
	fz_pixmap *pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &bbox);
	fz_clear_pixmap_with_value(ctx, pix, 0xff);

	// A page consists of a series of objects (text, line art, images,
	// gradients). These objects are passed to a device when the
	// interpreter runs the page. There are several devices, used for
	// different purposes:
	//
	//	draw device -- renders objects to a target pixmap.
	//
	//	text device -- extracts the text in reading order with styling
	//	information. This text can be used to provide text search.
	//
	//	list device -- records the graphic objects in a list that can
	//	be played back through another device. This is useful if you
	//	need to run the same page through multiple devices, without
	//	the overhead of parsing the page each time.

	// Create a draw device with the pixmap as its target.
	// Run the page with the transform.

	fz_device *dev = fz_new_draw_device(ctx, pix);
	fz_run_page(doc, page, dev, &transform, NULL);
	fz_free_device(dev);

	// Save the pixmap to a file.

	fz_write_png(ctx, pix, "out.png", 0);

	// Clean up.

	fz_drop_pixmap(ctx, pix);
	fz_free_page(doc, page);
	fz_close_document(doc);
	fz_free_context(ctx);
}
Ejemplo n.º 14
0
static void svg_stroke(fz_context *ctx, fz_device *dev, svg_document *doc, fz_path *path, svg_state *state)
{
	float opacity = state->opacity * state->stroke_opacity;
	fz_stroke_path(ctx, dev, path, &state->stroke, &state->transform, fz_device_rgb(ctx), state->stroke_color, opacity);
}
Ejemplo n.º 15
0
int
main(int argc, char *argv[])
{
	fz_context *ctx;
	FILE *script = NULL;
	int c;

	while ((c = fz_getopt(argc, argv, "o:p:v")) != -1)
	{
		switch(c)
		{
		case 'o': output = fz_optarg; break;
		case 'p': prefix = fz_optarg; break;
		case 'v': verbosity ^= 1; break;
		default: usage(); break;
		}
	}

	if (fz_optind == argc)
		usage();

	ctx = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT);
	if (!ctx)
	{
		fprintf(stderr, "cannot initialise context\n");
		exit(1);
	}
	pdfapp_init(ctx, &gapp);
	gapp.scrw = 640;
	gapp.scrh = 480;
	gapp.colorspace = fz_device_rgb(ctx);

	fz_try(ctx)
	{
		while (fz_optind < argc)
		{
			scriptname = argv[fz_optind++];
			script = fopen(scriptname, "rb");
			if (script == NULL)
				fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open script: %s", scriptname);

			do
			{
				char *line = my_getline(script);
				if (line == NULL)
					continue;
				if (verbosity)
					fprintf(stderr, "'%s'\n", line);
				if (match(&line, "%"))
				{
					/* Comment */
				}
				else if (match(&line, "PASSWORD"))
				{
					strcpy(pd_password, line);
				}
				else if (match(&line, "OPEN"))
				{
					char path[1024];
					if (file_open)
						pdfapp_close(&gapp);
					strcpy(filename, line);
					if (prefix)
					{
						sprintf(path, "%s%s", prefix, line);
					}
					else
					{
						strcpy(path, line);
					}
					pdfapp_open(&gapp, path, 0);
					file_open = 1;
				}
				else if (match(&line, "GOTO"))
				{
					pdfapp_gotopage(&gapp, atoi(line)-1);
				}
				else if (match(&line, "SCREENSHOT"))
				{
					char text[1024];

					sprintf(text, output, ++shotcount);
					if (strstr(text, ".pgm") || strstr(text, ".ppm") || strstr(text, ".pnm"))
						fz_write_pnm(ctx, gapp.image, text);
					else
						fz_write_png(ctx, gapp.image, text, 0);
				}
				else if (match(&line, "RESIZE"))
				{
					int w, h;
					sscanf(line, "%d %d", &w, &h);
					pdfapp_onresize(&gapp, w, h);
				}
				else if (match(&line, "CLICK"))
				{
					float x, y, b;
					int n;
					n = sscanf(line, "%f %f %f", &x, &y, &b);
					if (n < 1)
						x = 0.0f;
					if (n < 2)
						y = 0.0f;
					if (n < 3)
						b = 1;
					/* state = 1 = transition down */
					pdfapp_onmouse(&gapp, (int)x, (int)y, b, 0, 1);
					/* state = -1 = transition up */
					pdfapp_onmouse(&gapp, (int)x, (int)y, b, 0, -1);
				}
				else if (match(&line, "TEXT"))
				{
					unescape_string(td_textinput, line);
				}
				else
				{
					fprintf(stderr, "Unmatched: %s\n", line);
				}
			}
			while (!feof(script));

			fclose(script);
		}
	}
	fz_catch(ctx)
	{
		fprintf(stderr, "error: cannot execute '%s'\n", scriptname);
	}

	if (file_open)
		pdfapp_close(&gapp);

	fz_free_context(ctx);

	return 0;
}
Ejemplo n.º 16
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;
		}
	}
}
Ejemplo n.º 17
0
static fz_image *render_to_pixmap(fz_context *ctx, HBITMAP hbmp, SizeI size)
{
    int w = size.dx, h = size.dy;
    int stride = ((w * 3 + 3) / 4) * 4;

    unsigned char *data = (unsigned char *)fz_malloc(ctx, stride * h);

    BITMAPINFO bmi = { 0 };
    bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
    bmi.bmiHeader.biWidth = w;
    bmi.bmiHeader.biHeight = -h;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 24;
    bmi.bmiHeader.biCompression = BI_RGB;

    HDC hDC = GetDC(nullptr);
    int res = GetDIBits(hDC, hbmp, 0, h, data, &bmi, DIB_RGB_COLORS);
    ReleaseDC(nullptr, hDC);
    if (!res) {
        fz_free(ctx, data);
        fz_throw(ctx, FZ_ERROR_GENERIC, "GetDIBits failed");
    }

    // convert BGR with padding to RGB without padding
    unsigned char *out = data;
    bool is_grayscale = true;
    for (int y = 0; y < h; y++) {
        const unsigned char *in = data + y * stride;
        unsigned char green, blue;
        for (int x = 0; x < w; x++) {
            is_grayscale = is_grayscale && in[0] == in[1] && in[0] == in[2];
            blue = *in++;
            green = *in++;
            *out++ = *in++;
            *out++ = green;
            *out++ = blue;
        }
    }
    // convert grayscale RGB to proper grayscale
    if (is_grayscale) {
        const unsigned char *in = out = data;
        for (int i = 0; i < w * h; i++) {
            *out++ = *in++;
            in += 2;
        }
    }

    fz_compressed_buffer *buf = nullptr;
    fz_var(buf);

    fz_try(ctx) {
        buf = fz_malloc_struct(ctx, fz_compressed_buffer);
        buf->buffer = fz_new_buffer(ctx, w * h * 4 + 10);
        buf->params.type = FZ_IMAGE_FLATE;
        buf->params.u.flate.predictor = 1;

        z_stream zstm = { 0 };
        zstm.next_in = data;
        zstm.avail_in = out - data;
        zstm.next_out = buf->buffer->data;
        zstm.avail_out = buf->buffer->cap;

        res = deflateInit(&zstm, 9);
        if (res != Z_OK)
            fz_throw(ctx, FZ_ERROR_GENERIC, "deflate failure %d", res);
        res = deflate(&zstm, Z_FINISH);
        if (res != Z_STREAM_END)
            fz_throw(ctx, FZ_ERROR_GENERIC, "deflate failure %d", res);
        buf->buffer->len = zstm.total_out;
        res = deflateEnd(&zstm);
        if (res != Z_OK)
            fz_throw(ctx, FZ_ERROR_GENERIC, "deflate failure %d", res);
    }
    fz_always(ctx) {
        fz_free(ctx, data);
    }
    fz_catch(ctx) {
        fz_free_compressed_buffer(ctx, buf);
        fz_rethrow(ctx);
    }

    fz_colorspace *cs = is_grayscale ? fz_device_gray(ctx) : fz_device_rgb(ctx);
    return fz_new_image(ctx, w, h, 8, cs, 96, 96, 0, 0, nullptr, nullptr, buf, nullptr);
}
Ejemplo n.º 18
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;
	}
}
Ejemplo n.º 19
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;
}
Ejemplo n.º 20
0
static int
xps_parse_gradient_stops(fz_context *ctx, xps_document *doc, char *base_uri, fz_xml *node,
	struct stop *stops, int maxcount)
{
	fz_colorspace *colorspace;
	float sample[FZ_MAX_COLORS];
	float rgb[3];
	int before, after;
	int count;
	int i;

	/* We may have to insert 2 extra stops when postprocessing */
	maxcount -= 2;

	count = 0;
	while (node && count < maxcount)
	{
		if (fz_xml_is_tag(node, "GradientStop"))
		{
			char *offset = fz_xml_att(node, "Offset");
			char *color = fz_xml_att(node, "Color");
			if (offset && color)
			{
				stops[count].offset = fz_atof(offset);
				stops[count].index = count;

				xps_parse_color(ctx, doc, base_uri, color, &colorspace, sample);

				fz_convert_color(ctx, fz_device_rgb(ctx), rgb, colorspace, sample + 1);

				stops[count].r = rgb[0];
				stops[count].g = rgb[1];
				stops[count].b = rgb[2];
				stops[count].a = sample[0];

				count ++;
			}
		}
		node = fz_xml_next(node);
	}

	if (count == 0)
	{
		fz_warn(ctx, "gradient brush has no gradient stops");
		stops[0].offset = 0;
		stops[0].r = 0;
		stops[0].g = 0;
		stops[0].b = 0;
		stops[0].a = 1;
		stops[1].offset = 1;
		stops[1].r = 1;
		stops[1].g = 1;
		stops[1].b = 1;
		stops[1].a = 1;
		return 2;
	}

	if (count == maxcount)
		fz_warn(ctx, "gradient brush exceeded maximum number of gradient stops");

	/* Postprocess to make sure the range of offsets is 0.0 to 1.0 */

	qsort(stops, count, sizeof(struct stop), cmp_stop);

	before = -1;
	after = -1;

	for (i = 0; i < count; i++)
	{
		if (stops[i].offset < 0)
			before = i;
		if (stops[i].offset > 1)
		{
			after = i;
			break;
		}
	}

	/* Remove all stops < 0 except the largest one */
	if (before > 0)
	{
		memmove(stops, stops + before, (count - before) * sizeof(struct stop));
		count -= before;
	}

	/* Remove all stops > 1 except the smallest one */
	if (after >= 0)
		count = after + 1;

	/* Expand single stop to 0 .. 1 */
	if (count == 1)
	{
		stops[1] = stops[0];
		stops[0].offset = 0;
		stops[1].offset = 1;
		return 2;
	}

	/* First stop < 0 -- interpolate value to 0 */
	if (stops[0].offset < 0)
	{
		float d = -stops[0].offset / (stops[1].offset - stops[0].offset);
		stops[0].offset = 0;
		stops[0].r = lerp(stops[0].r, stops[1].r, d);
		stops[0].g = lerp(stops[0].g, stops[1].g, d);
		stops[0].b = lerp(stops[0].b, stops[1].b, d);
		stops[0].a = lerp(stops[0].a, stops[1].a, d);
	}

	/* Last stop > 1 -- interpolate value to 1 */
	if (stops[count-1].offset > 1)
	{
		float d = (1 - stops[count-2].offset) / (stops[count-1].offset - stops[count-2].offset);
		stops[count-1].offset = 1;
		stops[count-1].r = lerp(stops[count-2].r, stops[count-1].r, d);
		stops[count-1].g = lerp(stops[count-2].g, stops[count-1].g, d);
		stops[count-1].b = lerp(stops[count-2].b, stops[count-1].b, d);
		stops[count-1].a = lerp(stops[count-2].a, stops[count-1].a, d);
	}

	/* First stop > 0 -- insert a duplicate at 0 */
	if (stops[0].offset > 0)
	{
		memmove(stops + 1, stops, count * sizeof(struct stop));
		stops[0] = stops[1];
		stops[0].offset = 0;
		count++;
	}

	/* Last stop < 1 -- insert a duplicate at 1 */
	if (stops[count-1].offset < 1)
	{
		stops[count] = stops[count-1];
		stops[count].offset = 1;
		count++;
	}

	return count;
}
Ejemplo n.º 21
0
int main(int argc, char **argv)
{
	char *filename = argc >= 2 ? argv[1] : "";
	pthread_t *thread = NULL;
	fz_locks_context locks;
	pthread_mutex_t mutex[FZ_LOCK_MAX];
	fz_context *ctx;
	fz_document *doc;
	int threads;
	int i;

	// Initialize FZ_LOCK_MAX number of non-recursive mutexes.

	for (i = 0; i < FZ_LOCK_MAX; i++)
	{
		if (pthread_mutex_init(&mutex[i], NULL) != 0)
			fail("pthread_mutex_init()");
	}

	// Initialize the locking structure with function pointers to
	// the locking functions and to the user data. In this case
	// the user data is a pointer to the array of mutexes so the
	// locking functions can find the relevant lock to change when
	// they are called. This way we avoid global variables.

	locks.user = mutex;
	locks.lock = lock_mutex;
	locks.unlock = unlock_mutex;

	// This is the main threads context function, so supply the
	// locking structure. This context will be used to parse all
	// the pages from the document.

	ctx = fz_new_context(NULL, &locks, FZ_STORE_UNLIMITED);

	// Register default file types.

	fz_register_document_handlers(ctx);

	// Open the PDF, XPS or CBZ document. Note, this binds doc to ctx.
	// You must only ever use doc with ctx - never a clone of it!

	doc = fz_open_document(ctx, filename);

	// Retrieve the number of pages, which translates to the
	// number of threads used for rendering pages.

	threads = fz_count_pages(ctx, doc);
	fprintf(stderr, "spawning %d threads, one per page...\n", threads);

	thread = malloc(threads * sizeof (pthread_t));

	for (i = 0; i < threads; i++)
	{
		fz_page *page;
		fz_rect bbox;
		fz_irect rbox;
		fz_display_list *list;
		fz_device *dev;
		fz_pixmap *pix;
		struct data *data;

		// Load the relevant page for each thread. Note, that this
		// cannot be done on the worker threads, as each use of doc
		// uses ctx, and only one thread can be using ctx at a time.

		page = fz_load_page(ctx, doc, i);

		// Compute the bounding box for each page.

		fz_bound_page(ctx, page, &bbox);

		// Create a display list that will hold the drawing
		// commands for the page. Once we have the display list
		// this can safely be used on any other thread as it is
		// not bound to a given context.

		list = fz_new_display_list(ctx, &bbox);

		// Run the loaded page through a display list device
		// to populate the page's display list.

		dev = fz_new_list_device(ctx, list);
		fz_run_page(ctx, page, dev, &fz_identity, NULL);
		fz_close_device(ctx, dev);
		fz_drop_device(ctx, dev);

		// The page is no longer needed, all drawing commands
		// are now in the display list.

		fz_drop_page(ctx, page);

		// Create a white pixmap using the correct dimensions.

		pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), fz_round_rect(&rbox, &bbox), 0);
		fz_clear_pixmap_with_value(ctx, pix, 0xff);

		// Populate the data structure to be sent to the
		// rendering thread for this page.

		data = malloc(sizeof (struct data));

		data->pagenumber = i + 1;
		data->ctx = ctx;
		data->list = list;
		data->bbox = bbox;
		data->pix = pix;

		// Create the thread and pass it the data structure.

		if (pthread_create(&thread[i], NULL, renderer, data) != 0)
			fail("pthread_create()");
	}

	// Now each thread is rendering pages, so wait for each thread
	// to complete its rendering.

	fprintf(stderr, "joining %d threads...\n", threads);
	for (i = threads - 1; i >= 0; i--)
	{
		char filename[42];
		struct data *data;

		if (pthread_join(thread[i], (void **) &data) != 0)
			fail("pthread_join");

		sprintf(filename, "out%04d.png", i);
		fprintf(stderr, "\tSaving %s...\n", filename);

		// Write the rendered image to a PNG file

		fz_save_pixmap_as_png(ctx, data->pix, filename);

		// Free the thread's pixmap and display list since
		// they were allocated by the main thread above.

		fz_drop_pixmap(ctx, data->pix);
		fz_drop_display_list(ctx, data->list);

		// Free the data structured passed back and forth
		// between the main thread and rendering thread.

		free(data);
	}

	fprintf(stderr, "finally!\n");
	fflush(NULL);

	free(thread);

	// Finally the document is closed and the main thread's
	// context is freed.

	fz_drop_document(ctx, doc);
	fz_drop_context(ctx);

	return 0;
}
Ejemplo n.º 22
0
static int make_fake_doc(pdfapp_t *app)
{
	fz_context *ctx = app->ctx;
	fz_matrix ctm = { 1, 0, 0, 1, 0, 0 };
	fz_rect bounds;
	pdf_page *newpage = NULL;
	pdf_document *pdf = NULL;
	fz_device *dev = NULL;
	fz_path *path = NULL;
	fz_stroke_state stroke = fz_default_stroke_state;
	float red[3] = { 1, 0, 0 };
	int i;

	fz_var(pdf);
	fz_var(dev);
	fz_var(newpage);

	fz_try(ctx)
	{
		pdf = pdf_create_document(ctx);
		app->doc = &pdf->super;
		bounds.x0 = 0;
		bounds.y0 = 0;
		bounds.x1 = app->winw;
		bounds.y1 = app->winh;

		newpage = pdf_create_page(ctx, pdf, bounds, 72, 0);

		dev = pdf_page_write(ctx, pdf, newpage);

		/* Now the page content */
		fz_begin_page(ctx, dev, &bounds, &ctm);

		path = fz_new_path(ctx);
		fz_moveto(ctx, path, 0, 0);
		fz_lineto(ctx, path, bounds.x1, bounds.y1);
		fz_moveto(ctx, path, 0, bounds.y1);
		fz_lineto(ctx, path, bounds.x1, 0);

		stroke.linewidth = fz_min(bounds.x1, bounds.y1)/4;

		fz_stroke_path(ctx, dev, path, &stroke, &ctm, fz_device_rgb(ctx), red, 1);

		fz_end_page(ctx, dev);

		fz_drop_device(ctx, dev);
		dev = NULL;

		/* Create enough copies of our blank(ish) page so that the
		 * page number is preserved if and when a subsequent load
		 * works. */
		for (i = 0; i < app->pagecount; i++)
			pdf_insert_page(ctx, pdf, newpage, INT_MAX);
	}
	fz_always(ctx)
	{
		fz_drop_path(ctx, path);
		pdf_drop_page(ctx, newpage);
		fz_drop_device(ctx, dev);
		dev = NULL;
	}
	fz_catch(ctx)
	{
		fz_rethrow(ctx);
	}

	return 0;
}
Ejemplo n.º 23
0
static void draw_list_mark(fz_context *ctx, fz_html *box, float page_top, float page_bot, fz_device *dev, const fz_matrix *ctm, int n)
{
    fz_font *font;
    fz_text *text;
    fz_matrix trm;
    fz_html_flow *line;
    float y, w;
    float color[3];
    const char *s;
    char buf[40];
    int c, g;

    fz_scale(&trm, box->em, -box->em);

    text = fz_new_text(ctx);

    line = find_list_mark_anchor(ctx, box);
    if (line)
    {
        y = line->y;
    }
    else
    {
        float h = fz_from_css_number_scale(box->style.line_height, box->em, box->em, box->em);
        float a = box->em * 0.8;
        float d = box->em * 0.2;
        if (a + d > h)
            h = a + d;
        y = box->y + a + (h - a - d) / 2;
    }

    if (y > page_bot || y < page_top)
        return;

    format_list_number(ctx, box->style.list_style_type, n, buf, sizeof buf);

    s = buf;
    w = 0;
    while (*s)
    {
        s += fz_chartorune(&c, s);
        g = fz_encode_character_with_fallback(ctx, box->style.font, c, UCDN_SCRIPT_LATIN, &font);
        w += fz_advance_glyph(ctx, font, g) * box->em;
    }

    s = buf;
    trm.e = box->x - w;
    trm.f = y;
    while (*s)
    {
        s += fz_chartorune(&c, s);
        g = fz_encode_character_with_fallback(ctx, box->style.font, c, UCDN_SCRIPT_LATIN, &font);
        fz_add_text(ctx, text, font, 0, &trm, g, c);
        trm.e += fz_advance_glyph(ctx, font, g) * box->em;
    }

    color[0] = box->style.color.r / 255.0f;
    color[1] = box->style.color.g / 255.0f;
    color[2] = box->style.color.b / 255.0f;

    fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), color, 1);

    fz_drop_text(ctx, text);
}
Ejemplo n.º 24
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);
	}
}
Ejemplo n.º 25
0
static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float page_bot, fz_device *dev, const fz_matrix *ctm)
{
    fz_font *font;
    fz_html_flow *node;
    fz_text *text;
    fz_matrix trm;
    const char *s;
    float color[3];
    int c, g;

    for (node = box->flow_head; node; node = node->next)
    {
        if (node->type == FLOW_IMAGE)
        {
            if (node->y >= page_bot || node->y + node->h <= page_top)
                continue;
        }
        else
        {
            if (node->y > page_bot || node->y < page_top)
                continue;
        }

        if (node->type == FLOW_WORD)
        {
            fz_scale(&trm, node->em, -node->em);

            color[0] = node->style->color.r / 255.0f;
            color[1] = node->style->color.g / 255.0f;
            color[2] = node->style->color.b / 255.0f;

            /* TODO: reuse text object if color is unchanged */
            text = fz_new_text(ctx);


            trm.e = node->x;
            trm.f = node->y;
            s = node->content.text;
            if (node->char_r2l)
            {
                float w = 0;
                const char *t = s;

                while (*t)
                {
                    t += fz_chartorune(&c, t);
                    if (node->mirror)
                        c = ucdn_mirror(c);
                    g = fz_encode_character_with_fallback(ctx, node->style->font, c, 0, &font);
                    w += fz_advance_glyph(ctx, font, g) * node->em;
                }

                trm.e += w;
                while (*s)
                {
                    s += fz_chartorune(&c, s);
                    if (node->mirror)
                        c = ucdn_mirror(c);
                    g = fz_encode_character_with_fallback(ctx, node->style->font, c, 0, &font);
                    trm.e -= fz_advance_glyph(ctx, font, g) * node->em;
                    if (node->style->visibility == V_VISIBLE)
                        fz_add_text(ctx, text, font, 0, &trm, g, c);
                }
                trm.e += w;
            }
            else
            {
                while (*s)
                {
                    s += fz_chartorune(&c, s);
                    g = fz_encode_character_with_fallback(ctx, node->style->font, c, 0, &font);
                    if (node->style->visibility == V_VISIBLE)
                        fz_add_text(ctx, text, font, 0, &trm, g, c);
                    trm.e += fz_advance_glyph(ctx, font, g) * node->em;
                }
            }

            if (text)
            {
                fz_fill_text(ctx, dev, text, ctm, fz_device_rgb(ctx), color, 1);
                fz_drop_text(ctx, text);
            }
        }
        else if (node->type == FLOW_IMAGE)
        {
            if (node->style->visibility == V_VISIBLE)
            {
                fz_matrix local_ctm = *ctm;
                fz_pre_translate(&local_ctm, node->x, node->y);
                fz_pre_scale(&local_ctm, node->w, node->h);
                fz_fill_image(ctx, dev, node->content.image, &local_ctm, 1);
            }
        }
    }
}
Ejemplo n.º 26
0
static void
fz_test_fill_image(fz_context *ctx, fz_device *dev_, fz_image *image, const fz_matrix *ctm, float alpha, const fz_color_params *color_params)
{
	fz_test_device *dev = (fz_test_device*)dev_;

	while (dev->resolved == 0) /* So we can break out */
	{
		fz_pixmap *pix;
		unsigned int count, i, k, h, sa, ss;
		unsigned char *s;
		fz_compressed_buffer *buffer;

		if (*dev->is_color || !image->colorspace || fz_colorspace_is_gray(ctx, image->colorspace))
			break;

		if ((dev->options & FZ_TEST_OPT_IMAGES) == 0)
		{
			/* Don't test every pixel. Upgrade us from "black and white" to "probably color" */
			if (*dev->is_color == 0)
				*dev->is_color = 1;
			dev->resolved = 1;
			if (dev->passthrough == NULL)
				fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
			break;
		}

		buffer = fz_compressed_image_buffer(ctx, image);
		if (buffer && image->bpc == 8)
		{
			fz_stream *stream = fz_open_compressed_buffer(ctx, buffer);
			count = (unsigned int)image->w * (unsigned int)image->h;
			if (image->colorspace == fz_device_rgb(ctx))
			{
				int threshold_u8 = dev->threshold * 255;
				for (i = 0; i < count; i++)
				{
					int r = fz_read_byte(ctx, stream);
					int g = fz_read_byte(ctx, stream);
					int b = fz_read_byte(ctx, stream);
					if (is_rgb_color_u8(threshold_u8, r, g, b))
					{
						*dev->is_color = 1;
						dev->resolved = 1;
						fz_drop_stream(ctx, stream);
						if (dev->passthrough == NULL)
							fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
						break;
					}
				}
			}
			else
			{
				fz_color_converter cc;
				unsigned int n = (unsigned int)image->n;

				fz_init_cached_color_converter(ctx, &cc, NULL, fz_device_rgb(ctx), image->colorspace, color_params);

				fz_try(ctx)
				{
					for (i = 0; i < count; i++)
					{
						float cs[FZ_MAX_COLORS];
						float ds[FZ_MAX_COLORS];

						for (k = 0; k < n; k++)
							cs[k] = fz_read_byte(ctx, stream) / 255.0f;

						cc.convert(ctx, &cc, ds, cs);

						if (is_rgb_color(dev->threshold, ds[0], ds[1], ds[2]))
						{
							*dev->is_color = 1;
							dev->resolved = 1;
							if (dev->passthrough == NULL)
							{
								fz_drop_stream(ctx, stream);
								fz_fin_cached_color_converter(ctx, &cc);
								fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
							}
							break;
						}
					}
				}
				fz_always(ctx)
					fz_fin_cached_color_converter(ctx, &cc);
				fz_catch(ctx)
					fz_rethrow(ctx);
			}
			fz_drop_stream(ctx, stream);
			break;
		}

		pix = fz_get_pixmap_from_image(ctx, image, NULL, NULL, 0, 0);
		if (pix == NULL) /* Should never happen really, but... */
			break;

		count = pix->w;
		h = pix->h;
		s = pix->samples;
		sa = pix->alpha;
		ss = pix->stride - pix->w * pix->n;

		if (pix->colorspace == fz_device_rgb(ctx))
		{
			int threshold_u8 = dev->threshold * 255;
			while (h--)
			{
				for (i = 0; i < count; i++)
				{
					if ((!sa || s[3] != 0) && is_rgb_color_u8(threshold_u8, s[0], s[1], s[2]))
					{
						*dev->is_color = 1;
						dev->resolved = 1;
						if (dev->passthrough == NULL)
						{
							fz_drop_pixmap(ctx, pix);
							fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
						}
						break;
					}
					s += 3 + sa;
				}
				s += ss;
			}
		}
		else
		{
			fz_color_converter cc;
			unsigned int n = (unsigned int)pix->n-1;

			fz_init_cached_color_converter(ctx, &cc, NULL, fz_device_rgb(ctx), pix->colorspace, color_params);

			fz_try(ctx)
			{
				while (h--)
				{
					for (i = 0; i < count; i++)
					{
						float cs[FZ_MAX_COLORS];
						float ds[FZ_MAX_COLORS];

						for (k = 0; k < n; k++)
							cs[k] = (*s++) / 255.0f;
						if (sa && *s++ == 0)
							continue;

						cc.convert(ctx, &cc, ds, cs);

						if (is_rgb_color(dev->threshold, ds[0], ds[1], ds[2]))
						{
							*dev->is_color = 1;
							dev->resolved = 1;
							if (dev->passthrough == NULL)
							{
								fz_fin_cached_color_converter(ctx, &cc);
								fz_drop_pixmap(ctx, pix);
								fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
							}
							break;
						}
					}
					s += ss;
				}
			}
			fz_always(ctx)
				fz_fin_cached_color_converter(ctx, &cc);
			fz_catch(ctx)
				fz_rethrow(ctx);
		}

		fz_drop_pixmap(ctx, pix);
		break;
	}
Ejemplo n.º 27
0
static void
fz_test_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha)
{
	fz_test_device *t = (fz_test_device*)dev;

	fz_pixmap *pix;
	unsigned int count, i, k;
	unsigned char *s;

	if (*t->is_color || !image->colorspace || image->colorspace == fz_device_gray(ctx))
		return;

	if (image->buffer && image->bpc == 8)
	{
		fz_stream *stream = fz_open_compressed_buffer(ctx, image->buffer);
		count = (unsigned int)image->w * (unsigned int)image->h;
		if (image->colorspace == fz_device_rgb(ctx))
		{
			int threshold_u8 = t->threshold * 255;
			for (i = 0; i < count; i++)
			{
				int r = fz_read_byte(ctx, stream);
				int g = fz_read_byte(ctx, stream);
				int b = fz_read_byte(ctx, stream);
				if (is_rgb_color_u8(threshold_u8, r, g, b))
				{
					*t->is_color = 1;
					dev->hints |= FZ_IGNORE_IMAGE;
					fz_drop_stream(ctx, stream);
					fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
					break;
				}
			}
		}
		else
		{
			fz_color_converter cc;
			unsigned int n = (unsigned int)image->n;

			fz_init_cached_color_converter(ctx, &cc, fz_device_rgb(ctx), image->colorspace);
			for (i = 0; i < count; i++)
			{
				float cs[FZ_MAX_COLORS];
				float ds[FZ_MAX_COLORS];

				for (k = 0; k < n; k++)
					cs[k] = fz_read_byte(ctx, stream) / 255.0f;

				cc.convert(ctx, &cc, ds, cs);

				if (is_rgb_color(t->threshold, ds[0], ds[1], ds[2]))
				{
					*t->is_color = 1;
					dev->hints |= FZ_IGNORE_IMAGE;
					break;
				}
			}
			fz_fin_cached_color_converter(ctx, &cc);
		}
		fz_drop_stream(ctx, stream);
		return;
	}

	pix = fz_new_pixmap_from_image(ctx, image, 0, 0);
	if (pix == NULL) /* Should never happen really, but... */
		return;

	count = (unsigned int)pix->w * (unsigned int)pix->h;
	s = pix->samples;

	if (pix->colorspace == fz_device_rgb(ctx))
	{
		int threshold_u8 = t->threshold * 255;
		for (i = 0; i < count; i++)
		{
			if (s[3] != 0 && is_rgb_color_u8(threshold_u8, s[0], s[1], s[2]))
			{
				*t->is_color = 1;
				dev->hints |= FZ_IGNORE_IMAGE;
				fz_drop_pixmap(ctx, pix);
				fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
				break;
			}
			s += 4;
		}
	}
	else
	{
		fz_color_converter cc;
		unsigned int n = (unsigned int)pix->n-1;

		fz_init_cached_color_converter(ctx, &cc, fz_device_rgb(ctx), pix->colorspace);
		for (i = 0; i < count; i++)
		{
			float cs[FZ_MAX_COLORS];
			float ds[FZ_MAX_COLORS];

			for (k = 0; k < n; k++)
				cs[k] = (*s++) / 255.0f;
			if (*s++ == 0)
				continue;

			cc.convert(ctx, &cc, ds, cs);

			if (is_rgb_color(t->threshold, ds[0], ds[1], ds[2]))
			{
				*t->is_color = 1;
				dev->hints |= FZ_IGNORE_IMAGE;
				fz_drop_pixmap(ctx, pix);
				fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
				break;
			}
		}
		fz_fin_cached_color_converter(ctx, &cc);
	}

	fz_drop_pixmap(ctx, pix);
}
Ejemplo n.º 28
0
static void
fz_test_fill_other_image(fz_context *ctx, fz_test_device *dev, fz_pixmap *pix, const fz_color_params *color_params)
{
	unsigned int count, i, k, h, sa, ss;
	unsigned char *s;

	count = pix->w;
	h = pix->h;
	s = pix->samples;
	sa = pix->alpha;
	ss = pix->stride - pix->w * pix->n;

	if (pix->colorspace == fz_device_rgb(ctx))
	{
		int threshold_u8 = dev->threshold * 255;
		while (h--)
		{
			for (i = 0; i < count; i++)
			{
				if ((!sa || s[3] != 0) && is_rgb_color_u8(threshold_u8, s[0], s[1], s[2]))
				{
					*dev->is_color = 1;
					dev->resolved = 1;
					if (dev->passthrough == NULL)
						fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
					break;
				}
				s += 3 + sa;
			}
			s += ss;
		}
	}
	else
	{
		fz_color_converter cc;
		unsigned int n = (unsigned int)pix->n-1;

		fz_init_cached_color_converter(ctx, &cc, NULL, fz_device_rgb(ctx), pix->colorspace, color_params);

		fz_try(ctx)
		{
			while (h--)
			{
				for (i = 0; i < count; i++)
				{
					float cs[FZ_MAX_COLORS];
					float ds[FZ_MAX_COLORS];

					for (k = 0; k < n; k++)
						cs[k] = (*s++) / 255.0f;
					if (sa && *s++ == 0)
						continue;

					cc.convert(ctx, &cc, ds, cs);

					if (is_rgb_color(dev->threshold, ds[0], ds[1], ds[2]))
					{
						*dev->is_color = 1;
						dev->resolved = 1;
						if (dev->passthrough == NULL)
							fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
						break;
					}
				}
				s += ss;
			}
		}
		fz_always(ctx)
			fz_fin_cached_color_converter(ctx, &cc);
		fz_catch(ctx)
			fz_rethrow(ctx);
	}
}
Ejemplo n.º 29
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;

		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);
	}
}
Ejemplo n.º 30
0
DrPage * DrPDFExtractor::ExtractPage(unsigned int pageno)
{
    fz_page * page = fz_load_page(m_doc, pageno);
    if (page == NULL) {
        return NULL;
    }

    DrPage * dpage = new DrPage;
    dpage->SetPageNo(pageno);
    
    std::list<DrChar *> charlist;
    std::list<DrPhrase *> phraselist;
    std::list<DrLine *> linelist;
    std::list<DrZone *> &zonelist = dpage->m_zonelist;
    
    
    fz_matrix transform;
    fz_rotate(&transform,0);
    fz_pre_scale(&transform, 1.0f, 1.0f);
    
    fz_rect bounds;
    fz_bound_page(m_doc, page, &bounds);
    fz_transform_rect(&bounds, &transform);
    fz_irect bbox;
    fz_round_rect(&bbox, &bounds);
    fz_matrix ttransform = transform;
    fz_pixmap *pix = fz_new_pixmap_with_bbox(m_ctx, fz_device_rgb(m_ctx), &bbox);
    fz_clear_pixmap_with_value(m_ctx, pix, 0xff);
    
    fz_device * dev = fz_new_draw_device(m_ctx,pix);
    fz_run_page(m_doc, page, dev, &transform, NULL);
    fz_free_device(dev);

	fz_text_sheet * sheet = fz_new_text_sheet(m_ctx);
	fz_text_page * tpage = fz_new_text_page(m_ctx);
    fz_device * cdev = fz_new_text_device(m_ctx, sheet, tpage);
    fz_run_page(m_doc, page, cdev, &ttransform, NULL);
    
    
    ExtractChars(charlist,tpage);
    fz_free_device(cdev);
    
	//    DrThumbnail * thumb = new DrThumbnail(m_ctx,pix,pageno);
	//   dpage->m_thumbnail = thumb;

    
    DrTextGrouper::TextGroup(phraselist, charlist);
    
    
    std::list<DrPhrase *>::iterator itphrase = phraselist.begin();
    while (itphrase != phraselist.end()) {
        if ((*itphrase)->IsSpacePhrase()) {
            delete *itphrase;
            itphrase = phraselist.erase(itphrase);
        }
        else itphrase++;
    }
    
    DrTextGrouper::TextGroup(linelist, phraselist);
    DrTextGrouper::TextGroup(zonelist, linelist);
    dpage->CalculatePageBox();
        //    fz_free_text_sheet(m_ctx, tsheet);
        //    fz_free_text_page(m_ctx, tpage);
    fz_free_page(m_doc, page);
    return dpage;
}