Clean up some warnings.
This commit is contained in:
parent
a19567508e
commit
dba6a91ec1
25 changed files with 453 additions and 431 deletions
216
src/image/png/BasicPngWriter.cpp
Normal file
216
src/image/png/BasicPngWriter.cpp
Normal file
|
@ -0,0 +1,216 @@
|
|||
#include "BasicPngWriter.h"
|
||||
|
||||
#include "Image.h"
|
||||
#include "File.h"
|
||||
#include "BufferBitStream.h"
|
||||
#include "OutputBitStream.h"
|
||||
#include "ImageBitStream.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
#include "PngFilter.h"
|
||||
#include "Lz77Encoder.h"
|
||||
#include "ZlibEncoder.h"
|
||||
#include "HuffmanEncoder.h"
|
||||
#include "CyclicRedundancyChecker.h"
|
||||
|
||||
#include "ByteUtils.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
BasicPngWriter::BasicPngWriter()
|
||||
: IImageWriter(ImgFormat::PNG)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BasicPngWriter::~BasicPngWriter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr<BasicPngWriter> BasicPngWriter::Create()
|
||||
{
|
||||
return std::make_unique<BasicPngWriter>();
|
||||
}
|
||||
|
||||
void BasicPngWriter::setCompressionMethod(Deflate::CompressionMethod method)
|
||||
{
|
||||
mCompressionMethod = method;
|
||||
}
|
||||
|
||||
void BasicPngWriter::setPngInfo(const PngInfo& info)
|
||||
{
|
||||
mPngInfoUserSet = true;
|
||||
mPngInfo = info;
|
||||
}
|
||||
|
||||
void BasicPngWriter::writeSignature()
|
||||
{
|
||||
mOutStream->writeByte(mPngHeader.getHighBitCheck());
|
||||
mOutStream->writeBytes(StringUtils::toBytes(mPngHeader.getFileName()));
|
||||
mOutStream->writeBytes(mPngHeader.getSignature());
|
||||
}
|
||||
|
||||
void BasicPngWriter::writeHeader()
|
||||
{
|
||||
writeSignature();
|
||||
|
||||
if (!mPngInfoUserSet)
|
||||
{
|
||||
if (mWorkingImage->getNumChannels() == 1)
|
||||
{
|
||||
mPngInfo.mColorType = PngInfo::ColorType::GREYSCALE;
|
||||
}
|
||||
else if (mWorkingImage->getNumChannels() == 2)
|
||||
{
|
||||
mPngInfo.mColorType = PngInfo::ColorType::GREYSCALE_ALPHA;
|
||||
}
|
||||
else if (mWorkingImage->getNumChannels() == 3)
|
||||
{
|
||||
mPngInfo.mColorType = PngInfo::ColorType::RGB;
|
||||
}
|
||||
else if (mWorkingImage->getNumChannels() == 4)
|
||||
{
|
||||
mPngInfo.mColorType = PngInfo::ColorType::RGB_ALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
mPngHeader.setPngInfo(mPngInfo);
|
||||
mPngHeader.setImageData(mWorkingImage->getWidth(), mWorkingImage->getHeight(), mWorkingImage->getBitDepth());
|
||||
|
||||
auto length = mPngHeader.getLength();
|
||||
mOutStream->write(length);
|
||||
|
||||
mOutStream->writeBytes(StringUtils::toBytes(mPngHeader.getChunkName()));
|
||||
|
||||
mPngHeader.updateData();
|
||||
mOutStream->writeBytes(mPngHeader.getData());
|
||||
|
||||
auto crc = mPngHeader.getCrc();
|
||||
|
||||
//std::cout << mPngHeader.toString() << "*********" << std::endl;
|
||||
mOutStream->write(crc);
|
||||
}
|
||||
|
||||
void BasicPngWriter::writeEndChunk()
|
||||
{
|
||||
//std::cout << "Start writing end chunk" << std::endl;
|
||||
unsigned length{ 0 };
|
||||
mOutStream->write(length);
|
||||
|
||||
mOutStream->writeBytes(StringUtils::toBytes("IEND"));
|
||||
std::vector<unsigned char> char_data = StringUtils::toBytes("IEND");
|
||||
|
||||
CyclicRedundancyChecker crc_check;
|
||||
for (auto c : char_data)
|
||||
{
|
||||
crc_check.addValue(c);
|
||||
}
|
||||
auto crc = crc_check.getChecksum();
|
||||
mOutStream->write(crc);
|
||||
|
||||
//std::cout << "Writing end chunk" << std::endl;
|
||||
}
|
||||
|
||||
void BasicPngWriter::writeDataChunks(const BufferBitStream& buffer)
|
||||
{
|
||||
auto num_bytes = buffer.getBuffer().size();
|
||||
std::size_t max_bytes{ 32000 };
|
||||
|
||||
auto num_dat_chunks = num_bytes / max_bytes + 1;
|
||||
std::size_t offset = 0;
|
||||
for (std::size_t idx = 0; idx < num_dat_chunks; idx++)
|
||||
{
|
||||
auto length = max_bytes;
|
||||
if (idx == num_dat_chunks - 1)
|
||||
{
|
||||
length = num_bytes - num_dat_chunks * num_bytes;
|
||||
}
|
||||
|
||||
//std::cout << "Writing idat length " << num_bytes << std::endl;
|
||||
mOutStream->write(static_cast<uint32_t>(num_bytes));
|
||||
|
||||
std::vector<unsigned char> char_data = StringUtils::toBytes("IDAT");
|
||||
mOutStream->writeBytes(char_data);
|
||||
|
||||
CyclicRedundancyChecker crc_check;
|
||||
for (auto c : char_data)
|
||||
{
|
||||
crc_check.addValue(c);
|
||||
}
|
||||
|
||||
for (unsigned jdx = 0; jdx < num_bytes; jdx++)
|
||||
{
|
||||
auto val = buffer.getBuffer()[idx * max_bytes + jdx];
|
||||
mOutStream->writeByte(val);
|
||||
crc_check.addValue(val);
|
||||
}
|
||||
|
||||
auto crc = crc_check.getChecksum();
|
||||
//std::cout << "Writing idat crc" << crc << std::endl;
|
||||
mOutStream->write(crc);
|
||||
//std::cout << "Finished Writing idat crc" << crc << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void BasicPngWriter::write(const Path& path, Image* image)
|
||||
{
|
||||
std::unique_ptr<File> out_file;
|
||||
|
||||
if (path.empty())
|
||||
{
|
||||
out_file = std::make_unique<File>(path);
|
||||
out_file->open(File::AccessMode::Write);
|
||||
mOutStream = std::make_unique<OutputBitStream>(out_file->getOutHandle());
|
||||
}
|
||||
else
|
||||
{
|
||||
mOutStream = std::make_unique<BufferBitStream>();
|
||||
}
|
||||
|
||||
mWorkingImage = image;
|
||||
|
||||
auto image_bit_stream = std::make_unique<ImageBitStream>(image);
|
||||
auto raw_image_stream = image_bit_stream.get();
|
||||
|
||||
mInStream = std::move(image_bit_stream);
|
||||
|
||||
writeHeader();
|
||||
|
||||
auto filter_out_stream = std::make_unique<BufferBitStream>();
|
||||
PngFilter filter(raw_image_stream, filter_out_stream.get());
|
||||
filter.encode();
|
||||
|
||||
filter_out_stream->resetOffsets();
|
||||
|
||||
std::unique_ptr<BufferBitStream> lz77_out_stream;
|
||||
|
||||
if (mCompressionMethod == Deflate::CompressionMethod::NONE)
|
||||
{
|
||||
lz77_out_stream = std::move(filter_out_stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
lz77_out_stream = std::make_unique<BufferBitStream>();
|
||||
Lz77Encoder lz77_encoder(filter_out_stream.get(), lz77_out_stream.get());
|
||||
|
||||
if (mCompressionMethod == Deflate::CompressionMethod::FIXED_HUFFMAN)
|
||||
{
|
||||
auto huffman_encoder = std::make_unique<HuffmanEncoder>();
|
||||
huffman_encoder->setUseFixedCode(true);
|
||||
lz77_encoder.setPrefixCodeGenerator(std::move(huffman_encoder));
|
||||
}
|
||||
lz77_encoder.encode();
|
||||
lz77_out_stream->resetOffsets();
|
||||
}
|
||||
|
||||
BufferBitStream zlib_out_stream;
|
||||
ZlibEncoder zlib_encoder(lz77_out_stream.get(), &zlib_out_stream);
|
||||
zlib_encoder.setDeflateCompressionMethod(mCompressionMethod);
|
||||
zlib_encoder.encode();
|
||||
zlib_out_stream.resetOffsets();
|
||||
|
||||
writeDataChunks(zlib_out_stream);
|
||||
|
||||
writeEndChunk();
|
||||
}
|
52
src/image/png/BasicPngWriter.h
Normal file
52
src/image/png/BasicPngWriter.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
|
||||
#include "IImageWriter.h"
|
||||
|
||||
#include "PngHeader.h"
|
||||
#include "Image.h"
|
||||
#include "DeflateElements.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
using Path = std::filesystem::path;
|
||||
|
||||
class BitStream;
|
||||
class BufferBitStream;
|
||||
|
||||
class BasicPngWriter : public IImageWriter
|
||||
{
|
||||
public:
|
||||
BasicPngWriter();
|
||||
|
||||
~BasicPngWriter();
|
||||
|
||||
static std::unique_ptr<BasicPngWriter> Create();
|
||||
|
||||
void setCompressionMethod(Deflate::CompressionMethod method);
|
||||
|
||||
void setPngInfo(const PngInfo& info);
|
||||
|
||||
void write(const Path& path, Image* image) override;
|
||||
|
||||
private:
|
||||
void writeSignature();
|
||||
void writeHeader();
|
||||
|
||||
void writeDataChunks(const BufferBitStream& buffer);
|
||||
|
||||
void writeEndChunk();
|
||||
|
||||
//void writeIDatChunk();
|
||||
|
||||
Image* mWorkingImage{ nullptr };
|
||||
std::unique_ptr<BitStream> mInStream;
|
||||
std::unique_ptr<BitStream> mOutStream;
|
||||
|
||||
unsigned mPngInfoUserSet{ false };
|
||||
PngInfo mPngInfo;
|
||||
PngHeader mPngHeader;
|
||||
|
||||
Deflate::CompressionMethod mCompressionMethod{ Deflate::CompressionMethod::DYNAMIC_HUFFMAN };
|
||||
};
|
|
@ -1,29 +1,19 @@
|
|||
#include "PngWriter.h"
|
||||
|
||||
#include "Image.h"
|
||||
#include "File.h"
|
||||
#include "BufferBitStream.h"
|
||||
#include "OutputBitStream.h"
|
||||
#include "ImageBitStream.h"
|
||||
#include "StringUtils.h"
|
||||
|
||||
#include "PngFilter.h"
|
||||
#include "Lz77Encoder.h"
|
||||
#include "ZlibEncoder.h"
|
||||
#include "HuffmanEncoder.h"
|
||||
#include "CyclicRedundancyChecker.h"
|
||||
|
||||
#include "ByteUtils.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Win32WicImageWriter.h"
|
||||
#else
|
||||
#include "BasicPngWriter.h"
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
PngWriter::PngWriter()
|
||||
: IImageWriter(ImgFormat::PNG)
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
mWriterImpl = std::make_unique<Win32WicImageWriter>(mFormat);
|
||||
#else
|
||||
mWriterImpl = std::make_unique<BasicPngWriter>(mFormat);
|
||||
#endif
|
||||
}
|
||||
|
||||
PngWriter::~PngWriter()
|
||||
|
@ -36,209 +26,7 @@ std::unique_ptr<PngWriter> PngWriter::Create()
|
|||
return std::make_unique<PngWriter>();
|
||||
}
|
||||
|
||||
void PngWriter::setCompressionMethod(Deflate::CompressionMethod method)
|
||||
void PngWriter::write(const Path& path, Image* image)
|
||||
{
|
||||
mCompressionMethod = method;
|
||||
}
|
||||
|
||||
void PngWriter::setPath(const Path& path)
|
||||
{
|
||||
mPath = path;
|
||||
}
|
||||
|
||||
void PngWriter::setPngInfo(const PngInfo& info)
|
||||
{
|
||||
mPngInfoUserSet = true;
|
||||
mPngInfo = info;
|
||||
}
|
||||
|
||||
void PngWriter::writeSignature()
|
||||
{
|
||||
mOutStream->writeByte(mPngHeader.getHighBitCheck());
|
||||
mOutStream->writeBytes(StringUtils::toBytes(mPngHeader.getFileName()));
|
||||
mOutStream->writeBytes(mPngHeader.getSignature());
|
||||
}
|
||||
|
||||
void PngWriter::writeHeader()
|
||||
{
|
||||
writeSignature();
|
||||
|
||||
if (!mPngInfoUserSet)
|
||||
{
|
||||
if (mWorkingImage->getNumChannels() == 1)
|
||||
{
|
||||
mPngInfo.mColorType = PngInfo::ColorType::GREYSCALE;
|
||||
}
|
||||
else if (mWorkingImage->getNumChannels() == 2)
|
||||
{
|
||||
mPngInfo.mColorType = PngInfo::ColorType::GREYSCALE_ALPHA;
|
||||
}
|
||||
else if (mWorkingImage->getNumChannels() == 3)
|
||||
{
|
||||
mPngInfo.mColorType = PngInfo::ColorType::RGB;
|
||||
}
|
||||
else if (mWorkingImage->getNumChannels() == 4)
|
||||
{
|
||||
mPngInfo.mColorType = PngInfo::ColorType::RGB_ALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
mPngHeader.setPngInfo(mPngInfo);
|
||||
mPngHeader.setImageData(mWorkingImage->getWidth(), mWorkingImage->getHeight(), mWorkingImage->getBitDepth());
|
||||
|
||||
auto length = mPngHeader.getLength();
|
||||
mOutStream->write(length);
|
||||
|
||||
mOutStream->writeBytes(StringUtils::toBytes(mPngHeader.getChunkName()));
|
||||
|
||||
mPngHeader.updateData();
|
||||
mOutStream->writeBytes(mPngHeader.getData());
|
||||
|
||||
auto crc = mPngHeader.getCrc();
|
||||
|
||||
//std::cout << mPngHeader.toString() << "*********" << std::endl;
|
||||
mOutStream->write(crc);
|
||||
}
|
||||
|
||||
void PngWriter::writeEndChunk()
|
||||
{
|
||||
//std::cout << "Start writing end chunk" << std::endl;
|
||||
unsigned length{0};
|
||||
mOutStream->write(length);
|
||||
|
||||
mOutStream->writeBytes(StringUtils::toBytes("IEND"));
|
||||
std::vector<unsigned char> char_data = StringUtils::toBytes("IEND");
|
||||
|
||||
CyclicRedundancyChecker crc_check;
|
||||
for (auto c : char_data)
|
||||
{
|
||||
crc_check.addValue(c);
|
||||
}
|
||||
auto crc = crc_check.getChecksum();
|
||||
mOutStream->write(crc);
|
||||
|
||||
//std::cout << "Writing end chunk" << std::endl;
|
||||
}
|
||||
|
||||
void PngWriter::writeDataChunks(const BufferBitStream& buffer)
|
||||
{
|
||||
auto num_bytes = buffer.getBuffer().size();
|
||||
auto max_bytes{32000};
|
||||
|
||||
auto num_dat_chunks = num_bytes/max_bytes + 1;
|
||||
std::size_t offset = 0;
|
||||
for(std::size_t idx=0;idx<num_dat_chunks;idx++)
|
||||
{
|
||||
auto length = max_bytes;
|
||||
if (idx == num_dat_chunks - 1)
|
||||
{
|
||||
length = num_bytes - num_dat_chunks*num_bytes;
|
||||
}
|
||||
|
||||
//std::cout << "Writing idat length " << num_bytes << std::endl;
|
||||
mOutStream->write(num_bytes);
|
||||
|
||||
std::vector<unsigned char> char_data = StringUtils::toBytes("IDAT");
|
||||
mOutStream->writeBytes(char_data);
|
||||
|
||||
CyclicRedundancyChecker crc_check;
|
||||
for (auto c : char_data)
|
||||
{
|
||||
crc_check.addValue(c);
|
||||
}
|
||||
|
||||
for(unsigned jdx=0; jdx<num_bytes; jdx++)
|
||||
{
|
||||
auto val = buffer.getBuffer()[idx*max_bytes + jdx];
|
||||
mOutStream->writeByte(val);
|
||||
crc_check.addValue(val);
|
||||
}
|
||||
|
||||
auto crc = crc_check.getChecksum();
|
||||
//std::cout << "Writing idat crc" << crc << std::endl;
|
||||
mOutStream->write(crc);
|
||||
//std::cout << "Finished Writing idat crc" << crc << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void PngWriter::writePlatform(Image* image)
|
||||
{
|
||||
mPlatformWriter = std::make_unique<Win32WicImageWriter>();
|
||||
mPlatformWriter->write(mPath, image, PlatformImageWriter::ImgFormat::PNG);
|
||||
}
|
||||
|
||||
void PngWriter::write(Image* image)
|
||||
{
|
||||
if (image->getPlatformImage())
|
||||
{
|
||||
writePlatform(image);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mPath.empty())
|
||||
{
|
||||
mWorkingFile = std::make_unique<File>(mPath);
|
||||
mWorkingFile->open(File::AccessMode::Write);
|
||||
mOutStream = std::make_unique<OutputBitStream>(mWorkingFile->getOutHandle());
|
||||
}
|
||||
else
|
||||
{
|
||||
mOutStream = std::make_unique<BufferBitStream>();
|
||||
}
|
||||
|
||||
mWorkingImage = image;
|
||||
|
||||
auto image_bit_stream = std::make_unique<ImageBitStream>(image);
|
||||
auto raw_image_stream = image_bit_stream.get();
|
||||
|
||||
mInStream = std::move(image_bit_stream);
|
||||
|
||||
writeHeader();
|
||||
|
||||
auto filter_out_stream = std::make_unique<BufferBitStream>();
|
||||
PngFilter filter(raw_image_stream, filter_out_stream.get());
|
||||
filter.encode();
|
||||
|
||||
filter_out_stream->resetOffsets();
|
||||
|
||||
std::unique_ptr<BufferBitStream> lz77_out_stream;
|
||||
|
||||
if (mCompressionMethod == Deflate::CompressionMethod::NONE)
|
||||
{
|
||||
lz77_out_stream = std::move(filter_out_stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
lz77_out_stream = std::make_unique<BufferBitStream>();
|
||||
Lz77Encoder lz77_encoder(filter_out_stream.get(), lz77_out_stream.get());
|
||||
|
||||
if (mCompressionMethod == Deflate::CompressionMethod::FIXED_HUFFMAN)
|
||||
{
|
||||
auto huffman_encoder = std::make_unique<HuffmanEncoder>();
|
||||
huffman_encoder->setUseFixedCode(true);
|
||||
lz77_encoder.setPrefixCodeGenerator(std::move(huffman_encoder));
|
||||
}
|
||||
lz77_encoder.encode();
|
||||
lz77_out_stream->resetOffsets();
|
||||
}
|
||||
|
||||
BufferBitStream zlib_out_stream;
|
||||
ZlibEncoder zlib_encoder(lz77_out_stream.get(), &zlib_out_stream);
|
||||
zlib_encoder.setDeflateCompressionMethod(mCompressionMethod);
|
||||
zlib_encoder.encode();
|
||||
zlib_out_stream.resetOffsets();
|
||||
|
||||
writeDataChunks(zlib_out_stream);
|
||||
|
||||
writeEndChunk();
|
||||
|
||||
if (mWorkingFile)
|
||||
{
|
||||
mWorkingFile->close();
|
||||
}
|
||||
}
|
||||
|
||||
void PngWriter::write(const std::unique_ptr<Image>& image)
|
||||
{
|
||||
write(image.get());
|
||||
}
|
||||
mWriterImpl->write(path, image);
|
||||
}
|
|
@ -1,21 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "PngHeader.h"
|
||||
#include "Image.h"
|
||||
#include "DeflateElements.h"
|
||||
#include "PlatformImageWriter.h"
|
||||
#include "IImageWriter.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
using Path = std::filesystem::path;
|
||||
|
||||
class BitStream;
|
||||
class BufferBitStream;
|
||||
class File;
|
||||
|
||||
class PngWriter
|
||||
class PngWriter : public IImageWriter
|
||||
{
|
||||
public:
|
||||
PngWriter();
|
||||
|
@ -23,40 +14,10 @@ public:
|
|||
|
||||
static std::unique_ptr<PngWriter> Create();
|
||||
|
||||
void setCompressionMethod(Deflate::CompressionMethod method);
|
||||
|
||||
void setPath(const Path& path);
|
||||
|
||||
void setPngInfo(const PngInfo& info);
|
||||
|
||||
void write(const std::unique_ptr<Image>& image);
|
||||
void write(Image* image);
|
||||
void write(const Path& path, Image* image) override;
|
||||
|
||||
private:
|
||||
void writePlatform(Image* image);
|
||||
|
||||
void writeSignature();
|
||||
void writeHeader();
|
||||
|
||||
void writeDataChunks(const BufferBitStream& buffer);
|
||||
|
||||
void writeEndChunk();
|
||||
|
||||
//void writeIDatChunk();
|
||||
|
||||
Path mPath;
|
||||
Image* mWorkingImage{nullptr};
|
||||
std::unique_ptr<BitStream> mInStream;
|
||||
std::unique_ptr<BitStream> mOutStream;
|
||||
std::unique_ptr<File> mWorkingFile;
|
||||
|
||||
unsigned mPngInfoUserSet{false};
|
||||
PngInfo mPngInfo;
|
||||
PngHeader mPngHeader;
|
||||
|
||||
Deflate::CompressionMethod mCompressionMethod{Deflate::CompressionMethod::DYNAMIC_HUFFMAN};
|
||||
|
||||
std::unique_ptr<PlatformImageWriter> mPlatformWriter;
|
||||
std::unique_ptr<IImageWriter> mWriterImpl;
|
||||
};
|
||||
|
||||
using PngWriterPtr = std::unique_ptr<PngWriter>;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue