From dba6a91ec1a39a61dbe417f38a47f9bd0c5b36ca Mon Sep 17 00:00:00 2001 From: jmsgrogan Date: Mon, 16 Jan 2023 11:56:46 +0000 Subject: [PATCH] Clean up some warnings. --- CMakeLists.txt | 6 +- src/audio/AudioSynth.cpp | 4 +- src/audio/AudioWriter.cpp | 6 +- .../huffman/HuffmanCodeLengthTable.cpp | 24 +- .../huffman/HuffmanCodeLengthTable.h | 6 +- src/core/Color.cpp | 39 ++- src/core/Color.h | 45 +--- src/image/CMakeLists.txt | 3 + src/image/IImageWriter.h | 28 +++ src/image/PlatformImageWriter.h | 15 +- src/image/png/BasicPngWriter.cpp | 216 ++++++++++++++++ src/image/png/BasicPngWriter.h | 52 ++++ src/image/png/PngWriter.cpp | 234 +----------------- src/image/png/PngWriter.h | 47 +--- src/image/win32/Win32WicImageWriter.cpp | 16 +- src/image/win32/Win32WicImageWriter.h | 4 +- src/mesh/MeshBuilder.h | 4 +- src/mesh/MeshPrimitives.cpp | 74 +++--- src/mesh/MeshPrimitives.h | 10 +- src/publishing/pdf/PdfDocument.h | 2 +- src/publishing/pdf/PdfXRefTable.cpp | 12 +- src/publishing/pdf/PdfXRefTable.h | 14 +- .../win32/directx/DirectX2dIntegration.cpp | 6 +- test/image/TestPngWriter.cpp | 14 +- test/test_utils/TestRenderUtils.h | 3 +- 25 files changed, 453 insertions(+), 431 deletions(-) create mode 100644 src/image/IImageWriter.h create mode 100644 src/image/png/BasicPngWriter.cpp create mode 100644 src/image/png/BasicPngWriter.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 91e8c17..078c3dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,8 @@ project(NotesTK) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) +set(CMAKE_COMPILE_WARNING_AS_ERROR ON) + set_property( GLOBAL PROPERTY USE_FOLDERS ON) set (CMAKE_MODULE_PATH infra/cmake) @@ -12,7 +14,9 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -if(FALSE) +if(MSVC) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3") +elseif(FALSE) set(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage") set(GCC_COVERAGE_LINK_FLAGS "-lgcov") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}") diff --git a/src/audio/AudioSynth.cpp b/src/audio/AudioSynth.cpp index dfe3b3c..23b9c1b 100644 --- a/src/audio/AudioSynth.cpp +++ b/src/audio/AudioSynth.cpp @@ -28,11 +28,11 @@ AudioSamplePtr AudioSynth::getSineWave(double freq, unsigned duration) const const double tick_duration = 1.0/sample_rate; const double pi_2 = 2.0 * M_PI; - const short max_short = std::numeric_limits::max(); + constexpr short max_short = std::numeric_limits::max(); for(unsigned idx=0; idx(std::sin(pi_2*freq*t)); } sample->setChannelData(data, 0); return sample; diff --git a/src/audio/AudioWriter.cpp b/src/audio/AudioWriter.cpp index 55ad1a5..220296d 100644 --- a/src/audio/AudioWriter.cpp +++ b/src/audio/AudioWriter.cpp @@ -32,13 +32,13 @@ bool AudioWriter::write(const AudioSamplePtr& sample) auto handle = outfile.getOutHandle(); const auto sample_rate = sample->getSampleRate(); - const auto num_channels = sample->getNumChannels(); + const auto num_channels = static_cast(sample->getNumChannels()); const auto bytes_per_sample = sample->getBitDepth() / 8; unsigned byte_rate = sample_rate*num_channels*bytes_per_sample; handle->write("RIFF", 4); auto data = sample->getChannelData(0); - const auto num_samples = data.size(); + const auto num_samples = static_cast(data.size()); unsigned content_size = 36 + bytes_per_sample* num_samples*num_channels; BinaryStream::write(handle, content_size); @@ -56,7 +56,7 @@ bool AudioWriter::write(const AudioSamplePtr& sample) /* write data subchunk */ handle->write("data", 4); - BinaryStream::write(handle, bytes_per_sample* num_samples*num_channels); // bits/sample + BinaryStream::write(handle, static_cast(bytes_per_sample* num_samples*num_channels)); // bits/sample handle->write(reinterpret_cast(&data[0]), data.size()*sizeof(short)); diff --git a/src/compression/huffman/HuffmanCodeLengthTable.cpp b/src/compression/huffman/HuffmanCodeLengthTable.cpp index fc1ad5e..e0f7511 100644 --- a/src/compression/huffman/HuffmanCodeLengthTable.cpp +++ b/src/compression/huffman/HuffmanCodeLengthTable.cpp @@ -25,15 +25,15 @@ void HuffmanCodeLengthTable::buildCompressedLengthSequence() const auto count = entry.second; if (count < 3) { - for(unsigned idx=0; idx(19, 0); + mCompressedLengthCounts = std::vector(19, 0); for (const auto& entry : mCompressedLengthSequence) { mCompressedLengthCounts[entry.first]++; @@ -89,7 +89,7 @@ const std::vector& HuffmanCodeL return mCompressedLengthSequence; } -const std::vector HuffmanCodeLengthTable::getCompressedLengthCounts() const +const std::vector HuffmanCodeLengthTable::getCompressedLengthCounts() const { return mCompressedLengthCounts; } @@ -106,7 +106,7 @@ bool HuffmanCodeLengthTable::readNextSymbol(unsigned& result, BitStream* stream) return false; } - unsigned working_index{0}; + std::size_t working_index{0}; auto length = getCodeLength(working_index); auto delta = length; @@ -188,7 +188,7 @@ void HuffmanCodeLengthTable::buildPrefixCodes() const auto code = next_code[length]; next_code[length]++; auto prefix_code = PrefixCode(code, length); - mTree.addCodeLengthEntry(length, {PrefixCode(code, length), idx}); + mTree.addCodeLengthEntry(length, {PrefixCode(code, length), static_cast(idx)}); mCodes.push_back(prefix_code); } } @@ -206,7 +206,7 @@ std::string HuffmanCodeLengthTable::dumpPrefixCodes() const return mTree.dump(); } -unsigned HuffmanCodeLengthTable::mapToDeflateIndex(unsigned index) const +std::size_t HuffmanCodeLengthTable::mapToDeflateIndex(std::size_t index) const { if (index>= DEFLATE_PERMUTATION_SIZE) { @@ -240,7 +240,7 @@ void HuffmanCodeLengthTable::setInputLengthSequence(const std::vector(DEFLATE_PERMUTATION_SIZE, 0); - for(unsigned idx=0; idx(sequence[idx]) << std::endl; diff --git a/src/compression/huffman/HuffmanCodeLengthTable.h b/src/compression/huffman/HuffmanCodeLengthTable.h index ea8b5ae..50a1226 100644 --- a/src/compression/huffman/HuffmanCodeLengthTable.h +++ b/src/compression/huffman/HuffmanCodeLengthTable.h @@ -28,13 +28,13 @@ public: using CompressedSequenceEntry = std::pair; const std::vector& getCompressedLengthSequence() const; - const std::vector getCompressedLengthCounts() const; + const std::vector getCompressedLengthCounts() const; std::size_t getNumCodeLengths() const; unsigned getCodeLength(std::size_t treeIndex) const; - unsigned mapToDeflateIndex(unsigned index) const; + std::size_t mapToDeflateIndex(std::size_t index) const; void setInputLengthSequence(const std::vector& sequence, bool targetDeflate = true); @@ -49,7 +49,7 @@ private: std::vector mCodes; std::vector mCompressedLengthSequence; - std::vector mCompressedLengthCounts; + std::vector mCompressedLengthCounts; static constexpr unsigned DEFLATE_PERMUTATION_SIZE{19}; static constexpr unsigned DEFLATE_PERMUTATION[DEFLATE_PERMUTATION_SIZE]{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; diff --git a/src/core/Color.cpp b/src/core/Color.cpp index f3d45b7..9d860ba 100644 --- a/src/core/Color.cpp +++ b/src/core/Color.cpp @@ -1,6 +1,6 @@ #include "Color.h" -Color::Color(unsigned r, unsigned g, unsigned b, double a) +Color::Color(unsigned char r, unsigned char g, unsigned char b, double a) : mR(r), mG(g), mB(b), @@ -9,26 +9,7 @@ Color::Color(unsigned r, unsigned g, unsigned b, double a) } -Color::Color(Name name) -{ - if (name == Name::WHITE) - { - Color(255, 255, 255); - } - else - { - Color(255, 255, 255); - } -} - -std::shared_ptr Color::CreateShared(unsigned r, unsigned g, unsigned b, - double a ) -{ - return std::make_shared(r, g, b, a); -} - -std::unique_ptr Color::Create(unsigned r, unsigned g, unsigned b, - double a ) +std::unique_ptr Color::Create(unsigned char r, unsigned char g, unsigned char b, double a ) { return std::make_unique(r, g, b, a); } @@ -38,17 +19,17 @@ std::unique_ptr Color::Create(const Color& color) return std::make_unique(color); } -unsigned Color::getR() const +unsigned char Color::getR() const { return mR; } -unsigned Color::getG() const +unsigned char Color::getG() const { return mG; } -unsigned Color::getB() const +unsigned char Color::getB() const { return mB; } @@ -57,3 +38,13 @@ double Color::getAlpha() const { return mAlpha; } + +std::vector Color::getAsVectorDouble() const +{ + return { mR / 255.0, mG / 255.0, mB / 255.0, mAlpha }; +} + +uint32_t Color::getAsUInt32() const +{ + return static_cast(mB + (mG << 8) + (mR << 16)); +} \ No newline at end of file diff --git a/src/core/Color.h b/src/core/Color.h index 390520a..f091b68 100644 --- a/src/core/Color.h +++ b/src/core/Color.h @@ -2,30 +2,24 @@ #include #include -#include class Color { public: + Color(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, double a = 1.0); - enum class Name - { - WHITE - }; - - Color(unsigned r = 0, unsigned g = 0, unsigned b = 0, double a = 1.0); - - Color(Name name); - - static std::shared_ptr CreateShared(unsigned r, unsigned g, unsigned b, double a = 1.0); - static std::unique_ptr Create(unsigned r, unsigned g, unsigned b, double a = 1.0); + static std::unique_ptr Create(unsigned char r, unsigned char g, unsigned char b, double a = 1.0); static std::unique_ptr Create(const Color& color); - unsigned getR() const; - unsigned getG() const; - unsigned getB() const; + unsigned char getR() const; + unsigned char getG() const; + unsigned char getB() const; double getAlpha() const; + std::vector getAsVectorDouble() const; + + uint32_t getAsUInt32() const; + bool operator==(const Color& rhs) const { return (mR == rhs.mR) @@ -39,25 +33,10 @@ public: return !operator==(rhs); } - std::vector getAsVectorDouble() const - { - return {mR/255.0, mG/255.0, mB/255.0, mAlpha}; - } - - uint32_t getAsUInt32() const - { - return mB + (mG<<8) + (mR<<16); - } - - static Color White() - { - return { 255, 255, 255, 1 }; - } - private: - unsigned mR{0}; - unsigned mG{0}; - unsigned mB{0}; + unsigned char mR{0}; + unsigned char mG{0}; + unsigned char mB{0}; double mAlpha{0.0}; }; diff --git a/src/image/CMakeLists.txt b/src/image/CMakeLists.txt index 850c14b..f6fabc1 100644 --- a/src/image/CMakeLists.txt +++ b/src/image/CMakeLists.txt @@ -4,9 +4,11 @@ set(platform_LIB_INCLUDES) list(APPEND image_HEADERS Image.h + IImageWriter.h PlatformImage.h PlatformImageWriter.h png/PngWriter.h + png/BasicPngWriter.h png/PngReader.h ) @@ -14,6 +16,7 @@ list(APPEND image_LIB_INCLUDES Image.cpp ImageBitStream.cpp PlatformImage.cpp + png/BasicPngWriter.cpp png/PngWriter.cpp png/PngReader.cpp png/PngHeader.cpp diff --git a/src/image/IImageWriter.h b/src/image/IImageWriter.h new file mode 100644 index 0000000..4fd092d --- /dev/null +++ b/src/image/IImageWriter.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +using Path = std::filesystem::path; + +class Image; + +class IImageWriter +{ +public: + enum class ImgFormat + { + PNG, + UNKNOWN + }; + + IImageWriter(ImgFormat format) + : mFormat(format) + { + + }; + + virtual void write(const Path& path, Image* image) = 0; + +protected: + ImgFormat mFormat{ ImgFormat::UNKNOWN }; +}; \ No newline at end of file diff --git a/src/image/PlatformImageWriter.h b/src/image/PlatformImageWriter.h index 7f315b1..6ce2fb1 100644 --- a/src/image/PlatformImageWriter.h +++ b/src/image/PlatformImageWriter.h @@ -1,18 +1,13 @@ #pragma once -#include +#include "IImageWriter.h" -using Path = std::filesystem::path; - -class Image; - -class PlatformImageWriter +class PlatformImageWriter : public IImageWriter { public: - enum class ImgFormat + PlatformImageWriter(ImgFormat format) + : IImageWriter(format) { - PNG - }; - virtual void write(const Path& path, Image* image, ImgFormat format = ImgFormat::PNG) = 0; + } }; \ No newline at end of file diff --git a/src/image/png/BasicPngWriter.cpp b/src/image/png/BasicPngWriter.cpp new file mode 100644 index 0000000..c891ddd --- /dev/null +++ b/src/image/png/BasicPngWriter.cpp @@ -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 + +BasicPngWriter::BasicPngWriter() + : IImageWriter(ImgFormat::PNG) +{ + +} + +BasicPngWriter::~BasicPngWriter() +{ + +} + +std::unique_ptr BasicPngWriter::Create() +{ + return std::make_unique(); +} + +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 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(num_bytes)); + + std::vector 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 out_file; + + if (path.empty()) + { + out_file = std::make_unique(path); + out_file->open(File::AccessMode::Write); + mOutStream = std::make_unique(out_file->getOutHandle()); + } + else + { + mOutStream = std::make_unique(); + } + + mWorkingImage = image; + + auto image_bit_stream = std::make_unique(image); + auto raw_image_stream = image_bit_stream.get(); + + mInStream = std::move(image_bit_stream); + + writeHeader(); + + auto filter_out_stream = std::make_unique(); + PngFilter filter(raw_image_stream, filter_out_stream.get()); + filter.encode(); + + filter_out_stream->resetOffsets(); + + std::unique_ptr lz77_out_stream; + + if (mCompressionMethod == Deflate::CompressionMethod::NONE) + { + lz77_out_stream = std::move(filter_out_stream); + } + else + { + lz77_out_stream = std::make_unique(); + Lz77Encoder lz77_encoder(filter_out_stream.get(), lz77_out_stream.get()); + + if (mCompressionMethod == Deflate::CompressionMethod::FIXED_HUFFMAN) + { + auto huffman_encoder = std::make_unique(); + 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(); +} \ No newline at end of file diff --git a/src/image/png/BasicPngWriter.h b/src/image/png/BasicPngWriter.h new file mode 100644 index 0000000..5331e6f --- /dev/null +++ b/src/image/png/BasicPngWriter.h @@ -0,0 +1,52 @@ +#pragma once + +#include "IImageWriter.h" + +#include "PngHeader.h" +#include "Image.h" +#include "DeflateElements.h" + +#include +#include +#include + +using Path = std::filesystem::path; + +class BitStream; +class BufferBitStream; + +class BasicPngWriter : public IImageWriter +{ +public: + BasicPngWriter(); + + ~BasicPngWriter(); + + static std::unique_ptr 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 mInStream; + std::unique_ptr mOutStream; + + unsigned mPngInfoUserSet{ false }; + PngInfo mPngInfo; + PngHeader mPngHeader; + + Deflate::CompressionMethod mCompressionMethod{ Deflate::CompressionMethod::DYNAMIC_HUFFMAN }; +}; \ No newline at end of file diff --git a/src/image/png/PngWriter.cpp b/src/image/png/PngWriter.cpp index 2a24c41..c81a942 100644 --- a/src/image/png/PngWriter.cpp +++ b/src/image/png/PngWriter.cpp @@ -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 - PngWriter::PngWriter() + : IImageWriter(ImgFormat::PNG) { - +#ifdef _WIN32 + mWriterImpl = std::make_unique(mFormat); +#else + mWriterImpl = std::make_unique(mFormat); +#endif } PngWriter::~PngWriter() @@ -36,209 +26,7 @@ std::unique_ptr PngWriter::Create() return std::make_unique(); } -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 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;idxwrite(num_bytes); - - std::vector 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; jdxwriteByte(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(); - 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(mPath); - mWorkingFile->open(File::AccessMode::Write); - mOutStream = std::make_unique(mWorkingFile->getOutHandle()); - } - else - { - mOutStream = std::make_unique(); - } - - mWorkingImage = image; - - auto image_bit_stream = std::make_unique(image); - auto raw_image_stream = image_bit_stream.get(); - - mInStream = std::move(image_bit_stream); - - writeHeader(); - - auto filter_out_stream = std::make_unique(); - PngFilter filter(raw_image_stream, filter_out_stream.get()); - filter.encode(); - - filter_out_stream->resetOffsets(); - - std::unique_ptr lz77_out_stream; - - if (mCompressionMethod == Deflate::CompressionMethod::NONE) - { - lz77_out_stream = std::move(filter_out_stream); - } - else - { - lz77_out_stream = std::make_unique(); - Lz77Encoder lz77_encoder(filter_out_stream.get(), lz77_out_stream.get()); - - if (mCompressionMethod == Deflate::CompressionMethod::FIXED_HUFFMAN) - { - auto huffman_encoder = std::make_unique(); - 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) -{ - write(image.get()); -} + mWriterImpl->write(path, image); +} \ No newline at end of file diff --git a/src/image/png/PngWriter.h b/src/image/png/PngWriter.h index d149c08..6cb994d 100644 --- a/src/image/png/PngWriter.h +++ b/src/image/png/PngWriter.h @@ -1,21 +1,12 @@ #pragma once -#include "PngHeader.h" #include "Image.h" -#include "DeflateElements.h" -#include "PlatformImageWriter.h" +#include "IImageWriter.h" #include #include -#include -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 Create(); - void setCompressionMethod(Deflate::CompressionMethod method); - - void setPath(const Path& path); - - void setPngInfo(const PngInfo& info); - - void write(const std::unique_ptr& 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 mInStream; - std::unique_ptr mOutStream; - std::unique_ptr mWorkingFile; - - unsigned mPngInfoUserSet{false}; - PngInfo mPngInfo; - PngHeader mPngHeader; - - Deflate::CompressionMethod mCompressionMethod{Deflate::CompressionMethod::DYNAMIC_HUFFMAN}; - - std::unique_ptr mPlatformWriter; + std::unique_ptr mWriterImpl; }; using PngWriterPtr = std::unique_ptr; diff --git a/src/image/win32/Win32WicImageWriter.cpp b/src/image/win32/Win32WicImageWriter.cpp index d532045..6612a42 100644 --- a/src/image/win32/Win32WicImageWriter.cpp +++ b/src/image/win32/Win32WicImageWriter.cpp @@ -8,7 +8,13 @@ #include #include -void Win32WicImageWriter::write(const Path& path, Image* image, ImgFormat format ) +Win32WicImageWriter::Win32WicImageWriter(ImgFormat format) + : PlatformImageWriter(format) +{ + +} + +void Win32WicImageWriter::write(const Path& path, Image* image) { Win32WicInterface wic_interface; @@ -18,21 +24,21 @@ void Win32WicImageWriter::write(const Path& path, Image* image, ImgFormat format hr = pStream->InitializeFromFilename(path.wstring().c_str(), GENERIC_WRITE); Microsoft::WRL::ComPtr pEncoder; - hr = wic_interface.getFactory()->CreateEncoder(GUID_ContainerFormatPng, NULL, &pEncoder); + hr = wic_interface.getFactory()->CreateEncoder(GUID_ContainerFormatPng, nullptr, &pEncoder); hr = pEncoder->Initialize(pStream.Get(), WICBitmapEncoderNoCache); Microsoft::WRL::ComPtr pFrameEncode; - hr = pEncoder->CreateNewFrame(&pFrameEncode, NULL); + hr = pEncoder->CreateNewFrame(&pFrameEncode, nullptr); - hr = pFrameEncode->Initialize(NULL); + hr = pFrameEncode->Initialize(nullptr); hr = pFrameEncode->SetSize(image->getWidth(), image->getHeight()); WICPixelFormatGUID out_format = GUID_WICPixelFormatDontCare; hr = pFrameEncode->SetPixelFormat(&out_format); - hr = pFrameEncode->WriteSource(dynamic_cast(image->getPlatformImage())->getBitmap(), NULL); + hr = pFrameEncode->WriteSource(dynamic_cast(image->getPlatformImage())->getBitmap(), nullptr); hr = pFrameEncode->Commit(); diff --git a/src/image/win32/Win32WicImageWriter.h b/src/image/win32/Win32WicImageWriter.h index 4d683c9..c42599e 100644 --- a/src/image/win32/Win32WicImageWriter.h +++ b/src/image/win32/Win32WicImageWriter.h @@ -5,5 +5,7 @@ class Win32WicImageWriter : public PlatformImageWriter { public: - void write(const Path& path, Image* image, ImgFormat format = ImgFormat::PNG) override; + Win32WicImageWriter(ImgFormat format); + + void write(const Path& path, Image* image) override; }; \ No newline at end of file diff --git a/src/mesh/MeshBuilder.h b/src/mesh/MeshBuilder.h index 081f72e..2bbf539 100644 --- a/src/mesh/MeshBuilder.h +++ b/src/mesh/MeshBuilder.h @@ -6,8 +6,8 @@ #include -using EdgeIds = std::vector >; -using FaceIds = std::vector >; +using EdgeIds = std::vector >; +using FaceIds = std::vector >; using VecPoints = std::vector; class MeshBuilder diff --git a/src/mesh/MeshPrimitives.cpp b/src/mesh/MeshPrimitives.cpp index 468af62..31d8298 100644 --- a/src/mesh/MeshPrimitives.cpp +++ b/src/mesh/MeshPrimitives.cpp @@ -32,14 +32,14 @@ std::unique_ptr MeshPrimitives::buildRectangleAsTriMesh() return MeshBuilder::buildTriMesh(locations, edge_ids, face_ids); } -std::unique_ptr MeshPrimitives::buildCircleAsTriMesh(unsigned numSegments) +std::unique_ptr MeshPrimitives::buildCircleAsTriMesh(std::size_t numSegments) { VecPoints locations(numSegments + 1); locations[0] = {0, 0}; const double delta_theta = (2.0*M_PI)/double(numSegments); double theta = 0.0; - for(unsigned idx=1; idx<=numSegments; idx++) + for(std::size_t idx=1; idx<=numSegments; idx++) { const double x = sin(theta); const double y = cos(theta); @@ -49,7 +49,7 @@ std::unique_ptr MeshPrimitives::buildCircleAsTriMesh(unsigned numSegmen } EdgeIds edge_ids(2*numSegments); - for(unsigned idx=0; idx MeshPrimitives::buildCircleAsTriMesh(unsigned numSegmen } FaceIds face_ids(numSegments); - for(unsigned idx=0; idx MeshPrimitives::buildCircleAsTriMesh(unsigned numSegmen return MeshBuilder::buildTriMesh(locations, edge_ids, face_ids); } -std::unique_ptr MeshPrimitives::buildCircleAsLineMesh(unsigned numSegments) +std::unique_ptr MeshPrimitives::buildCircleAsLineMesh(std::size_t numSegments) { VecPoints locations(numSegments); const double delta_theta = (2.0*M_PI)/double(numSegments); @@ -101,10 +101,10 @@ std::unique_ptr MeshPrimitives::buildCircleAsLineMesh(unsigned numSegm return MeshBuilder::buildLineMesh(locations, edge_ids); } -std::unique_ptr MeshPrimitives::buildRoundedRectangleAsTriMesh(double radius, double aspect_ratio, unsigned num_segments) +std::unique_ptr MeshPrimitives::buildRoundedRectangleAsTriMesh(double radius, double aspect_ratio, std::size_t num_segments) { - unsigned num_fans = 4; - unsigned num_nodes_per_fan = num_segments + 2; + std::size_t num_fans = 4; + std::size_t num_nodes_per_fan = num_segments + 2; VecPoints locations(num_fans * num_nodes_per_fan); double rect_start_x = radius; @@ -115,8 +115,8 @@ std::unique_ptr MeshPrimitives::buildRoundedRectangleAsTriMesh(double r double running_theta = 0; locations[0] = {rect_end_x, radius}; - unsigned offset = 1; - for (unsigned idx=0; idx<=num_segments; idx++) + std::size_t offset = 1; + for (std::size_t idx=0; idx<=num_segments; idx++) { locations[offset + idx] = {rect_end_x + radius*sin(running_theta), radius*(1.0 - cos(running_theta))}; running_theta += delta_theta; @@ -126,7 +126,7 @@ std::unique_ptr MeshPrimitives::buildRoundedRectangleAsTriMesh(double r locations[offset] = {rect_end_x, rect_end_y}; offset++; running_theta = 0; - for (unsigned idx=0; idx<=num_segments;idx++) + for (std::size_t idx=0; idx<=num_segments;idx++) { locations[offset + idx] = {rect_end_x + radius*cos(running_theta), rect_end_y + radius*sin(running_theta)}; running_theta += delta_theta; @@ -136,7 +136,7 @@ std::unique_ptr MeshPrimitives::buildRoundedRectangleAsTriMesh(double r locations[offset] = {rect_start_x, rect_end_y}; offset ++; running_theta = 0; - for (unsigned idx=0; idx<=num_segments;idx++) + for (std::size_t idx=0; idx<=num_segments;idx++) { locations[offset + idx] = {rect_start_x - radius*sin(running_theta), rect_end_y + radius*cos(running_theta)}; running_theta += delta_theta; @@ -146,37 +146,37 @@ std::unique_ptr MeshPrimitives::buildRoundedRectangleAsTriMesh(double r locations[offset] = {rect_start_x, radius}; offset++; running_theta = 0; - for (unsigned idx=0; idx<=num_segments;idx++) + for (std::size_t idx=0; idx<=num_segments;idx++) { locations[offset + idx] = {rect_start_x - radius*cos(running_theta), radius *(1 - sin(running_theta))}; running_theta += delta_theta; } - unsigned num_edges_per_fan = 2*num_segments + 1; - unsigned num_inner_rect_edges = 3*num_fans; + std::size_t num_edges_per_fan = 2*num_segments + 1; + std::size_t num_inner_rect_edges = 3*num_fans; EdgeIds edge_ids(num_edges_per_fan*num_fans + num_inner_rect_edges + 1); // Fan edges - for (unsigned jdx=0; jdx< num_fans; jdx++) + for (std::size_t jdx=0; jdx< num_fans; jdx++) { - unsigned node_offset = jdx*num_nodes_per_fan; - unsigned edge_offset = jdx*num_edges_per_fan; + std::size_t node_offset = jdx*num_nodes_per_fan; + std::size_t edge_offset = jdx*num_edges_per_fan; // Inner edges - for(unsigned idx=0; idx<=num_segments; idx++) + for(std::size_t idx=0; idx<=num_segments; idx++) { edge_ids[edge_offset + idx] = {node_offset, node_offset + idx + 1}; } // Outer edges - for(unsigned idx=0; idx MeshPrimitives::buildRectangleAsLineMesh() return MeshBuilder::buildLineMesh(locations, edge_ids); } -std::unique_ptr MeshPrimitives::buildExplodedGridAsTriMesh(unsigned numX, unsigned numY) +std::unique_ptr MeshPrimitives::buildExplodedGridAsTriMesh(std::size_t numX, std::size_t numY) { double delta_x = 1.0/double(numX); double delta_y = 1.0/double(numY); @@ -207,9 +207,9 @@ std::unique_ptr MeshPrimitives::buildExplodedGridAsTriMesh(unsigned num VecPoints locations (4 * numX * numY); double offset_x = delta_x/2.0; double offset_y = delta_y/2.0; - for (unsigned idx=0; idx MeshPrimitives::buildExplodedGridAsTriMesh(unsigned num } EdgeIds edge_ids(5 * numX * numY); - for (unsigned idx=0; idx MeshPrimitives::buildExplodedGridAsTriMesh(unsigned num } FaceIds face_ids(2 *numX * numY); - for (unsigned idx=0; idx MeshPrimitives::buildExplodedGridAsTriMesh(unsigned num return MeshBuilder::buildTriMesh(locations, edge_ids, face_ids); } -std::unique_ptr MeshPrimitives::buildExplodedGridAsLineMesh(unsigned numX, unsigned numY) +std::unique_ptr MeshPrimitives::buildExplodedGridAsLineMesh(std::size_t numX, std::size_t numY) { double delta_x = 1.0/double(numX); double delta_y = 1.0/double(numY); @@ -266,9 +266,9 @@ std::unique_ptr MeshPrimitives::buildExplodedGridAsLineMesh(unsigned n VecPoints locations (4 * numX * numY); double offset_x = delta_x/2.0; double offset_y = delta_y/2.0; - for (unsigned idx=0; idx MeshPrimitives::buildExplodedGridAsLineMesh(unsigned n } EdgeIds edge_ids(4 * numX * numY); - for (unsigned idx=0; idx buildCircleAsTriMesh(unsigned numSegments = 24); + static std::unique_ptr buildCircleAsTriMesh(std::size_t numSegments = 24); - static std::unique_ptr buildCircleAsLineMesh(unsigned numSegments = 24); + static std::unique_ptr buildCircleAsLineMesh(std::size_t numSegments = 24); static std::unique_ptr buildRectangleAsTriMesh(); static std::unique_ptr buildRectangleAsLineMesh(); - static std::unique_ptr buildExplodedGridAsTriMesh(unsigned numX, unsigned numY); + static std::unique_ptr buildExplodedGridAsTriMesh(std::size_t numX, std::size_t numY); - static std::unique_ptr buildExplodedGridAsLineMesh(unsigned numX, unsigned numY); + static std::unique_ptr buildExplodedGridAsLineMesh(std::size_t numX, std::size_t numY); - static std::unique_ptr buildRoundedRectangleAsTriMesh(double radius, double aspect_ratio = 1.0, unsigned num_segments = 4); + static std::unique_ptr buildRoundedRectangleAsTriMesh(double radius, double aspect_ratio = 1.0, std::size_t num_segments = 4); }; diff --git a/src/publishing/pdf/PdfDocument.h b/src/publishing/pdf/PdfDocument.h index f9a4779..a616307 100644 --- a/src/publishing/pdf/PdfDocument.h +++ b/src/publishing/pdf/PdfDocument.h @@ -35,7 +35,7 @@ private: std::string mVersion {"1.7"}; PdfXRefTablePtr mXRefTable; - unsigned mXRefOffset{0}; + std::size_t mXRefOffset{0}; PdfDocumentCatalogPtr mCatalog; }; diff --git a/src/publishing/pdf/PdfXRefTable.cpp b/src/publishing/pdf/PdfXRefTable.cpp index a340f1a..7165a13 100644 --- a/src/publishing/pdf/PdfXRefTable.cpp +++ b/src/publishing/pdf/PdfXRefTable.cpp @@ -16,8 +16,8 @@ std::string PdfXRefTable::toString() content += "\n"; for (const auto& record : section.mRecords) { - auto offsetString = StringUtils::toPaddedString(10, record.mOffsetBytes); - auto generationString = StringUtils::toPaddedString(5, record.mGenerationNumber); + auto offsetString = StringUtils::toPaddedString(10, static_cast(record.mOffsetBytes)); + auto generationString = StringUtils::toPaddedString(5, static_cast(record.mGenerationNumber)); auto freeString = record.mIsFree ? "f" : "n"; content += offsetString + " " + generationString + " " + freeString + "\n"; @@ -27,7 +27,7 @@ std::string PdfXRefTable::toString() return content; } -unsigned PdfXRefTable::getNextOffset() +std::size_t PdfXRefTable::getNextOffset() { auto lastNumRecords = mSections[mSections.size() - 1].mRecords.size(); if (lastNumRecords > 0) @@ -45,7 +45,7 @@ unsigned PdfXRefTable::getNextOffset() } } -void PdfXRefTable::addRecord(unsigned numBytes, unsigned generation, unsigned isFree) +void PdfXRefTable::addRecord(std::size_t numBytes, std::size_t generation, unsigned isFree) { XRefRecord record; @@ -56,9 +56,9 @@ void PdfXRefTable::addRecord(unsigned numBytes, unsigned generation, unsigned is mLastAddedBytes = numBytes; } -unsigned PdfXRefTable::getNumEntries() +std::size_t PdfXRefTable::getNumEntries() { - unsigned count = 0; + std::size_t count = 0; for (const auto& section : mSections) { count += section.mRecords.size(); diff --git a/src/publishing/pdf/PdfXRefTable.h b/src/publishing/pdf/PdfXRefTable.h index 961209a..a544bad 100644 --- a/src/publishing/pdf/PdfXRefTable.h +++ b/src/publishing/pdf/PdfXRefTable.h @@ -6,14 +6,14 @@ struct XRefRecord { - unsigned mOffsetBytes{0}; - unsigned mGenerationNumber{0}; + std::size_t mOffsetBytes{0}; + std::size_t mGenerationNumber{0}; bool mIsFree{false}; }; struct TableSubSection { - unsigned mStartIndex{0}; + std::size_t mStartIndex{0}; std::vector mRecords; }; @@ -22,14 +22,14 @@ class PdfXRefTable public: PdfXRefTable(); - void addRecord(unsigned numBytes, unsigned generation, unsigned isFree); + void addRecord(std::size_t numBytes, std::size_t generation, unsigned isFree); - unsigned getNextOffset(); + std::size_t getNextOffset(); - unsigned getNumEntries(); + std::size_t getNumEntries(); std::string toString(); private: - unsigned mLastAddedBytes{0}; + std::size_t mLastAddedBytes{0}; std::vector mSections; }; diff --git a/src/windows/ui_interfaces/win32/directx/DirectX2dIntegration.cpp b/src/windows/ui_interfaces/win32/directx/DirectX2dIntegration.cpp index ac8a8ba..b602aba 100644 --- a/src/windows/ui_interfaces/win32/directx/DirectX2dIntegration.cpp +++ b/src/windows/ui_interfaces/win32/directx/DirectX2dIntegration.cpp @@ -76,9 +76,9 @@ void DirectX2dIntegration::wrapBuffer(ID3D12Resource* renderTarget) mDxInterface->get11On12Device()->CreateWrappedResource(renderTarget, &d3d11Flags, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT, IID_PPV_ARGS(&mWrappedBackBuffers[mWrappedBackBuffers.size()-1])); - float dpiX{ 0.0 }; - float dpiY{ 0.0 }; - mDx2dInterface->getFactory()->GetDesktopDpi(&dpiX, &dpiY); + float dpiX{ 96.0 }; + float dpiY{ 96.0 }; + //mDx2dInterface->getFactory()->GetDesktopDpi(&dpiX, &dpiY); const auto pixel_format = D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED); const auto bitmap_props = D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, pixel_format, dpiX, dpiY); diff --git a/test/image/TestPngWriter.cpp b/test/image/TestPngWriter.cpp index aca35a2..3db10b3 100644 --- a/test/image/TestPngWriter.cpp +++ b/test/image/TestPngWriter.cpp @@ -30,9 +30,8 @@ TEST_CASE(TestCompressedPng, "image") image->getGridT()->setData(data); PngWriter writer; - writer.setPath(TestUtils::getTestOutputDir() / "test_compressed.png"); - writer.setCompressionMethod(Deflate::CompressionMethod::NONE); - writer.write(image); + //writer.setCompressionMethod(Deflate::CompressionMethod::NONE); + writer.write(TestUtils::getTestOutputDir() / "test_compressed.png", image.get()); return; File test_file(TestUtils::getTestOutputDir() / "test_compressed.png"); @@ -64,9 +63,8 @@ TEST_CASE(TestFixedPng, "image") image->getGridT()->setData(data); PngWriter writer; - writer.setPath(TestUtils::getTestOutputDir() / "test_fixed.png"); - writer.setCompressionMethod(Deflate::CompressionMethod::FIXED_HUFFMAN); - writer.write(image); + //writer.setCompressionMethod(Deflate::CompressionMethod::FIXED_HUFFMAN); + writer.write(TestUtils::getTestOutputDir() / "test_fixed.png", image.get()); //return; File test_file(TestUtils::getTestOutputDir() / "test_fixed.png"); @@ -94,8 +92,8 @@ TEST_CASE(TestDynamicCompressedPng, "image") image->getGridT()->setData(data); PngWriter writer; - writer.setPath(TestUtils::getTestOutputDir() / "test_dynamic.png"); - writer.write(image); + //writer.setPath(TestUtils::getTestOutputDir() / "test_dynamic.png"); + writer.write(TestUtils::getTestOutputDir() / "test_dynamic.png", image.get()); //return; File test_file(TestUtils::getTestOutputDir() / "test_dynamic.png"); diff --git a/test/test_utils/TestRenderUtils.h b/test/test_utils/TestRenderUtils.h index 83f093a..977fc00 100644 --- a/test/test_utils/TestRenderUtils.h +++ b/test/test_utils/TestRenderUtils.h @@ -37,8 +37,7 @@ public: auto image = mSurface->getImage(); PngWriter writer; - writer.setPath(path); - writer.write(image); + writer.write(path, image); } void writeSvg(const Path& path)