Make scale_for_display less likely to leave confusing gaps (#2589). 2589-lines
authorCarl Hetherington <cth@carlh.net>
Sun, 3 Sep 2023 16:33:19 +0000 (18:33 +0200)
committerCarl Hetherington <cth@carlh.net>
Sun, 3 Sep 2023 22:23:17 +0000 (00:23 +0200)
src/lib/util.cc
test/util_test.cc

index 4ec425d40920b7d60b5bb555b4730c24bb28ed48..a80f86c3ec7fb6e9333511d002a4fe55d3dd2ad7 100644 (file)
@@ -982,19 +982,25 @@ copy_in_bits (boost::filesystem::path from, boost::filesystem::path to, std::fun
 dcp::Size
 scale_for_display (dcp::Size s, dcp::Size display_container, dcp::Size film_container, PixelQuanta quanta)
 {
-       /* Now scale it down if the display container is smaller than the film container */
-       if (display_container != film_container) {
-               float const scale = min (
-                       float (display_container.width) / film_container.width,
-                       float (display_container.height) / film_container.height
+       if (std::abs(display_container.ratio() - film_container.ratio()) < 0.01) {
+               /* The display ratio is very close to what it should be, but it might not be exactly the same.
+                * Allow the image to stretch slightly (differently in x and y) so that we are less likely
+                * to get single pixel gaps in the preview.
+                */
+               return quanta.round(
+                       static_cast<float>(s.width) * display_container.width / film_container.width,
+                       static_cast<float>(s.height) * display_container.height / film_container.height
                        );
-
-               s.width = lrintf (s.width * scale);
-               s.height = lrintf (s.height * scale);
-               s = quanta.round (s);
+       } else {
+               /* The display ratio is quite different to the film, so scale it so that the dimension
+                * that needs to fit does fit.
+                */
+               auto const scale = min(
+                       static_cast<float>(display_container.width) / film_container.width,
+                       static_cast<float>(display_container.height) / film_container.height
+                       );
+               return quanta.round(s.width * scale, s.height * scale);
        }
-
-       return s;
 }
 
 
index 49d0b3bc297ab3458ddae7ab6691234a1508b636..59dfb5c90561c6f297d8713b272fb67ac5817334 100644 (file)
@@ -155,3 +155,23 @@ BOOST_AUTO_TEST_CASE(word_wrap_test)
        BOOST_CHECK(word_wrap("hello this is a longer bit of text and it should be word-wrapped", 31) == string{"hello this is a longer bit of \ntext and it should be word-\nwrapped\n"});
        BOOST_CHECK_EQUAL(word_wrap("hellocan'twrapthissadly", 5), "hello\ncan't\nwrapt\nhissa\ndly\n");
 }
+
+
+BOOST_AUTO_TEST_CASE(scale_for_display_test)
+{
+       /* 1998x1076 image in a flat frame, displayed in 1104x596.
+        * In the DCP there will be 2px black top and bottom.
+        * So the display width should definitely be 1104, and it then follows that
+        * the display height should be scaled by the same factor as the width has been.
+        */
+       BOOST_CHECK(scale_for_display(dcp::Size(1998, 1076), dcp::Size(1104, 596), dcp::Size(1998, 1080), PixelQuanta(2, 2)) == dcp::Size(1104, 594));
+
+       /* 1800x1080 image in a flat frame, displayed in 1104x596.
+        * In the DCP there should be 99px black left and right.
+        * So the display height should definitely be 596.
+        */
+       BOOST_CHECK(scale_for_display(dcp::Size(1800, 1080), dcp::Size(1104, 596), dcp::Size(1998, 1080), PixelQuanta(2, 2)) == dcp::Size(994, 596));
+
+       /* This happens sometimes as windows are getting resized */
+       BOOST_CHECK(scale_for_display(dcp::Size(1998, 1076), dcp::Size(64, 64), dcp::Size(1998, 1080), PixelQuanta(2, 2)) == dcp::Size(64, 34));
+}