mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-02-06 04:13:39 +01:00
Bugfix - find inline image stream length
This commit is contained in:
parent
5e603b7781
commit
a9acfa31e3
@ -21,6 +21,7 @@
|
|||||||
#include "pdfimage.h"
|
#include "pdfimage.h"
|
||||||
#include "pdfpattern.h"
|
#include "pdfpattern.h"
|
||||||
#include "pdfexecutionpolicy.h"
|
#include "pdfexecutionpolicy.h"
|
||||||
|
#include "pdfstreamfilters.h"
|
||||||
|
|
||||||
#include <QPainterPathStroker>
|
#include <QPainterPathStroker>
|
||||||
|
|
||||||
@ -547,10 +548,23 @@ void PDFPageContentProcessor::processContent(const QByteArray& content)
|
|||||||
dataLength = loader.readIntegerFromDictionary(dictionary, "Length", 0);
|
dataLength = loader.readIntegerFromDictionary(dictionary, "Length", 0);
|
||||||
}
|
}
|
||||||
else if (dictionary->hasKey("Filter"))
|
else if (dictionary->hasKey("Filter"))
|
||||||
|
{
|
||||||
|
dataLength = -1;
|
||||||
|
|
||||||
|
// We will try to use stream filter hint
|
||||||
|
PDFDocumentDataLoaderDecorator loader(m_document);
|
||||||
|
QByteArray filterName = loader.readNameFromDictionary(dictionary, "Filter");
|
||||||
|
if (!filterName.isEmpty())
|
||||||
|
{
|
||||||
|
dataLength = PDFStreamFilterStorage::getStreamDataLength(content, filterName, startDataPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataLength == -1)
|
||||||
{
|
{
|
||||||
// We will use EI operator position to determine stream length
|
// We will use EI operator position to determine stream length
|
||||||
dataLength = operatorEIPosition - startDataPosition;
|
dataLength = operatorEIPosition - startDataPosition;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We will calculate stream size from the with/height and bit per component
|
// We will calculate stream size from the with/height and bit per component
|
||||||
|
@ -457,6 +457,44 @@ QByteArray PDFFlateDecodeFilter::recompress(const QByteArray& data)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFInteger PDFFlateDecodeFilter::getStreamDataLength(const QByteArray& data, PDFInteger offset) const
|
||||||
|
{
|
||||||
|
if (offset < 0 || offset >= data.size())
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
z_stream stream = { };
|
||||||
|
stream.next_in = const_cast<Bytef*>(convertByteArrayToUcharPtr(data) + offset);
|
||||||
|
stream.avail_in = data.size() - offset;
|
||||||
|
|
||||||
|
std::array<Bytef, 1024> outputBuffer = { };
|
||||||
|
|
||||||
|
int error = inflateInit(&stream);
|
||||||
|
if (error != Z_OK)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
stream.next_out = outputBuffer.data();
|
||||||
|
stream.avail_out = static_cast<uInt>(outputBuffer.size());
|
||||||
|
|
||||||
|
error = inflate(&stream, Z_NO_FLUSH);
|
||||||
|
} while (error == Z_OK);
|
||||||
|
|
||||||
|
PDFInteger dataLength = stream.total_in;
|
||||||
|
inflateEnd(&stream);
|
||||||
|
|
||||||
|
if (error == Z_STREAM_END)
|
||||||
|
{
|
||||||
|
return dataLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray PDFFlateDecodeFilter::uncompress(const QByteArray& data)
|
QByteArray PDFFlateDecodeFilter::uncompress(const QByteArray& data)
|
||||||
{
|
{
|
||||||
QByteArray result;
|
QByteArray result;
|
||||||
@ -676,6 +714,16 @@ QByteArray PDFStreamFilterStorage::getDecodedStream(const PDFStream* stream, con
|
|||||||
return getDecodedStream(stream, [](const PDFObject& object) -> const PDFObject& { return object; }, securityHandler);
|
return getDecodedStream(stream, [](const PDFObject& object) -> const PDFObject& { return object; }, securityHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFInteger PDFStreamFilterStorage::getStreamDataLength(const QByteArray& data, const QByteArray& filterName, PDFInteger offset)
|
||||||
|
{
|
||||||
|
if (const PDFStreamFilter* filter = getFilter(filterName))
|
||||||
|
{
|
||||||
|
return filter->getStreamDataLength(data, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
PDFStreamFilterStorage::PDFStreamFilterStorage()
|
PDFStreamFilterStorage::PDFStreamFilterStorage()
|
||||||
{
|
{
|
||||||
// Initialize map with the filters
|
// Initialize map with the filters
|
||||||
@ -931,4 +979,12 @@ QByteArray PDFCryptFilter::apply(const QByteArray& data,
|
|||||||
return securityHandler->decryptByFilter(data, cryptFilterName, objectReference);
|
return securityHandler->decryptByFilter(data, cryptFilterName, objectReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDFInteger PDFStreamFilter::getStreamDataLength(const QByteArray& data, PDFInteger offset) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(data);
|
||||||
|
Q_UNUSED(offset);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdf
|
} // namespace pdf
|
||||||
|
@ -54,6 +54,14 @@ public:
|
|||||||
/// \param securityHandler Security handler for Crypt filters
|
/// \param securityHandler Security handler for Crypt filters
|
||||||
static QByteArray getDecodedStream(const PDFStream* stream, const PDFSecurityHandler* securityHandler);
|
static QByteArray getDecodedStream(const PDFStream* stream, const PDFSecurityHandler* securityHandler);
|
||||||
|
|
||||||
|
/// Tries to find stream data length using given filter. Stream will
|
||||||
|
/// start at given \p offset in \p data. If stream length cannot be determined,
|
||||||
|
/// then -1 is returned.
|
||||||
|
/// \param data Buffer data
|
||||||
|
/// \param filterName Filter name
|
||||||
|
/// \param offset Offset to buffer, at which stream data starts
|
||||||
|
static PDFInteger getStreamDataLength(const QByteArray& data, const QByteArray& filterName, PDFInteger offset);
|
||||||
|
|
||||||
struct StreamFilters
|
struct StreamFilters
|
||||||
{
|
{
|
||||||
bool valid = true;
|
bool valid = true;
|
||||||
@ -148,6 +156,12 @@ public:
|
|||||||
{
|
{
|
||||||
return apply(data, [](const PDFObject& object) -> const PDFObject& { return object; }, parameters, securityHandler);
|
return apply(data, [](const PDFObject& object) -> const PDFObject& { return object; }, parameters, securityHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tries to find stream data length. Stream will start at given \p offset in \p data.
|
||||||
|
/// If stream length cannot be determined, then -1 is returned.
|
||||||
|
/// \param data Buffer data
|
||||||
|
/// \param offset Offset to buffer, at which stream data starts
|
||||||
|
virtual PDFInteger getStreamDataLength(const QByteArray& data, PDFInteger offset) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PDFFORQTLIBSHARED_EXPORT PDFAsciiHexDecodeFilter : public PDFStreamFilter
|
class PDFFORQTLIBSHARED_EXPORT PDFAsciiHexDecodeFilter : public PDFStreamFilter
|
||||||
@ -197,6 +211,8 @@ public:
|
|||||||
const PDFObject& parameters,
|
const PDFObject& parameters,
|
||||||
const PDFSecurityHandler* securityHandler) const override;
|
const PDFSecurityHandler* securityHandler) const override;
|
||||||
|
|
||||||
|
virtual PDFInteger getStreamDataLength(const QByteArray& data, PDFInteger offset) const;
|
||||||
|
|
||||||
/// Recompresses data. So, first, data are decompressed, and then
|
/// Recompresses data. So, first, data are decompressed, and then
|
||||||
/// recompressed again with maximal compress ratio possible.
|
/// recompressed again with maximal compress ratio possible.
|
||||||
/// \param data Compressed data to be recompressed
|
/// \param data Compressed data to be recompressed
|
||||||
|
Loading…
x
Reference in New Issue
Block a user