mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
CCITT fax decoder, finishing
This commit is contained in:
@ -312,7 +312,7 @@ PDFImageData PDFCCITTFaxDecoder::decode()
|
|||||||
|
|
||||||
int row = 0;
|
int row = 0;
|
||||||
const size_t lineSize = m_parameters.columns + 2;
|
const size_t lineSize = m_parameters.columns + 2;
|
||||||
codingLine.resize(lineSize, m_parameters.columns);
|
codingLine.resize(lineSize, 0);
|
||||||
referenceLine.resize(lineSize, m_parameters.columns);
|
referenceLine.resize(lineSize, m_parameters.columns);
|
||||||
bool isUsing2DEncoding = m_parameters.K < 0;
|
bool isUsing2DEncoding = m_parameters.K < 0;
|
||||||
bool isEndOfLineOccured = m_parameters.hasEndOfLine;
|
bool isEndOfLineOccured = m_parameters.hasEndOfLine;
|
||||||
@ -334,7 +334,6 @@ PDFImageData PDFCCITTFaxDecoder::decode()
|
|||||||
int a0_index = 0;
|
int a0_index = 0;
|
||||||
bool isCurrentPixelBlack = false;
|
bool isCurrentPixelBlack = false;
|
||||||
|
|
||||||
|
|
||||||
if (isUsing2DEncoding)
|
if (isUsing2DEncoding)
|
||||||
{
|
{
|
||||||
int b1_index = 0;
|
int b1_index = 0;
|
||||||
@ -444,22 +443,74 @@ PDFImageData PDFCCITTFaxDecoder::decode()
|
|||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.write((isCurrentPixelBlack != m_parameters.hasBlackIsOne) ? 0 : 1);
|
writer.write((isCurrentPixelBlack != m_parameters.hasBlackIsOne) ? 1 : 0);
|
||||||
}
|
}
|
||||||
writer.finishLine();
|
writer.finishLine();
|
||||||
|
|
||||||
++row;
|
++row;
|
||||||
|
|
||||||
|
// Check if we have reached desired number of rows (and end-of-block mode
|
||||||
|
// is not set). If yes, then break the reading.
|
||||||
if (!m_parameters.hasEndOfBlock && row == m_parameters.rows)
|
if (!m_parameters.hasEndOfBlock && row == m_parameters.rows)
|
||||||
{
|
{
|
||||||
// We have reached number of rows, stop reading the data
|
// We have reached number of rows, stop reading the data
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pokracovat zde
|
|
||||||
|
bool foundEndOfLine = false;
|
||||||
|
if (m_parameters.hasEndOfLine)
|
||||||
|
{
|
||||||
|
// End of line is required, try to scan it (until end of stream is reached).
|
||||||
|
while (!m_reader.isAtEnd())
|
||||||
|
{
|
||||||
|
if (m_reader.look(12) == 1)
|
||||||
|
{
|
||||||
|
m_reader.read(12);
|
||||||
|
foundEndOfLine = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_reader.read(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!m_parameters.hasEncodedByteAlign)
|
||||||
|
{
|
||||||
|
// Skip fill zeros and possibly find EOL
|
||||||
|
foundEndOfLine = skipFillAndEOL();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If end of line is found, be do not perform align to bytes (end of line
|
||||||
|
// has perference against byte align)
|
||||||
|
if (m_parameters.hasEncodedByteAlign && !foundEndOfLine)
|
||||||
|
{
|
||||||
|
m_reader.alignToBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_reader.isAtEnd())
|
||||||
|
{
|
||||||
|
// Have we finished reading?
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateIsUsing2DEncoding();
|
||||||
|
|
||||||
|
if (m_parameters.hasEndOfBlock && foundEndOfLine)
|
||||||
|
{
|
||||||
|
if (m_reader.look(60) == 0x1001001001001ULL)
|
||||||
|
{
|
||||||
|
// End of block found, stop reading the data
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::swap(codingLine, referenceLine);
|
std::swap(codingLine, referenceLine);
|
||||||
|
std::fill(codingLine.begin(), codingLine.end(), 0);
|
||||||
|
std::fill(std::next(referenceLine.begin(), a0_index + 1), referenceLine.end(), m_parameters.columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return PDFImageData(1, 1, m_parameters.columns, row, (m_parameters.columns + 7) / 8, m_parameters.maskingType, writer.takeByteArray(), { }, { }, { });
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFCCITTFaxDecoder::skipFill()
|
void PDFCCITTFaxDecoder::skipFill()
|
||||||
@ -467,7 +518,7 @@ void PDFCCITTFaxDecoder::skipFill()
|
|||||||
// This functions skips zero bits (because codewords have at most 12 bits,
|
// This functions skips zero bits (because codewords have at most 12 bits,
|
||||||
// we use 12 bit lookahead to ensure, that we do not broke data sequence).
|
// we use 12 bit lookahead to ensure, that we do not broke data sequence).
|
||||||
|
|
||||||
while (m_reader.look(12) == 0)
|
while (!m_reader.isAtEnd() && m_reader.look(12) == 0)
|
||||||
{
|
{
|
||||||
m_reader.read(1);
|
m_reader.read(1);
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,8 @@ struct PDFCCITTFaxDecoderParameters
|
|||||||
/// If this flag is true, then 1 means black pixel, 0 white pixel. Otherwise, if false,
|
/// If this flag is true, then 1 means black pixel, 0 white pixel. Otherwise, if false,
|
||||||
/// then 0 means black pixel and 1 white pixel.
|
/// then 0 means black pixel and 1 white pixel.
|
||||||
bool hasBlackIsOne = false;
|
bool hasBlackIsOne = false;
|
||||||
|
|
||||||
|
PDFImageData::MaskingType maskingType = PDFImageData::MaskingType::None;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CCITT_2D_Code_Mode;
|
enum CCITT_2D_Code_Mode;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "pdfconstants.h"
|
#include "pdfconstants.h"
|
||||||
#include "pdfexception.h"
|
#include "pdfexception.h"
|
||||||
#include "pdfutils.h"
|
#include "pdfutils.h"
|
||||||
|
#include "pdfccittfaxdecoder.h"
|
||||||
|
|
||||||
#include <openjpeg.h>
|
#include <openjpeg.h>
|
||||||
#include <jpeglib.h>
|
#include <jpeglib.h>
|
||||||
@ -166,6 +167,26 @@ PDFImage PDFImage::createImage(const PDFDocument* document, const PDFStream* str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PDFDictionary* filterParamsDictionary = nullptr;
|
||||||
|
if (filterParameters.isDictionary())
|
||||||
|
{
|
||||||
|
filterParamsDictionary = filterParameters.getDictionary();
|
||||||
|
}
|
||||||
|
else if (filterParameters.isArray())
|
||||||
|
{
|
||||||
|
const PDFArray* filterParametersArray = filterParameters.getArray();
|
||||||
|
const size_t filterParamsCount = filterParametersArray->getCount();
|
||||||
|
|
||||||
|
if (filterParamsCount)
|
||||||
|
{
|
||||||
|
const PDFObject& object = document->getObject(filterParametersArray->getItem(filterParamsCount - 1));
|
||||||
|
if (object.isDictionary())
|
||||||
|
{
|
||||||
|
filterParamsDictionary = object.getDictionary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (imageFilterName == "DCTDecode" || imageFilterName == "DCT")
|
if (imageFilterName == "DCTDecode" || imageFilterName == "DCT")
|
||||||
{
|
{
|
||||||
int colorTransform = loader.readIntegerFromDictionary(dictionary, "ColorTransform", -1);
|
int colorTransform = loader.readIntegerFromDictionary(dictionary, "ColorTransform", -1);
|
||||||
@ -493,7 +514,26 @@ PDFImage PDFImage::createImage(const PDFDocument* document, const PDFStream* str
|
|||||||
}
|
}
|
||||||
else if (imageFilterName == "CCITTFaxDecode" || imageFilterName == "CCF")
|
else if (imageFilterName == "CCITTFaxDecode" || imageFilterName == "CCF")
|
||||||
{
|
{
|
||||||
throw PDFRendererException(RenderErrorType::NotImplemented, PDFTranslationContext::tr("Not implemented image filter 'CCITTFaxDecode'."));
|
if (!filterParamsDictionary)
|
||||||
|
{
|
||||||
|
throw PDFRendererException(RenderErrorType::Error, PDFTranslationContext::tr("Invalid parameters for filter CCITT fax decode."));
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFCCITTFaxDecoderParameters parameters;
|
||||||
|
parameters.maskingType = maskingType;
|
||||||
|
|
||||||
|
parameters.K = loader.readIntegerFromDictionary(filterParamsDictionary, "K", 0);
|
||||||
|
parameters.hasEndOfLine = loader.readBooleanFromDictionary(filterParamsDictionary, "EndOfLine", false);
|
||||||
|
parameters.hasEncodedByteAlign = loader.readBooleanFromDictionary(filterParamsDictionary, "EncodedByteAlign", false);
|
||||||
|
parameters.columns = loader.readIntegerFromDictionary(filterParamsDictionary, "Columns", 1728);
|
||||||
|
parameters.rows = loader.readIntegerFromDictionary(filterParamsDictionary, "Rows", 0);
|
||||||
|
parameters.hasEndOfBlock = loader.readBooleanFromDictionary(filterParamsDictionary, "EndOfBlock", true);
|
||||||
|
parameters.hasBlackIsOne = loader.readBooleanFromDictionary(filterParamsDictionary, "BlackIs1", false);
|
||||||
|
parameters.damagedRowsBeforeError = loader.readIntegerFromDictionary(filterParamsDictionary, "DamagedRowsBeforeError", 0);
|
||||||
|
|
||||||
|
QByteArray imageDataBuffer = document->getDecodedStream(stream);
|
||||||
|
PDFCCITTFaxDecoder decoder(&imageDataBuffer, parameters);
|
||||||
|
image.m_imageData = decoder.decode();
|
||||||
}
|
}
|
||||||
else if (imageFilterName == "JBIG2Decode")
|
else if (imageFilterName == "JBIG2Decode")
|
||||||
{
|
{
|
||||||
|
@ -56,10 +56,24 @@ PDFBitReader::Value PDFBitReader::read(PDFBitReader::Value bits)
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFBitReader::Value PDFBitReader::look(PDFBitReader::Value bits) const
|
PDFBitReader::Value PDFBitReader::look(Value bits) const
|
||||||
{
|
{
|
||||||
PDFBitReader temp(*this);
|
PDFBitReader temp(*this);
|
||||||
return temp.read(bits);
|
|
||||||
|
Value result = 0;
|
||||||
|
for (Value i = 0; i < bits; ++i)
|
||||||
|
{
|
||||||
|
if (!temp.isAtEnd())
|
||||||
|
{
|
||||||
|
result = (result << 1) | temp.read(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = (result << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDFBitReader::seek(qint64 position)
|
void PDFBitReader::seek(qint64 position)
|
||||||
|
Reference in New Issue
Block a user