/* Default: color_transform = -1 (unset), l2factor = 0, jpegtables = NULL */ fz_stream * fz_open_dctd(fz_context *ctx, fz_stream *chain, int color_transform, int l2factor, fz_stream *jpegtables) { fz_dctd *state = NULL; fz_var(state); fz_try(ctx) { state = fz_malloc_struct(ctx, fz_dctd); state->ctx = ctx; state->chain = chain; state->jpegtables = jpegtables; state->curr_stm = chain; state->color_transform = color_transform; state->init = 0; state->l2factor = l2factor; state->cinfo.client_data = NULL; } fz_catch(ctx) { fz_free(ctx, state); fz_drop_stream(ctx, chain); fz_drop_stream(ctx, jpegtables); fz_rethrow(ctx); } return fz_new_stream(ctx, state, next_dctd, close_dctd); }
static void close_dctd(fz_context *ctx, void *state_) { fz_dctd *state = (fz_dctd *)state_; if (setjmp(state->jb)) { fz_warn(ctx, "jpeg error: %s", state->msg); goto skip; } /* We call jpeg_abort rather than the more usual * jpeg_finish_decompress here. This has the same effect, * but doesn't spew warnings if we didn't read enough data etc. */ if (state->init) jpeg_abort((j_common_ptr)&state->cinfo); skip: if (state->cinfo.src) state->curr_stm->rp = state->curr_stm->wp - state->cinfo.src->bytes_in_buffer; if (state->init) jpeg_destroy_decompress(&state->cinfo); fz_dct_mem_term(state); fz_free(ctx, state->scanline); fz_drop_stream(ctx, state->chain); fz_drop_stream(ctx, state->jpegtables); fz_free(ctx, state); }
/* * Build a chain of filters given filter names and param dicts. * If head is given, start filter chain with it. * Assume ownership of head. */ static fz_stream * build_filter_chain(fz_context *ctx, fz_stream *chain, pdf_document *doc, pdf_obj *fs, pdf_obj *ps, int num, int gen, fz_compression_params *params) { pdf_obj *f; pdf_obj *p; int i, n; fz_try(ctx) { n = pdf_array_len(ctx, fs); for (i = 0; i < n; i++) { fz_stream *chain2; f = pdf_array_get(ctx, fs, i); p = pdf_array_get(ctx, ps, i); chain2 = chain; chain = NULL; chain = build_filter(ctx, chain2, doc, f, p, num, gen, (i == n-1 ? params : NULL)); } } fz_catch(ctx) { fz_drop_stream(ctx, chain); fz_rethrow(ctx); } return chain; }
fz_buffer * pdf_load_raw_renumbered_stream(fz_context *ctx, pdf_document *doc, int num, int gen, int orig_num, int orig_gen) { fz_stream *stm; pdf_obj *dict; int len; fz_buffer *buf; if (num > 0 && num < pdf_xref_len(ctx, doc)) { pdf_xref_entry *entry = pdf_get_xref_entry(ctx, doc, num); if (entry->stm_buf) return fz_keep_buffer(ctx, entry->stm_buf); } dict = pdf_load_object(ctx, doc, num, gen); len = pdf_to_int(ctx, pdf_dict_get(ctx, dict, PDF_NAME_Length)); pdf_drop_obj(ctx, dict); stm = pdf_open_raw_renumbered_stream(ctx, doc, num, gen, orig_num, orig_gen); buf = fz_read_all(ctx, stm, len); fz_drop_stream(ctx, stm); return buf; }
static void fz_decode_tiff_flate(fz_context *ctx, struct tiff *tiff, fz_stream *chain, unsigned char *wp, int wlen) { fz_stream *stm = fz_open_flated(ctx, chain, 15); fz_read(ctx, stm, wp, wlen); fz_drop_stream(ctx, stm); }
xps_document * xps_open_document(fz_context *ctx, const char *filename) { char buf[2048]; fz_stream *file; char *p; xps_document *doc; if (strstr(filename, "/_rels/.rels") || strstr(filename, "\\_rels\\.rels")) { fz_strlcpy(buf, filename, sizeof buf); p = strstr(buf, "/_rels/.rels"); if (!p) p = strstr(buf, "\\_rels\\.rels"); *p = 0; return xps_open_document_with_directory(ctx, buf); } file = fz_open_file(ctx, filename); fz_try(ctx) doc = xps_open_document_with_stream(ctx, file); fz_always(ctx) fz_drop_stream(ctx, file); fz_catch(ctx) fz_rethrow_message(ctx, "cannot load document '%s'", filename); return doc; }
static void fz_process_mesh_type5(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_mesh_processor *painter) { fz_stream *stream = fz_open_compressed_buffer(ctx, shade->buffer); fz_vertex *buf = NULL; fz_vertex *ref = NULL; int first; int ncomp = painter->ncomp; int i, k; int vprow = shade->u.m.vprow; int bpcoord = shade->u.m.bpcoord; int bpcomp = shade->u.m.bpcomp; float x0 = shade->u.m.x0; float x1 = shade->u.m.x1; float y0 = shade->u.m.y0; float y1 = shade->u.m.y1; float *c0 = shade->u.m.c0; float *c1 = shade->u.m.c1; float x, y, c[FZ_MAX_COLORS]; fz_var(buf); fz_var(ref); fz_try(ctx) { ref = fz_malloc_array(ctx, vprow, sizeof(fz_vertex)); buf = fz_malloc_array(ctx, vprow, sizeof(fz_vertex)); first = 1; while (!fz_is_eof_bits(ctx, stream)) { for (i = 0; i < vprow; i++) { x = read_sample(ctx, stream, bpcoord, x0, x1); y = read_sample(ctx, stream, bpcoord, y0, y1); for (k = 0; k < ncomp; k++) c[k] = read_sample(ctx, stream, bpcomp, c0[k], c1[k]); fz_prepare_vertex(ctx, painter, &buf[i], ctm, x, y, c); } if (!first) for (i = 0; i < vprow - 1; i++) paint_quad(ctx, painter, &ref[i], &ref[i+1], &buf[i+1], &buf[i]); SWAP(ref,buf); first = 0; } } fz_always(ctx) { fz_free(ctx, ref); fz_free(ctx, buf); fz_drop_stream(ctx, stream); } fz_catch(ctx) { fz_rethrow(ctx); } }
static void close_lzwd(fz_context *ctx, void *state_) { fz_lzwd *lzw = (fz_lzwd *)state_; fz_sync_bits(ctx, lzw->chain); fz_drop_stream(ctx, lzw->chain); fz_free(ctx, lzw); }
static void close_leech(fz_context *ctx, void *state_) { fz_leech *state = (fz_leech *)state_; fz_drop_stream(ctx, state->chain); fz_free(ctx, state); }
static void close_sgilog16(fz_context *ctx, void *state_) { fz_sgilog16 *state = (fz_sgilog16 *)state_; fz_stream *chain = state->chain; fz_free(ctx, state->temp); fz_free(ctx, state); fz_drop_stream(ctx, chain); }
/* Default: early_change = 1 */ fz_stream * fz_open_lzwd(fz_context *ctx, fz_stream *chain, int early_change, int min_bits, int reverse_bits, int old_tiff) { fz_lzwd *lzw = NULL; int i; fz_var(lzw); fz_try(ctx) { if (min_bits > MAX_BITS) { fz_warn(ctx, "out of range initial lzw code size"); min_bits = MAX_BITS; } lzw = fz_malloc_struct(ctx, fz_lzwd); lzw->chain = chain; lzw->eod = 0; lzw->early_change = early_change; lzw->reverse_bits = reverse_bits; lzw->old_tiff = old_tiff; lzw->min_bits = min_bits; lzw->code_bits = lzw->min_bits; lzw->code = -1; lzw->next_code = LZW_FIRST(lzw); lzw->old_code = -1; lzw->rp = lzw->bp; lzw->wp = lzw->bp; for (i = 0; i < LZW_CLEAR(lzw); i++) { lzw->table[i].value = i; lzw->table[i].first_char = i; lzw->table[i].length = 1; lzw->table[i].prev = -1; } for (i = LZW_CLEAR(lzw); i < NUM_CODES; i++) { lzw->table[i].value = 0; lzw->table[i].first_char = 0; lzw->table[i].length = 0; lzw->table[i].prev = -1; } } fz_catch(ctx) { fz_free(ctx, lzw); fz_drop_stream(ctx, chain); fz_rethrow(ctx); } return fz_new_stream(ctx, lzw, next_lzwd, close_lzwd); }
void fz_drop_archive(fz_context *ctx, fz_archive *arch) { if (!arch) return; if (arch->drop_archive) arch->drop_archive(ctx, arch); fz_drop_stream(ctx, arch->file); fz_free(ctx, arch); }
static void fz_test_fill_image(fz_context *ctx, fz_device *dev_, fz_image *image, 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_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); fz_try(ctx) fz_test_fill_compressed_8bpc_image(ctx, dev, image, stream, color_params); fz_always(ctx) fz_drop_stream(ctx, stream); fz_catch(ctx) fz_rethrow(ctx); } else { fz_pixmap *pix = fz_get_pixmap_from_image(ctx, image, NULL, NULL, 0, 0); if (pix == NULL) /* Should never happen really, but... */ break; fz_try(ctx) fz_test_fill_other_image(ctx, dev, pix, color_params); fz_always(ctx) fz_drop_pixmap(ctx, pix); fz_catch(ctx) fz_rethrow(ctx); } break; } if (dev->passthrough) fz_fill_image(ctx, dev->passthrough, image, ctm, alpha, color_params); }
static void fz_decode_tiff_fax(fz_context *ctx, struct tiff *tiff, int comp, fz_stream *chain, unsigned char *wp, int wlen) { fz_stream *stm; int black_is_1 = tiff->photometric == 0; int k = comp == 4 ? -1 : 0; int encoded_byte_align = comp == 2; stm = fz_open_faxd(ctx, chain, k, 0, encoded_byte_align, tiff->imagewidth, tiff->imagelength, 0, black_is_1); fz_read(ctx, stm, wp, wlen); fz_drop_stream(ctx, stm); }
static fz_buffer * pdf_load_image_stream(fz_context *ctx, pdf_document *doc, int num, int gen, int orig_num, int orig_gen, fz_compression_params *params, int *truncated) { fz_stream *stm = NULL; pdf_obj *dict, *obj; int i, len, n; fz_buffer *buf; fz_var(buf); if (num > 0 && num < pdf_xref_len(ctx, doc)) { pdf_xref_entry *entry = pdf_get_xref_entry(ctx, doc, num); /* Return ref to existing buffer, but only if uncompressed, * or shortstoppable */ if (can_reuse_buffer(ctx, entry, params)) return fz_keep_buffer(ctx, entry->stm_buf); } dict = pdf_load_object(ctx, doc, num, gen); len = pdf_to_int(ctx, pdf_dict_get(ctx, dict, PDF_NAME_Length)); obj = pdf_dict_get(ctx, dict, PDF_NAME_Filter); len = pdf_guess_filter_length(len, pdf_to_name(ctx, obj)); n = pdf_array_len(ctx, obj); for (i = 0; i < n; i++) len = pdf_guess_filter_length(len, pdf_to_name(ctx, pdf_array_get(ctx, obj, i))); pdf_drop_obj(ctx, dict); stm = pdf_open_image_stream(ctx, doc, num, gen, orig_num, orig_gen, params); fz_try(ctx) { if (truncated) buf = fz_read_best(ctx, stm, len, truncated); else buf = fz_read_all(ctx, stm, len); } fz_always(ctx) { fz_drop_stream(ctx, stm); } fz_catch(ctx) { fz_rethrow_message(ctx, "cannot read raw stream (%d %d R)", num, gen); } return buf; }
static void fz_decode_tiff_jpeg(fz_context *ctx, struct tiff *tiff, fz_stream *chain, unsigned char *wp, int wlen) { fz_stream *stm; fz_stream *jpegtables = NULL; int color_transform = -1; /* unset */ if (tiff->jpegtables && (int)tiff->jpegtableslen > 0) jpegtables = fz_open_memory(ctx, tiff->jpegtables, (int)tiff->jpegtableslen); if (tiff->photometric == 2 /* RGB */ || tiff->photometric == 3 /* RGBPal */) color_transform = 0; stm = fz_open_dctd(ctx, chain, color_transform, 0, jpegtables); fz_read(ctx, stm, wp, wlen); fz_drop_stream(ctx, stm); }
static fz_document * svg_open_document(fz_context *ctx, const char *filename) { fz_stream *file; fz_document *doc; file = fz_open_file(ctx, filename); fz_try(ctx) doc = svg_open_document_with_stream(ctx, file); fz_always(ctx) fz_drop_stream(ctx, file); fz_catch(ctx) fz_rethrow(ctx); return doc; }
fz_archive * fz_open_archive(fz_context *ctx, const char *filename) { fz_stream *file; fz_archive *arch = NULL; file = fz_open_file(ctx, filename); fz_try(ctx) arch = fz_open_archive_with_stream(ctx, file); fz_always(ctx) fz_drop_stream(ctx, file); fz_catch(ctx) fz_rethrow(ctx); return arch; }
static img_document * img_open_document(fz_context *ctx, const char *filename) { fz_stream *stm; img_document *doc; stm = fz_open_file(ctx, filename); fz_try(ctx) doc = img_open_document_with_stream(ctx, stm); fz_always(ctx) fz_drop_stream(ctx, stm); fz_catch(ctx) fz_rethrow(ctx); return doc; }
fz_stream * fz_open_leecher(fz_context *ctx, fz_stream *chain, fz_buffer *buffer) { fz_leech *state = NULL; fz_var(state); fz_try(ctx) { state = fz_malloc_struct(ctx, fz_leech); state->chain = chain; state->buffer = buffer; } fz_catch(ctx) { fz_free(ctx, state); fz_drop_stream(ctx, chain); fz_rethrow(ctx); } return fz_new_stream(ctx, state, next_leech, close_leech); }
/* * Construct a filter to decode a stream, constraining * to stream length and decrypting. */ static fz_stream * pdf_open_filter(fz_context *ctx, pdf_document *doc, fz_stream *chain, pdf_obj *stmobj, int num, fz_off_t offset, fz_compression_params *imparams) { pdf_obj *filters; pdf_obj *params; int orig_num, orig_gen; filters = pdf_dict_geta(ctx, stmobj, PDF_NAME_Filter, PDF_NAME_F); params = pdf_dict_geta(ctx, stmobj, PDF_NAME_DecodeParms, PDF_NAME_DP); chain = pdf_open_raw_filter(ctx, chain, doc, stmobj, num, &orig_num, &orig_gen, offset); fz_var(chain); fz_try(ctx) { if (pdf_is_name(ctx, filters)) { fz_stream *chain2 = chain; chain = NULL; chain = build_filter(ctx, chain2, doc, filters, params, orig_num, orig_gen, imparams); } else if (pdf_array_len(ctx, filters) > 0) { fz_stream *chain2 = chain; chain = NULL; chain = build_filter_chain(ctx, chain2, doc, filters, params, orig_num, orig_gen, imparams); } } fz_catch(ctx) { fz_drop_stream(ctx, chain); fz_rethrow(ctx); } return chain; }
fz_buffer * fz_read_file(fz_context *ctx, const char *filename) { fz_stream *stm; fz_buffer *buf = NULL; fz_var(buf); stm = fz_open_file(ctx, filename); fz_try(ctx) { buf = fz_read_all(ctx, stm, 0); } fz_always(ctx) { fz_drop_stream(ctx, stm); } fz_catch(ctx) { fz_rethrow(ctx); } return buf; }
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); }
fz_pixmap * fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_image *image, int indexed, int l2factor) { fz_pixmap *tile = NULL; int stride, len, i; unsigned char *samples = NULL; int f = 1<<l2factor; int w = (image->w + f-1) >> l2factor; int h = (image->h + f-1) >> l2factor; fz_var(tile); fz_var(samples); fz_try(ctx) { tile = fz_new_pixmap(ctx, image->colorspace, w, h); tile->interpolate = image->interpolate; stride = (w * image->n * image->bpc + 7) / 8; samples = fz_malloc_array(ctx, h, stride); len = fz_read(ctx, stm, samples, h * stride); /* Pad truncated images */ if (len < stride * h) { fz_warn(ctx, "padding truncated image"); memset(samples + len, 0, stride * h - len); } /* Invert 1-bit image masks */ if (image->imagemask) { /* 0=opaque and 1=transparent so we need to invert */ unsigned char *p = samples; len = h * stride; for (i = 0; i < len; i++) p[i] = ~p[i]; } fz_unpack_tile(ctx, tile, samples, image->n, image->bpc, stride, indexed); fz_free(ctx, samples); samples = NULL; /* color keyed transparency */ if (image->usecolorkey && !image->mask) fz_mask_color_key(tile, image->n, image->colorkey); if (indexed) { fz_pixmap *conv; fz_decode_indexed_tile(ctx, tile, image->decode, (1 << image->bpc) - 1); conv = fz_expand_indexed_pixmap(ctx, tile); fz_drop_pixmap(ctx, tile); tile = conv; } else { fz_decode_tile(ctx, tile, image->decode); } /* pre-blended matte color */ if (image->usecolorkey && image->mask) fz_unblend_masked_tile(ctx, tile, image); } fz_always(ctx) { fz_drop_stream(ctx, stm); } fz_catch(ctx) { if (tile) fz_drop_pixmap(ctx, tile); fz_free(ctx, samples); fz_rethrow(ctx); } return tile; }
int main(int argc, char **argv) { fz_context *ctx; fz_stream *fi; pdf_cmap *cmap; int k, m, n, i; struct cidrange *r; if (argc != 2) { fprintf(stderr, "usage: cmapclean input.cmap\n"); return 1; } ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); if (!ctx) { fprintf(stderr, "cannot initialise context\n"); return 1; } fi = fz_open_file(ctx, argv[1]); cmap = pdf_load_cmap(ctx, fi); fz_drop_stream(ctx, fi); printf("begincmap\n"); printf("/CMapName /%s def\n", cmap->cmap_name); printf("/WMode %d def\n", cmap->wmode); if (cmap->usecmap_name[0]) printf("/%s usecmap\n", cmap->usecmap_name); if (cmap->codespace_len) { printf("begincodespacerange\n"); for (k = 0; k < cmap->codespace_len; k++) { if (cmap->codespace[k].n == 1) printf("<%02x> <%02x>\n", cmap->codespace[k].low, cmap->codespace[k].high); else if (cmap->codespace[k].n == 2) printf("<%04x> <%04x>\n", cmap->codespace[k].low, cmap->codespace[k].high); else if (cmap->codespace[k].n == 3) printf("<%06x> <%06x>\n", cmap->codespace[k].low, cmap->codespace[k].high); else if (cmap->codespace[k].n == 4) printf("<%08x> <%08x>\n", cmap->codespace[k].low, cmap->codespace[k].high); else printf("<%x> <%x>\n", cmap->codespace[k].low, cmap->codespace[k].high); } printf("endcodespacerange\n"); } n = cmap->rlen + cmap->xlen; r = fz_malloc(ctx, n * sizeof *r); i = 0; for (k = 0; k < cmap->rlen; k++) { r[i].lo = cmap->ranges[k].low; r[i].hi = cmap->ranges[k].high; r[i].v = cmap->ranges[k].out; ++i; } for (k = 0; k < cmap->xlen; k++) { r[i].lo = cmap->xranges[k].low; r[i].hi = cmap->xranges[k].high; r[i].v = cmap->xranges[k].out; ++i; } qsort(r, n, sizeof *r, cmpcidrange); if (n) { printf("begincidchar\n"); for (i = 0; i < n; ++i) { for (k = r[i].lo, m = r[i].v; k <= r[i].hi; ++k, ++m) { pc(k); printf("%u\n", m); } } printf("endcidchar\n"); } #if 0 if (cmap->mlen > 0) { printf("beginbfchar\n"); for (k = 0; k < cmap->mlen; k++) { pc(cmap->mranges[k].low); printf("<"); for (m = 0; m < cmap->mranges[k].len; ++m) printf("%04x", cmap->mranges[k].out[m]); printf(">\n"); } printf("endbfchar\n"); } #endif printf("endcmap\n"); fz_drop_context(ctx); return 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; }
int main(int argc, char **argv) { pdf_cmap *cmap; fz_stream *fi; FILE *fo; char name[256]; char *realname; int i, k, m; fz_context *ctx; if (argc < 3) { fprintf(stderr, "usage: cmapdump output.c lots of cmap files\n"); return 1; } ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); if (!ctx) { fprintf(stderr, "cannot initialise context\n"); return 1; } #undef fopen fo = fopen(argv[1], "wb"); if (!fo) { fprintf(stderr, "cmapdump: could not open output file '%s'\n", argv[1]); return 1; } fprintf(fo, "/* This is an automatically generated file. Do not edit. */\n"); for (i = 2; i < argc; i++) { realname = strrchr(argv[i], '/'); if (!realname) realname = strrchr(argv[i], '\\'); if (realname) realname ++; else realname = argv[i]; /* ignore VCS folders (such as .svn) */ if (*realname == '.') continue; if (strlen(realname) > (sizeof name - 1)) { fprintf(stderr, "cmapdump: file name too long\n"); if (fclose(fo)) { fprintf(stderr, "cmapdump: could not close output file '%s'\n", argv[1]); return 1; } return 1; } strcpy(name, realname); clean(name); fi = fz_open_file(ctx, argv[i]); cmap = pdf_load_cmap(ctx, fi); fz_drop_stream(ctx, fi); fprintf(fo, "\n/* %s */\n\n", cmap->cmap_name); if (cmap->rlen) { fprintf(fo, "static const pdf_range cmap_%s_ranges[] = {", name); for (k = 0; k < cmap->rlen; k++) { if (k % 4 == 0) fprintf(fo, "\n"); fprintf(fo, "{%uu,%uu,%uu},", cmap->ranges[k].low, cmap->ranges[k].high, cmap->ranges[k].out); } fprintf(fo, "\n};\n\n"); } if (cmap->xlen) { fprintf(fo, "static const pdf_xrange cmap_%s_xranges[] = {", name); for (k = 0; k < cmap->xlen; k++) { if (k % 4 == 0) fprintf(fo, "\n"); fprintf(fo, "{%uu,%uu,%uu},", cmap->xranges[k].low, cmap->xranges[k].high, cmap->xranges[k].out); } fprintf(fo, "\n};\n\n"); } if (cmap->mlen > 0) { fprintf(fo, "static const pdf_mrange cmap_%s_mranges[] = {", name); for (k = 0; k < cmap->mlen; k++) { fprintf(fo, "\n{%uu,%uu,{", cmap->mranges[k].low, cmap->mranges[k].len); for (m = 0; m < PDF_MRANGE_CAP; ++m) fprintf(fo, "%uu,", cmap->mranges[k].out[m]); fprintf(fo, "}},"); } fprintf(fo, "\n};\n\n"); } fprintf(fo, "static pdf_cmap cmap_%s = {\n", name); fprintf(fo, "\t{-1, pdf_drop_cmap_imp}, "); fprintf(fo, "\"%s\", ", cmap->cmap_name); fprintf(fo, "\"%s\", 0, ", cmap->usecmap_name); fprintf(fo, "%u, ", cmap->wmode); fprintf(fo, "%u,\n\t{ ", cmap->codespace_len); if (cmap->codespace_len == 0) { fprintf(fo, "{0,0,0},"); } for (k = 0; k < cmap->codespace_len; k++) { fprintf(fo, "{%u,%uu,%uu},", cmap->codespace[k].n, cmap->codespace[k].low, cmap->codespace[k].high); } fprintf(fo, " },\n"); if (cmap->rlen) fprintf(fo, "\t%u, %u, (pdf_range*) cmap_%s_ranges,\n", cmap->rlen, cmap->rlen, name); else fprintf(fo, "\t0, 0, NULL,\n"); if (cmap->xlen) fprintf(fo, "\t%u, %u, (pdf_xrange*) cmap_%s_xranges,\n", cmap->xlen, cmap->xlen, name); else fprintf(fo, "\t0, 0, NULL,\n"); if (cmap->mlen) fprintf(fo, "\t%u, %u, (pdf_mrange*) cmap_%s_mranges,\n", cmap->mlen, cmap->mlen, name); else fprintf(fo, "\t0, 0, NULL,\n"); fprintf(fo, "};\n"); if (getenv("verbose")) printf("\t{\"%s\",&cmap_%s},\n", cmap->cmap_name, name); pdf_drop_cmap(ctx, cmap); } if (fclose(fo)) { fprintf(stderr, "cmapdump: could not close output file '%s'\n", argv[1]); return 1; } fz_drop_context(ctx); return 0; }
static void fz_decode_tiff_uncompressed(fz_context *ctx, struct tiff *tiff, fz_stream *stm, unsigned char *wp, int wlen) { fz_read(ctx, stm, wp, wlen); fz_drop_stream(ctx, stm); }
/* dest points to the new pages content-streams-dict, src is a reference to one source content-stream */ int copy_content_stream_of_page(fz_context *dest_ctx, pdf_obj *dest, fz_context *src_ctx, pdf_obj *src, struct put_info *info, struct pos_info *pos) { if(!pdf_is_array(dest_ctx, dest) && !pdf_is_indirect(src_ctx, src)) return(-1); /* translation: 1 0 0 1 diff_x diff_y scale: scale 0 0 scale 0 0 rotation: cos sin -sin cos 0 0 ------------------------------------------------- rotation 0: 1 0 0 1 0 0 rotation 90: 0 1 -1 0 0 0 rotation 180: -1 0 0 -1 0 0 rotation 270: 0 -1 1 0 0 0 */ fz_buffer *buffer = fz_new_buffer(dest_ctx, 1024); fz_output *output = fz_new_output_with_buffer(dest_ctx, buffer); fz_printf(dest_ctx, output, "q\n"); /* set the outer clip region */ fz_printf(dest_ctx, output, "%f %f %f %f re W n\n", pos->outer_clip_x, pos->outer_clip_y, pos->outer_clip_width, pos->outer_clip_height); /* position the page correctly */ if(pos->rotate == 0) { fz_printf(dest_ctx, output, "1 0 0 1 %f %f cm\n", pos->x + pos->content_translate_x, pos->y + pos->content_translate_y); } else if(pos->rotate == 90) { fz_printf(dest_ctx, output, "0 1 -1 0 %f %f cm\n", pos->x + pos->width, pos->y); } else if(pos->rotate == 180) { fz_printf(dest_ctx, output, "-1 0 0 -1 %f %f cm\n", pos->width + pos->x - pos->content_translate_x, pos->height + pos->y - pos->content_translate_y); } else if(pos->rotate == 270) { fz_printf(dest_ctx, output, "0 -1 1 0 %f %f cm\n", pos->x, pos->y + pos->height); } if(pos->bleed_clip_x != 0.0 || pos->bleed_clip_y != 0.0 || pos->bleed_clip_width != 0.0 || pos->bleed_clip_height != 0.0) { fz_printf(dest_ctx, output, "%f %f %f %f re W n\n", pos->bleed_clip_x, pos->bleed_clip_y, pos->bleed_clip_width, pos->bleed_clip_height); } int src_num = pdf_to_num(src_ctx, src); int src_gen = pdf_to_gen(src_ctx, src); fz_stream *input = pdf_open_stream(src_ctx, info->src_doc, src_num, src_gen); rename_res_in_content_stream(src_ctx, input, dest_ctx, output, info->rename_dict); fz_printf(dest_ctx, output, "Q"); fz_drop_output(dest_ctx, output); fz_drop_stream(dest_ctx, input); int new_num = pdf_create_object(dest_ctx, info->dest_doc); pdf_obj *new_ref = pdf_new_indirect(dest_ctx, info->dest_doc, new_num, 0); /* each stream has a dict containing at least its length... */ pdf_obj *stream_info_dict = pdf_new_dict(dest_ctx, info->dest_doc, 1); pdf_dict_puts_drop(dest_ctx, stream_info_dict, "Length", pdf_new_int(dest_ctx, info->dest_doc, buffer->len)); pdf_update_object(dest_ctx, info->dest_doc, new_num, stream_info_dict); pdf_drop_obj(dest_ctx, stream_info_dict); pdf_update_stream(dest_ctx, info->dest_doc, new_ref, buffer, 0); fz_drop_buffer(dest_ctx, buffer); pdf_array_push(dest_ctx, dest, new_ref); pdf_drop_obj(dest_ctx, new_ref); return(0); }
static unsigned char * gif_read_tbid(fz_context *ctx, struct info *info, unsigned char *dest, unsigned char *p, unsigned char *end) { fz_stream *stm, *lzwstm = NULL; unsigned int mincodesize, y; fz_buffer *compressed = NULL, *uncompressed = NULL; const unsigned char *ct; unsigned char *sp; if (end - p < 1) fz_throw(ctx, FZ_ERROR_GENERIC, "premature end in table based image data in gif image"); mincodesize = *p; fz_var(compressed); fz_var(lzwstm); fz_var(uncompressed); fz_try(ctx) { compressed = fz_new_buffer(ctx, 0); p = gif_read_subblocks(ctx, info, p + 1, end, compressed); stm = fz_open_buffer(ctx, compressed); lzwstm = fz_open_lzwd(ctx, stm, 0, mincodesize + 1, 1, 0); uncompressed = fz_read_all(ctx, lzwstm, info->width * info->height); sp = uncompressed->data; if (info->has_lct) ct = info->lct; else if (info->has_gct) ct = info->gct; else ct = dct; if (info->image_interlaced) { for (y = 0; y < info->image_height; y += 8, sp += info->image_width) gif_read_line(ctx, info, dest, ct, y, sp); for (y = 4; y < info->image_height; y += 8, sp += info->image_width) gif_read_line(ctx, info, dest, ct, y, sp); for (y = 2; y < info->image_height; y += 4, sp += info->image_width) gif_read_line(ctx, info, dest, ct, y, sp); for (y = 1; y < info->image_height; y += 2, sp += info->image_width) gif_read_line(ctx, info, dest, ct, y, sp); } else for (y = 0; y < info->image_height; y++, sp += info->image_width) gif_read_line(ctx, info, dest, ct, y, sp); } fz_always(ctx) { fz_drop_buffer(ctx, uncompressed); fz_drop_buffer(ctx, compressed); fz_drop_stream(ctx, lzwstm); } fz_catch(ctx) { fz_rethrow(ctx); } return p; }