Skip to content

Commit

Permalink
Core (LV::Video): Apply modern C++-isms to PNG writer.
Browse files Browse the repository at this point in the history
  • Loading branch information
kaixiong committed Jan 24, 2025
1 parent 337a0fe commit 6e5fe53
Showing 1 changed file with 47 additions and 46 deletions.
93 changes: 47 additions & 46 deletions libvisual/libvisual/private/lv_video_png.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "lv_video_png.hpp"
#include "lv_common.h"
#include <iostream>
#include <bit>
#include <vector>
#include <csetjmp>
#include <png.h>
Expand All @@ -34,8 +35,8 @@ namespace LV {

void handle_png_read (png_structp png_ptr, png_bytep data, png_size_t length)
{
auto io_ptr = png_get_io_ptr (png_ptr);
auto& input = *static_cast<std::istream*> (io_ptr);
auto io_ptr {png_get_io_ptr (png_ptr)};
auto& input {*static_cast<std::istream*> (io_ptr)};

if (!input.read (reinterpret_cast<char*> (data), length)) {
std::longjmp (png_jmpbuf (png_ptr), -1);
Expand All @@ -44,8 +45,8 @@ namespace LV {

void handle_png_write (png_structp png_ptr, png_bytep data, png_size_t length)
{
auto io_ptr = png_get_io_ptr (png_ptr);
auto& output = *static_cast<std::ostream*> (io_ptr);
auto io_ptr {png_get_io_ptr (png_ptr)};
auto& output {*static_cast<std::ostream*> (io_ptr)};

if (!output.write(reinterpret_cast<char*>(data), length)) {
std::longjmp (png_jmpbuf (png_ptr), -1);
Expand All @@ -54,8 +55,8 @@ namespace LV {

void handle_png_flush (png_structp png_ptr)
{
auto io_ptr = png_get_io_ptr (png_ptr);
auto& output = *static_cast<std::ostream*> (io_ptr);
auto io_ptr {png_get_io_ptr (png_ptr)};
auto& output {*static_cast<std::ostream*> (io_ptr)};

output.flush ();
}
Expand Down Expand Up @@ -92,46 +93,46 @@ namespace LV {

VideoPtr bitmap_load_png (std::istream& input)
{
auto saved_stream_pos = input.tellg ();
auto saved_stream_pos {input.tellg ()};

png_byte signature[8];
input.read (reinterpret_cast<char*> (signature), sizeof (signature));

bool is_png = !png_sig_cmp (signature, 0, sizeof (signature));
auto is_png {!png_sig_cmp (signature, 0, sizeof (signature))};

if (!is_png) {
return nullptr;
}

auto png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
nullptr,
handle_png_load_error,
handle_png_load_warning);
auto png_ptr {png_create_read_struct (PNG_LIBPNG_VER_STRING,
nullptr,
handle_png_load_error,
handle_png_load_warning)};
if (!png_ptr) {
return nullptr;
}

auto info_ptr = png_create_info_struct (png_ptr);
auto info_ptr {png_create_info_struct (png_ptr)};
if (!info_ptr) {
png_destroy_read_struct (&png_ptr, nullptr, nullptr);
return nullptr;
}

auto end_info = png_create_info_struct (png_ptr);
auto end_info {png_create_info_struct (png_ptr)};
if (!end_info) {
png_destroy_read_struct (&png_ptr, &info_ptr, nullptr);
return nullptr;
}

uint8_t* pixels = nullptr;
uint8_t** pixel_row_ptrs = nullptr;
uint8_t* pixels {nullptr};
uint8_t** pixel_row_ptrs {nullptr};

if (setjmp (png_jmpbuf (png_ptr))) {
input.seekg (saved_stream_pos);

png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);

delete []pixel_row_ptrs;
delete[] pixel_row_ptrs;
visual_mem_free (pixels);

return nullptr;
Expand All @@ -143,8 +144,8 @@ namespace LV {

png_read_info (png_ptr, info_ptr);

auto color_type = png_get_color_type (png_ptr, info_ptr);
auto bit_depth = png_get_bit_depth (png_ptr, info_ptr);
auto color_type {png_get_color_type (png_ptr, info_ptr)};
auto bit_depth {png_get_bit_depth (png_ptr, info_ptr)};

if (color_type == PNG_COLOR_TYPE_PALETTE) {
png_set_palette_to_rgb (png_ptr);
Expand All @@ -171,13 +172,13 @@ namespace LV {
png_set_gray_to_rgb (png_ptr);
}

#if VISUAL_LITTLE_ENDIAN
png_set_bgr (png_ptr);
#endif
if constexpr (std::endian::native == std::endian::little) {
png_set_bgr (png_ptr);
}

png_read_update_info (png_ptr, info_ptr);

VisVideoDepth depth = VISUAL_VIDEO_DEPTH_NONE;
auto depth {VISUAL_VIDEO_DEPTH_NONE};

switch (png_get_color_type (png_ptr, info_ptr)) {
case PNG_COLOR_TYPE_RGB:
Expand All @@ -190,57 +191,57 @@ namespace LV {
std::longjmp (png_jmpbuf (png_ptr), -1);
}

auto width = png_get_image_width (png_ptr, info_ptr);
auto height = png_get_image_height (png_ptr, info_ptr);
auto row_stride = png_get_rowbytes (png_ptr, info_ptr);
auto width {png_get_image_width (png_ptr, info_ptr)};
auto height {png_get_image_height (png_ptr, info_ptr)};
auto row_stride {png_get_rowbytes (png_ptr, info_ptr)};

// NOTE: We have to use visual_mem_malloc() here as LV::Video
// will free the buffer with visual_mem_free()
pixels = static_cast<uint8_t*> (visual_mem_malloc (row_stride * height));

pixel_row_ptrs = new uint8_t*[height];

for (unsigned int y = 0; y < height; y++) {
for (unsigned int y {0}; y < height; y++) {
pixel_row_ptrs[y] = pixels + y * row_stride;
}

png_read_image (png_ptr, pixel_row_ptrs);

png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);

delete []pixel_row_ptrs;
delete[] pixel_row_ptrs;

return Video::wrap (pixels, true, width, height, depth);
}

bool bitmap_save_png(Video const& bitmap, std::ostream &output)
bool bitmap_save_png(Video const& bitmap, std::ostream& output)
{
auto saved_stream_pos = output.tellp ();
auto saved_stream_pos {output.tellp ()};

auto png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING,
nullptr,
handle_png_save_error,
handle_png_save_warning);
auto png_ptr {png_create_write_struct (PNG_LIBPNG_VER_STRING,
nullptr,
handle_png_save_error,
handle_png_save_warning)};
if (!png_ptr) {
visual_log (VISUAL_LOG_ERROR, "Failed to create PNG write struct.");
return false;
}

auto info_ptr = png_create_info_struct (png_ptr);
auto info_ptr {png_create_info_struct (png_ptr)};
if (!info_ptr) {
visual_log (VISUAL_LOG_ERROR, "Failed to create PNG info struct.");
png_destroy_write_struct (&png_ptr, nullptr);
return false;
}

auto bitmap_width = bitmap.get_width ();
auto bitmap_height = bitmap.get_height ();
auto bitmap_width {bitmap.get_width ()};
auto bitmap_height {bitmap.get_height ()};

std::vector<png_byte*> pixel_row_ptrs;
pixel_row_ptrs.reserve (bitmap_height);

for (auto y = 0; y < bitmap_height; y++) {
pixel_row_ptrs.push_back (static_cast<png_byte *> (bitmap.get_pixel_ptr (0, y)));
for (auto y {0}; y < bitmap_height; y++) {
pixel_row_ptrs.push_back (static_cast<png_byte*> (bitmap.get_pixel_ptr (0, y)));
}

if (setjmp (png_jmpbuf (png_ptr))) {
Expand All @@ -249,8 +250,8 @@ namespace LV {
png_destroy_write_struct (&png_ptr, &info_ptr);
}

int bit_depth = 0;
int color_type = 0;
auto bit_depth {0};
auto color_type {0};

switch (bitmap.get_depth ()) {
case VISUAL_VIDEO_DEPTH_8BIT: {
Expand All @@ -274,9 +275,9 @@ namespace LV {
}
}

#if VISUAL_LITTLE_ENDIAN
png_set_bgr (png_ptr);
#endif
if constexpr (std::endian::native == std::endian::little) {
png_set_bgr (png_ptr);
}

png_set_filter (png_ptr, 0, PNG_FILTER_NONE);

Expand All @@ -287,13 +288,13 @@ namespace LV {
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);

if (color_type == PNG_COLOR_TYPE_PALETTE) {
auto const& colors = bitmap.get_palette ().colors;
auto const& colors {bitmap.get_palette ().colors};

std::vector<png_color> out_palette;
out_palette.reserve (colors.size ());

for (auto const& color : colors) {
out_palette.push_back ({color.r, color.g, color.b});
out_palette.emplace_back (color.r, color.g, color.b);
}

png_set_PLTE (png_ptr, info_ptr, out_palette.data (), out_palette.size ());
Expand Down

0 comments on commit 6e5fe53

Please sign in to comment.