From b1e0dcff16740d5a99e58c298284c5d589b3034f Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sun, 5 Sep 2010 15:00:44 +0000 Subject: [PATCH] handle stream filter abbreviations from table H.1 git-svn-id: svn+q:///qpdf/trunk@1025 71b93d88-0707-0410-a8cf-f5a4172ac649 --- ChangeLog | 9 ++++++++ libqpdf/QPDFWriter.cc | 4 +++- libqpdf/QPDF_Stream.cc | 26 +++++++++++++++++++++++- libqpdf/qpdf/QPDF_Stream.hh | 2 ++ qpdf/qpdf.testcov | 1 + qpdf/qtest/qpdf.test | 12 ++++++++++- qpdf/qtest/qpdf/filter-abbreviation.out | Bin 0 -> 734 bytes qpdf/qtest/qpdf/filter-abbreviation.pdf | Bin 0 -> 743 bytes 8 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 qpdf/qtest/qpdf/filter-abbreviation.out create mode 100644 qpdf/qtest/qpdf/filter-abbreviation.pdf diff --git a/ChangeLog b/ChangeLog index 6add548a..5484137e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-09-05 Jay Berkenbilt + + * libqpdf/QPDF_Stream.cc (filterable): Handle inline image filter + abbreviations as stream filter abbreviations. Although this is + not technically allowed by the PDF specification, table H.1 in the + pre-ISO spec indicates that Adobe's readers accept them. Thanks + to Jian Ma for bringing this to my + attention. + 2010-08-14 Jay Berkenbilt * 2.2.0: release diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index 2985118a..68fd62f5 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -993,7 +993,9 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level, // compressed with a lossy compression scheme, but we // don't support any of those right now. QPDFObjectHandle filter_obj = stream_dict.getKey("/Filter"); - if (filter_obj.isName() && (filter_obj.getName() == "/FlateDecode")) + if (filter_obj.isName() && + ((filter_obj.getName() == "/FlateDecode") || + (filter_obj.getName() == "/Fl"))) { QTC::TC("qpdf", "QPDFWriter not recompressing /FlateDecode"); filter = false; diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index 72be2e32..db6cfb58 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -18,6 +18,8 @@ #include +std::map QPDF_Stream::filter_abbreviations; + QPDF_Stream::QPDF_Stream(QPDF* qpdf, int objid, int generation, QPDFObjectHandle stream_dict, off_t offset, int length) : @@ -93,6 +95,21 @@ QPDF_Stream::filterable(std::vector& filters, int& predictor, int& columns, bool& early_code_change) { + if (filter_abbreviations.empty()) + { + // The PDF specification provides these filter abbreviations + // for use in inline images, but according to table H.1 in the + // pre-ISO versions of the PDF specification, Adobe Reader + // also accepts them for stream filters. + filter_abbreviations["/AHx"] = "/ASCIIHexDecode"; + filter_abbreviations["/A85"] = "/ASCII85Decode"; + filter_abbreviations["/LZW"] = "/LZWDecode"; + filter_abbreviations["/Fl"] = "/FlateDecode"; + filter_abbreviations["/RL"] = "/RunLengthDecode"; + filter_abbreviations["/CCF"] = "/CCITTFaxDecode"; + filter_abbreviations["/DCT"] = "/DCTDecode"; + } + // Initialize values to their defaults as per the PDF spec predictor = 1; columns = 0; @@ -243,7 +260,14 @@ QPDF_Stream::filterable(std::vector& filters, for (std::vector::iterator iter = filters.begin(); iter != filters.end(); ++iter) { - std::string const& filter = *iter; + std::string& filter = *iter; + + if (filter_abbreviations.count(filter)) + { + QTC::TC("qpdf", "QPDF_Stream expand filter abbreviation"); + filter = filter_abbreviations[filter]; + } + if (! ((filter == "/Crypt") || (filter == "/FlateDecode") || (filter == "/LZWDecode") || diff --git a/libqpdf/qpdf/QPDF_Stream.hh b/libqpdf/qpdf/QPDF_Stream.hh index ed70ae8f..144a9274 100644 --- a/libqpdf/qpdf/QPDF_Stream.hh +++ b/libqpdf/qpdf/QPDF_Stream.hh @@ -38,6 +38,8 @@ class QPDF_Stream: public QPDFObject void setObjGen(int objid, int generation); private: + static std::map filter_abbreviations; + void replaceFilterData(QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms, size_t length); diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index f4354891..85455a68 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -185,3 +185,4 @@ QPDFObjectHandle prepend page contents 0 QPDFObjectHandle append page contents 0 QPDF_Stream getRawStreamData 0 QPDF_Stream getStreamData 0 +QPDF_Stream expand filter abbreviation 0 diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index 35b2be51..c6040bf8 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -111,7 +111,7 @@ $td->runtest("new stream", show_ntests(); # ---------- $td->notify("--- Miscellaneous Tests ---"); -$n_tests += 23; +$n_tests += 25; $td->runtest("qpdf version", {$td->COMMAND => "qpdf --version"}, @@ -229,6 +229,16 @@ $td->runtest("C check version 2", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); +# Stream filter abbreviations from table H.1 +$td->runtest("stream filter abbreviations", + {$td->COMMAND => "qpdf --static-id filter-abbreviation.pdf a.pdf"}, + {$td->STRING => "", + $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); +$td->runtest("check output", + {$td->FILE => "a.pdf"}, + {$td->FILE => "filter-abbreviation.out"}); + show_ntests(); # ---------- $td->notify("--- Error Condition Tests ---"); diff --git a/qpdf/qtest/qpdf/filter-abbreviation.out b/qpdf/qtest/qpdf/filter-abbreviation.out new file mode 100644 index 0000000000000000000000000000000000000000..aa9bf28e9bfa4ce0a11af9149fdd065f855b6f3d GIT binary patch literal 734 zcmY!laBZ^4|D>$ol3WFSpVYkck_-hS zBVz@9x6GW9)FL3AlUS1KlA4^K0#xXyU<#5cDlSnlGE=a#<0>vGN=?k=s+i;2AJ~1! zK%nLRU(wI}mt1oFCmdR--c->c_d~(%$*rX&N%$K$ zer(hXnWo$xRAe&W`Awc{#DqSDKbUXIx1XN z^8_6{_`aDgJae7GlLR-}tH!ghjI~XGM=ycdRvu%wQlD{+eR_gEjD!(+O z@J*fbqT@W4E~;Ygdl~vC$1Y9HOM!Y6$N~kOIZ_ZJ0tz00CKf1RQ_S@+DBwc5afpFY zAcrUOrn9{bCma-2SWjHzIHB*UbMkr!$H_-UybqZePBU_zz_82$$udZMMFgd$!7Vd3 z!Vy`JNDD|T$}Ls^#kF&OPHAplv4V+$en3%bN@j9NevyKq5zwg$`r!)E3Wf?sKpd-} zAC#XDj9;LwK??f8nN_I@mJ0fwE(*~$2BroUmL@3{DF&$~CPt>lMk&c@rfEsZscA+@ zDM@Cjb~eU_CWfY#MrNkQrWTgwmc~ZL7A9s!W+ukQ7RE;AmZo;GC?S)a#K5HH##Sfr xv9po$M6!$eKV!CkjGKxi8BCrsU*WZ^4|D>$ol3WFSpVYkck_-hS zBVz@9x6GW9)FL3AqW}l`ehQ`_nWEwn1tT*BJ3Fr8lA_eaT&{{auKj`ChYSQ-?*A42 z%zw!x*MGvHmFi6u9dbVu?4I0O%Cg60R>+t8yFFie#!b6BGhdBM@|c9bf#b(U&5&uz z?LkE*^PS(6I?sDA$tPfcUfNNo^g{Uc1v-zWx1HVX zaK`@gj;PPmQ_*Q4#M$CWh0DoF_1BwLr2J5^)hhscGfW)HQVg*p7JLl(==H?YEm?-E66s4wQCYR(FDHs|7<5NLDTp?P)P{9a@V-@s+ z^7DZa4YV~#K|eUNDpkQ!LEqCwA=<{k)WE{hB*h}dAl1ag$kf;lecn@&kEn0#lx%Y_jX#U+VFB^5=f QXi_@% literal 0 HcmV?d00001