Non compressing png writer is ok.
This commit is contained in:
parent
33369b1775
commit
e4f9393ee7
18 changed files with 196 additions and 23 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -51,6 +51,8 @@ public:
|
||||||
|
|
||||||
std::optional<unsigned char> readNextByte();
|
std::optional<unsigned char> readNextByte();
|
||||||
|
|
||||||
|
std::string dumpBinary();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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())
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue