X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fimage.cc;h=3b8c1a28ef48aa1d9b96638b708fb8a19a8f944b;hb=0b6c6de07f9a3aa28c2e8ca8ef30340e3fa1bfc6;hp=4722563c45d532f397bb5231adf3ffdc548c4835;hpb=e4b65ba64c319281d6bff15e950ebce697c9621a;p=dcpomatic.git diff --git a/src/lib/image.cc b/src/lib/image.cc index 4722563c4..3b8c1a28e 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -26,15 +26,18 @@ extern "C" { #include #include #include -#include } #include "image.h" #include "exceptions.h" #include "scaler.h" +#include "md5_digester.h" + +#include "i18n.h" using std::string; using std::min; using std::cout; +using std::cerr; using boost::shared_ptr; using libdcp::Size; @@ -88,26 +91,38 @@ Image::crop_scale_window (Crop crop, libdcp::Size inter_size, libdcp::Size out_s */ assert (aligned ()); + assert (out_size.width >= inter_size.width); + assert (out_size.height >= inter_size.height); + + /* Here's an image of out_size */ shared_ptr out (new Image (out_format, out_size, out_aligned)); out->make_black (); - - libdcp::Size cropped_size = crop.apply (size ()); + /* Size of the image after any crop */ + libdcp::Size const cropped_size = crop.apply (size ()); + + /* Scale context for a scale from cropped_size to inter_size */ struct SwsContext* scale_context = sws_getContext ( cropped_size.width, cropped_size.height, pixel_format(), inter_size.width, inter_size.height, out_format, scaler->ffmpeg_id (), 0, 0, 0 ); + if (!scale_context) { + throw StringError (N_("Could not allocate SwsContext")); + } + + /* Prepare input data pointers with crop */ uint8_t* scale_in_data[components()]; for (int c = 0; c < components(); ++c) { scale_in_data[c] = data()[c] + int (rint (bytes_per_pixel(c) * crop.left)) + stride()[c] * (crop.top / line_factor(c)); } + /* Corner of the image within out_size */ Position const corner ((out_size.width - inter_size.width) / 2, (out_size.height - inter_size.height) / 2); - uint8_t* scale_out_data[components()]; - for (int c = 0; c < components(); ++c) { + uint8_t* scale_out_data[out->components()]; + for (int c = 0; c < out->components(); ++c) { scale_out_data[c] = out->data()[c] + int (rint (out->bytes_per_pixel(c) * corner.x)) + out->stride()[c] * corner.y; } @@ -152,51 +167,6 @@ Image::scale (libdcp::Size out_size, Scaler const * scaler, AVPixelFormat out_fo return scaled; } -/** Run a FFmpeg post-process on this image and return the processed version. - * @param pp Flags for the required set of post processes. - * @return Post-processed image. - */ -shared_ptr -Image::post_process (string pp, bool aligned) const -{ - shared_ptr out (new Image (pixel_format(), size (), aligned)); - - int pp_format = 0; - switch (pixel_format()) { - case PIX_FMT_YUV420P: - pp_format = PP_FORMAT_420; - break; - case PIX_FMT_YUV422P10LE: - case PIX_FMT_YUV422P: - case PIX_FMT_UYVY422: - pp_format = PP_FORMAT_422; - break; - case PIX_FMT_YUV444P: - case PIX_FMT_YUV444P9BE: - case PIX_FMT_YUV444P9LE: - case PIX_FMT_YUV444P10BE: - case PIX_FMT_YUV444P10LE: - pp_format = PP_FORMAT_444; - default: - throw PixelFormatError ("post_process", pixel_format()); - } - - pp_mode* mode = pp_get_mode_by_name_and_quality (pp.c_str (), PP_QUALITY_MAX); - pp_context* context = pp_get_context (size().width, size().height, pp_format | PP_CPU_CAPS_MMX2); - - pp_postprocess ( - (const uint8_t **) data(), stride(), - out->data(), out->stride(), - size().width, size().height, - 0, 0, mode, context, 0 - ); - - pp_free_mode (mode); - pp_free_context (context); - - return out; -} - shared_ptr Image::crop (Crop crop, bool aligned) const { @@ -348,6 +318,9 @@ Image::make_black () case PIX_FMT_RGBA: case PIX_FMT_ABGR: case PIX_FMT_BGRA: + case PIX_FMT_RGB555LE: + case PIX_FMT_RGB48LE: + case PIX_FMT_RGB48BE: memset (data()[0], 0, lines(0) * stride()[0]); break; @@ -519,8 +492,13 @@ Image::allocate () OS X crashes on this illegal read, though other operating systems don't seem to mind. The nasty + 1 in this malloc makes sure there is always a byte for that instruction to read safely. + + Further to the above, valgrind is now telling me that ff_rgb24ToY_ssse3 + over-reads by more then _avx. I can't follow the code to work out how much, + so I'll just over-allocate by 32 bytes and have done with it. Empirical + testing suggests that it works. */ - _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * lines (i) + 1); + _data[i] = (uint8_t *) wrapped_av_malloc (_stride[i] * lines (i) + 32); } } @@ -650,3 +628,15 @@ Image::aligned () const return _aligned; } +string +Image::digest () const +{ + MD5Digester digester; + + for (int i = 0; i < components(); ++i) { + digester.add (data()[i], line_size()[i]); + } + + return digester.get (); +} +