Move Image::as_png() out to image_as_png().
authorCarl Hetherington <cth@carlh.net>
Sat, 18 Dec 2021 20:26:05 +0000 (21:26 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 23 Dec 2021 11:59:56 +0000 (12:59 +0100)
src/lib/image.cc
src/lib/image.h
src/lib/image_png.cc [new file with mode: 0644]
src/lib/image_png.h [new file with mode: 0644]
src/lib/reel_writer.cc
src/lib/wscript
src/tools/dcpomatic_player.cc
test/image_test.cc
test/test.cc

index 9bb503acbe96507cf9629b3ecdd8c1592e2a57f1..ad88568cddf5d489a097d070dd71fc8b4b59b6b7 100644 (file)
@@ -42,7 +42,6 @@ extern "C" {
 #include <libswscale/swscale.h>
 }
 DCPOMATIC_ENABLE_WARNINGS
-#include <png.h>
 #if HAVE_VALGRIND_MEMCHECK_H
 #include <valgrind/memcheck.h>
 #endif
@@ -1336,98 +1335,6 @@ Image::memory_used () const
        return m;
 }
 
-class Memory
-{
-public:
-       Memory ()
-               : data(0)
-               , size(0)
-       {}
-
-       ~Memory ()
-       {
-               free (data);
-       }
-
-       uint8_t* data;
-       size_t size;
-};
-
-static void
-png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
-{
-       auto mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
-       size_t size = mem->size + length;
-
-       if (mem->data) {
-               mem->data = reinterpret_cast<uint8_t*>(realloc(mem->data, size));
-       } else {
-               mem->data = reinterpret_cast<uint8_t*>(malloc(size));
-       }
-
-       if (!mem->data) {
-               throw EncodeError (N_("could not allocate memory for PNG"));
-       }
-
-       memcpy (mem->data + mem->size, data, length);
-       mem->size += length;
-}
-
-static void
-png_flush (png_structp)
-{
-
-}
-
-static void
-png_error_fn (png_structp, char const * message)
-{
-       throw EncodeError (String::compose("Error during PNG write: %1", message));
-}
-
-
-dcp::ArrayData
-Image::as_png () const
-{
-       DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
-       DCPOMATIC_ASSERT (planes() == 1);
-       if (pixel_format() != AV_PIX_FMT_RGBA) {
-               return convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, Image::Alignment::PADDED, false)->as_png();
-       }
-
-       /* error handling? */
-       png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, reinterpret_cast<void*>(const_cast<Image*>(this)), png_error_fn, 0);
-       if (!png_ptr) {
-               throw EncodeError (N_("could not create PNG write struct"));
-       }
-
-       Memory state;
-
-       png_set_write_fn (png_ptr, &state, png_write_data, png_flush);
-
-       png_infop info_ptr = png_create_info_struct(png_ptr);
-       if (!info_ptr) {
-               png_destroy_write_struct (&png_ptr, &info_ptr);
-               throw EncodeError (N_("could not create PNG info struct"));
-       }
-
-       png_set_IHDR (png_ptr, info_ptr, size().width, size().height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
-
-       png_byte ** row_pointers = reinterpret_cast<png_byte **>(png_malloc(png_ptr, size().height * sizeof(png_byte *)));
-       for (int i = 0; i < size().height; ++i) {
-               row_pointers[i] = (png_byte *) (data()[0] + i * stride()[0]);
-       }
-
-       png_write_info (png_ptr, info_ptr);
-       png_write_image (png_ptr, row_pointers);
-       png_write_end (png_ptr, info_ptr);
-
-       png_destroy_write_struct (&png_ptr, &info_ptr);
-       png_free (png_ptr, row_pointers);
-
-       return dcp::ArrayData (state.data, state.size);
-}
-
 
 void
 Image::video_range_to_full_range ()
index 328252e684c79ba609741ad0bb8d13691203b775..73d08b90244eeb5c88d280b1538d5771bbd49113 100644 (file)
@@ -95,8 +95,6 @@ public:
 
        size_t memory_used () const;
 
-       dcp::ArrayData as_png () const;
-
        static std::shared_ptr<const Image> ensure_alignment (std::shared_ptr<const Image> image, Alignment alignment);
 
 private:
diff --git a/src/lib/image_png.cc b/src/lib/image_png.cc
new file mode 100644 (file)
index 0000000..b97ef5a
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+    Copyright (C) 2021 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    DCP-o-matic is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "dcpomatic_assert.h"
+#include "exceptions.h"
+#include "image.h"
+#include <png.h>
+
+#include "i18n.h"
+
+
+using std::shared_ptr;
+
+
+class Memory
+{
+public:
+       Memory () {}
+       Memory (Memory const&) = delete;
+       Memory& operator= (Memory const&) = delete;
+
+       ~Memory ()
+       {
+               free (data);
+       }
+
+       uint8_t* data = nullptr;
+       size_t size = 0;
+};
+
+
+static void
+png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
+{
+       auto mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
+       size_t size = mem->size + length;
+
+       if (mem->data) {
+               mem->data = reinterpret_cast<uint8_t*>(realloc(mem->data, size));
+       } else {
+               mem->data = reinterpret_cast<uint8_t*>(malloc(size));
+       }
+
+       if (!mem->data) {
+               throw EncodeError (N_("could not allocate memory for PNG"));
+       }
+
+       memcpy (mem->data + mem->size, data, length);
+       mem->size += length;
+}
+
+
+static void
+png_flush (png_structp)
+{
+
+}
+
+
+static void
+png_error_fn (png_structp, char const * message)
+{
+       throw EncodeError (String::compose("Error during PNG write: %1", message));
+}
+
+
+dcp::ArrayData
+image_as_png (shared_ptr<const Image> image)
+{
+       DCPOMATIC_ASSERT (image->bytes_per_pixel(0) == 4);
+       DCPOMATIC_ASSERT (image->planes() == 1);
+       if (image->pixel_format() != AV_PIX_FMT_RGBA) {
+               return image_as_png(image->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, Image::Alignment::PADDED, false));
+       }
+
+       /* error handling? */
+       auto png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, reinterpret_cast<void*>(const_cast<Image*>(image.get())), png_error_fn, 0);
+       if (!png_ptr) {
+               throw EncodeError (N_("could not create PNG write struct"));
+       }
+
+       Memory state;
+
+       png_set_write_fn (png_ptr, &state, png_write_data, png_flush);
+
+       auto info_ptr = png_create_info_struct(png_ptr);
+       if (!info_ptr) {
+               png_destroy_write_struct (&png_ptr, &info_ptr);
+               throw EncodeError (N_("could not create PNG info struct"));
+       }
+
+       int const width = image->size().width;
+       int const height = image->size().height;
+
+       png_set_IHDR (png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+
+       auto row_pointers = reinterpret_cast<png_byte **>(png_malloc(png_ptr, image->size().height * sizeof(png_byte *)));
+       auto const data = image->data()[0];
+       auto const stride = image->stride()[0];
+       for (int i = 0; i < height; ++i) {
+               row_pointers[i] = reinterpret_cast<png_byte *>(data + i * stride);
+       }
+
+       png_write_info (png_ptr, info_ptr);
+       png_write_image (png_ptr, row_pointers);
+       png_write_end (png_ptr, info_ptr);
+
+       png_destroy_write_struct (&png_ptr, &info_ptr);
+       png_free (png_ptr, row_pointers);
+
+       return dcp::ArrayData (state.data, state.size);
+}
+
+
diff --git a/src/lib/image_png.h b/src/lib/image_png.h
new file mode 100644 (file)
index 0000000..b3c0774
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+    Copyright (C) 2021 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    DCP-o-matic is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+dcp::ArrayData image_as_png (std::shared_ptr<const Image> image);
index 78148d18f1fb4b6c301b59269f177124d1da253e..2830ca3f0f8abcc0ff3f76b8f764f7ed54684675 100644 (file)
 
 */
 
-#include "reel_writer.h"
-#include "film.h"
+
+#include "audio_buffers.h"
+#include "compose.hpp"
+#include "config.h"
 #include "cross.h"
-#include "job.h"
-#include "log.h"
 #include "dcpomatic_log.h"
 #include "digester.h"
+#include "film.h"
 #include "font_data.h"
-#include "compose.hpp"
-#include "config.h"
-#include "audio_buffers.h"
 #include "image.h"
+#include "image_png.h"
+#include "job.h"
+#include "log.h"
+#include "reel_writer.h"
 #include <dcp/atmos_asset.h>
 #include <dcp/atmos_asset_writer.h>
 #include <dcp/certificate_chain.h>
 
 #include "i18n.h"
 
-using std::list;
-using std::string;
+
 using std::cout;
+using std::dynamic_pointer_cast;
 using std::exception;
+using std::list;
+using std::make_shared;
 using std::map;
 using std::set;
-using std::vector;
 using std::shared_ptr;
-using std::make_shared;
+using std::string;
+using std::vector;
+using std::weak_ptr;
 using boost::optional;
-using std::dynamic_pointer_cast;
 #if BOOST_VERSION >= 106100
 using namespace boost::placeholders;
 #endif
-using std::weak_ptr;
 using dcp::ArrayData;
 using dcp::Data;
 using dcp::raw_convert;
 using namespace dcpomatic;
 
+
 int const ReelWriter::_info_size = 48;
 
+
 static dcp::MXFMetadata
 mxf_metadata ()
 {
@@ -896,7 +901,7 @@ ReelWriter::write (PlayerText subs, TextType type, optional<DCPTextTrack> track,
        for (auto i: subs.bitmap) {
                asset->add (
                        make_shared<dcp::SubtitleImage>(
-                               i.image->as_png(),
+                               image_as_png(i.image),
                                dcp::Time(period.from.seconds() - _period.from.seconds(), tcr),
                                dcp::Time(period.to.seconds() - _period.from.seconds(), tcr),
                                i.rectangle.x, dcp::HAlign::LEFT, i.rectangle.y, dcp::VAlign::TOP,
index 7bc30e865d506736010e369102369e9a8014e68c..ee7f796127382cfb948f0b1d9fcd4578c60e8aab 100644 (file)
@@ -121,6 +121,7 @@ sources = """
           image_decoder.cc
           image_examiner.cc
           image_filename_sorter.cc
+          image_png.cc
           image_proxy.cc
           j2k_image_proxy.cc
           job.cc
index d6b4e5d8330c6e2daa6d52fc32a5b3c37e2a1953..d52ffd1ec4260473f1599a4303e87d1d235a3733 100644 (file)
 #include "wx/system_information_dialog.h"
 #include "wx/player_stress_tester.h"
 #include "wx/verify_dcp_progress_dialog.h"
-#include "wx/nag_dialog.h"
-#include "lib/cross.h"
-#include "lib/config.h"
-#include "lib/util.h"
-#include "lib/internet.h"
-#include "lib/update_checker.h"
+#include "wx/wx_signal_manager.h"
+#include "wx/wx_util.h"
 #include "lib/compose.hpp"
+#include "lib/config.h"
+#include "lib/cross.h"
 #include "lib/dcp_content.h"
-#include "lib/job_manager.h"
-#include "lib/job.h"
-#include "lib/film.h"
-#include "lib/null_log.h"
-#include "lib/video_content.h"
-#include "lib/text_content.h"
-#include "lib/ratio.h"
-#include "lib/verify_dcp_job.h"
 #include "lib/dcp_examiner.h"
-#include "lib/examine_content_job.h"
-#include "lib/server.h"
+#include "lib/dcpomatic_log.h"
 #include "lib/dcpomatic_socket.h"
-#include "lib/scoped_temporary.h"
+#include "lib/examine_content_job.h"
 #include "lib/ffmpeg_content.h"
-#include "lib/dcpomatic_log.h"
 #include "lib/file_log.h"
+#include "lib/film.h"
+#include "lib/image.h"
+#include "lib/image_png.h"
+#include "lib/internet.h"
+#include "lib/job.h"
+#include "lib/job_manager.h"
+#include "lib/null_log.h"
+#include "lib/ratio.h"
+#include "lib/scoped_temporary.h"
+#include "lib/server.h"
+#include "lib/text_content.h"
+#include "lib/update_checker.h"
+#include "lib/util.h"
+#include "lib/verify_dcp_job.h"
+#include "lib/video_content.h"
 #include <dcp/cpl.h>
 #include <dcp/dcp.h>
 #include <dcp/raw_convert.h>
index 7369bd24feac9ec03e4a21d2fb86aaa8bef7389d..18d96d4fc4a4f388f158ce6e1cc3119fd950bc88 100644 (file)
@@ -30,6 +30,7 @@
 #include "lib/image.h"
 #include "lib/image_content.h"
 #include "lib/image_decoder.h"
+#include "lib/image_png.h"
 #include "lib/ffmpeg_image_proxy.h"
 #include "test.h"
 #include <boost/test/unit_test.hpp>
@@ -375,8 +376,8 @@ BOOST_AUTO_TEST_CASE (as_png_test)
        auto proxy = make_shared<FFmpegImageProxy>("test/data/3d_test/000001.png");
        auto image_rgb = proxy->image(Image::Alignment::PADDED).image;
        auto image_bgr = image_rgb->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_BGRA, Image::Alignment::PADDED, false);
-       image_rgb->as_png().write ("build/test/as_png_rgb.png");
-       image_bgr->as_png().write ("build/test/as_png_bgr.png");
+       image_as_png(image_rgb).write ("build/test/as_png_rgb.png");
+       image_as_png(image_bgr).write ("build/test/as_png_bgr.png");
 
        check_image ("test/data/3d_test/000001.png", "build/test/as_png_rgb.png");
        check_image ("test/data/3d_test/000001.png", "build/test/as_png_bgr.png");
@@ -391,7 +392,7 @@ fade_test_format_black (AVPixelFormat f, string name)
        yuv.make_black ();
        yuv.fade (0);
        string const filename = "fade_test_black_" + name + ".png";
-       yuv.convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, Image::Alignment::PADDED, false)->as_png().write("build/test/" + filename);
+       image_as_png(yuv.convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, Image::Alignment::PADDED, false)).write("build/test/" + filename);
        check_image ("test/data/" + filename, "build/test/" + filename);
 }
 
@@ -404,7 +405,7 @@ fade_test_format_red (AVPixelFormat f, float amount, string name)
        auto red = proxy->image(Image::Alignment::PADDED).image->convert_pixel_format(dcp::YUVToRGB::REC709, f, Image::Alignment::PADDED, false);
        red->fade (amount);
        string const filename = "fade_test_red_" + name + ".png";
-       red->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, Image::Alignment::PADDED, false)->as_png().write("build/test/" + filename);
+       image_as_png(red->convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, Image::Alignment::PADDED, false)).write("build/test/" + filename);
        check_image ("test/data/" + filename, "build/test/" + filename);
 }
 
index fba59ffeb7a676749a0d2153a4e45c1a5c4aae2b..08b37bcb181e6db50430ffe09529318ca068e41e 100644 (file)
@@ -693,7 +693,7 @@ png_flush (png_structp)
 
 
 static void
-png_error_fn (png_structp png_ptr, char const * message)
+png_error_fn (png_structp, char const * message)
 {
        throw EncodeError (String::compose("Error during PNG write: %1", message));
 }