diff options
Diffstat (limited to 'pdf/pdf_stream.c')
-rw-r--r-- | pdf/pdf_stream.c | 270 |
1 files changed, 187 insertions, 83 deletions
diff --git a/pdf/pdf_stream.c b/pdf/pdf_stream.c index c66e703e..84f966ec 100644 --- a/pdf/pdf_stream.c +++ b/pdf/pdf_stream.c @@ -1,5 +1,5 @@ -#include "fitz.h" -#include "mupdf.h" +#include "fitz-internal.h" +#include "mupdf-internal.h" /* * Check if an object is a stream or not. @@ -20,24 +20,24 @@ pdf_is_stream(pdf_document *xref, int num, int gen) * Scan stream dictionary for an explicit /Crypt filter */ static int -pdf_stream_has_crypt(fz_context *ctx, fz_obj *stm) +pdf_stream_has_crypt(fz_context *ctx, pdf_obj *stm) { - fz_obj *filters; - fz_obj *obj; + pdf_obj *filters; + pdf_obj *obj; int i; - filters = fz_dict_getsa(stm, "Filter", "F"); + filters = pdf_dict_getsa(stm, "Filter", "F"); if (filters) { - if (!strcmp(fz_to_name(filters), "Crypt")) + if (!strcmp(pdf_to_name(filters), "Crypt")) return 1; - if (fz_is_array(filters)) + if (pdf_is_array(filters)) { - int n = fz_array_len(filters); + int n = pdf_array_len(filters); for (i = 0; i < n; i++) { - obj = fz_array_get(filters, i); - if (!strcmp(fz_to_name(obj), "Crypt")) + obj = pdf_array_get(filters, i); + if (!strcmp(pdf_to_name(obj), "Crypt")) return 1; } } @@ -49,15 +49,15 @@ pdf_stream_has_crypt(fz_context *ctx, fz_obj *stm) * Create a filter given a name and param dictionary. */ static fz_stream * -build_filter(fz_stream *chain, pdf_document * xref, fz_obj * f, fz_obj * p, int num, int gen) +build_filter(fz_stream *chain, pdf_document * xref, pdf_obj * f, pdf_obj * p, int num, int gen, pdf_image_params *params) { fz_context *ctx = chain->ctx; - char *s = fz_to_name(f); + char *s = pdf_to_name(f); - int predictor = fz_to_int(fz_dict_gets(p, "Predictor")); - int columns = fz_to_int(fz_dict_gets(p, "Columns")); - int colors = fz_to_int(fz_dict_gets(p, "Colors")); - int bpc = fz_to_int(fz_dict_gets(p, "BitsPerComponent")); + int predictor = pdf_to_int(pdf_dict_gets(p, "Predictor")); + int columns = pdf_to_int(pdf_dict_gets(p, "Columns")); + int colors = pdf_to_int(pdf_dict_gets(p, "Colors")); + int bpc = pdf_to_int(pdf_dict_gets(p, "BitsPerComponent")); if (predictor == 0) predictor = 1; if (columns == 0) columns = 1; @@ -72,34 +72,71 @@ build_filter(fz_stream *chain, pdf_document * xref, fz_obj * f, fz_obj * p, int else if (!strcmp(s, "CCITTFaxDecode") || !strcmp(s, "CCF")) { - fz_obj *k = fz_dict_gets(p, "K"); - fz_obj *eol = fz_dict_gets(p, "EndOfLine"); - fz_obj *eba = fz_dict_gets(p, "EncodedByteAlign"); - fz_obj *columns = fz_dict_gets(p, "Columns"); - fz_obj *rows = fz_dict_gets(p, "Rows"); - fz_obj *eob = fz_dict_gets(p, "EndOfBlock"); - fz_obj *bi1 = fz_dict_gets(p, "BlackIs1"); + pdf_obj *k = pdf_dict_gets(p, "K"); + pdf_obj *eol = pdf_dict_gets(p, "EndOfLine"); + pdf_obj *eba = pdf_dict_gets(p, "EncodedByteAlign"); + pdf_obj *columns = pdf_dict_gets(p, "Columns"); + pdf_obj *rows = pdf_dict_gets(p, "Rows"); + pdf_obj *eob = pdf_dict_gets(p, "EndOfBlock"); + pdf_obj *bi1 = pdf_dict_gets(p, "BlackIs1"); + if (params) + { + /* We will shortstop here */ + params->type = PDF_IMAGE_FAX; + params->u.fax.k = (k ? pdf_to_int(k) : 0); + params->u.fax.eol = (eol ? pdf_to_bool(eol) : 0); + params->u.fax.eba = (eba ? pdf_to_bool(eba) : 0); + params->u.fax.columns = (columns ? pdf_to_int(columns) : 1728); + params->u.fax.rows = (rows ? pdf_to_int(rows) : 0); + params->u.fax.eob = (eob ? pdf_to_bool(eob) : 1); + params->u.fax.bi1 = (bi1 ? pdf_to_bool(bi1) : 0); + return chain; + } return fz_open_faxd(chain, - k ? fz_to_int(k) : 0, - eol ? fz_to_bool(eol) : 0, - eba ? fz_to_bool(eba) : 0, - columns ? fz_to_int(columns) : 1728, - rows ? fz_to_int(rows) : 0, - eob ? fz_to_bool(eob) : 1, - bi1 ? fz_to_bool(bi1) : 0); + k ? pdf_to_int(k) : 0, + eol ? pdf_to_bool(eol) : 0, + eba ? pdf_to_bool(eba) : 0, + columns ? pdf_to_int(columns) : 1728, + rows ? pdf_to_int(rows) : 0, + eob ? pdf_to_bool(eob) : 1, + bi1 ? pdf_to_bool(bi1) : 0); } else if (!strcmp(s, "DCTDecode") || !strcmp(s, "DCT")) { - fz_obj *ct = fz_dict_gets(p, "ColorTransform"); - return fz_open_dctd(chain, ct ? fz_to_int(ct) : -1); + pdf_obj *ct = pdf_dict_gets(p, "ColorTransform"); + if (params) + { + /* We will shortstop here */ + params->type = PDF_IMAGE_JPEG; + params->u.jpeg.ct = (ct ? pdf_to_int(ct) : -1); + return chain; + } + return fz_open_dctd(chain, ct ? pdf_to_int(ct) : -1); } else if (!strcmp(s, "RunLengthDecode") || !strcmp(s, "RL")) + { + if (params) + { + /* We will shortstop here */ + params->type = PDF_IMAGE_RLD; + return chain; + } return fz_open_rld(chain); - + } else if (!strcmp(s, "FlateDecode") || !strcmp(s, "Fl")) { + if (params) + { + /* We will shortstop here */ + params->type = PDF_IMAGE_FLATE; + params->u.flate.predictor = predictor; + params->u.flate.columns = columns; + params->u.flate.colors = colors; + params->u.flate.bpc = bpc; + return chain; + } chain = fz_open_flated(chain); if (predictor > 1) chain = fz_open_predict(chain, predictor, columns, colors, bpc); @@ -108,8 +145,19 @@ build_filter(fz_stream *chain, pdf_document * xref, fz_obj * f, fz_obj * p, int else if (!strcmp(s, "LZWDecode") || !strcmp(s, "LZW")) { - fz_obj *ec = fz_dict_gets(p, "EarlyChange"); - chain = fz_open_lzwd(chain, ec ? fz_to_int(ec) : 1); + pdf_obj *ec = pdf_dict_gets(p, "EarlyChange"); + if (params) + { + /* We will shortstop here */ + params->type = PDF_IMAGE_LZW; + params->u.lzw.predictor = predictor; + params->u.lzw.columns = columns; + params->u.lzw.colors = colors; + params->u.lzw.bpc = bpc; + params->u.lzw.ec = (ec ? pdf_to_int(ec) : 1); + return chain; + } + chain = fz_open_lzwd(chain, ec ? pdf_to_int(ec) : 1); if (predictor > 1) chain = fz_open_predict(chain, predictor, columns, colors, bpc); return chain; @@ -118,9 +166,9 @@ build_filter(fz_stream *chain, pdf_document * xref, fz_obj * f, fz_obj * p, int else if (!strcmp(s, "JBIG2Decode")) { fz_buffer *globals = NULL; - fz_obj *obj = fz_dict_gets(p, "JBIG2Globals"); + pdf_obj *obj = pdf_dict_gets(p, "JBIG2Globals"); if (obj) - globals = pdf_load_stream(xref, fz_to_num(obj), fz_to_gen(obj)); + globals = pdf_load_stream(xref, pdf_to_num(obj), pdf_to_gen(obj)); /* fz_open_jbig2d takes possession of globals */ return fz_open_jbig2d(chain, globals); } @@ -130,7 +178,7 @@ build_filter(fz_stream *chain, pdf_document * xref, fz_obj * f, fz_obj * p, int else if (!strcmp(s, "Crypt")) { - fz_obj *name; + pdf_obj *name; if (!xref->crypt) { @@ -138,9 +186,9 @@ build_filter(fz_stream *chain, pdf_document * xref, fz_obj * f, fz_obj * p, int return chain; } - name = fz_dict_gets(p, "Name"); - if (fz_is_name(name)) - return pdf_open_crypt_with_filter(chain, xref->crypt, fz_to_name(name), num, gen); + name = pdf_dict_gets(p, "Name"); + if (pdf_is_name(name)) + return pdf_open_crypt_with_filter(chain, xref->crypt, pdf_to_name(name), num, gen); return chain; } @@ -155,18 +203,18 @@ build_filter(fz_stream *chain, pdf_document * xref, fz_obj * f, fz_obj * p, int * Assume ownership of head. */ static fz_stream * -build_filter_chain(fz_stream *chain, pdf_document *xref, fz_obj *fs, fz_obj *ps, int num, int gen) +build_filter_chain(fz_stream *chain, pdf_document *xref, pdf_obj *fs, pdf_obj *ps, int num, int gen, pdf_image_params *params) { - fz_obj *f; - fz_obj *p; + pdf_obj *f; + pdf_obj *p; int i, n; - n = fz_array_len(fs); + n = pdf_array_len(fs); for (i = 0; i < n; i++) { - f = fz_array_get(fs, i); - p = fz_array_get(ps, i); - chain = build_filter(chain, xref, f, p, num, gen); + f = pdf_array_get(fs, i); + p = pdf_array_get(ps, i); + chain = build_filter(chain, xref, f, p, num, gen, (i == n-1 ? params : NULL)); } return chain; @@ -178,7 +226,7 @@ build_filter_chain(fz_stream *chain, pdf_document *xref, fz_obj *fs, fz_obj *ps, * stream length, followed by a decryption filter. */ static fz_stream * -pdf_open_raw_filter(fz_stream *chain, pdf_document *xref, fz_obj *stmobj, int num, int gen) +pdf_open_raw_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int num, int gen) { int hascrypt; int len; @@ -187,7 +235,7 @@ pdf_open_raw_filter(fz_stream *chain, pdf_document *xref, fz_obj *stmobj, int nu /* don't close chain when we close this filter */ fz_keep_stream(chain); - len = fz_to_int(fz_dict_gets(stmobj, "Length")); + len = pdf_to_int(pdf_dict_gets(stmobj, "Length")); chain = fz_open_null(chain, len); fz_try(ctx) @@ -210,20 +258,20 @@ pdf_open_raw_filter(fz_stream *chain, pdf_document *xref, fz_obj *stmobj, int nu * to stream length and decrypting. */ static fz_stream * -pdf_open_filter(fz_stream *chain, pdf_document *xref, fz_obj *stmobj, int num, int gen) +pdf_open_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int num, int gen, pdf_image_params *imparams) { - fz_obj *filters; - fz_obj *params; + pdf_obj *filters; + pdf_obj *params; - filters = fz_dict_getsa(stmobj, "Filter", "F"); - params = fz_dict_getsa(stmobj, "DecodeParms", "DP"); + filters = pdf_dict_getsa(stmobj, "Filter", "F"); + params = pdf_dict_getsa(stmobj, "DecodeParms", "DP"); chain = pdf_open_raw_filter(chain, xref, stmobj, num, gen); - if (fz_is_name(filters)) - chain = build_filter(chain, xref, filters, params, num, gen); - else if (fz_array_len(filters) > 0) - chain = build_filter_chain(chain, xref, filters, params, num, gen); + if (pdf_is_name(filters)) + chain = build_filter(chain, xref, filters, params, num, gen, imparams); + else if (pdf_array_len(filters) > 0) + chain = build_filter_chain(chain, xref, filters, params, num, gen, imparams); fz_lock_stream(chain); return chain; @@ -234,21 +282,21 @@ pdf_open_filter(fz_stream *chain, pdf_document *xref, fz_obj *stmobj, int num, i * constraining to stream length, and without decryption. */ fz_stream * -pdf_open_inline_stream(pdf_document *xref, fz_obj *stmobj, int length, fz_stream *chain) +pdf_open_inline_stream(pdf_document *xref, pdf_obj *stmobj, int length, fz_stream *chain, pdf_image_params *imparams) { - fz_obj *filters; - fz_obj *params; + pdf_obj *filters; + pdf_obj *params; - filters = fz_dict_getsa(stmobj, "Filter", "F"); - params = fz_dict_getsa(stmobj, "DecodeParms", "DP"); + filters = pdf_dict_getsa(stmobj, "Filter", "F"); + params = pdf_dict_getsa(stmobj, "DecodeParms", "DP"); /* don't close chain when we close this filter */ fz_keep_stream(chain); - if (fz_is_name(filters)) - return build_filter(chain, xref, filters, params, 0, 0); - if (fz_array_len(filters) > 0) - return build_filter_chain(chain, xref, filters, params, 0, 0); + if (pdf_is_name(filters)) + return build_filter(chain, xref, filters, params, 0, 0, imparams); + if (pdf_array_len(filters) > 0) + return build_filter_chain(chain, xref, filters, params, 0, 0, imparams); return fz_open_null(chain, length); } @@ -290,6 +338,12 @@ pdf_open_raw_stream(pdf_document *xref, int num, int gen) fz_stream * pdf_open_stream(pdf_document *xref, int num, int gen) { + return pdf_open_image_stream(xref, num, gen, NULL); +} + +fz_stream * +pdf_open_image_stream(pdf_document *xref, int num, int gen, pdf_image_params *params) +{ pdf_xref_entry *x; fz_stream *stm; @@ -304,20 +358,64 @@ pdf_open_stream(pdf_document *xref, int num, int gen) if (x->stm_ofs == 0) fz_throw(xref->ctx, "object is not a stream"); - stm = pdf_open_filter(xref->file, xref, x->obj, num, gen); + stm = pdf_open_filter(xref->file, xref, x->obj, num, gen, params); fz_seek(xref->file, x->stm_ofs, 0); return stm; } fz_stream * -pdf_open_stream_with_offset(pdf_document *xref, int num, int gen, fz_obj *dict, int stm_ofs) +pdf_open_image_decomp_stream(fz_context *ctx, fz_buffer *buffer, pdf_image_params *params, int *factor) +{ + fz_stream *chain = fz_open_buffer(ctx, buffer); + + switch (params->type) + { + case PDF_IMAGE_FAX: + *factor = 1; + return fz_open_faxd(chain, + params->u.fax.k, + params->u.fax.eol, + params->u.fax.eba, + params->u.fax.columns, + params->u.fax.rows, + params->u.fax.eob, + params->u.fax.bi1); + case PDF_IMAGE_JPEG: + if (*factor > 8) + *factor = 8; + return fz_open_resized_dctd(chain, params->u.jpeg.ct, *factor); + case PDF_IMAGE_RLD: + *factor = 1; + return fz_open_rld(chain); + case PDF_IMAGE_FLATE: + *factor = 1; + chain = fz_open_flated(chain); + if (params->u.flate.predictor > 1) + chain = fz_open_predict(chain, params->u.flate.predictor, params->u.flate.columns, params->u.flate.colors, params->u.flate.bpc); + return chain; + case PDF_IMAGE_LZW: + *factor = 1; + chain = fz_open_lzwd(chain, params->u.lzw.ec); + if (params->u.lzw.predictor > 1) + chain = fz_open_predict(chain, params->u.lzw.predictor, params->u.lzw.columns, params->u.lzw.colors, params->u.lzw.bpc); + return chain; + default: + *factor = 1; + break; + } + + return chain; +} + +fz_stream * +pdf_open_stream_with_offset(pdf_document *xref, int num, int gen, pdf_obj *dict, int stm_ofs) { fz_stream *stm; if (stm_ofs == 0) fz_throw(xref->ctx, "object is not a stream"); - stm = pdf_open_filter(xref->file, xref, dict, num, gen); + stm = pdf_open_filter(xref->file, xref, dict, num, gen, NULL); fz_seek(xref->file, stm_ofs, 0); return stm; } @@ -329,16 +427,16 @@ fz_buffer * pdf_load_raw_stream(pdf_document *xref, int num, int gen) { fz_stream *stm; - fz_obj *dict; + pdf_obj *dict; int len; fz_buffer *buf; dict = pdf_load_object(xref, num, gen); /* RJW: "cannot load stream dictionary (%d %d R)", num, gen */ - len = fz_to_int(fz_dict_gets(dict, "Length")); + len = pdf_to_int(pdf_dict_gets(dict, "Length")); - fz_drop_obj(dict); + pdf_drop_obj(dict); stm = pdf_open_raw_stream(xref, num, gen); /* RJW: "cannot open raw stream (%d %d R)", num, gen */ @@ -372,9 +470,15 @@ pdf_guess_filter_length(int len, char *filter) fz_buffer * pdf_load_stream(pdf_document *xref, int num, int gen) { + return pdf_load_image_stream(xref, num, gen, NULL); +} + +fz_buffer * +pdf_load_image_stream(pdf_document *xref, int num, int gen, pdf_image_params *params) +{ fz_context *ctx = xref->ctx; fz_stream *stm = NULL; - fz_obj *dict, *obj; + pdf_obj *dict, *obj; int i, len, n; fz_buffer *buf; @@ -383,16 +487,16 @@ pdf_load_stream(pdf_document *xref, int num, int gen) dict = pdf_load_object(xref, num, gen); /* RJW: "cannot load stream dictionary (%d %d R)", num, gen */ - len = fz_to_int(fz_dict_gets(dict, "Length")); - obj = fz_dict_gets(dict, "Filter"); - len = pdf_guess_filter_length(len, fz_to_name(obj)); - n = fz_array_len(obj); + len = pdf_to_int(pdf_dict_gets(dict, "Length")); + obj = pdf_dict_gets(dict, "Filter"); + len = pdf_guess_filter_length(len, pdf_to_name(obj)); + n = pdf_array_len(obj); for (i = 0; i < n; i++) - len = pdf_guess_filter_length(len, fz_to_name(fz_array_get(obj, i))); + len = pdf_guess_filter_length(len, pdf_to_name(pdf_array_get(obj, i))); - fz_drop_obj(dict); + pdf_drop_obj(dict); - stm = pdf_open_stream(xref, num, gen); + stm = pdf_open_image_stream(xref, num, gen, params); /* RJW: "cannot open stream (%d %d R)", num, gen */ fz_try(ctx) |