Various alignment adjustments.
[dcpomatic.git] / src / lib / image.cc
index 4859ebe14876320718ae162f65c2361c5817b8ad..ce3f5817d5cd78e12f6ae1a67348e8711d224cf1 100644 (file)
@@ -297,6 +297,15 @@ Image::crop_scale_window (
                out->make_part_black (corner.x + cropped_size.width, out_size.width - cropped_size.width);
        }
 
+       if (
+               video_range == VideoRange::VIDEO &&
+               out_video_range == VideoRange::FULL &&
+               av_pix_fmt_desc_get(_pixel_format)->flags & AV_PIX_FMT_FLAG_RGB
+          ) {
+               /* libswscale will not convert video range for RGB sources, so we have to do it ourselves */
+               out->video_range_to_full_range ();
+       }
+
        return out;
 }
 
@@ -1018,10 +1027,10 @@ Image::Image (Image const & other)
        }
 }
 
-Image::Image (AVFrame const * frame)
+Image::Image (AVFrame const * frame, bool aligned)
        : _size (frame->width, frame->height)
        , _pixel_format (static_cast<AVPixelFormat>(frame->format))
-       , _aligned (true)
+       , _aligned (aligned)
 {
        DCPOMATIC_ASSERT (_pixel_format != AV_PIX_FMT_NONE);
 
@@ -1130,7 +1139,7 @@ Image::aligned () const
 
 
 PositionImage
-merge (list<PositionImage> images)
+merge (list<PositionImage> images, bool aligned)
 {
        if (images.empty ()) {
                return {};
@@ -1145,7 +1154,7 @@ merge (list<PositionImage> images)
                all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
        }
 
-       auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), true);
+       auto merged = make_shared<Image>(images.front().image->pixel_format(), dcp::Size(all.width, all.height), aligned);
        merged->make_transparent ();
        for (auto const& i: images) {
                merged->alpha_blend (i.image, i.position - all.position());
@@ -1303,16 +1312,18 @@ Image::fade (float f)
        }
 }
 
+
 shared_ptr<const Image>
-Image::ensure_aligned (shared_ptr<const Image> image)
+Image::ensure_aligned (shared_ptr<const Image> image, bool aligned)
 {
-       if (image->aligned()) {
+       if (image->aligned() == aligned) {
                return image;
        }
 
-       return make_shared<Image>(image, true);
+       return make_shared<Image>(image, aligned);
 }
 
+
 size_t
 Image::memory_used () const
 {
@@ -1433,13 +1444,29 @@ 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];
                }
                break;
        }
+       case AV_PIX_FMT_RGB48LE:
+       {
+               float const factor = 65536.0 / 56064.0;
+               uint16_t* p = reinterpret_cast<uint16_t*>(data()[0]);
+               int const lines = sample_size(0).height;
+               for (int y = 0; y < lines; ++y) {
+                       uint16_t* q = p;
+                       int const line_size_pixels = line_size()[0] / 2;
+                       for (int x = 0; x < line_size_pixels; ++x) {
+                               *q = clamp(lrintf((*q - 4096) * factor), 0L, 65535L);
+                               ++q;
+                       }
+                       p += stride()[0] / 2;
+               }
+               break;
+       }
        case AV_PIX_FMT_GBRP12LE:
        {
                float const factor = 4096.0 / 3504.0;
@@ -1450,7 +1477,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;
                                }
                        }