summaryrefslogtreecommitdiffstats
path: root/libqpdf/QPDF_Stream.cc
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2017-08-19 15:18:14 +0200
committerJay Berkenbilt <ejb@ql.org>2017-08-21 23:44:22 +0200
commit9744414c66e3f85700ebc8b32d90f45ff97221bd (patch)
tree47abed5c4105fe3f0089ab9afdf1d053d806b39d /libqpdf/QPDF_Stream.cc
parentae90d2c485318beb8b4b938d09ffaf5c6f0a5e21 (diff)
downloadqpdf-9744414c66e3f85700ebc8b32d90f45ff97221bd.tar.zst
Enable finer grained control of stream decoding
This commit adds several API methods that enable control over which types of filters QPDF will attempt to decode. It also adds support for /RunLengthDecode and /DCTDecode filters for both encoding and decoding.
Diffstat (limited to 'libqpdf/QPDF_Stream.cc')
-rw-r--r--libqpdf/QPDF_Stream.cc68
1 files changed, 55 insertions, 13 deletions
diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc
index 31d583b8..bcf9be92 100644
--- a/libqpdf/QPDF_Stream.cc
+++ b/libqpdf/QPDF_Stream.cc
@@ -9,6 +9,8 @@
#include <qpdf/Pl_ASCII85Decoder.hh>
#include <qpdf/Pl_ASCIIHexDecoder.hh>
#include <qpdf/Pl_LZWDecoder.hh>
+#include <qpdf/Pl_RunLength.hh>
+#include <qpdf/Pl_DCT.hh>
#include <qpdf/Pl_Count.hh>
#include <qpdf/QTC.hh>
@@ -82,10 +84,10 @@ QPDF_Stream::getDict() const
}
PointerHolder<Buffer>
-QPDF_Stream::getStreamData()
+QPDF_Stream::getStreamData(qpdf_stream_decode_level_e decode_level)
{
Pl_Buffer buf("stream data buffer");
- if (! pipeStreamData(&buf, true, false, false, false))
+ if (! pipeStreamData(&buf, 0, decode_level, false))
{
throw std::logic_error("getStreamData called on unfilterable stream");
}
@@ -97,7 +99,7 @@ PointerHolder<Buffer>
QPDF_Stream::getRawStreamData()
{
Pl_Buffer buf("stream data buffer");
- pipeStreamData(&buf, false, false, false, false);
+ pipeStreamData(&buf, 0, qpdf_dl_none, false);
QTC::TC("qpdf", "QPDF_Stream getRawStreamData");
return buf.getBuffer();
}
@@ -178,6 +180,8 @@ QPDF_Stream::understandDecodeParams(
bool
QPDF_Stream::filterable(std::vector<std::string>& filters,
+ bool& specialized_compression,
+ bool& lossy_compression,
int& predictor, int& columns,
bool& early_code_change)
{
@@ -254,11 +258,20 @@ QPDF_Stream::filterable(std::vector<std::string>& filters,
filter = filter_abbreviations[filter];
}
- if (! ((filter == "/Crypt") ||
- (filter == "/FlateDecode") ||
- (filter == "/LZWDecode") ||
- (filter == "/ASCII85Decode") ||
- (filter == "/ASCIIHexDecode")))
+ if (filter == "/RunLengthDecode")
+ {
+ specialized_compression = true;
+ }
+ else if (filter == "/DCTDecode")
+ {
+ specialized_compression = true;
+ lossy_compression = true;
+ }
+ else if (! ((filter == "/Crypt") ||
+ (filter == "/FlateDecode") ||
+ (filter == "/LZWDecode") ||
+ (filter == "/ASCII85Decode") ||
+ (filter == "/ASCIIHexDecode")))
{
filterable = false;
}
@@ -350,17 +363,35 @@ QPDF_Stream::filterable(std::vector<std::string>& filters,
}
bool
-QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool filter,
- bool normalize, bool compress,
+QPDF_Stream::pipeStreamData(Pipeline* pipeline,
+ unsigned long encode_flags,
+ qpdf_stream_decode_level_e decode_level,
bool suppress_warnings)
{
std::vector<std::string> filters;
int predictor = 1;
int columns = 0;
bool early_code_change = true;
+ bool specialized_compression = false;
+ bool lossy_compression = false;
+ bool filter = (! ((encode_flags == 0) && (decode_level == qpdf_dl_none)));
if (filter)
{
- filter = filterable(filters, predictor, columns, early_code_change);
+ filter = filterable(filters, specialized_compression, lossy_compression,
+ predictor, columns, early_code_change);
+ if ((decode_level < qpdf_dl_all) && lossy_compression)
+ {
+ filter = false;
+ }
+ if ((decode_level < qpdf_dl_specialized) && specialized_compression)
+ {
+ filter = false;
+ }
+ QTC::TC("qpdf", "QPDF_Stream special filters",
+ (! filter) ? 0 :
+ lossy_compression ? 1 :
+ specialized_compression ? 2 :
+ 3);
}
if (pipeline == 0)
@@ -375,14 +406,14 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool filter,
if (filter)
{
- if (compress)
+ if (encode_flags & qpdf_ef_compress)
{
pipeline = new Pl_Flate("compress object stream", pipeline,
Pl_Flate::a_deflate);
to_delete.push_back(pipeline);
}
- if (normalize)
+ if (encode_flags & qpdf_ef_normalize)
{
pipeline = new Pl_QPDFTokenizer("normalizer", pipeline);
to_delete.push_back(pipeline);
@@ -427,6 +458,17 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool filter,
early_code_change);
to_delete.push_back(pipeline);
}
+ else if (filter == "/RunLengthDecode")
+ {
+ pipeline = new Pl_RunLength("runlength decode", pipeline,
+ Pl_RunLength::a_decode);
+ to_delete.push_back(pipeline);
+ }
+ else if (filter == "/DCTDecode")
+ {
+ pipeline = new Pl_DCT("DCT decode", pipeline);
+ to_delete.push_back(pipeline);
+ }
else
{
throw std::logic_error(