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 << "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<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)
|
||||
{
|
||||
mUncompressedBlockLength = datalength;
|
||||
|
||||
unsigned char working_block{0};
|
||||
working_block |= static_cast<unsigned char>(mInFinalBlock);
|
||||
working_block |= (static_cast<unsigned char>(mCompressionMethod) << 1);
|
||||
|
||||
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);
|
||||
|
||||
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<uint16_t>(~datalength));
|
||||
std::cout << "Writing iverse data length " << ~mUncompressedBlockLength << " " << ByteUtils::toString(~mUncompressedBlockLength) << std::endl;
|
||||
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();
|
||||
//std::cout << "Writing next byte " << static_cast<int>(byte) << std::endl;
|
||||
|
|
|
@ -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<unsigned char, unsigned>;
|
||||
using CodeLengthCountEntry = std::pair<unsigned, std::vector<CodeLengthEntry> >;
|
||||
std::vector<CodeLengthCountEntry> mCodeLengthMapping;
|
||||
|
|
|
@ -64,7 +64,7 @@ bool DeflateEncoder::encode()
|
|||
bool DeflateEncoder::decode()
|
||||
{
|
||||
auto working_block = std::make_unique<DeflateBlock>(mInputStream, mOutputStream);
|
||||
working_block->readHeader();
|
||||
working_block->read();
|
||||
|
||||
std::cout << working_block->getMetaData() << std::endl;
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
#include "File.h"
|
||||
|
||||
#include "FileLogger.h"
|
||||
#include "ByteUtils.h"
|
||||
|
||||
#include <streambuf>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
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<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
|
||||
{
|
||||
return mInHandle.get();
|
||||
|
|
|
@ -51,6 +51,8 @@ public:
|
|||
|
||||
std::optional<unsigned char> readNextByte();
|
||||
|
||||
std::string dumpBinary();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -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<num_bytes;idx++)
|
||||
{
|
||||
writeByte(ByteUtils::getByteN(data, idx));
|
||||
}
|
||||
const auto byte0 = data >> 8;
|
||||
const auto byte1 = (data << 8) >> 8;
|
||||
writeByte(byte0);
|
||||
writeByte(byte1);
|
||||
}
|
||||
|
||||
int BitStream::getCurrentByteOffset() const
|
||||
|
|
|
@ -57,8 +57,6 @@ public:
|
|||
mChecksumCalculator = nullptr;
|
||||
}
|
||||
|
||||
//unsigned getSize() = 0;
|
||||
|
||||
protected:
|
||||
int mByteOffset{-1};
|
||||
unsigned mBitOffset{0};
|
||||
|
|
|
@ -11,7 +11,14 @@ std::vector<unsigned char> BufferBitStream::peekNextNBytes(unsigned n) const
|
|||
{
|
||||
std::vector<unsigned char> ret (n, 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())
|
||||
{
|
||||
|
|
|
@ -22,6 +22,16 @@ void Image<T>::initialize()
|
|||
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>
|
||||
void Image<T>::setPixelValue(unsigned idx, unsigned jdx, const Color& color)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,8 @@ public:
|
|||
T getByte(unsigned idx, unsigned jdx) const;
|
||||
|
||||
void setData(const std::vector<T>& data);
|
||||
|
||||
void setDataItem(std::size_t index, T);
|
||||
void setWidth(unsigned width);
|
||||
void setHeight(unsigned height);
|
||||
void setBitDepth(unsigned bitDepth);
|
||||
|
|
|
@ -31,6 +31,12 @@ std::optional<unsigned char> ImageBitStream::readNextByte()
|
|||
|
||||
void ImageBitStream::writeByte(unsigned char data)
|
||||
{
|
||||
mByteOffset++;
|
||||
|
||||
if (isFinished() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
mImage->setDataItem(mByteOffset, data);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,32 @@ public:
|
|||
|
||||
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:
|
||||
|
|
|
@ -13,6 +13,26 @@ public:
|
|||
|
||||
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;
|
||||
|
||||
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
|
||||
{
|
||||
switch(method)
|
||||
|
|
|
@ -31,6 +31,8 @@ public:
|
|||
ADAM7 = 1
|
||||
};
|
||||
|
||||
unsigned getNumChannels() const;
|
||||
|
||||
std::string toString(ColorType colorType) const;
|
||||
|
||||
std::string toString(CompressionMethod method) const;
|
||||
|
|
|
@ -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<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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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; idx<image->getWidth()*image->getBytesPerRow(); idx++)
|
||||
{
|
||||
std::cout << "Image val: " << idx << " | " << static_cast<int>(image->getDataRef()[idx]) << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
int main()
|
||||
{
|
||||
unsigned width = 10;
|
||||
unsigned height = 10;
|
||||
unsigned width = 20;
|
||||
unsigned height = 20;
|
||||
unsigned numChannels = 1;
|
||||
auto image = Image<unsigned char>::Create(width, height);
|
||||
image->setNumChannels(numChannels);
|
||||
|
@ -19,7 +19,8 @@ int main()
|
|||
std::vector<unsigned char> data(width*height, 0);
|
||||
for (unsigned idx=0; idx<width*height; idx++)
|
||||
{
|
||||
data[idx] = 10;
|
||||
unsigned char val = 255 * idx /(width*height);
|
||||
data[idx] = val;
|
||||
}
|
||||
|
||||
image->setData(data);
|
||||
|
|
Loading…
Reference in a new issue