Small bits of c++11 tidying.
[dcpomatic.git] / src / lib / image.cc
index abbc6e71aa87c5bdee0983496850f9efd48f5329..3a23d1abb49c69aa077644edee893f7b621c3029 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-    Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 
     This file is part of DCP-o-matic.
 
 
 */
 
 
 */
 
+
 /** @file src/image.cc
  *  @brief A class to describe a video image.
  */
 
 /** @file src/image.cc
  *  @brief A class to describe a video image.
  */
 
-#include "image.h"
+
+#include "compose.hpp"
+#include "dcpomatic_socket.h"
 #include "exceptions.h"
 #include "exceptions.h"
-#include "timer.h"
+#include "image.h"
 #include "rect.h"
 #include "rect.h"
+#include "timer.h"
 #include "util.h"
 #include "util.h"
-#include "compose.hpp"
-#include "dcpomatic_socket.h"
 #include <dcp/rgb_xyz.h>
 #include <dcp/transfer_function.h>
 extern "C" {
 #include <dcp/rgb_xyz.h>
 #include <dcp/transfer_function.h>
 extern "C" {
-#include <libswscale/swscale.h>
-#include <libavutil/pixfmt.h>
-#include <libavutil/pixdesc.h>
 #include <libavutil/frame.h>
 #include <libavutil/frame.h>
+#include <libavutil/pixdesc.h>
+#include <libavutil/pixfmt.h>
+#include <libswscale/swscale.h>
 }
 #include <png.h>
 #if HAVE_VALGRIND_MEMCHECK_H
 }
 #include <png.h>
 #if HAVE_VALGRIND_MEMCHECK_H
@@ -43,16 +45,19 @@ extern "C" {
 #endif
 #include <iostream>
 
 #endif
 #include <iostream>
 
+
 #include "i18n.h"
 
 #include "i18n.h"
 
-using std::string;
-using std::min;
-using std::max;
-using std::cout;
+
 using std::cerr;
 using std::cerr;
+using std::cout;
 using std::list;
 using std::list;
+using std::make_shared;
+using std::max;
+using std::min;
 using std::runtime_error;
 using std::runtime_error;
-using boost::shared_ptr;
+using std::shared_ptr;
+using std::string;
 using dcp::Size;
 
 
 using dcp::Size;
 
 
@@ -67,7 +72,7 @@ Image::vertical_factor (int n) const
                return 1;
        }
 
                return 1;
        }
 
-       AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
+       auto d = av_pix_fmt_desc_get(_pixel_format);
        if (!d) {
                throw PixelFormatError ("line_factor()", _pixel_format);
        }
        if (!d) {
                throw PixelFormatError ("line_factor()", _pixel_format);
        }
@@ -82,7 +87,7 @@ Image::horizontal_factor (int n) const
                return 1;
        }
 
                return 1;
        }
 
-       AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
+       auto d = av_pix_fmt_desc_get(_pixel_format);
        if (!d) {
                throw PixelFormatError ("sample_size()", _pixel_format);
        }
        if (!d) {
                throw PixelFormatError ("sample_size()", _pixel_format);
        }
@@ -97,8 +102,8 @@ dcp::Size
 Image::sample_size (int n) const
 {
        return dcp::Size (
 Image::sample_size (int n) const
 {
        return dcp::Size (
-               lrint (ceil (static_cast<double>(size().width) / horizontal_factor (n))),
-               lrint (ceil (static_cast<double>(size().height) / vertical_factor (n)))
+               lrint (ceil(static_cast<double>(size().width) / horizontal_factor (n))),
+               lrint (ceil(static_cast<double>(size().height) / vertical_factor (n)))
                );
 }
 
                );
 }
 
