#include "memory_util.h"
#include "rect.h"
#include "timer.h"
-#include "warnings.h"
#include <dcp/rgb_xyz.h>
#include <dcp/transfer_function.h>
-DCPOMATIC_DISABLE_WARNINGS
+#include <dcp/warnings.h>
+LIBDCP_DISABLE_WARNINGS
extern "C" {
#include <libavutil/frame.h>
#include <libavutil/pixdesc.h>
#include <libavutil/pixfmt.h>
#include <libswscale/swscale.h>
}
-DCPOMATIC_ENABLE_WARNINGS
-#include <png.h>
+LIBDCP_ENABLE_WARNINGS
#if HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#endif
sws_freeContext (scale_context);
- if (corrected_crop != Crop() && cropped_size == inter_size) {
- /* We are cropping without any scaling or pixel format conversion, so FFmpeg may have left some
- data behind in our image. Clear it out. It may get to the point where we should just stop
- trying to be clever with cropping.
- */
- out->make_part_black (corner.x + cropped_size.width, out_size.width - cropped_size.width);
- }
+ /* There are some cases where there will be unwanted image data left in the image at this point:
+ *
+ * 1. When we are cropping without any scaling or pixel format conversion.
+ * 2. When we are scaling to certain sizes and placing the result into a larger
+ * black frame.
+ *
+ * Clear out the sides of the image to take care of those cases.
+ */
+ auto const pad = (out_size.width - inter_size.width) / 2;
+ out->make_part_black(0, pad);
+ out->make_part_black(corner.x + inter_size.width, pad);
if (
video_range == VideoRange::VIDEO &&
auto conv = dcp::ColourConversion::srgb_to_xyz();
double fast_matrix[9];
dcp::combined_rgb_to_xyz (conv, fast_matrix);
- double const * lut_in = conv.in()->lut (8, false);
- double const * lut_out = conv.out()->lut (16, true);
+ auto lut_in = conv.in()->lut(0, 1, 8, false);
+ auto lut_out = conv.out()->lut(0, 1, 16, true);
int const this_bpp = 6;
for (int ty = start_ty, oy = start_oy; ty < size().height && oy < other->size().height; ++ty, ++oy) {
uint16_t* tp = reinterpret_cast<uint16_t*> (data()[0] + ty * stride()[0] + start_tx * this_bpp);
double const b = lut_in[op[blue]];
/* RGB to XYZ, including Bradford transform and DCI companding */
- double const x = max (0.0, min (65535.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
- double const y = max (0.0, min (65535.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
- double const z = max (0.0, min (65535.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
+ double const x = max(0.0, min(1.0, r * fast_matrix[0] + g * fast_matrix[1] + b * fast_matrix[2]));
+ double const y = max(0.0, min(1.0, r * fast_matrix[3] + g * fast_matrix[4] + b * fast_matrix[5]));
+ double const z = max(0.0, min(1.0, r * fast_matrix[6] + g * fast_matrix[7] + b * fast_matrix[8]));
/* Out gamma LUT and blend */
- tp[0] = lrint(lut_out[lrint(x)] * 65535) * alpha + tp[0] * (1 - alpha);
- tp[1] = lrint(lut_out[lrint(y)] * 65535) * alpha + tp[1] * (1 - alpha);
- tp[2] = lrint(lut_out[lrint(z)] * 65535) * alpha + tp[2] * (1 - alpha);
+ tp[0] = lrint(lut_out[lrint(x * 65535)] * 65535) * alpha + tp[0] * (1 - alpha);
+ tp[1] = lrint(lut_out[lrint(y * 65535)] * 65535) * alpha + tp[1] * (1 - alpha);
+ tp[2] = lrint(lut_out[lrint(z * 65535)] * 65535) * alpha + tp[2] * (1 - alpha);
tp += this_bpp / 2;
op += other_bpp;
}
-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 png_ptr, char const * message)
-{
- reinterpret_cast<Image*>(png_get_error_ptr(png_ptr))->png_error (message);
-}
-
-
-void
-Image::png_error (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 ()
{