Continue png writing.
This commit is contained in:
parent
5400a232dd
commit
8f97e9b7a1
29 changed files with 714 additions and 302 deletions
284
src/compression/deflate/DeflateBlock.cpp
Normal file
284
src/compression/deflate/DeflateBlock.cpp
Normal file
|
@ -0,0 +1,284 @@
|
|||
#include "DeflateBlock.h"
|
||||
|
||||
#include "ByteUtils.h"
|
||||
#include "AbstractChecksumCalculator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
DeflateBlock::DeflateBlock(BitStream* inputStream, BitStream* outputStream)
|
||||
: mInputStream(inputStream),
|
||||
mOutputStream(outputStream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool DeflateBlock::readNextCodeLengthSymbol(unsigned char& final_symbol)
|
||||
{
|
||||
unsigned working_index{0};
|
||||
auto count = mCodeLengthMapping[working_index].first;
|
||||
auto delta = count;
|
||||
|
||||
bool found{false};
|
||||
unsigned char buffer{0};
|
||||
unsigned char working_bits{0};
|
||||
unsigned working_symbol{0};
|
||||
|
||||
while(!found)
|
||||
{
|
||||
auto valid = mInputStream->readNextNBits(delta, buffer);
|
||||
working_bits = (working_bits << delta) | buffer;
|
||||
|
||||
for(const auto& entry : mCodeLengthMapping[working_index].second)
|
||||
{
|
||||
if (entry.first == working_bits)
|
||||
{
|
||||
found = true;
|
||||
working_symbol = entry.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
working_index++;
|
||||
if (working_index >= mCodeLengthMapping.size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
auto new_count = mCodeLengthMapping[working_index].first;
|
||||
delta = new_count - count;
|
||||
count = new_count;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
{
|
||||
final_symbol = working_symbol;
|
||||
std::cout << "Found symbol " << working_symbol << " with bits " << ByteUtils::toString(working_bits) << std::endl;
|
||||
std::cout << "At Byte offset " << mInputStream->getCurrentByteOffset() << " and bit offset " << mInputStream->getCurrentBitOffset() << std::endl;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "SYMBOL NOT FOUND " << " with bits " << ByteUtils::toString(working_bits) << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DeflateBlock::setCodeLengthAlphabetLengths(const std::vector<unsigned char>& lengths)
|
||||
{
|
||||
mCodeLengthAlphabetLengths = lengths;
|
||||
}
|
||||
|
||||
void DeflateBlock::setCodeLengthLength(unsigned length)
|
||||
{
|
||||
mHclen = length;
|
||||
}
|
||||
|
||||
void DeflateBlock::setLiteralsTableLength(unsigned length)
|
||||
{
|
||||
mHlit = length;
|
||||
}
|
||||
|
||||
void DeflateBlock::setDistanceTableLength(unsigned length)
|
||||
{
|
||||
mHdist = length;
|
||||
}
|
||||
|
||||
void DeflateBlock::setIsFinalBlock(bool isFinal)
|
||||
{
|
||||
mInFinalBlock = isFinal;
|
||||
}
|
||||
|
||||
void DeflateBlock::flushToStream()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DeflateBlock::readLiteralCodeLengths()
|
||||
{
|
||||
std::vector<unsigned> lengths;
|
||||
unsigned char symbol{0};
|
||||
|
||||
while(lengths.size() < mHlit)
|
||||
{
|
||||
bool valid = readNextCodeLengthSymbol(symbol);
|
||||
|
||||
if (!valid)
|
||||
{
|
||||
std::cout << "Hit unknown symbol - bailing out" << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
if (symbol < 16)
|
||||
{
|
||||
lengths.push_back(symbol);
|
||||
}
|
||||
else if(symbol == 16)
|
||||
{
|
||||
unsigned char num_reps{0};
|
||||
mInputStream->readNextNBits(2, num_reps);
|
||||
|
||||
auto last_val = lengths[lengths.size()-1];
|
||||
std::cout << "Got val 16 doing " << 3 + num_reps << std::endl;
|
||||
for(unsigned idx=0; idx< 3 + num_reps; idx++)
|
||||
{
|
||||
lengths.push_back(last_val);
|
||||
}
|
||||
}
|
||||
else if(symbol == 17)
|
||||
{
|
||||
unsigned char num_reps{0};
|
||||
mInputStream->readNextNBits(3, num_reps);
|
||||
|
||||
std::cout << "Got val 17 doing " << 3 + num_reps << std::endl;
|
||||
for(unsigned idx=0; idx< 3 + num_reps; idx++)
|
||||
{
|
||||
lengths.push_back(0);
|
||||
}
|
||||
}
|
||||
else if(symbol == 18)
|
||||
{
|
||||
unsigned char num_reps{0};
|
||||
mInputStream->readNextNBits(7, num_reps);
|
||||
|
||||
std::cout << "Got val 18 doing " << 11 + num_reps << std::endl;
|
||||
for(unsigned idx=0; idx< 11 + num_reps; idx++)
|
||||
{
|
||||
lengths.push_back(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeflateBlock::buildCodeLengthMapping()
|
||||
{
|
||||
for(unsigned idx=1; idx<8; idx++)
|
||||
{
|
||||
std::vector<unsigned> entries;
|
||||
for(unsigned jdx=0; jdx<mCodeLengthAlphabetLengths.size(); jdx++)
|
||||
{
|
||||
if (mCodeLengthAlphabetLengths[jdx] == idx)
|
||||
{
|
||||
entries.push_back(jdx);
|
||||
}
|
||||
}
|
||||
|
||||
if (entries.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
CodeLengthCountEntry count_entry{idx, {}};
|
||||
std::sort(entries.begin(), entries.end());
|
||||
|
||||
unsigned char offset = 0x01 << idx - 1;
|
||||
unsigned char count{0};
|
||||
for (auto entry : entries)
|
||||
{
|
||||
count_entry.second.push_back(CodeLengthEntry{offset + count, entry});
|
||||
count++;
|
||||
}
|
||||
mCodeLengthMapping.push_back(count_entry);
|
||||
}
|
||||
|
||||
for (const auto& map_data : mCodeLengthMapping)
|
||||
{
|
||||
std::cout << "Map entry " << map_data.first << " has vals: " << std::endl;
|
||||
for (const auto& entry : map_data.second)
|
||||
{
|
||||
std::cout << "Key " << ByteUtils::toString(entry.first) << " val: " << entry.second << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeflateBlock::readDynamicHuffmanTable()
|
||||
{
|
||||
unsigned char h_lit{0};
|
||||
mInputStream->readNextNBits(5, h_lit);
|
||||
mHlit = h_lit + 257;
|
||||
std::cout << "Got HLIT " << mHlit << std::endl;
|
||||
|
||||
unsigned char h_dist{0};
|
||||
mInputStream->readNextNBits(5, h_dist);
|
||||
mHdist = h_dist + 1;
|
||||
std::cout << "Got HDIST " << mHdist << std::endl;
|
||||
|
||||
unsigned char h_clen{0};
|
||||
mInputStream->readNextNBits(4, h_clen);
|
||||
mHclen = h_clen + 4;
|
||||
std::cout << "Got HCLEN " << mHclen << std::endl;
|
||||
|
||||
mCodeLengthAlphabetLengths = std::vector<unsigned char>(19, 0);
|
||||
unsigned char buffer{0};
|
||||
for(unsigned idx = 0; idx< mHclen; idx++)
|
||||
{
|
||||
mInputStream->readNextNBits(3, buffer);
|
||||
mCodeLengthAlphabetLengths[CODE_LENGTH_ALPHABET_PERMUTATION[idx]] = buffer;
|
||||
std::cout << "Got code length for " << CODE_LENGTH_ALPHABET_PERMUTATION[idx] << " of " << static_cast<unsigned>(buffer) << std::endl;
|
||||
}
|
||||
|
||||
buildCodeLengthMapping();
|
||||
|
||||
readLiteralCodeLengths();
|
||||
}
|
||||
|
||||
std::string DeflateBlock::getMetaData() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << "DeflateBlock Metadata \n";
|
||||
|
||||
sstr << "Final block: " << mInFinalBlock << '\n';
|
||||
sstr << "Compression method: " << Deflate::toString(mCompressionMethod) << '\n';
|
||||
|
||||
return sstr.str();
|
||||
}
|
||||
|
||||
bool DeflateBlock::isFinalBlock() const
|
||||
{
|
||||
return mInFinalBlock;
|
||||
}
|
||||
|
||||
void DeflateBlock::readHeader()
|
||||
{
|
||||
auto working_byte = mInputStream->getCurrentByte();
|
||||
std::cout << "Into process data "<< std::endl;
|
||||
std::cout << mInputStream->logNextNBytes(9);
|
||||
|
||||
unsigned char final_block{0};
|
||||
mInputStream->readNextNBits(1, final_block);
|
||||
mInFinalBlock = bool(final_block);
|
||||
|
||||
unsigned char compression_type{0};
|
||||
mInputStream->readNextNBits(2, compression_type);
|
||||
mCompressionMethod = static_cast<Deflate::CompressionMethod>(compression_type);
|
||||
}
|
||||
|
||||
void DeflateBlock::write(uint16_t 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;
|
||||
mOutputStream->writeByte(working_block);
|
||||
|
||||
std::cout << "Writing data length " << datalength << " " << ByteUtils::toString(datalength) << std::endl;
|
||||
mOutputStream->writeWord(datalength);
|
||||
|
||||
std::cout << "Writing iverse data length " << ~datalength << " " << ByteUtils::toString(~datalength) << std::endl;
|
||||
mOutputStream->writeWord(static_cast<uint16_t>(~datalength));
|
||||
|
||||
for(unsigned idx=0; idx<datalength;idx++)
|
||||
{
|
||||
auto byte = *mInputStream->readNextByte();
|
||||
std::cout << "Writing next byte " << static_cast<int>(byte) << std::endl;
|
||||
mOutputStream->writeByte(byte);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue