From 66612995734f0cef9ebd595763a00590f4dddf8b Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sat, 27 Feb 2021 19:44:17 +0300 Subject: [PATCH] Support reading grayscale pngs --- libs/gfx/include/psemek/gfx/pixmap.hpp | 1 + libs/gfx/source/png.cpp | 34 ++++++++++++++++++-------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/libs/gfx/include/psemek/gfx/pixmap.hpp b/libs/gfx/include/psemek/gfx/pixmap.hpp index 353a6e69..02babf58 100644 --- a/libs/gfx/include/psemek/gfx/pixmap.hpp +++ b/libs/gfx/include/psemek/gfx/pixmap.hpp @@ -24,5 +24,6 @@ namespace psemek::gfx void write_ppm(pixmap_rgb const & p, std::ostream & os); pixmap_rgba read_png(std::istream & is); + pixmap_monochrome read_png_monochrome(std::istream & is); } diff --git a/libs/gfx/source/png.cpp b/libs/gfx/source/png.cpp index 80199aef..6bd63cb2 100644 --- a/libs/gfx/source/png.cpp +++ b/libs/gfx/source/png.cpp @@ -3,14 +3,13 @@ #include #include -#include - #include namespace psemek::gfx { - pixmap_rgba read_png(std::istream & is) + template + basic_pixmap read_png_impl(std::istream & is, png_byte expected_color_type) { png_error_ptr error = [](png_structp, png_const_charp str) { @@ -52,17 +51,22 @@ namespace psemek::gfx auto const color_type = png_get_color_type(png, info); auto const bit_depth = png_get_bit_depth(png, info); - if (color_type != PNG_COLOR_TYPE_RGBA) - throw std::runtime_error("PNG color types other than RGBA are not supported"); + if (color_type != expected_color_type) + throw std::runtime_error("PNG color type not supported"); - if (bit_depth != 8) - throw std::runtime_error("PNG bit depths other than 8 are not supported"); + if (bit_depth == 16) + png_set_strip_16(png); - pixmap_rgba result({width, height}); + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand_gray_1_2_4_to_8(png); + + png_read_update_info(png, info); + + basic_pixmap result({width, height}); auto const row_bytes = png_get_rowbytes(png, info); - if (row_bytes != width * 4) - throw std::runtime_error("PNG row bytes is wrong"); + if (row_bytes != width * sizeof(Pixel)) + throw std::runtime_error("PNG row bytes mismatch"); for (std::uint32_t i = 0; i < height; ++i) png_read_row(png, reinterpret_cast(result.data() + i * width), nullptr); @@ -70,4 +74,14 @@ namespace psemek::gfx return result; } + pixmap_rgba read_png(std::istream & is) + { + return read_png_impl(is, PNG_COLOR_TYPE_RGBA); + } + + pixmap_monochrome read_png_monochrome(std::istream & is) + { + return read_png_impl(is, PNG_COLOR_TYPE_GRAY); + } + }