Harden alpha blend tests and fix alpha_blend again.
authorCarl Hetherington <cth@carlh.net>
Thu, 11 Jan 2018 00:45:23 +0000 (00:45 +0000)
committerCarl Hetherington <cth@carlh.net>
Thu, 11 Jan 2018 00:45:23 +0000 (00:45 +0000)
src/lib/image.cc
test/image_test.cc

index cb03e1a..c3795df 100644 (file)
@@ -607,18 +607,52 @@ Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
                break;
        }
        case AV_PIX_FMT_YUV420P10:
+       {
+               shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
+               dcp::Size const ts = size();
+               dcp::Size const os = yuv->size();
+               for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
+                       int const hty = ty / 2;
+                       int const hoy = oy / 2;
+                       uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
+                       uint16_t* tU = ((uint16_t *) (data()[1] + (hty * stride()[1]))) + start_tx / 2;
+                       uint16_t* tV = ((uint16_t *) (data()[2] + (hty * stride()[2]))) + start_tx / 2;
+                       uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
+                       uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (hoy * yuv->stride()[1]))) + start_ox / 2;
+                       uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (hoy * yuv->stride()[2]))) + start_ox / 2;
+                       uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
+                       for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
+                               float const a = float(alpha[3]) / 255;
+                               *tY = *oY * a + *tY * (1 - a);
+                               *tU = *oU * a + *tU * (1 - a);
+                               *tV = *oV * a + *tV * (1 - a);
+                               ++tY;
+                               ++oY;
+                               if (tx % 2) {
+                                       ++tU;
+                                       ++tV;
+                               }
+                               if (ox % 2) {
+                                       ++oU;
+                                       ++oV;
+                               }
+                               alpha += 4;
+                       }
+               }
+               break;
+       }
        case AV_PIX_FMT_YUV422P10LE:
        {
                shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
                dcp::Size const ts = size();
                dcp::Size const os = yuv->size();
                for (int ty = start_ty, oy = start_oy; ty < ts.height && oy < os.height; ++ty, ++oy) {
-                       uint16_t* tY = (uint16_t *) (data()[0] + (ty * stride()[0])) + start_tx;
-                       uint8_t* tU = data()[1] + (ty * stride()[1]) + start_tx;
-                       uint8_t* tV = data()[2] + (ty * stride()[2]) + start_tx;
-                       uint16_t* oY = (uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0])) + start_ox;
-                       uint8_t* oU = yuv->data()[1] + (oy * yuv->stride()[1]) + start_ox;
-                       uint8_t* oV = yuv->data()[2] + (oy * yuv->stride()[2]) + start_ox;
+                       uint16_t* tY = ((uint16_t *) (data()[0] + (ty * stride()[0]))) + start_tx;
+                       uint16_t* tU = ((uint16_t *) (data()[1] + (ty * stride()[1]))) + start_tx / 2;
+                       uint16_t* tV = ((uint16_t *) (data()[2] + (ty * stride()[2]))) + start_tx / 2;
+                       uint16_t* oY = ((uint16_t *) (yuv->data()[0] + (oy * yuv->stride()[0]))) + start_ox;
+                       uint16_t* oU = ((uint16_t *) (yuv->data()[1] + (oy * yuv->stride()[1]))) + start_ox / 2;
+                       uint16_t* oV = ((uint16_t *) (yuv->data()[2] + (oy * yuv->stride()[2]))) + start_ox / 2;
                        uint8_t* alpha = other->data()[0] + (oy * other->stride()[0]) + start_ox * 4;
                        for (int tx = start_tx, ox = start_ox; tx < ts.width && ox < os.width; ++tx, ++ox) {
                                float const a = float(alpha[3]) / 255;
@@ -626,11 +660,15 @@ Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
                                *tU = *oU * a + *tU * (1 - a);
                                *tV = *oV * a + *tV * (1 - a);
                                ++tY;
-                               ++tU;
-                               ++tV;
                                ++oY;
-                               ++oU;
-                               ++oV;
+                               if (tx % 2) {
+                                       ++tU;
+                                       ++tV;
+                               }
+                               if (ox % 2) {
+                                       ++oU;
+                                       ++oV;
+                               }
                                alpha += 4;
                        }
                }
index b0bbe25..299ef2e 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
@@ -142,7 +142,7 @@ alpha_blend_test_one (AVPixelFormat format, string suffix)
        shared_ptr<Image> raw = proxy->image();
        shared_ptr<Image> background = raw->convert_pixel_format (dcp::YUV_TO_RGB_REC709, format, true, false);
 
-       shared_ptr<Image> overlay (new Image (AV_PIX_FMT_BGRA, raw->size(), true));
+       shared_ptr<Image> overlay (new Image (AV_PIX_FMT_BGRA, dcp::Size(431, 891), true));
        overlay->make_transparent ();
 
        for (int y = 0; y < 128; ++y) {
@@ -169,7 +169,7 @@ alpha_blend_test_one (AVPixelFormat format, string suffix)
                }
        }
 
-       background->alpha_blend (overlay, Position<int> (0, 0));
+       background->alpha_blend (overlay, Position<int> (13, 17));
 
        shared_ptr<Image> save = background->convert_pixel_format (dcp::YUV_TO_RGB_REC709, AV_PIX_FMT_RGB24, false, false);
 
@@ -185,7 +185,8 @@ BOOST_AUTO_TEST_CASE (alpha_blend_test)
        alpha_blend_test_one (AV_PIX_FMT_RGBA, "rgba");
        alpha_blend_test_one (AV_PIX_FMT_RGB48LE, "rgb48le");
        alpha_blend_test_one (AV_PIX_FMT_YUV420P, "yuv420p");
-       alpha_blend_test_one (AV_PIX_FMT_YUV420P10LE, "yuv420p10le");
+       alpha_blend_test_one (AV_PIX_FMT_YUV420P10, "yuv420p10");
+       alpha_blend_test_one (AV_PIX_FMT_YUV422P10LE, "yuv422p10le");
 }
 
 /** Test merge (list<PositionImage>) with a single image */