From 680191a11d882ea151ee9dbae965a23777a3be5c Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sun, 6 Aug 2017 19:55:31 +0000 Subject: [PATCH] Move ToPng() into Image, make PiRaw static-only --- image.h | 44 +++++++++++++++++++++++++++++ piphoto.cc | 5 ++-- piraw.h | 82 ++++++++---------------------------------------------- 3 files changed, 57 insertions(+), 74 deletions(-) diff --git a/image.h b/image.h index 1fa381d..571b81b 100644 --- a/image.h +++ b/image.h @@ -1,5 +1,10 @@ #pragma once +#include +#include + +#include + #include "color.h" #include "coord.h" @@ -13,6 +18,8 @@ class Image : public std::array, Y> { void DrawYLine(const Coord& start, const Color& color, uint32_t length); void DrawRectangle(const Coord& start, const Color& color, uint32_t x_length, uint32_t y_length); void DrawSquare(const Coord& start, const Color& color, uint32_t length); + + std::string ToPng(); }; template @@ -53,3 +60,40 @@ template void Image::DrawSquare(const Coord& start, const Color& color, uint32_t length) { DrawRectangle(start, color, length, length); } + +static void WriteCallback(png_structp png_ptr, png_bytep data, png_size_t length) { + auto dest = static_cast(png_get_io_ptr(png_ptr)); + dest->append(reinterpret_cast(data), length); +} + +template +std::string Image::ToPng() { + std::string ret; + + auto png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + assert(png_ptr); + auto info_ptr = png_create_info_struct(png_ptr); + assert(info_ptr); + + png_set_write_fn(png_ptr, &ret, &WriteCallback, nullptr); + png_set_IHDR(png_ptr, info_ptr, X / 2, Y / 2, + 16, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_write_info(png_ptr, info_ptr); + for (auto& row : *this) { + std::array out_row; + for (uint32_t x = 0; x < X; ++x) { + out_row[x * 3 + 0] = htons(static_cast(row[x].r)); + out_row[x * 3 + 1] = htons(static_cast(row[x].g)); + out_row[x * 3 + 2] = htons(static_cast(row[x].b)); + } + png_write_row(png_ptr, reinterpret_cast(out_row.data())); + } + png_write_end(png_ptr, nullptr); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + png_destroy_write_struct(&png_ptr, &info_ptr); + + return ret; +} diff --git a/piphoto.cc b/piphoto.cc index 4a500e9..35895fd 100644 --- a/piphoto.cc +++ b/piphoto.cc @@ -9,8 +9,7 @@ #include "util.h" int main() { - auto raw = PiRaw2::FromJpeg(ReadFile("test.jpg")); - auto* image = raw.GetImage(); + auto image = PiRaw2::FromJpeg(ReadFile("test.jpg")); auto closest = ColorCheckerClosest(*image); for (uint32_t cc = 0; cc < kColorCheckerSrgb.size(); ++cc) { const auto& coord = closest.at(cc); @@ -22,5 +21,5 @@ int main() { image->DrawSquare({std::max(8U, coord.x) - 8, std::max(8U, coord.y) - 8}, color, 16); image->DrawSquare({std::max(9U, coord.x) - 9, std::max(9U, coord.y) - 9}, kWhite, 18); } - WriteFile("test.png", raw.ToPng()); + WriteFile("test.png", image->ToPng()); } diff --git a/piraw.h b/piraw.h index 18d7ce8..7330f46 100644 --- a/piraw.h +++ b/piraw.h @@ -1,8 +1,5 @@ #pragma once -#include -#include - #include #include @@ -16,16 +13,12 @@ using string_view = experimental::string_view; template class PiRaw { public: - PiRaw(std::unique_ptr>); - static PiRaw FromJpeg(const std::string_view& jpeg); - static PiRaw FromRaw(const std::string_view& raw); - - std::string ToPng(); - - Image* GetImage(); - const Image& GetImage() const; + static std::unique_ptr> FromJpeg(const std::string_view& jpeg); + static std::unique_ptr> FromRaw(const std::string_view& raw); private: + PiRaw() {} + static constexpr uint32_t kJpegHeaderBytes = 32768; static constexpr const char* kJpegHeaderMagic = "BRCM"; static constexpr uint32_t kPixelsPerChunk = 4; @@ -40,27 +33,21 @@ class PiRaw { typedef std::array Chunk; - static Chunk GetChunk(const std::string_view& raw, const uint32_t x_chunk, const uint32_t y); - static Color CombineRaw(uint32_t y0x0, uint32_t y0x1, uint32_t y1x0, uint32_t y1x1); - - std::unique_ptr> image_; + static constexpr Chunk GetChunk(const std::string_view& raw, const uint32_t x_chunk, const uint32_t y); + static constexpr Color CombineRaw(uint32_t y0x0, uint32_t y0x1, uint32_t y1x0, uint32_t y1x1); }; typedef PiRaw<3280, 2464, 10, 16, 2> PiRaw2; template -PiRaw::PiRaw(std::unique_ptr> image) - : image_(std::move(image)) {} - -template -PiRaw PiRaw::FromJpeg(const std::string_view& jpeg) { +typename std::unique_ptr> PiRaw::FromJpeg(const std::string_view& jpeg) { auto container_len = GetRawBytes() + kJpegHeaderBytes; assert(jpeg.substr(jpeg.size() - container_len, 4) == kJpegHeaderMagic); return FromRaw(jpeg.substr(jpeg.size() - GetRawBytes(), GetRawBytes())); } template -PiRaw PiRaw::FromRaw(const std::string_view& raw) { +typename std::unique_ptr> PiRaw::FromRaw(const std::string_view& raw) { static_assert(X % 2 == 0); static_assert(Y % 2 == 0); static_assert(kPixelsPerChunk == 4); @@ -77,7 +64,7 @@ PiRaw PiRaw::FromRaw(const std::string_view& raw) image->at(out_y).at(out_x + 1) = CombineRaw(chunk1.at(2), chunk1.at(3), chunk2.at(2), chunk2.at(3)); } } - return PiRaw(std::move(image)); + return image; } template @@ -106,7 +93,7 @@ constexpr uint32_t PiRaw::Align(uint32_t val) { } template -typename PiRaw::Chunk PiRaw::GetChunk(const std::string_view& raw, const uint32_t x_chunk, const uint32_t y) { +constexpr typename PiRaw::Chunk PiRaw::GetChunk(const std::string_view& raw, const uint32_t x_chunk, const uint32_t y) { // Function is bit depth & layout specific static_assert(D == 10); @@ -126,7 +113,7 @@ typename PiRaw::Chunk PiRaw::GetChunk(const std::s } template -Color PiRaw::CombineRaw(uint32_t y0x0, uint32_t y0x1, uint32_t y1x0, uint32_t y1x1) { +constexpr Color PiRaw::CombineRaw(uint32_t y0x0, uint32_t y0x1, uint32_t y1x0, uint32_t y1x1) { // Function is bit layout specific Color ret; ret.r = y1x1; @@ -134,50 +121,3 @@ Color PiRaw::CombineRaw(uint32_t y0x0, uint32_t y0x1, uint32_t y1 ret.b = y0x0; return ret; } - -static void WriteCallback(png_structp png_ptr, png_bytep data, png_size_t length) { - auto dest = static_cast(png_get_io_ptr(png_ptr)); - dest->append(reinterpret_cast(data), length); -} - -template -std::string PiRaw::ToPng() { - std::string ret; - - auto png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - assert(png_ptr); - auto info_ptr = png_create_info_struct(png_ptr); - assert(info_ptr); - - png_set_write_fn(png_ptr, &ret, &WriteCallback, nullptr); - png_set_IHDR(png_ptr, info_ptr, X / 2, Y / 2, - 16, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - - png_write_info(png_ptr, info_ptr); - for (auto& row : *image_) { - std::array out_row; - for (uint32_t x = 0; x < X; ++x) { - out_row[x * 3 + 0] = htons(static_cast(row[x].r)); - out_row[x * 3 + 1] = htons(static_cast(row[x].g)); - out_row[x * 3 + 2] = htons(static_cast(row[x].b)); - } - png_write_row(png_ptr, reinterpret_cast(out_row.data())); - } - png_write_end(png_ptr, nullptr); - - png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); - png_destroy_write_struct(&png_ptr, &info_ptr); - - return ret; -} - -template -Image* PiRaw::GetImage() { - return image_.get(); -} - -template -const Image& PiRaw::GetImage() const { - return *image_; -}