151 lines
3.3 KiB
C++
151 lines
3.3 KiB
C++
#include "PngReader.h"
|
|
|
|
#include "BinaryStream.h"
|
|
#include "BitStream.h"
|
|
#include "BufferBitStream.h"
|
|
|
|
#include "ZlibEncoder.h"
|
|
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
PngReader::~PngReader()
|
|
{
|
|
|
|
}
|
|
|
|
void PngReader::setPath(const Path& path)
|
|
{
|
|
mPath = path;
|
|
}
|
|
|
|
bool PngReader::checkSignature()
|
|
{
|
|
const int highBitCheck = 0x89;
|
|
const auto firstPos = mFile->GetInHandle()->get();
|
|
if (firstPos != highBitCheck)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
std::string fileType;
|
|
BinaryStream::getNextString(mFile->GetInHandle(), fileType, 3);
|
|
if (fileType != "PNG")
|
|
{
|
|
return false;
|
|
}
|
|
|
|
std::vector<char> sequence{13, 10, 26, 10};
|
|
for (auto c : sequence)
|
|
{
|
|
if (mFile->GetInHandle()->get() != c)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
mCurrentOffset += 8;
|
|
return true;
|
|
}
|
|
|
|
bool PngReader::readChunk()
|
|
{
|
|
unsigned length = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
|
|
|
std::string chunkType;
|
|
BinaryStream::getNextString(mFile->GetInHandle(), chunkType, 4);
|
|
mCurrentOffset += 8;
|
|
|
|
std::cout << "Got chunk with type: " << chunkType << " and length: " << length << std::endl;
|
|
bool lastChunk = false;
|
|
if (chunkType == "IHDR")
|
|
{
|
|
readHeaderChunk();
|
|
}
|
|
else if(chunkType == "IEND")
|
|
{
|
|
lastChunk = true;
|
|
}
|
|
else if(chunkType == "IDAT")
|
|
{
|
|
readIDATChunk(length);
|
|
}
|
|
else
|
|
{
|
|
for(unsigned idx=0;idx<length;idx++)
|
|
{
|
|
mFile->GetInHandle()->get();
|
|
}
|
|
}
|
|
|
|
unsigned crcCheck = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
|
|
|
mCurrentOffset += 4;
|
|
return !lastChunk;
|
|
}
|
|
|
|
void PngReader::readIDATChunk(unsigned length)
|
|
{
|
|
if (mAwaitingDataBlock)
|
|
{
|
|
mEncoder->setCompressionMethod(*mFile->readNextByte());
|
|
mEncoder->setExtraFlags(*mFile->readNextByte());
|
|
for(unsigned idx=0; idx<length-2; idx++)
|
|
{
|
|
mInputStream->writeByte(*mFile->readNextByte());
|
|
}
|
|
mAwaitingDataBlock = false;
|
|
}
|
|
else
|
|
{
|
|
for(unsigned idx=0; idx<length; idx++)
|
|
{
|
|
mInputStream->writeByte(*mFile->readNextByte());
|
|
}
|
|
}
|
|
}
|
|
|
|
void PngReader::readHeaderChunk()
|
|
{
|
|
mIHDRChunk.width = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
|
mIHDRChunk.height = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
|
mIHDRChunk.bitDepth = mFile->GetInHandle()->get();
|
|
mIHDRChunk.colorType = mFile->GetInHandle()->get();
|
|
mIHDRChunk.compressionMethod = mFile->GetInHandle()->get();
|
|
mIHDRChunk.filterMethod = mFile->GetInHandle()->get();
|
|
mIHDRChunk.interlaceMethod = mFile->GetInHandle()->get();
|
|
|
|
mCurrentOffset += 13;
|
|
|
|
logHeader();
|
|
}
|
|
|
|
void PngReader::logHeader()
|
|
{
|
|
std::cout << "IHDR\n" << mIHDRChunk.toString() << "*************\n";
|
|
}
|
|
|
|
std::unique_ptr<Image<unsigned char> > PngReader::read()
|
|
{
|
|
auto image = std::make_unique<Image<unsigned char> >(5, 5);
|
|
|
|
mFile = std::make_unique<File>(mPath);
|
|
mFile->Open(true);
|
|
|
|
if (!checkSignature())
|
|
{
|
|
std::cout << "Signature check failed" << std::endl;
|
|
return image;
|
|
}
|
|
|
|
mInputStream = std::make_unique<BufferBitStream>();
|
|
mOutputStream = std::make_unique<BufferBitStream>();
|
|
mEncoder = std::make_unique<ZlibEncoder>(mInputStream.get(), mOutputStream.get());
|
|
|
|
while(readChunk())
|
|
{
|
|
|
|
}
|
|
mEncoder->decode();
|
|
return std::move(image);
|
|
}
|