Some encode/decode practice.
This commit is contained in:
parent
8a41337e2d
commit
ff962a6b16
29 changed files with 727 additions and 305 deletions
|
@ -1,38 +1,22 @@
|
|||
list(APPEND image_HEADERS
|
||||
Image.h
|
||||
PngWriter.h
|
||||
PngWriterBasic.h
|
||||
PngWriterImpl.h
|
||||
)
|
||||
|
||||
list(APPEND image_LIB_INCLUDES
|
||||
Image.cpp
|
||||
PngWriter.cpp
|
||||
PngWriterBasic.cpp
|
||||
PngReader.cpp
|
||||
)
|
||||
|
||||
list(APPEND image_LIBS core)
|
||||
list(APPEND image_LIBS core compression)
|
||||
list(APPEND image_DEFINES "")
|
||||
|
||||
find_package(PNG QUIET)
|
||||
if(PNG_FOUND)
|
||||
list(APPEND image_LIBS PNG::PNG)
|
||||
list(APPEND image_LIB_INCLUDES
|
||||
PngWriterLibPng.cpp
|
||||
)
|
||||
list(APPEND image_DEFINES HAS_LIBPNG)
|
||||
else()
|
||||
message(STATUS "LIBRARY CHECK: libPNG not found - disabling libPNG based image i/o.")
|
||||
endif()
|
||||
|
||||
|
||||
add_library(image SHARED ${image_LIB_INCLUDES} ${image_HEADERS})
|
||||
#target_compile_definitions(image PRIVATE ${image_DEFINES})
|
||||
|
||||
target_include_directories(image PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
)
|
||||
target_include_directories(image PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set_target_properties( image PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
||||
|
||||
target_link_libraries( image PUBLIC ${image_LIBS})
|
||||
|
|
|
@ -23,4 +23,19 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void drawAlternatingStrips(std::vector<unsigned char>& data, unsigned width, unsigned height, unsigned channels, unsigned bytesPerRow)
|
||||
{
|
||||
for(unsigned jdx=0;jdx<height;jdx++)
|
||||
{
|
||||
const auto heightOffset = jdx*bytesPerRow;
|
||||
for(unsigned idx=0;idx<width*channels;idx+=channels)
|
||||
{
|
||||
const auto index = heightOffset + idx;
|
||||
data[index] = (idx%2 == 0) ? 255*jdx/(height+1) : 0;
|
||||
data[index+1] = 0;
|
||||
data[index+2] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
33
src/image/PngElements.h
Normal file
33
src/image/PngElements.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace Png
|
||||
{
|
||||
struct IHDRChunk
|
||||
{
|
||||
unsigned width{0};
|
||||
unsigned height{0};
|
||||
char bitDepth{0};
|
||||
char colorType{0};
|
||||
char compressionMethod{0};
|
||||
char filterMethod{0};
|
||||
char interlaceMethod{0};
|
||||
|
||||
std::string toString() const
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << "width: " << width << "\n";
|
||||
sstr << "height: " << height << "\n";
|
||||
sstr << "bitDepth: " << (int)bitDepth << "\n";
|
||||
sstr << "colorType: " << (int)colorType << "\n";
|
||||
sstr << "compressionMethod: " << (int)compressionMethod << "\n";
|
||||
sstr << "filterMethod: " << (int)filterMethod << "\n";
|
||||
sstr << "interlaceMethod: " << (int)interlaceMethod << "\n";
|
||||
return sstr.str();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
#include "PngReader.h"
|
||||
#include "BinaryStream.h"
|
||||
|
||||
#include "Image.h"
|
||||
#include "BinaryStream.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
@ -11,120 +10,135 @@ PngReader::~PngReader()
|
|||
|
||||
}
|
||||
|
||||
void PngReader::setPath(const std::string& path)
|
||||
void PngReader::setPath(const Path& path)
|
||||
{
|
||||
mPath = path;
|
||||
mPath = path;
|
||||
}
|
||||
|
||||
bool PngReader::checkSignature()
|
||||
{
|
||||
const int highBitCheck = 0x89;
|
||||
const auto firstPos = mFile->GetInHandle()->get();
|
||||
if (firstPos != highBitCheck)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
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::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;
|
||||
}
|
||||
}
|
||||
std::vector<char> sequence{13, 10, 26, 10};
|
||||
for (auto c : sequence)
|
||||
{
|
||||
if (mFile->GetInHandle()->get() != c)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mCurrentOffset += 8;
|
||||
return true;
|
||||
mCurrentOffset += 8;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PngReader::readChunk()
|
||||
{
|
||||
unsigned length = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
||||
unsigned length = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
||||
|
||||
std::string chunkType;
|
||||
BinaryStream::getNextString(mFile->GetInHandle(), chunkType, 4);
|
||||
mCurrentOffset += 8;
|
||||
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")
|
||||
{
|
||||
parseHeader();
|
||||
}
|
||||
else if(chunkType == "IEND")
|
||||
{
|
||||
lastChunk = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(unsigned idx=0;idx<length;idx++)
|
||||
{
|
||||
mFile->GetInHandle()->get();
|
||||
}
|
||||
}
|
||||
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());
|
||||
unsigned crcCheck = *BinaryStream::getNextDWord(mFile->GetInHandle());
|
||||
|
||||
mCurrentOffset += 4;
|
||||
return !lastChunk;
|
||||
mCurrentOffset += 4;
|
||||
return !lastChunk;
|
||||
}
|
||||
|
||||
void PngReader::parseHeader()
|
||||
void PngReader::readIDATChunk(unsigned length)
|
||||
{
|
||||
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();
|
||||
if (mAwaitingDataBlock)
|
||||
{
|
||||
mImageData.setCompressionMethod(mFile->readNextByte());
|
||||
mImageData.setExtraFlags(mFile->readNextByte());
|
||||
mImageData.setDataSize(length-2);
|
||||
for(unsigned idx=0; idx<length-2; idx++)
|
||||
{
|
||||
mImageData.setByte(idx, mFile->readNextByte());
|
||||
}
|
||||
mAwaitingDataBlock = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(unsigned idx=0; idx<length; idx++)
|
||||
{
|
||||
mImageData.setByte(idx, mFile->readNextByte());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mCurrentOffset += 13;
|
||||
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();
|
||||
|
||||
logHeader();
|
||||
mCurrentOffset += 13;
|
||||
|
||||
logHeader();
|
||||
}
|
||||
|
||||
void PngReader::logHeader()
|
||||
{
|
||||
std::stringstream sstr;
|
||||
sstr << "IHDR\n";
|
||||
sstr << "width: " << mIHDRChunk.width << "\n";
|
||||
sstr << "height: " << mIHDRChunk.height << "\n";
|
||||
sstr << "bitDepth: " << (int)mIHDRChunk.bitDepth << "\n";
|
||||
sstr << "colorType: " << (int)mIHDRChunk.colorType << "\n";
|
||||
sstr << "compressionMethod: " << (int)mIHDRChunk.compressionMethod << "\n";
|
||||
sstr << "filterMethod: " << (int)mIHDRChunk.filterMethod << "\n";
|
||||
sstr << "interlaceMethod: " << (int)mIHDRChunk.interlaceMethod << "\n";
|
||||
|
||||
sstr << "************\n";
|
||||
std::cout << sstr.str() << std::endl;
|
||||
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);
|
||||
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;
|
||||
std::cout << "Signature check failed" << std::endl;
|
||||
return image;
|
||||
}
|
||||
|
||||
while(readChunk())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return std::move(image);
|
||||
mImageData.processData();
|
||||
return std::move(image);
|
||||
}
|
||||
|
|
|
@ -1,44 +1,42 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "File.h"
|
||||
#include "Image.h"
|
||||
#include "PngElements.h"
|
||||
#include "ZlibData.h"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <filesystem>
|
||||
|
||||
using Path = std::filesystem::path;
|
||||
|
||||
class PngReader
|
||||
{
|
||||
public:
|
||||
~PngReader();
|
||||
void setPath(const std::string& path);
|
||||
void setPath(const Path& path);
|
||||
|
||||
std::unique_ptr<Image<unsigned char> > read();
|
||||
|
||||
private:
|
||||
|
||||
struct IHDRChunk
|
||||
{
|
||||
unsigned width{0};
|
||||
unsigned height{0};
|
||||
char bitDepth{0};
|
||||
char colorType{0};
|
||||
char compressionMethod{0};
|
||||
char filterMethod{0};
|
||||
char interlaceMethod{0};
|
||||
};
|
||||
|
||||
bool readChunk();
|
||||
void parseHeader();
|
||||
|
||||
void readHeaderChunk();
|
||||
|
||||
void readIDATChunk(unsigned length);
|
||||
|
||||
void logHeader();
|
||||
|
||||
bool checkSignature();
|
||||
|
||||
unsigned mCurrentOffset{0};
|
||||
|
||||
IHDRChunk mIHDRChunk;
|
||||
Png::IHDRChunk mIHDRChunk;
|
||||
|
||||
std::unique_ptr<Image<unsigned char> > mWorkingImage;
|
||||
std::unique_ptr<File> mFile;
|
||||
std::string mPath;
|
||||
Path mPath;
|
||||
|
||||
ZlibData mImageData;
|
||||
bool mAwaitingDataBlock{true};
|
||||
};
|
||||
|
|
|
@ -2,21 +2,11 @@
|
|||
|
||||
#include "Image.h"
|
||||
|
||||
#ifdef HAS_LIBPNG
|
||||
#include <png.h>
|
||||
#include "PngWriterLibPng.h"
|
||||
#else
|
||||
#include "PngWriterBasic.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
PngWriter::PngWriter()
|
||||
{
|
||||
#ifdef HAS_LIBPNG
|
||||
mImpl = std::make_unique<PngWriterLibPng>();
|
||||
#else
|
||||
mImpl = std::make_unique<PngWriterBasic>();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr<PngWriter> PngWriter::Create()
|
||||
|
@ -24,14 +14,14 @@ std::unique_ptr<PngWriter> PngWriter::Create()
|
|||
return std::make_unique<PngWriter>();
|
||||
}
|
||||
|
||||
void PngWriter::SetPath(const std::string& path)
|
||||
void PngWriter::setPath(const Path& path)
|
||||
{
|
||||
mImpl->setPath(path);
|
||||
mPath = path;
|
||||
}
|
||||
|
||||
void PngWriter::Write(const std::unique_ptr<Image<unsigned char> >& image) const
|
||||
void PngWriter::write(const std::unique_ptr<Image<unsigned char> >& image) const
|
||||
{
|
||||
mImpl->write(image);
|
||||
//mImpl->write(image);
|
||||
//auto fp = fopen(mPath.c_str(), "wb");
|
||||
|
||||
//auto png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "Image.h"
|
||||
|
||||
class PngWriterImpl;
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
using Path = std::filesystem::path;
|
||||
|
||||
class PngWriter
|
||||
{
|
||||
|
@ -14,13 +15,12 @@ public:
|
|||
|
||||
static std::unique_ptr<PngWriter> Create();
|
||||
|
||||
void SetPath(const std::string& path);
|
||||
void setPath(const Path& path);
|
||||
|
||||
void Write(const std::unique_ptr<Image<unsigned char> >& image) const;
|
||||
void write(const std::unique_ptr<Image<unsigned char> >& image) const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<PngWriterImpl> mImpl;
|
||||
|
||||
Path mPath;
|
||||
};
|
||||
|
||||
using PngWriterPtr = std::unique_ptr<PngWriter>;
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
#include "PngWriterBasic.h"
|
||||
|
||||
void PngWriterBasic::setPath(const std::string& path)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void PngWriterBasic::write(const std::unique_ptr<Image<unsigned char> >& image) const
|
||||
{
|
||||
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "PngWriterImpl.h"
|
||||
|
||||
class PngWriterBasic : public PngWriterImpl
|
||||
{
|
||||
public:
|
||||
void setPath(const std::string& path) override;
|
||||
|
||||
void write(const std::unique_ptr<Image<unsigned char>>& image) const override;
|
||||
|
||||
private:
|
||||
std::string mPath;
|
||||
};
|
|
@ -1,16 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "Image.h"
|
||||
|
||||
class PngWriterImpl
|
||||
{
|
||||
public:
|
||||
virtual ~PngWriterImpl() = default;
|
||||
|
||||
virtual void setPath(const std::string& path) = 0;
|
||||
|
||||
virtual void write(const std::unique_ptr<Image<unsigned char> >& image) const = 0;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue