#include <libswscale/swscale.h>
}
LIBDCP_ENABLE_WARNINGS
-#include <png.h>
#if HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#endif
}
-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 ()
{
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:
--- /dev/null
+/*
+ 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);
+}
+
+
--- /dev/null
+/*
+ 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);
#include "film.h"
#include "font_data.h"
#include "image.h"
+#include "image_png.h"
#include "job.h"
#include "log.h"
#include "reel_writer.h"
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,
image_decoder.cc
image_examiner.cc
image_filename_sorter.cc
+ image_png.cc
image_proxy.cc
j2k_image_proxy.cc
job.cc
#include "lib/ffmpeg_content.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/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>
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");
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);
}
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);
}
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));
}