Commit b1e0dcff16740d5a99e58c298284c5d589b3034f
1 parent
0c1dab0c
handle stream filter abbreviations from table H.1
git-svn-id: svn+q:///qpdf/trunk@1025 71b93d88-0707-0410-a8cf-f5a4172ac649
Showing
8 changed files
with
51 additions
and
3 deletions
ChangeLog
| 1 | +2010-09-05 Jay Berkenbilt <ejb@ql.org> | |
| 2 | + | |
| 3 | + * libqpdf/QPDF_Stream.cc (filterable): Handle inline image filter | |
| 4 | + abbreviations as stream filter abbreviations. Although this is | |
| 5 | + not technically allowed by the PDF specification, table H.1 in the | |
| 6 | + pre-ISO spec indicates that Adobe's readers accept them. Thanks | |
| 7 | + to Jian Ma <stronghorse@tom.com> for bringing this to my | |
| 8 | + attention. | |
| 9 | + | |
| 1 | 10 | 2010-08-14 Jay Berkenbilt <ejb@ql.org> |
| 2 | 11 | |
| 3 | 12 | * 2.2.0: release | ... | ... |
libqpdf/QPDFWriter.cc
| ... | ... | @@ -993,7 +993,9 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level, |
| 993 | 993 | // compressed with a lossy compression scheme, but we |
| 994 | 994 | // don't support any of those right now. |
| 995 | 995 | QPDFObjectHandle filter_obj = stream_dict.getKey("/Filter"); |
| 996 | - if (filter_obj.isName() && (filter_obj.getName() == "/FlateDecode")) | |
| 996 | + if (filter_obj.isName() && | |
| 997 | + ((filter_obj.getName() == "/FlateDecode") || | |
| 998 | + (filter_obj.getName() == "/Fl"))) | |
| 997 | 999 | { |
| 998 | 1000 | QTC::TC("qpdf", "QPDFWriter not recompressing /FlateDecode"); |
| 999 | 1001 | filter = false; | ... | ... |
libqpdf/QPDF_Stream.cc
| ... | ... | @@ -18,6 +18,8 @@ |
| 18 | 18 | |
| 19 | 19 | #include <stdexcept> |
| 20 | 20 | |
| 21 | +std::map<std::string, std::string> QPDF_Stream::filter_abbreviations; | |
| 22 | + | |
| 21 | 23 | QPDF_Stream::QPDF_Stream(QPDF* qpdf, int objid, int generation, |
| 22 | 24 | QPDFObjectHandle stream_dict, |
| 23 | 25 | off_t offset, int length) : |
| ... | ... | @@ -93,6 +95,21 @@ QPDF_Stream::filterable(std::vector<std::string>& filters, |
| 93 | 95 | int& predictor, int& columns, |
| 94 | 96 | bool& early_code_change) |
| 95 | 97 | { |
| 98 | + if (filter_abbreviations.empty()) | |
| 99 | + { | |
| 100 | + // The PDF specification provides these filter abbreviations | |
| 101 | + // for use in inline images, but according to table H.1 in the | |
| 102 | + // pre-ISO versions of the PDF specification, Adobe Reader | |
| 103 | + // also accepts them for stream filters. | |
| 104 | + filter_abbreviations["/AHx"] = "/ASCIIHexDecode"; | |
| 105 | + filter_abbreviations["/A85"] = "/ASCII85Decode"; | |
| 106 | + filter_abbreviations["/LZW"] = "/LZWDecode"; | |
| 107 | + filter_abbreviations["/Fl"] = "/FlateDecode"; | |
| 108 | + filter_abbreviations["/RL"] = "/RunLengthDecode"; | |
| 109 | + filter_abbreviations["/CCF"] = "/CCITTFaxDecode"; | |
| 110 | + filter_abbreviations["/DCT"] = "/DCTDecode"; | |
| 111 | + } | |
| 112 | + | |
| 96 | 113 | // Initialize values to their defaults as per the PDF spec |
| 97 | 114 | predictor = 1; |
| 98 | 115 | columns = 0; |
| ... | ... | @@ -243,7 +260,14 @@ QPDF_Stream::filterable(std::vector<std::string>& filters, |
| 243 | 260 | for (std::vector<std::string>::iterator iter = filters.begin(); |
| 244 | 261 | iter != filters.end(); ++iter) |
| 245 | 262 | { |
| 246 | - std::string const& filter = *iter; | |
| 263 | + std::string& filter = *iter; | |
| 264 | + | |
| 265 | + if (filter_abbreviations.count(filter)) | |
| 266 | + { | |
| 267 | + QTC::TC("qpdf", "QPDF_Stream expand filter abbreviation"); | |
| 268 | + filter = filter_abbreviations[filter]; | |
| 269 | + } | |
| 270 | + | |
| 247 | 271 | if (! ((filter == "/Crypt") || |
| 248 | 272 | (filter == "/FlateDecode") || |
| 249 | 273 | (filter == "/LZWDecode") || | ... | ... |
libqpdf/qpdf/QPDF_Stream.hh
| ... | ... | @@ -38,6 +38,8 @@ class QPDF_Stream: public QPDFObject |
| 38 | 38 | void setObjGen(int objid, int generation); |
| 39 | 39 | |
| 40 | 40 | private: |
| 41 | + static std::map<std::string, std::string> filter_abbreviations; | |
| 42 | + | |
| 41 | 43 | void replaceFilterData(QPDFObjectHandle const& filter, |
| 42 | 44 | QPDFObjectHandle const& decode_parms, |
| 43 | 45 | size_t length); | ... | ... |
qpdf/qpdf.testcov
qpdf/qtest/qpdf.test
| ... | ... | @@ -111,7 +111,7 @@ $td->runtest("new stream", |
| 111 | 111 | show_ntests(); |
| 112 | 112 | # ---------- |
| 113 | 113 | $td->notify("--- Miscellaneous Tests ---"); |
| 114 | -$n_tests += 23; | |
| 114 | +$n_tests += 25; | |
| 115 | 115 | |
| 116 | 116 | $td->runtest("qpdf version", |
| 117 | 117 | {$td->COMMAND => "qpdf --version"}, |
| ... | ... | @@ -229,6 +229,16 @@ $td->runtest("C check version 2", |
| 229 | 229 | $td->EXIT_STATUS => 0}, |
| 230 | 230 | $td->NORMALIZE_NEWLINES); |
| 231 | 231 | |
| 232 | +# Stream filter abbreviations from table H.1 | |
| 233 | +$td->runtest("stream filter abbreviations", | |
| 234 | + {$td->COMMAND => "qpdf --static-id filter-abbreviation.pdf a.pdf"}, | |
| 235 | + {$td->STRING => "", | |
| 236 | + $td->EXIT_STATUS => 0}, | |
| 237 | + $td->NORMALIZE_NEWLINES); | |
| 238 | +$td->runtest("check output", | |
| 239 | + {$td->FILE => "a.pdf"}, | |
| 240 | + {$td->FILE => "filter-abbreviation.out"}); | |
| 241 | + | |
| 232 | 242 | show_ntests(); |
| 233 | 243 | # ---------- |
| 234 | 244 | $td->notify("--- Error Condition Tests ---"); | ... | ... |
qpdf/qtest/qpdf/filter-abbreviation.out
0 → 100644
No preview for this file type
qpdf/qtest/qpdf/filter-abbreviation.pdf
0 → 100644
No preview for this file type