Remove old NetPBM & PNG code in favour of new stb_* implementations
This commit is contained in:
parent
1c54dd85a5
commit
1b949c0b7f
8 changed files with 31 additions and 369 deletions
|
|
@ -107,7 +107,7 @@ namespace psemek::fonts
|
|||
{
|
||||
auto data = bmfont_data::parse(std::move(description));
|
||||
|
||||
auto pixmap = gfx::read_png_monochrome(std::move(texture));
|
||||
auto pixmap = gfx::read_image<std::uint8_t>(std::move(texture));
|
||||
gfx::texture_2d atlas;
|
||||
atlas.load(pixmap);
|
||||
atlas.linear_filter();
|
||||
|
|
|
|||
|
|
@ -8,7 +8,10 @@ namespace psemek::fonts
|
|||
{
|
||||
auto data = bmfont_data::parse(std::move(description));
|
||||
|
||||
auto pixmap = gfx::read_png(std::move(texture));
|
||||
gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);
|
||||
gl::PixelStorei(gl::PACK_ALIGNMENT, 1);
|
||||
|
||||
auto pixmap = gfx::read_image<gfx::color_rgb>(std::move(texture));
|
||||
gfx::texture_2d atlas;
|
||||
atlas.load(pixmap);
|
||||
atlas.linear_mipmap_filter();
|
||||
|
|
|
|||
|
|
@ -17,17 +17,7 @@ namespace psemek::gfx
|
|||
using pixmap_rgba = basic_pixmap<color_rgba>;
|
||||
using pixmap_float = basic_pixmap<float>;
|
||||
|
||||
pixmap_monochrome read_pbm(std::istream & is);
|
||||
pixmap_monochrome read_pgm(std::istream & is);
|
||||
pixmap_rgb read_ppm(std::istream & is);
|
||||
|
||||
void write_pgm(pixmap_monochrome const & p, std::ostream & os);
|
||||
void write_ppm(pixmap_rgb const & p, std::ostream & os);
|
||||
|
||||
pixmap_rgba read_png(io::istream && is);
|
||||
pixmap_monochrome read_png_monochrome(io::istream && is);
|
||||
|
||||
void write_png(pixmap_rgba const & p, io::ostream && os);
|
||||
// Image reading
|
||||
|
||||
template <typename Pixel>
|
||||
basic_pixmap<Pixel> read_image(io::istream && is);
|
||||
|
|
@ -36,6 +26,8 @@ namespace psemek::gfx
|
|||
extern template pixmap_rgb read_image<color_rgb>(io::istream && is);
|
||||
extern template pixmap_rgba read_image<color_rgba>(io::istream && is);
|
||||
|
||||
// Image writing
|
||||
|
||||
void write_image_png(pixmap_monochrome const & p, io::ostream && os);
|
||||
void write_image_png(pixmap_rgb const & p, io::ostream && os);
|
||||
void write_image_png(pixmap_rgba const & p, io::ostream && os);
|
||||
|
|
@ -50,6 +42,11 @@ namespace psemek::gfx
|
|||
|
||||
void write_image_hdr(basic_pixmap<color_3f> const & p, io::ostream && os);
|
||||
|
||||
void write_image_pgm(pixmap_monochrome const & p, io::ostream && os);
|
||||
void write_image_ppm(pixmap_rgb const & p, io::ostream && os);
|
||||
|
||||
// Utilities
|
||||
|
||||
template <typename Pixel, std::size_t N>
|
||||
auto to_srgb(util::array<Pixel, N> pm, float g = 1.f / 2.2f)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ namespace psemek::gfx
|
|||
{
|
||||
auto data = uri_loader(texture.uri);
|
||||
auto & target = textures_.emplace_back();
|
||||
target.load_srgb(gfx::read_png(io::memory_istream(data.string_view())));
|
||||
target.load_srgb(gfx::read_image<gfx::color_rgba>(io::memory_istream(data.string_view())));
|
||||
target.linear_mipmap_filter();
|
||||
target.anisotropy();
|
||||
target.generate_mipmap();
|
||||
|
|
|
|||
|
|
@ -1,208 +0,0 @@
|
|||
#include <psemek/gfx/pixmap.hpp>
|
||||
#include <psemek/util/exception.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
namespace psemek::gfx
|
||||
{
|
||||
|
||||
pixmap_monochrome read_pbm(std::istream & is)
|
||||
{
|
||||
auto fail = [](std::string str)
|
||||
{
|
||||
throw util::exception("Error loading PBM image: " + str);
|
||||
};
|
||||
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
|
||||
bool binary = true;
|
||||
|
||||
if (line == "P1")
|
||||
{
|
||||
binary = false;
|
||||
}
|
||||
else if (line == "P4")
|
||||
{
|
||||
binary = true;
|
||||
}
|
||||
else
|
||||
fail("unknown format " + line);
|
||||
|
||||
if (!binary)
|
||||
fail("P1 format is not supported");
|
||||
|
||||
std::getline(is, line);
|
||||
if (!is)
|
||||
fail("stream error");
|
||||
std::istringstream sline(line);
|
||||
|
||||
std::size_t width, height;
|
||||
pixmap_monochrome pixmap;
|
||||
|
||||
sline >> width >> height;
|
||||
if (!sline)
|
||||
fail("stream error");
|
||||
|
||||
pixmap.resize({width, height});
|
||||
|
||||
std::size_t bytes = width * height;
|
||||
if ((bytes % 8) == 0)
|
||||
bytes = bytes / 8;
|
||||
else
|
||||
bytes = (bytes + 7) / 8;
|
||||
std::vector<std::uint8_t> data(bytes);
|
||||
is.read(reinterpret_cast<char *>(data.data()), bytes);
|
||||
|
||||
for (std::size_t i = 0; i < width * height; ++i)
|
||||
{
|
||||
std::size_t b = i / 8;
|
||||
std::size_t o = 7 - (i % 8);
|
||||
bool const white = (data[b] & (1 << o)) == 0;
|
||||
pixmap.data()[i] = white ? 255 : 0;
|
||||
}
|
||||
|
||||
if (!is)
|
||||
fail("stream error");
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
pixmap_monochrome read_pgm(std::istream & is)
|
||||
{
|
||||
auto fail = [](std::string str)
|
||||
{
|
||||
throw util::exception("Error loading PGM image: " + str);
|
||||
};
|
||||
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
|
||||
bool binary = true;
|
||||
|
||||
if (line == "P2")
|
||||
{
|
||||
binary = false;
|
||||
}
|
||||
else if (line == "P5")
|
||||
{
|
||||
binary = true;
|
||||
}
|
||||
else
|
||||
fail("unknown format " + line);
|
||||
|
||||
std::getline(is, line);
|
||||
if (!is)
|
||||
fail("stream error");
|
||||
std::istringstream sline(line);
|
||||
|
||||
std::size_t width, height;
|
||||
std::size_t max;
|
||||
pixmap_monochrome pixmap;
|
||||
|
||||
sline >> width >> height;
|
||||
if (!sline)
|
||||
fail("stream error");
|
||||
|
||||
std::getline(is, line);
|
||||
if (!is)
|
||||
fail("stream error");
|
||||
sline.clear();
|
||||
sline.str(line);
|
||||
sline >> max;
|
||||
if (!sline)
|
||||
fail("stream error");
|
||||
|
||||
if (max != 255)
|
||||
fail("max value " + std::to_string(max) + " is not supported");
|
||||
|
||||
pixmap.resize({width, height});
|
||||
|
||||
if (binary)
|
||||
is.read(reinterpret_cast<char *>(pixmap.data()), width * height * sizeof(pixmap.data()[0]));
|
||||
else
|
||||
fail("P2 format is not supported");
|
||||
|
||||
if (!is)
|
||||
fail("stream error");
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
pixmap_rgb read_ppm(std::istream & is)
|
||||
{
|
||||
auto fail = [](std::string str)
|
||||
{
|
||||
throw util::exception("Error loading PPM image: " + str);
|
||||
};
|
||||
|
||||
std::string line;
|
||||
std::getline(is, line);
|
||||
|
||||
bool binary = true;
|
||||
|
||||
if (line == "P3")
|
||||
{
|
||||
binary = false;
|
||||
}
|
||||
else if (line == "P6")
|
||||
{
|
||||
binary = true;
|
||||
}
|
||||
else
|
||||
fail("unknown format " + line);
|
||||
|
||||
std::getline(is, line);
|
||||
if (!is)
|
||||
fail("stream error");
|
||||
std::istringstream sline(line);
|
||||
|
||||
std::size_t width, height;
|
||||
std::size_t max;
|
||||
pixmap_rgb pixmap;
|
||||
|
||||
sline >> width >> height;
|
||||
|
||||
if (!sline)
|
||||
fail("stream error");
|
||||
|
||||
std::getline(is, line);
|
||||
if (!is)
|
||||
fail("stream error");
|
||||
sline.clear();
|
||||
sline.str(line);
|
||||
sline >> max;
|
||||
if (!sline)
|
||||
fail("stream error");
|
||||
|
||||
if (max != 255)
|
||||
fail("max value " + std::to_string(max) + " is not supported");
|
||||
|
||||
pixmap.resize({width, height});
|
||||
|
||||
if (binary)
|
||||
is.read(reinterpret_cast<char *>(pixmap.data()), width * height * sizeof(pixmap.data()[0]));
|
||||
else
|
||||
fail("P3 format is not supported");
|
||||
|
||||
if (!is)
|
||||
fail("stream error");
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
void write_pgm(pixmap_monochrome const & p, std::ostream & os)
|
||||
{
|
||||
os << "P5\n" << p.width() << " " << p.height() << "\n255\n";
|
||||
os.write(reinterpret_cast<char const *>(p.data()), p.width() * p.height() * sizeof(p.data()[0]));
|
||||
}
|
||||
|
||||
void write_ppm(pixmap_rgb const & p, std::ostream & os)
|
||||
{
|
||||
os << "P6\n" << p.width() << " " << p.height() << "\n255\n";
|
||||
os.write(reinterpret_cast<char const *>(p.data()), p.width() * p.height() * sizeof(p.data()[0]));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -160,7 +160,7 @@ namespace psemek::gfx
|
|||
text_mesh.setup<geom::point<float, 3>, gfx::normalized<color_rgba>, geom::point<std::uint16_t, 2>>();
|
||||
texture_mesh.setup<geom::point<float, 3>, gfx::normalized<geom::point<std::uint16_t, 2>>>();
|
||||
|
||||
font_texture.load(gfx::read_png_monochrome(io::memory_istream{resource::font_9x12_png.data}));
|
||||
font_texture.load(gfx::read_image<std::uint8_t>(io::memory_istream{resource::font_9x12_png.data}));
|
||||
|
||||
font_texture.bind();
|
||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_SWIZZLE_G, gl::RED);
|
||||
|
|
|
|||
|
|
@ -116,4 +116,20 @@ namespace psemek::gfx
|
|||
throw util::exception("Failed to write rgb hdr");
|
||||
}
|
||||
|
||||
void write_image_pgm(pixmap_monochrome const & p, io::ostream && os)
|
||||
{
|
||||
char header_buffer[256];
|
||||
int header_size = std::snprintf(header_buffer, 256, "P5\n%lu %lu\n255\n", p.width(), p.height());
|
||||
os.write(header_buffer, header_size);
|
||||
os.write(reinterpret_cast<char const *>(p.data()), p.width() * p.height());
|
||||
}
|
||||
|
||||
void write_image_ppm(pixmap_rgb const & p, io::ostream && os)
|
||||
{
|
||||
char header_buffer[256];
|
||||
int header_size = std::snprintf(header_buffer, 256, "P6\n%lu %lu\n255\n", p.width(), p.height());
|
||||
os.write(header_buffer, header_size);
|
||||
os.write(reinterpret_cast<char const *>(p.data()), p.width() * p.height() * 3);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,146 +0,0 @@
|
|||
#include <psemek/gfx/pixmap.hpp>
|
||||
|
||||
#include <psemek/log/log.hpp>
|
||||
#include <psemek/util/at_scope_exit.hpp>
|
||||
#include <psemek/util/exception.hpp>
|
||||
|
||||
#include <png.h>
|
||||
|
||||
namespace psemek::gfx
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template <typename Pixel>
|
||||
basic_pixmap<Pixel> read_png_impl(io::istream & is, bool monochrome)
|
||||
{
|
||||
png_error_ptr error = [](png_structp, png_const_charp str)
|
||||
{
|
||||
throw util::exception(str);
|
||||
};
|
||||
|
||||
png_error_ptr warn = [](png_structp, png_const_charp str)
|
||||
{
|
||||
log::warning() << str;
|
||||
};
|
||||
|
||||
auto png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, error, warn);
|
||||
if (!png) throw util::exception("png_create_read_struct returned null");
|
||||
|
||||
png_set_error_fn(png, nullptr, error, warn);
|
||||
|
||||
png_infop info = nullptr;
|
||||
png_infop end_info = nullptr;
|
||||
|
||||
[[maybe_unused]] auto png_dtor = util::at_scope_exit([&]{
|
||||
png_destroy_read_struct(&png, &info, &end_info);
|
||||
});
|
||||
|
||||
info = png_create_info_struct(png);
|
||||
if (!info) throw util::exception("png_create_info_struct returned null");
|
||||
|
||||
end_info = png_create_info_struct(png);
|
||||
if (!end_info) throw util::exception("png_create_info_struct returned null");
|
||||
|
||||
png_rw_ptr read = [](png_structp png, png_bytep ptr, size_t count){
|
||||
reinterpret_cast<io::istream *>(png_get_io_ptr(png))->read(reinterpret_cast<char *>(ptr), count);
|
||||
};
|
||||
png_set_read_fn(png, &is, read);
|
||||
|
||||
png_read_info(png, info);
|
||||
|
||||
auto const width = png_get_image_width(png, info);
|
||||
auto const height = png_get_image_height(png, info);
|
||||
auto const color_type = png_get_color_type(png, info);
|
||||
auto const bit_depth = png_get_bit_depth(png, info);
|
||||
|
||||
if (bit_depth == 16)
|
||||
png_set_strip_16(png);
|
||||
|
||||
if (monochrome && color_type != PNG_COLOR_TYPE_GRAY)
|
||||
throw util::exception("Invalid color type for monochrome PNG");
|
||||
|
||||
if (color_type & PNG_COLOR_MASK_PALETTE)
|
||||
png_set_palette_to_rgb(png);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
|
||||
png_set_expand_gray_1_2_4_to_8(png);
|
||||
|
||||
if (!(color_type & PNG_COLOR_MASK_ALPHA) && !monochrome)
|
||||
png_set_add_alpha(png, 0xff, PNG_FILLER_AFTER);
|
||||
|
||||
png_read_update_info(png, info);
|
||||
|
||||
basic_pixmap<Pixel> result({width, height});
|
||||
|
||||
auto const row_bytes = png_get_rowbytes(png, info);
|
||||
if (row_bytes != width * sizeof(Pixel))
|
||||
throw util::exception("PNG row bytes mismatch");
|
||||
|
||||
for (std::uint32_t i = 0; i < height; ++i)
|
||||
png_read_row(png, reinterpret_cast<png_bytep>(result.data() + i * width), nullptr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void write_png_impl(pixmap_rgba const & p, io::ostream & os)
|
||||
{
|
||||
png_error_ptr error = [](png_structp, png_const_charp str)
|
||||
{
|
||||
throw util::exception(str);
|
||||
};
|
||||
|
||||
png_error_ptr warn = [](png_structp, png_const_charp str)
|
||||
{
|
||||
log::warning() << str;
|
||||
};
|
||||
|
||||
auto png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, error, warn);
|
||||
if (!png) throw util::exception("png_create_write_struct returned null");
|
||||
|
||||
png_set_error_fn(png, nullptr, error, warn);
|
||||
|
||||
png_infop info = nullptr;
|
||||
|
||||
[[maybe_unused]] auto png_dtor = util::at_scope_exit([&]{
|
||||
png_destroy_write_struct(&png, &info);
|
||||
});
|
||||
|
||||
info = png_create_info_struct(png);
|
||||
if (!info) throw util::exception("png_create_info_struct returned null");
|
||||
|
||||
png_rw_ptr write = [](png_structp png, png_bytep ptr, size_t count){
|
||||
reinterpret_cast<io::ostream *>(png_get_io_ptr(png))->write(reinterpret_cast<char const *>(ptr), count);
|
||||
};
|
||||
png_flush_ptr flush = [](png_structp png){
|
||||
reinterpret_cast<io::ostream *>(png_get_io_ptr(png))->flush();
|
||||
};
|
||||
png_set_write_fn(png, &os, write, flush);
|
||||
|
||||
png_set_IHDR(png, info, p.width(), p.height(), 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
png_write_info(png, info);
|
||||
|
||||
for (std::uint32_t i = 0; i < p.height(); ++i)
|
||||
png_write_row(png, reinterpret_cast<png_byte const *>(p.data() + p.width() * i));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pixmap_rgba read_png(io::istream && is)
|
||||
{
|
||||
return read_png_impl<color_rgba>(is, false);
|
||||
}
|
||||
|
||||
pixmap_monochrome read_png_monochrome(io::istream && is)
|
||||
{
|
||||
return read_png_impl<std::uint8_t>(is, true);
|
||||
}
|
||||
|
||||
void write_png(pixmap_rgba const & p, io::ostream && os)
|
||||
{
|
||||
write_png_impl(p, os);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue