diff --git a/src/compression/deflate/DeflateBlock.cpp b/src/compression/deflate/DeflateBlock.cpp index 5b07615..7626675 100644 --- a/src/compression/deflate/DeflateBlock.cpp +++ b/src/compression/deflate/DeflateBlock.cpp @@ -233,7 +233,7 @@ std::string DeflateBlock::getMetaData() const sstr << "Final block: " << mInFinalBlock << '\n'; sstr << "Compression method: " << Deflate::toString(mCompressionMethod) << '\n'; - + sstr << "Uncompressed block length: " << mUncompressedBlockLength << '\n'; return sstr.str(); } @@ -242,11 +242,10 @@ bool DeflateBlock::isFinalBlock() const return mInFinalBlock; } -void DeflateBlock::readHeader() +bool DeflateBlock::read() { - auto working_byte = mInputStream->getCurrentByte(); - std::cout << "Into process data "<< std::endl; - std::cout << mInputStream->logNextNBytes(9); + auto working_byte = *mInputStream->readNextByte(); + std::cout << "Into process data, starts with: "<< ByteUtils::toString(working_byte) << std::endl; unsigned char final_block{0}; mInputStream->readNextNBits(1, final_block); @@ -255,26 +254,58 @@ void DeflateBlock::readHeader() unsigned char compression_type{0}; mInputStream->readNextNBits(2, compression_type); mCompressionMethod = static_cast(compression_type); + + if (mCompressionMethod == Deflate::CompressionMethod::NONE) + { + auto byte0 = *mInputStream->readNextByte(); + auto byte1 = *mInputStream->readNextByte(); + mUncompressedBlockLength = (byte0 << 8) | byte1; + + std::cout << "Check block 0: " << ByteUtils::toString(byte0) << std::endl; + std::cout << "Check block 1: " << ByteUtils::toString(byte1) << std::endl; + + auto byte2 = *mInputStream->readNextByte(); + auto byte3 = *mInputStream->readNextByte(); + uint16_t len_check = (byte2 << 8) | byte3; + + std::cout << "Check block 2: " << ByteUtils::toString(byte2) << std::endl; + std::cout << "Check block 3: " << ByteUtils::toString(byte3) << std::endl; + //if (!(byte0 ==(~byte2) && byte1 ==(~byte3))) + //{ + //std::cout << "Uncompressed block length check failed - aborting." << std::endl; + //return false; + //} + //else + //{ + for(unsigned idx=0; idxwriteByte(*mInputStream->readNextByte()); + } + //} + } + return true; } void DeflateBlock::write(uint16_t datalength) { + mUncompressedBlockLength = datalength; + unsigned char working_block{0}; working_block |= static_cast(mInFinalBlock); working_block |= (static_cast(mCompressionMethod) << 1); if (mCompressionMethod == Deflate::CompressionMethod::NONE) { - std::cout << "Writing compression block header " << static_cast(working_block) << std::endl; + std::cout << "Writing compression block header " << ByteUtils::toString(working_block) << std::endl; mOutputStream->writeByte(working_block); - std::cout << "Writing data length " << datalength << " " << ByteUtils::toString(datalength) << std::endl; + std::cout << "Writing data length " << mUncompressedBlockLength << " " << ByteUtils::toString(mUncompressedBlockLength) << std::endl; mOutputStream->writeWord(datalength); - std::cout << "Writing iverse data length " << ~datalength << " " << ByteUtils::toString(~datalength) << std::endl; - mOutputStream->writeWord(static_cast(~datalength)); + std::cout << "Writing iverse data length " << ~mUncompressedBlockLength << " " << ByteUtils::toString(~mUncompressedBlockLength) << std::endl; + mOutputStream->writeWord(static_cast(~mUncompressedBlockLength)); - for(unsigned idx=0; idxreadNextByte(); //std::cout << "Writing next byte " << static_cast(byte) << std::endl; diff --git a/src/compression/deflate/DeflateBlock.h b/src/compression/deflate/DeflateBlock.h index 7683b38..b5bf074 100644 --- a/src/compression/deflate/DeflateBlock.h +++ b/src/compression/deflate/DeflateBlock.h @@ -19,7 +19,7 @@ public: bool isFinalBlock() const; - void readHeader(); + bool read(); void readDynamicHuffmanTable(); @@ -47,6 +47,8 @@ private: unsigned mHdist{0}; unsigned mHclen{0}; + uint16_t mUncompressedBlockLength{0}; + using CodeLengthEntry = std::pair; using CodeLengthCountEntry = std::pair >; std::vector mCodeLengthMapping; diff --git a/src/compression/deflate/DeflateEncoder.cpp b/src/compression/deflate/DeflateEncoder.cpp index 92d1dc8..18f9031 100644 --- a/src/compression/deflate/DeflateEncoder.cpp +++ b/src/compression/deflate/DeflateEncoder.cpp @@ -64,7 +64,7 @@ bool DeflateEncoder::encode() bool DeflateEncoder::decode() { auto working_block = std::make_unique(mInputStream, mOutputStream); - working_block->readHeader(); + working_block->read(); std::cout << working_block->getMetaData() << std::endl; diff --git a/src/core/file_utilities/File.cpp b/src/core/file_utilities/File.cpp index 2dde794..b904a8b 100644 --- a/src/core/file_utilities/File.cpp +++ b/src/core/file_utilities/File.cpp @@ -1,7 +1,11 @@ #include "File.h" + #include "FileLogger.h" +#include "ByteUtils.h" + #include #include +#include File::File(std::filesystem::path path) : mFullPath(path), @@ -22,6 +26,30 @@ void File::SetAccessMode(AccessMode mode) mAccessMode = mode; } +std::string File::dumpBinary() +{ + mAccessMode = AccessMode::Read; + Open(); + + std::stringstream sstr; + sstr << "Count | Binary | Decimal | ASCII \n"; + unsigned count = 0; + while(mInHandle->peek() != EOF) + { + const unsigned char val = static_cast(mInHandle->get()); + const unsigned char ascii_val = std::isalpha(val) ? val : '.'; + sstr << count << " | " << ByteUtils::toString(val) << " | " << static_cast(val) << " | " << ascii_val << '\n'; + if (count < 0 && count % 10 == 0) + { + sstr << "\n"; + } + count++; + } + const auto out = sstr.str(); + Close(); + return out; +} + std::ifstream* File::GetInHandle() const { return mInHandle.get(); diff --git a/src/core/file_utilities/File.h b/src/core/file_utilities/File.h index cf842c6..2509be7 100644 --- a/src/core/file_utilities/File.h +++ b/src/core/file_utilities/File.h @@ -51,6 +51,8 @@ public: std::optional readNextByte(); + std::string dumpBinary(); + private: diff --git a/src/core/streams/BitStream.cpp b/src/core/streams/BitStream.cpp index 98116e9..2505199 100644 --- a/src/core/streams/BitStream.cpp +++ b/src/core/streams/BitStream.cpp @@ -30,11 +30,10 @@ void BitStream::write(uint32_t data) void BitStream::writeWord(uint16_t data) { - unsigned num_bytes = sizeof(uint16_t); - for(unsigned idx=0; idx> 8; + const auto byte1 = (data << 8) >> 8; + writeByte(byte0); + writeByte(byte1); } int BitStream::getCurrentByteOffset() const diff --git a/src/core/streams/BitStream.h b/src/core/streams/BitStream.h index 1421ce0..fc971e6 100644 --- a/src/core/streams/BitStream.h +++ b/src/core/streams/BitStream.h @@ -57,8 +57,6 @@ public: mChecksumCalculator = nullptr; } - //unsigned getSize() = 0; - protected: int mByteOffset{-1}; unsigned mBitOffset{0}; diff --git a/src/core/streams/BufferBitStream.cpp b/src/core/streams/BufferBitStream.cpp index 2aa9fbc..83225ec 100644 --- a/src/core/streams/BufferBitStream.cpp +++ b/src/core/streams/BufferBitStream.cpp @@ -11,7 +11,14 @@ std::vector BufferBitStream::peekNextNBytes(unsigned n) const { std::vector ret (n, 0); unsigned count = 0; - for(unsigned idx=mByteOffset; idx::initialize() mData = std::vector(getBytesPerRow()*mHeight, 10); } +template +void Image::setDataItem(std::size_t index, T item) +{ + if(index >= mData.size()) + { + return; + } + mData[index] = item; +} + template void Image::setPixelValue(unsigned idx, unsigned jdx, const Color& color) { diff --git a/src/image/Image.h b/src/image/Image.h index a699e72..be354a6 100644 --- a/src/image/Image.h +++ b/src/image/Image.h @@ -24,6 +24,8 @@ public: T getByte(unsigned idx, unsigned jdx) const; void setData(const std::vector& data); + + void setDataItem(std::size_t index, T); void setWidth(unsigned width); void setHeight(unsigned height); void setBitDepth(unsigned bitDepth); diff --git a/src/image/ImageBitStream.cpp b/src/image/ImageBitStream.cpp index 83e7aca..2e782ff 100644 --- a/src/image/ImageBitStream.cpp +++ b/src/image/ImageBitStream.cpp @@ -31,6 +31,12 @@ std::optional ImageBitStream::readNextByte() void ImageBitStream::writeByte(unsigned char data) { + mByteOffset++; + if (isFinished() ) + { + return; + } + mImage->setDataItem(mByteOffset, data); } diff --git a/src/image/png/PngFilter.h b/src/image/png/PngFilter.h index 02dd76f..fd933a4 100644 --- a/src/image/png/PngFilter.h +++ b/src/image/png/PngFilter.h @@ -62,7 +62,32 @@ public: void decode() { + auto image_stream = dynamic_cast(mOutputStream); + if (!image_stream) + { + MLOG_ERROR("Expected ImageStream in PngFilter decode - aborting."); + return; + } + const auto bytes_per_scanline = image_stream->getBytesPerScanline(); + unsigned count{0}; + + FilterType working_filter_type = FilterType::NONE; + while(auto byte = mInputStream->readNextByte()) + { + if (count % bytes_per_scanline == 0) + { + working_filter_type = static_cast(*byte); + } + else + { + if (working_filter_type == FilterType::NONE) + { + image_stream->writeByte(*byte); + } + } + count++; + } } private: diff --git a/src/image/png/PngHeader.h b/src/image/png/PngHeader.h index 17ee0b4..18ae8eb 100644 --- a/src/image/png/PngHeader.h +++ b/src/image/png/PngHeader.h @@ -13,6 +13,26 @@ public: const std::vector& getData() const; + uint32_t getWidth() const + { + return mWidth; + } + + uint32_t getHeight() const + { + return mHeight; + } + + unsigned char getBitDepth() const + { + return mBitDepth; + } + + const PngInfo& getPngInfo() const + { + return mPngInfo; + } + unsigned char getHighBitCheck() const; std::vector getSignature() const; diff --git a/src/image/png/PngInfo.cpp b/src/image/png/PngInfo.cpp index f0f603e..c505a1e 100644 --- a/src/image/png/PngInfo.cpp +++ b/src/image/png/PngInfo.cpp @@ -19,6 +19,25 @@ std::string PngInfo::toString(ColorType colorType) const } } +unsigned PngInfo::getNumChannels() const +{ + switch(mColorType) + { + case ColorType::GREYSCALE: + return 1; + case ColorType::RGB: + return 3; + case ColorType::PALETTE: + return 1; + case ColorType::GREYSCALE_ALPHA: + return 2; + case ColorType::RGB_ALPHA: + return 4; + default: + return 1; + } +} + std::string PngInfo::toString(CompressionMethod method) const { switch(method) diff --git a/src/image/png/PngInfo.h b/src/image/png/PngInfo.h index 3c78f72..d6e1e08 100644 --- a/src/image/png/PngInfo.h +++ b/src/image/png/PngInfo.h @@ -31,6 +31,8 @@ public: ADAM7 = 1 }; + unsigned getNumChannels() const; + std::string toString(ColorType colorType) const; std::string toString(CompressionMethod method) const; diff --git a/src/image/png/PngReader.cpp b/src/image/png/PngReader.cpp index 0b8322d..87b6fb2 100644 --- a/src/image/png/PngReader.cpp +++ b/src/image/png/PngReader.cpp @@ -3,6 +3,8 @@ #include "BinaryStream.h" #include "BitStream.h" #include "BufferBitStream.h" +#include "ImageBitStream.h" +#include "PngFilter.h" #include "ZlibEncoder.h" #include "CyclicRedundancyChecker.h" @@ -180,6 +182,17 @@ std::unique_ptr > PngReader::read() { } + + image->setWidth(mHeader.getWidth()); + image->setHeight(mHeader.getHeight()); + image->setBitDepth(mHeader.getBitDepth()); + image->setNumChannels(mHeader.getPngInfo().getNumChannels()); + image->initialize(); + + auto image_bit_stream = std::make_unique(image.get()); + PngFilter filter(mOutputStream.get(), image_bit_stream.get()); + filter.decode(); + return std::move(image); } diff --git a/test/image/TestPngReader.cpp b/test/image/TestPngReader.cpp index b0458fd..e046476 100644 --- a/test/image/TestPngReader.cpp +++ b/test/image/TestPngReader.cpp @@ -13,9 +13,17 @@ int main() const auto path = "/home/jmsgrogan/code/MediaTool-build/bin/test.png"; + File file(path); + std::cout << file.dumpBinary(); + PngReader reader; reader.setPath(path); auto image = reader.read(); + for(unsigned idx=0; idxgetWidth()*image->getBytesPerRow(); idx++) + { + std::cout << "Image val: " << idx << " | " << static_cast(image->getDataRef()[idx]) << std::endl; + } + return 0; } diff --git a/test/image/TestPngWriter.cpp b/test/image/TestPngWriter.cpp index 05e9097..6ac64a0 100644 --- a/test/image/TestPngWriter.cpp +++ b/test/image/TestPngWriter.cpp @@ -9,8 +9,8 @@ int main() { - unsigned width = 10; - unsigned height = 10; + unsigned width = 20; + unsigned height = 20; unsigned numChannels = 1; auto image = Image::Create(width, height); image->setNumChannels(numChannels); @@ -19,7 +19,8 @@ int main() std::vector data(width*height, 0); for (unsigned idx=0; idxsetData(data);