Non compressing png writer is ok.

This commit is contained in:
James Grogan 2022-11-25 09:43:14 +00:00
parent 33369b1775
commit e4f9393ee7
18 changed files with 196 additions and 23 deletions

View file

@ -233,7 +233,7 @@ std::string DeflateBlock::getMetaData() const
sstr << "Final block: " << mInFinalBlock << '\n'; sstr << "Final block: " << mInFinalBlock << '\n';
sstr << "Compression method: " << Deflate::toString(mCompressionMethod) << '\n'; sstr << "Compression method: " << Deflate::toString(mCompressionMethod) << '\n';
sstr << "Uncompressed block length: " << mUncompressedBlockLength << '\n';
return sstr.str(); return sstr.str();
} }
@ -242,11 +242,10 @@ bool DeflateBlock::isFinalBlock() const
return mInFinalBlock; return mInFinalBlock;
} }
void DeflateBlock::readHeader() bool DeflateBlock::read()
{ {
auto working_byte = mInputStream->getCurrentByte(); auto working_byte = *mInputStream->readNextByte();
std::cout << "Into process data "<< std::endl; std::cout << "Into process data, starts with: "<< ByteUtils::toString(working_byte) << std::endl;
std::cout << mInputStream->logNextNBytes(9);
unsigned char final_block{0}; unsigned char final_block{0};
mInputStream->readNextNBits(1, final_block); mInputStream->readNextNBits(1, final_block);
@ -255,26 +254,58 @@ void DeflateBlock::readHeader()
unsigned char compression_type{0}; unsigned char compression_type{0};
mInputStream->readNextNBits(2, compression_type); mInputStream->readNextNBits(2, compression_type);
mCompressionMethod = static_cast<Deflate::CompressionMethod>(compression_type); mCompressionMethod = static_cast<Deflate::CompressionMethod>(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; idx<mUncompressedBlockLength;idx++)
{
mOutputStream->writeByte(*mInputStream->readNextByte());
}
//}
}
return true;
} }
void DeflateBlock::write(uint16_t datalength) void DeflateBlock::write(uint16_t datalength)
{ {
mUncompressedBlockLength = datalength;
unsigned char working_block{0}; unsigned char working_block{0};
working_block |= static_cast<unsigned char>(mInFinalBlock); working_block |= static_cast<unsigned char>(mInFinalBlock);
working_block |= (static_cast<unsigned char>(mCompressionMethod) << 1); working_block |= (static_cast<unsigned char>(mCompressionMethod) << 1);
if (mCompressionMethod == Deflate::CompressionMethod::NONE) if (mCompressionMethod == Deflate::CompressionMethod::NONE)
{ {
std::cout << "Writing compression block header " << static_cast<int>(working_block) << std::endl; std::cout << "Writing compression block header " << ByteUtils::toString(working_block) << std::endl;
mOutputStream->writeByte(working_block); 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); mOutputStream->writeWord(datalength);
std::cout << "Writing iverse data length " << ~datalength << " " << ByteUtils::toString(~datalength) << std::endl; std::cout << "Writing iverse data length " << ~mUncompressedBlockLength << " " << ByteUtils::toString(~mUncompressedBlockLength) << std::endl;
mOutputStream->writeWord(static_cast<uint16_t>(~datalength)); mOutputStream->writeWord(static_cast<uint16_t>(~mUncompressedBlockLength));
for(unsigned idx=0; idx<datalength;idx++) for(unsigned idx=0; idx<mUncompressedBlockLength;idx++)
{ {
auto byte = *mInputStream->readNextByte(); auto byte = *mInputStream->readNextByte();
//std::cout << "Writing next byte " << static_cast<int>(byte) << std::endl; //std::cout << "Writing next byte " << static_cast<int>(byte) << std::endl;

View file

@ -19,7 +19,7 @@ public:
bool isFinalBlock() const; bool isFinalBlock() const;
void readHeader(); bool read();
void readDynamicHuffmanTable(); void readDynamicHuffmanTable();
@ -47,6 +47,8 @@ private:
unsigned mHdist{0}; unsigned mHdist{0};
unsigned mHclen{0}; unsigned mHclen{0};
uint16_t mUncompressedBlockLength{0};
using CodeLengthEntry = std::pair<unsigned char, unsigned>; using CodeLengthEntry = std::pair<unsigned char, unsigned>;
using CodeLengthCountEntry = std::pair<unsigned, std::vector<CodeLengthEntry> >; using CodeLengthCountEntry = std::pair<unsigned, std::vector<CodeLengthEntry> >;
std::vector<CodeLengthCountEntry> mCodeLengthMapping; std::vector<CodeLengthCountEntry> mCodeLengthMapping;

View file

@ -64,7 +64,7 @@ bool DeflateEncoder::encode()
bool DeflateEncoder::decode() bool DeflateEncoder::decode()
{ {
auto working_block = std::make_unique<DeflateBlock>(mInputStream, mOutputStream); auto working_block = std::make_unique<DeflateBlock>(mInputStream, mOutputStream);
working_block->readHeader(); working_block->read();
std::cout << working_block->getMetaData() << std::endl; std::cout << working_block->getMetaData() << std::endl;

View file

@ -1,7 +1,11 @@
#include "File.h" #include "File.h"
#include "FileLogger.h" #include "FileLogger.h"
#include "ByteUtils.h"
#include <streambuf> #include <streambuf>
#include <fstream> #include <fstream>
#include <sstream>
File::File(std::filesystem::path path) File::File(std::filesystem::path path)
: mFullPath(path), : mFullPath(path),
@ -22,6 +26,30 @@ void File::SetAccessMode(AccessMode mode)
mAccessMode = 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<unsigned char>(mInHandle->get());
const unsigned char ascii_val = std::isalpha(val) ? val : '.';
sstr << count << " | " << ByteUtils::toString(val) << " | " << static_cast<int>(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 std::ifstream* File::GetInHandle() const
{ {
return mInHandle.get(); return mInHandle.get();

View file

@ -51,6 +51,8 @@ public:
std::optional<unsigned char> readNextByte(); std::optional<unsigned char> readNextByte();
std::string dumpBinary();
private: private:

View file

@ -30,11 +30,10 @@ void BitStream::write(uint32_t data)
void BitStream::writeWord(uint16_t data) void BitStream::writeWord(uint16_t data)
{ {
unsigned num_bytes = sizeof(uint16_t); const auto byte0 = data >> 8;
for(unsigned idx=0; idx<num_bytes;idx++) const auto byte1 = (data << 8) >> 8;
{ writeByte(byte0);
writeByte(ByteUtils::getByteN(data, idx)); writeByte(byte1);
}
} }
int BitStream::getCurrentByteOffset() const int BitStream::getCurrentByteOffset() const

View file

@ -57,8 +57,6 @@ public:
mChecksumCalculator = nullptr; mChecksumCalculator = nullptr;
} }
//unsigned getSize() = 0;
protected: protected:
int mByteOffset{-1}; int mByteOffset{-1};
unsigned mBitOffset{0}; unsigned mBitOffset{0};

View file

@ -11,7 +11,14 @@ std::vector<unsigned char> BufferBitStream::peekNextNBytes(unsigned n) const
{ {
std::vector<unsigned char> ret (n, 0); std::vector<unsigned char> ret (n, 0);
unsigned count = 0; unsigned count = 0;
for(unsigned idx=mByteOffset; idx<mByteOffset + n; idx++)
int start = mByteOffset;
if (start<0)
{
start = 0;
}
for(unsigned idx=start; idx<start + n; idx++)
{ {
if (idx == mBuffer.size()) if (idx == mBuffer.size())
{ {

View file

@ -22,6 +22,16 @@ void Image<T>::initialize()
mData = std::vector<T>(getBytesPerRow()*mHeight, 10); mData = std::vector<T>(getBytesPerRow()*mHeight, 10);
} }
template<typename T>
void Image<T>::setDataItem(std::size_t index, T item)
{
if(index >= mData.size())
{
return;
}
mData[index] = item;
}
template<typename T> template<typename T>
void Image<T>::setPixelValue(unsigned idx, unsigned jdx, const Color& color) void Image<T>::setPixelValue(unsigned idx, unsigned jdx, const Color& color)
{ {

View file

@ -24,6 +24,8 @@ public:
T getByte(unsigned idx, unsigned jdx) const; T getByte(unsigned idx, unsigned jdx) const;
void setData(const std::vector<T>& data); void setData(const std::vector<T>& data);
void setDataItem(std::size_t index, T);
void setWidth(unsigned width); void setWidth(unsigned width);
void setHeight(unsigned height); void setHeight(unsigned height);
void setBitDepth(unsigned bitDepth); void setBitDepth(unsigned bitDepth);

View file

@ -31,6 +31,12 @@ std::optional<unsigned char> ImageBitStream::readNextByte()
void ImageBitStream::writeByte(unsigned char data) void ImageBitStream::writeByte(unsigned char data)
{ {
mByteOffset++;
if (isFinished() )
{
return;
}
mImage->setDataItem(mByteOffset, data);
} }

View file

@ -62,7 +62,32 @@ public:
void decode() void decode()
{ {
auto image_stream = dynamic_cast<ImageBitStream*>(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<FilterType>(*byte);
}
else
{
if (working_filter_type == FilterType::NONE)
{
image_stream->writeByte(*byte);
}
}
count++;
}
} }
private: private:

View file

@ -13,6 +13,26 @@ public:
const std::vector<unsigned char>& getData() const; const std::vector<unsigned char>& 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; unsigned char getHighBitCheck() const;
std::vector<unsigned char> getSignature() const; std::vector<unsigned char> getSignature() const;

View file

@ -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 std::string PngInfo::toString(CompressionMethod method) const
{ {
switch(method) switch(method)

View file

@ -31,6 +31,8 @@ public:
ADAM7 = 1 ADAM7 = 1
}; };
unsigned getNumChannels() const;
std::string toString(ColorType colorType) const; std::string toString(ColorType colorType) const;
std::string toString(CompressionMethod method) const; std::string toString(CompressionMethod method) const;

View file

@ -3,6 +3,8 @@
#include "BinaryStream.h" #include "BinaryStream.h"
#include "BitStream.h" #include "BitStream.h"
#include "BufferBitStream.h" #include "BufferBitStream.h"
#include "ImageBitStream.h"
#include "PngFilter.h"
#include "ZlibEncoder.h" #include "ZlibEncoder.h"
#include "CyclicRedundancyChecker.h" #include "CyclicRedundancyChecker.h"
@ -180,6 +182,17 @@ std::unique_ptr<Image<unsigned char> > 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<ImageBitStream>(image.get());
PngFilter filter(mOutputStream.get(), image_bit_stream.get());
filter.decode();
return std::move(image); return std::move(image);
} }

View file

@ -13,9 +13,17 @@ int main()
const auto path = "/home/jmsgrogan/code/MediaTool-build/bin/test.png"; const auto path = "/home/jmsgrogan/code/MediaTool-build/bin/test.png";
File file(path);
std::cout << file.dumpBinary();
PngReader reader; PngReader reader;
reader.setPath(path); reader.setPath(path);
auto image = reader.read(); auto image = reader.read();
for(unsigned idx=0; idx<image->getWidth()*image->getBytesPerRow(); idx++)
{
std::cout << "Image val: " << idx << " | " << static_cast<int>(image->getDataRef()[idx]) << std::endl;
}
return 0; return 0;
} }

View file

@ -9,8 +9,8 @@
int main() int main()
{ {
unsigned width = 10; unsigned width = 20;
unsigned height = 10; unsigned height = 20;
unsigned numChannels = 1; unsigned numChannels = 1;
auto image = Image<unsigned char>::Create(width, height); auto image = Image<unsigned char>::Create(width, height);
image->setNumChannels(numChannels); image->setNumChannels(numChannels);
@ -19,7 +19,8 @@ int main()
std::vector<unsigned char> data(width*height, 0); std::vector<unsigned char> data(width*height, 0);
for (unsigned idx=0; idx<width*height; idx++) for (unsigned idx=0; idx<width*height; idx++)
{ {
data[idx] = 10; unsigned char val = 255 * idx /(width*height);
data[idx] = val;
} }
image->setData(data); image->setData(data);