X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fimage.cc;h=9aecac8347a40bbbd0e7e4ff5a7fd2f85e608908;hb=61fb89205e631cdb49161bbc4b321d5a93868120;hp=861367637f218295883c6a4552a242198ce54c5e;hpb=4673b12dcf6340862f9f4f72fc6dca8553130b55;p=dcpomatic.git diff --git a/src/lib/image.cc b/src/lib/image.cc index 861367637..9aecac834 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -44,7 +44,6 @@ extern "C" { #include } LIBDCP_ENABLE_WARNINGS -#include #if HAVE_VALGRIND_MEMCHECK_H #include #endif @@ -293,13 +292,17 @@ Image::crop_scale_window ( 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 && @@ -475,6 +478,21 @@ Image::make_part_black (int const start, int const width) } break; } + case AV_PIX_FMT_YUV444P10LE: + { + y_part(); + for (int i = 1; i < 3; ++i) { + auto p = reinterpret_cast(data()[i]); + int const h = sample_size(i).height; + for (int y = 0; y < h; ++y) { + for (int x = start; x < (start + width); ++x) { + p[x] = ten_bit_uv; + } + p += stride()[i] / 2; + } + } + break; + } default: throw PixelFormatError ("make_part_black()", _pixel_format); } @@ -716,8 +734,8 @@ Image::alpha_blend (shared_ptr other, Position position) 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 (data()[0] + ty * stride()[0] + start_tx * this_bpp); @@ -731,14 +749,14 @@ Image::alpha_blend (shared_ptr other, Position position) 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; @@ -1371,102 +1389,6 @@ Image::memory_used () const } -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(png_get_io_ptr(png_ptr)); - size_t size = mem->size + length; - - if (mem->data) { - mem->data = reinterpret_cast(realloc(mem->data, size)); - } else { - mem->data = reinterpret_cast(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(const_cast(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_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 () {