@@ -106,7 +111,7 @@ Image::sample_size (int n) const
 int
 Image::planes () const
 {
 int
 Image::planes () const
 {
-       AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
+       auto d = av_pix_fmt_desc_get(_pixel_format);
        if (!d) {
                throw PixelFormatError ("planes()", _pixel_format);
        }
        if (!d) {
                throw PixelFormatError ("planes()", _pixel_format);
        }
@@ -172,10 +177,10 @@ Image::crop_scale_window (
        DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
        DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
 
        DCPOMATIC_ASSERT (out_size.width >= inter_size.width);
        DCPOMATIC_ASSERT (out_size.height >= inter_size.height);
 
-       shared_ptr<Image> out (new Image(out_format, out_size, out_aligned));
+       auto out = make_shared<Image>(out_format, out_size, out_aligned);
        out->make_black ();
 
        out->make_black ();
 
-       AVPixFmtDescriptor const * in_desc = av_pix_fmt_desc_get (_pixel_format);
+       auto in_desc = av_pix_fmt_desc_get (_pixel_format);
        if (!in_desc) {
                throw PixelFormatError ("crop_scale_window()", _pixel_format);
        }
        if (!in_desc) {
                throw PixelFormatError ("crop_scale_window()", _pixel_format);
        }
@@ -183,18 +188,29 @@ Image::crop_scale_window (
        /* Round down so that we crop only the number of pixels that is straightforward
         * considering any subsampling.
         */
        /* Round down so that we crop only the number of pixels that is straightforward
         * considering any subsampling.
         */
-       Crop rounded_crop(
+       Crop corrected_crop(
                round_width_for_subsampling(crop.left, in_desc),
                round_width_for_subsampling(crop.right, in_desc),
                round_height_for_subsampling(crop.top, in_desc),
                round_height_for_subsampling(crop.bottom, in_desc)
                );
 
                round_width_for_subsampling(crop.left, in_desc),
                round_width_for_subsampling(crop.right, in_desc),
                round_height_for_subsampling(crop.top, in_desc),
                round_height_for_subsampling(crop.bottom, in_desc)
                );
 
+       /* Also check that we aren't cropping more image than there actually is */
+       if ((corrected_crop.left + corrected_crop.right) >= (size().width - 4)) {
+               corrected_crop.left = 0;
+               corrected_crop.right = size().width - 4;
+       }
+
+       if ((corrected_crop.top + corrected_crop.bottom) >= (size().height - 4)) {
+               corrected_crop.top = 0;
+               corrected_crop.bottom = size().height - 4;
+       }
+
        /* Size of the image after any crop */
        /* Size of the image after any crop */
-       dcp::Size const cropped_size = rounded_crop.apply (size());
+       auto const cropped_size = corrected_crop.apply (size());
 
        /* Scale context for a scale from cropped_size to inter_size */
 
        /* Scale context for a scale from cropped_size to inter_size */
-       struct SwsContext* scale_context = sws_getContext (
+       auto scale_context = sws_getContext (
                        cropped_size.width, cropped_size.height, pixel_format(),
                        inter_size.width, inter_size.height, out_format,
                        fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
                        cropped_size.width, cropped_size.height, pixel_format(),
                        inter_size.width, inter_size.height, out_format,
                        fast ? SWS_FAST_BILINEAR : SWS_BICUBIC, 0, 0, 0
@@ -204,8 +220,8 @@ Image::crop_scale_window (
                throw runtime_error (N_("Could not allocate SwsContext"));
        }
 
                throw runtime_error (N_("Could not allocate SwsContext"));
        }
 
-       DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
-       int const lut[dcp::YUV_TO_RGB_COUNT] = {
+       DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
+       int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
                SWS_CS_ITU601,
                SWS_CS_ITU709
        };
                SWS_CS_ITU601,
                SWS_CS_ITU709
        };
@@ -223,19 +239,19 @@ Image::crop_scale_window (
        */
        sws_setColorspaceDetails (
                scale_context,
        */
        sws_setColorspaceDetails (
                scale_context,
-               sws_getCoefficients (lut[yuv_to_rgb]), video_range == VIDEO_RANGE_VIDEO ? 0 : 1,
-               sws_getCoefficients (lut[yuv_to_rgb]), out_video_range == VIDEO_RANGE_VIDEO ? 0 : 1,
+               sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), video_range == VIDEO_RANGE_VIDEO ? 0 : 1,
+               sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), out_video_range == VIDEO_RANGE_VIDEO ? 0 : 1,
                0, 1 << 16, 1 << 16
                );
 
        /* Prepare input data pointers with crop */
        uint8_t* scale_in_data[planes()];
        for (int c = 0; c < planes(); ++c) {
                0, 1 << 16, 1 << 16
                );
 
        /* Prepare input data pointers with crop */
        uint8_t* scale_in_data[planes()];
        for (int c = 0; c < planes(); ++c) {
-               int const x = lrintf(bytes_per_pixel(c) * rounded_crop.left);
-               scale_in_data[c] = data()[c] + x + stride()[c] * (rounded_crop.top / vertical_factor(c));
+               int const x = lrintf(bytes_per_pixel(c) * corrected_crop.left);
+               scale_in_data[c] = data()[c] + x + stride()[c] * (corrected_crop.top / vertical_factor(c));
        }
 
        }
 
-       AVPixFmtDescriptor const * out_desc = av_pix_fmt_desc_get (out_format);
+       auto out_desc = av_pix_fmt_desc_get (out_format);
        if (!out_desc) {
                throw PixelFormatError ("crop_scale_window()", out_format);
        }
        if (!out_desc) {
                throw PixelFormatError ("crop_scale_window()", out_format);
        }
@@ -261,7 +277,7 @@ Image::crop_scale_window (
 
        sws_freeContext (scale_context);
 
 
        sws_freeContext (scale_context);
 
-       if (rounded_crop != Crop() && cropped_size == inter_size) {
+       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.
                /* 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.
@@ -293,16 +309,15 @@ Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_fo
        */
        DCPOMATIC_ASSERT (aligned ());
 
        */
        DCPOMATIC_ASSERT (aligned ());
 
-       shared_ptr<Image> scaled (new Image (out_format, out_size, out_aligned));
-
-       struct SwsContext* scale_context = sws_getContext (
+       auto scaled = make_shared<Image>(out_format, out_size, out_aligned);
+       auto scale_context = sws_getContext (
                size().width, size().height, pixel_format(),
                out_size.width, out_size.height, out_format,
                (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
                );
 
                size().width, size().height, pixel_format(),
                out_size.width, out_size.height, out_format,
                (fast ? SWS_FAST_BILINEAR : SWS_BICUBIC) | SWS_ACCURATE_RND, 0, 0, 0
                );
 
-       DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUV_TO_RGB_COUNT);
-       int const lut[dcp::YUV_TO_RGB_COUNT] = {
+       DCPOMATIC_ASSERT (yuv_to_rgb < dcp::YUVToRGB::COUNT);
+       int const lut[static_cast<int>(dcp::YUVToRGB::COUNT)] = {
                SWS_CS_ITU601,
                SWS_CS_ITU709
        };
                SWS_CS_ITU601,
                SWS_CS_ITU709
        };
@@ -320,8 +335,8 @@ Image::scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_fo
        */
        sws_setColorspaceDetails (
                scale_context,
        */
        sws_setColorspaceDetails (
                scale_context,
-               sws_getCoefficients (lut[yuv_to_rgb]), 0,
-               sws_getCoefficients (lut[yuv_to_rgb]), 0,
+               sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
+               sws_getCoefficients (lut[static_cast<int>(yuv_to_rgb)]), 0,
                0, 1 << 16, 1 << 16
                );
 
                0, 1 << 16, 1 << 16
                );
 
@@ -343,7 +358,7 @@ Image::yuv_16_black (uint16_t v, bool alpha)
 {
        memset (data()[0], 0, sample_size(0).height * stride()[0]);
        for (int i = 1; i < 3; ++i) {
 {
        memset (data()[0], 0, sample_size(0).height * stride()[0]);
        for (int i = 1; i < 3; ++i) {
-               int16_t* p = reinterpret_cast<int16_t*> (data()[i]);
+               auto p = reinterpret_cast<int16_t*> (data()[i]);
                int const lines = sample_size(i).height;
                for (int y = 0; y < lines; ++y) {
                        /* We divide by 2 here because we are writing 2 bytes at a time */
                int const lines = sample_size(i).height;
                for (int y = 0; y < lines; ++y) {
                        /* We divide by 2 here because we are writing 2 bytes at a time */
@@ -634,7 +649,7 @@ Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
        }
        case AV_PIX_FMT_XYZ12LE:
        {
        }
        case AV_PIX_FMT_XYZ12LE:
        {
-               dcp::ColourConversion conv = dcp::ColourConversion::srgb_to_xyz();
+               auto conv = dcp::ColourConversion::srgb_to_xyz();
                double fast_matrix[9];
                dcp::combined_rgb_to_xyz (conv, fast_matrix);
                double const * lut_in = conv.in()->lut (8, false);
                double fast_matrix[9];
                dcp::combined_rgb_to_xyz (conv, fast_matrix);
                double const * lut_in = conv.in()->lut (8, false);
@@ -669,7 +684,7 @@ Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
        }
        case AV_PIX_FMT_YUV420P:
        {
        }
        case AV_PIX_FMT_YUV420P:
        {
-               shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
+               auto yuv = other->convert_pixel_format (dcp::YUVToRGB::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) {
                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) {
@@ -704,7 +719,7 @@ Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
        }
        case AV_PIX_FMT_YUV420P10:
        {
        }
        case AV_PIX_FMT_YUV420P10:
        {
-               shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
+               auto yuv = other->convert_pixel_format (dcp::YUVToRGB::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) {
                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) {
@@ -739,7 +754,7 @@ Image::alpha_blend (shared_ptr<const Image> other, Position<int> position)
        }
        case AV_PIX_FMT_YUV422P10LE:
        {
        }
        case AV_PIX_FMT_YUV422P10LE:
        {
-               shared_ptr<Image> yuv = other->convert_pixel_format (dcp::YUV_TO_RGB_REC709, _pixel_format, false, false);
+               auto yuv = other->convert_pixel_format (dcp::YUVToRGB::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) {
                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) {
@@ -819,7 +834,7 @@ Image::write_to_socket (shared_ptr<Socket> socket) const
 float
 Image::bytes_per_pixel (int c) const
 {
 float
 Image::bytes_per_pixel (int c) const
 {
-       AVPixFmtDescriptor const * d = av_pix_fmt_desc_get(_pixel_format);
+       auto d = av_pix_fmt_desc_get(_pixel_format);
        if (!d) {
                throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
        }
        if (!d) {
                throw PixelFormatError ("bytes_per_pixel()", _pixel_format);
        }
@@ -941,7 +956,7 @@ Image::allocate ()
 }
 
 Image::Image (Image const & other)
 }
 
 Image::Image (Image const & other)
-       : boost::enable_shared_from_this<Image>(other)
+       : std::enable_shared_from_this<Image>(other)
        , _size (other._size)
        , _pixel_format (other._pixel_format)
        , _aligned (other._aligned)
        , _size (other._size)
        , _pixel_format (other._pixel_format)
        , _aligned (other._aligned)
@@ -1068,11 +1083,12 @@ Image::aligned () const
        return _aligned;
 }
 
        return _aligned;
 }
 
+
 PositionImage
 merge (list<PositionImage> images)
 {
        if (images.empty ()) {
 PositionImage
 merge (list<PositionImage> images)
 {
        if (images.empty ()) {
-               return PositionImage ();
+               return {};
        }
 
        if (images.size() == 1) {
        }
 
        if (images.size() == 1) {
@@ -1080,19 +1096,20 @@ merge (list<PositionImage> images)
        }
 
        dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
        }
 
        dcpomatic::Rect<int> all (images.front().position, images.front().image->size().width, images.front().image->size().height);
-       for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
-               all.extend (dcpomatic::Rect<int> (i->position, i->image->size().width, i->image->size().height));
+       for (auto const& i: images) {
+               all.extend (dcpomatic::Rect<int>(i.position, i.image->size().width, i.image->size().height));
        }
 
        }
 
-       shared_ptr<Image> merged (new 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), true);
        merged->make_transparent ();
        merged->make_transparent ();
-       for (list<PositionImage>::const_iterator i = images.begin(); i != images.end(); ++i) {
-               merged->alpha_blend (i->image, i->position - all.position());
+       for (auto const& i: images) {
+               merged->alpha_blend (i.image, i.position - all.position());
        }
 
        return PositionImage (merged, all.position ());
 }
 
        }
 
        return PositionImage (merged, all.position ());
 }
 
+
 bool
 operator== (Image const & a, Image const & b)
 {
 bool
 operator== (Image const & a, Image const & b)
 {
@@ -1248,7 +1265,7 @@ Image::ensure_aligned (shared_ptr<const Image> image)
                return image;
        }
 
                return image;
        }
 
-       return shared_ptr<Image> (new Image (image, true));
+       return make_shared<Image>(image, true);
 }
 
 size_t
 }
 
 size_t
@@ -1281,7 +1298,7 @@ public:
 static void
 png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
 {
 static void
 png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
 {
-       Memory* mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
+       auto mem = reinterpret_cast<Memory*>(png_get_io_ptr(png_ptr));
        size_t size = mem->size + length;
 
        if (mem->data) {
        size_t size = mem->size + length;
 
        if (mem->data) {
@@ -1322,7 +1339,7 @@ Image::as_png () const
        DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
        DCPOMATIC_ASSERT (planes() == 1);
        if (pixel_format() != AV_PIX_FMT_RGBA) {
        DCPOMATIC_ASSERT (bytes_per_pixel(0) == 4);
        DCPOMATIC_ASSERT (planes() == 1);
        if (pixel_format() != AV_PIX_FMT_RGBA) {
-               return convert_pixel_format(dcp::YUV_TO_RGB_REC709, AV_PIX_FMT_RGBA, true, false)->as_png();
+               return convert_pixel_format(dcp::YUVToRGB::REC709, AV_PIX_FMT_RGBA, true, false)->as_png();
        }
 
        /* error handling? */
        }
 
        /* error handling? */