Clamp results correctly when shifting video levels, and account for that in tests.
authorCarl Hetherington <cth@carlh.net>
Mon, 24 May 2021 22:32:39 +0000 (00:32 +0200)
committerCarl Hetherington <cth@carlh.net>
Tue, 25 May 2021 19:35:12 +0000 (21:35 +0200)
src/lib/image.cc
src/lib/util.h
test/video_level_test.cc

index 4859ebe14876320718ae162f65c2361c5817b8ad..eff53a2aae15635811795408b608cf07a9e6e73d 100644 (file)
@@ -1433,7 +1433,7 @@ Image::video_range_to_full_range ()
                for (int y = 0; y < lines; ++y) {
                        uint8_t* q = p;
                        for (int x = 0; x < line_size()[0]; ++x) {
-                               *q = int((*q - 16) * factor);
+                               *q = clamp(lrintf((*q - 16) * factor), 0L, 255L);
                                ++q;
                        }
                        p += stride()[0];
@@ -1450,7 +1450,7 @@ Image::video_range_to_full_range ()
                                uint16_t* q = p;
                                int const line_size_pixels = line_size()[c] / 2;
                                for (int x = 0; x < line_size_pixels; ++x) {
-                                       *q = int((*q - 256) * factor);
+                                       *q = clamp(lrintf((*q - 256) * factor), 0L, 4095L);
                                        ++q;
                                }
                        }
index fa0d9fdf2383d778d8ffe18e0961f6788609e209..013eabe120678c415f28e176a115ed729a12eae3 100644 (file)
@@ -150,4 +150,12 @@ list_to_vector (std::list<T> v)
 extern double db_to_linear (double db);
 extern double linear_to_db (double linear);
 
+
+template <class T>
+T clamp (T val, T minimum, T maximum)
+{
+       return std::max(std::min(val, maximum), minimum);
+}
+
+
 #endif
index c7e255394ac90d5855e739e2e83c1a7e32c25da0..c974c938d3002f71a4fc86b9f1518ab8597bbd9b 100644 (file)
@@ -344,8 +344,11 @@ image_FoV (string name)
        content->video->set_range (VideoRange::VIDEO);
 
        auto range = pixel_range (film, content);
-       BOOST_CHECK_EQUAL (range.first, 11);
-       BOOST_CHECK_EQUAL (range.second, 250);
+       /* We are taking some full-range content and saying it should be read as video range, after which its
+        * pixels will still be full range.
+        */
+       BOOST_CHECK_EQUAL (range.first, 0);
+       BOOST_CHECK_EQUAL (range.second, 255);
 
        return film;
 }
@@ -451,7 +454,10 @@ BOOST_AUTO_TEST_CASE (image_F_to_dcp)
 BOOST_AUTO_TEST_CASE (image_FoV_to_dcp)
 {
        auto range = dcp_range (image_FoV("image_FoV_to_dcp"));
-       check_int_close (range, {430, 4012}, 2);
+       /* The nearly-full-range of the input has become even more full, and clipped.
+        * XXX: I'm not sure why this doesn't quite hit 4095.
+        */
+       check_int_close (range, {0, 4095}, 16);
 }