diff --git a/JBIG2_Viewer/mainwindow.cpp b/JBIG2_Viewer/mainwindow.cpp index 7804535..eb1f0f5 100644 --- a/JBIG2_Viewer/mainwindow.cpp +++ b/JBIG2_Viewer/mainwindow.cpp @@ -12,6 +12,7 @@ #include #include #include +#include MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), @@ -90,7 +91,11 @@ void MainWindow::on_actionAdd_JBIG2_image_triggered() try { pdf::PDFJBIG2Decoder decoder(data, QByteArray(), this); + + QElapsedTimer timer; + timer.start(); pdf::PDFImageData imageData = decoder.decodeFileStream(); + qint64 time = timer.elapsed(); if (imageData.isValid()) { @@ -98,7 +103,7 @@ void MainWindow::on_actionAdd_JBIG2_image_triggered() const uchar* sourceData = reinterpret_cast(imageData.getData().constData()); Q_ASSERT(imageData.getData().size() == image.byteCount()); std::transform(sourceData, sourceData + imageData.getData().size(), image.bits(), [](const uchar value) { return ~value; }); - addImage(file.fileName(), qMove(image)); + addImage(file.fileName() + QString(", Decoded in %1 [msec]").arg(time), qMove(image)); } } catch (pdf::PDFException exception) diff --git a/PdfForQtLib/sources/pdfjbig2decoder.cpp b/PdfForQtLib/sources/pdfjbig2decoder.cpp index 27593c8..a794c5e 100644 --- a/PdfForQtLib/sources/pdfjbig2decoder.cpp +++ b/PdfForQtLib/sources/pdfjbig2decoder.cpp @@ -708,6 +708,17 @@ std::optional PDFJBIG2ArithmeticDecoder::getSignedInteger(PDFJBIG2Arith } } +void PDFJBIG2ArithmeticDecoder::finalize() +{ + if (m_lastByte == 0xFF) + { + if (m_reader->look(8) == 0xAC) + { + m_reader->read(8); + } + } +} + void PDFJBIG2ArithmeticDecoder::perform_INITDEC() { // Used figure G.1, in annex G, of specification @@ -1391,7 +1402,7 @@ void PDFJBIG2Decoder::processSymbolDictionary(const PDFJBIG2SegmentHeader& heade uint32_t HCFIRSTSYM = NSYMSDECODED; /* 6.5.5 step 4) c) - read height class */ - while (NSYMSDECODED < parameters.SDNUMNEWSYMS) + while (NSYMSDECODED <= parameters.SDNUMNEWSYMS) { /* 6.5.5 step 4) c) i) - Delta width acc. to 6.5.7 */ std::optional DW = parameters.SDHUFF ? parameters.SDHUFFDW_Decoder.readSignedInteger() : arithmeticDecoder.getSignedInteger(&arithmeticDecoderStates.states[PDFJBIG2ArithmeticDecoderStates::IADW]); @@ -1596,6 +1607,12 @@ void PDFJBIG2Decoder::processSymbolDictionary(const PDFJBIG2SegmentHeader& heade while (EXFLAGS.size() < symbolsSize) { const uint32_t EXRUNLENGTH = static_cast(checkInteger(parameters.SDHUFF ? parameters.EXRUNLENGTH_Decoder.readSignedInteger() : arithmeticDecoder.getSignedInteger(&arithmeticDecoderStates.states[PDFJBIG2ArithmeticDecoderStates::IAEX]))); + + if (EXRUNLENGTH + EXFLAGS.size() > symbolsSize) + { + throw PDFException(PDFTranslationContext::tr("JBIG2 - invalid export flags in symbol dictionary.")); + } + EXFLAGS.insert(EXFLAGS.end(), EXRUNLENGTH, CUREXFLAG); CUREXFLAG = !CUREXFLAG; } @@ -1603,7 +1620,7 @@ void PDFJBIG2Decoder::processSymbolDictionary(const PDFJBIG2SegmentHeader& heade if (!parameters.SDHUFF) { // Skipneme 1 byte na konci - m_reader.skipBytes(1); + arithmeticDecoder.finalize(); } std::vector bitmaps; @@ -1994,6 +2011,11 @@ void PDFJBIG2Decoder::processTextRegion(const PDFJBIG2SegmentHeader& header) { throw PDFException(PDFTranslationContext::tr("JBIG2 - invalid bitmap for generic region.")); } + + if (!parameters.SBHUFF) + { + decoder.finalize(); + } } void PDFJBIG2Decoder::processPatternDictionary(const PDFJBIG2SegmentHeader& header) @@ -2190,6 +2212,8 @@ void PDFJBIG2Decoder::processGenericRefinementRegion(const PDFJBIG2SegmentHeader { throw PDFException(PDFTranslationContext::tr("JBIG2 - invalid bitmap for generic refinement region.")); } + + decoder.finalize(); } void PDFJBIG2Decoder::processPageInformation(const PDFJBIG2SegmentHeader&) diff --git a/PdfForQtLib/sources/pdfjbig2decoder.h b/PdfForQtLib/sources/pdfjbig2decoder.h index d569e22..c74a88c 100644 --- a/PdfForQtLib/sources/pdfjbig2decoder.h +++ b/PdfForQtLib/sources/pdfjbig2decoder.h @@ -162,6 +162,10 @@ public: int32_t getIAID(uint32_t size, PDFJBIG2ArithmeticDecoderState* state); std::optional getSignedInteger(PDFJBIG2ArithmeticDecoderState* state); + /// This function is used to read last byte of byte sequence { 0xFF, 0xAC }, + /// when finishing data stream. + void finalize(); + private: /// Performs INITDEC operation as described in the specification void perform_INITDEC();