Fix video range in preview and DCP when source is VIDEO rather than FULL.
[dcpomatic.git] / src / lib / image.cc
index f86c105d4f8aa2d2ab76ce465fd8820d44bfa9bd..dfa093fbe3c38c61d8fa325078f0f073b78c2a6e 100644 (file)
@@ -249,7 +249,7 @@ Image::crop_scale_window (
           1 -> destination range JPEG (i.e. "full", 0-255)
 
           But remember: sws_setColorspaceDetails ignores these
-          parameters unless the both source and destination images
+          parameters unless both source and destination images
           are isYUV or isGray.  (If either is not, it uses video range).
        */
        sws_setColorspaceDetails (
@@ -292,20 +292,27 @@ 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 &&
                out_video_range == VideoRange::FULL &&
-               av_pix_fmt_desc_get(_pixel_format)->flags & AV_PIX_FMT_FLAG_RGB
+               ((av_pix_fmt_desc_get(_pixel_format)->flags & AV_PIX_FMT_FLAG_RGB) ||
+                (av_pix_fmt_desc_get(out_format)->flags & AV_PIX_FMT_FLAG_RGB))
           ) {
-               /* libswscale will not convert video range for RGB sources, so we have to do it ourselves */
+               /* libswscale will not convert video range if input or output is RGB, as far as I can see,
+                * so we have to do it ourselves.
+                */
                out->video_range_to_full_range ();
        }