Differentiate requested and actual crop.
authorCarl Hetherington <cth@carlh.net>
Sun, 3 Oct 2021 18:53:44 +0000 (20:53 +0200)
committerCarl Hetherington <cth@carlh.net>
Sun, 3 Oct 2021 21:41:02 +0000 (23:41 +0200)
This is so we limit cropping to what is possible considering
chroma subsampling.

src/lib/pixel_quanta.cc
src/lib/pixel_quanta.h
src/lib/player.cc
src/lib/player_video.cc
src/lib/video_content.cc
src/lib/video_content.h
src/tools/dcpomatic_cli.cc
src/wx/video_panel.cc

index 12eea5031a606a88427233b631f30822dde4cba2..09e6840645cf7d967a05b9dddbbbb92aaf2f84e1 100644 (file)
@@ -39,6 +39,20 @@ PixelQuanta::as_xml (xmlpp::Element* node) const
 }
 
 
+int
+PixelQuanta::round_x (int x_) const
+{
+       return x_ - (x_ % x);
+}
+
+
+int
+PixelQuanta::round_y (int y_) const
+{
+       return y_ - (y_ % y);
+}
+
+
 PixelQuanta
 max (PixelQuanta const& a, PixelQuanta const& b)
 {
index e4a03c9d2a126839294a8916d86261c5d4d52a50..c37ba189bb34895696d5a3a8b8656619f363678b 100644 (file)
@@ -52,6 +52,9 @@ public:
 
        void as_xml (xmlpp::Element* node) const;
 
+       int round_x (int x_) const;
+       int round_y (int y_) const;
+
        int x;
        int y;
 };
index 7951926e63f06ae47adb2071433058beccc96a7d..285126ced266a71f70575a7502c1d865407563f3 100644 (file)
@@ -922,7 +922,7 @@ Player::video (weak_ptr<Piece> wp, ContentVideo video)
 
        _last_video[wp] = std::make_shared<PlayerVideo>(
                video.image,
-               piece->content->video->crop (),
+               piece->content->video->actual_crop(),
                piece->content->video->fade (_film, video.frame),
                scale_for_display(piece->content->video->scaled_size(_film->frame_size()), _video_container_size, _film->frame_size()),
                _video_container_size,
index 7c36af31b54bbbb7e8c764b9f0b3dcba89145e5e..c9bc2dcde9b9e6f48f414cadcaae269cc6d1248b 100644 (file)
@@ -343,7 +343,7 @@ PlayerVideo::reset_metadata (shared_ptr<const Film> film, dcp::Size player_video
                return false;
        }
 
-       _crop = content->video->crop();
+       _crop = content->video->actual_crop();
        _fade = content->video->fade(film, _video_frame.get());
        _inter_size = scale_for_display(content->video->scaled_size(film->frame_size()), player_video_container_size, film->frame_size());
        _out_size = player_video_container_size;
index bffe2e3224cdfe8f0f9775f28ff2a7bac07b535d..0ef1021161d7a69004494d733da1b83bc02ca046 100644 (file)
@@ -218,7 +218,7 @@ VideoContent::VideoContent (Content* parent, vector<shared_ptr<Content> > c)
                        throw JoinError (_("Content to be joined must have the same video frame type."));
                }
 
-               if (c[i]->video->crop() != ref->crop()) {
+               if (c[i]->video->requested_crop() != ref->requested_crop()) {
                        throw JoinError (_("Content to be joined must have the same crop."));
                }
 
@@ -254,7 +254,7 @@ VideoContent::VideoContent (Content* parent, vector<shared_ptr<Content> > c)
        _use = ref->use ();
        _size = ref->size ();
        _frame_type = ref->frame_type ();
-       _crop = ref->crop ();
+       _crop = ref->requested_crop ();
        _custom_ratio = ref->custom_ratio ();
        _colour_conversion = ref->colour_conversion ();
        _fade_in = ref->fade_in ();
@@ -334,13 +334,14 @@ string
 VideoContent::identifier () const
 {
        char buffer[256];
+       auto const crop = actual_crop();
        snprintf (
                buffer, sizeof(buffer), "%d_%d_%d_%d_%d_%f_%d_%d%" PRId64 "_%" PRId64 "_%d",
                (_use ? 1 : 0),
-               crop().left,
-               crop().right,
-               crop().top,
-               crop().bottom,
+               crop.left,
+               crop.right,
+               crop.top,
+               crop.bottom,
                _custom_ratio.get_value_or(0),
                _custom_size ? _custom_size->width : 0,
                _custom_size ? _custom_size->height : 0,
@@ -399,7 +400,7 @@ VideoContent::size_after_3d_split () const
 dcp::Size
 VideoContent::size_after_crop () const
 {
-       return crop().apply (size_after_3d_split ());
+       return actual_crop().apply(size_after_3d_split());
 }
 
 
@@ -452,8 +453,10 @@ VideoContent::processing_description (shared_ptr<const Film> film)
                d += buffer;
        }
 
-       if ((crop().left || crop().right || crop().top || crop().bottom) && size() != dcp::Size (0, 0)) {
-               dcp::Size cropped = size_after_crop ();
+       auto const crop = actual_crop();
+
+       if ((crop.left || crop.right || crop.top || crop.bottom) && size() != dcp::Size(0, 0)) {
+               auto const cropped = size_after_crop ();
                d += String::compose (
                        _("\nCropped to %1x%2"),
                        cropped.width, cropped.height
@@ -668,3 +671,16 @@ VideoContent::set_custom_size (optional<dcp::Size> size)
 {
        maybe_set (_custom_size, size, VideoContentProperty::CUSTOM_SIZE);
 }
+
+
+Crop
+VideoContent::actual_crop () const
+{
+       return Crop(
+               _pixel_quanta.round_x(_crop.left),
+               _pixel_quanta.round_x(_crop.right),
+               _pixel_quanta.round_y(_crop.top),
+               _pixel_quanta.round_y(_crop.bottom)
+       );
+}
+
index de151e1451d9f9583168a65a19687a045cc5a309..ce645bb41fd714c8c6ad5c0b1c734827bbbee9a6 100644 (file)
@@ -113,27 +113,29 @@ public:
                return _frame_type;
        }
 
-       Crop crop () const {
+       Crop actual_crop () const;
+
+       Crop requested_crop () const {
                boost::mutex::scoped_lock lm (_mutex);
                return _crop;
        }
 
-       int left_crop () const {
+       int requested_left_crop () const {
                boost::mutex::scoped_lock lm (_mutex);
                return _crop.left;
        }
 
-       int right_crop () const {
+       int requested_right_crop () const {
                boost::mutex::scoped_lock lm (_mutex);
                return _crop.right;
        }
 
-       int top_crop () const {
+       int requested_top_crop () const {
                boost::mutex::scoped_lock lm (_mutex);
                return _crop.top;
        }
 
-       int bottom_crop () const {
+       int requested_bottom_crop () const {
                boost::mutex::scoped_lock lm (_mutex);
                return _crop.bottom;
        }
index 59d85d4c469de2a975d2be2caf4163e5d6422dee..75f57fa89ce4b659a50346c79df05b6f6acab978 100644 (file)
@@ -92,10 +92,10 @@ print_dump (shared_ptr<Film> film)
                if (c->video) {
                        cout << "\t" << c->video->size().width << "x" << c->video->size().height << "\n"
                             << "\t" << c->active_video_frame_rate(film) << "fps\n"
-                            << "\tcrop left " << c->video->left_crop()
-                            << " right " << c->video->right_crop()
-                            << " top " << c->video->top_crop()
-                            << " bottom " << c->video->bottom_crop() << "\n";
+                            << "\tcrop left " << c->video->requested_left_crop()
+                            << " right " << c->video->requested_right_crop()
+                            << " top " << c->video->requested_top_crop()
+                            << " bottom " << c->video->requested_bottom_crop() << "\n";
                        if (c->video->custom_ratio()) {
                                cout << "\tscale to custom ratio " << *c->video->custom_ratio() << ":1\n";
                        }
index 33961ea1dcae72d60ba9ab75c2e89f5d4213b625..52c3b9229afed23c83512f83b154dd69679938f2 100644 (file)
@@ -118,7 +118,7 @@ VideoPanel::create ()
                new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(crop_width, -1)),
                VideoContentProperty::CROP,
                &Content::video,
-               boost::mem_fn (&VideoContent::left_crop),
+               boost::mem_fn (&VideoContent::requested_left_crop),
                boost::mem_fn (&VideoContent::set_left_crop),
                boost::bind (&VideoPanel::left_crop_changed, this)
                );
@@ -132,7 +132,7 @@ VideoPanel::create ()
                new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(crop_width, -1)),
                VideoContentProperty::CROP,
                &Content::video,
-               boost::mem_fn (&VideoContent::right_crop),
+               boost::mem_fn (&VideoContent::requested_right_crop),
                boost::mem_fn (&VideoContent::set_right_crop),
                boost::bind (&VideoPanel::right_crop_changed, this)
                );
@@ -143,7 +143,7 @@ VideoPanel::create ()
                new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(crop_width, -1)),
                VideoContentProperty::CROP,
                &Content::video,
-               boost::mem_fn (&VideoContent::top_crop),
+               boost::mem_fn (&VideoContent::requested_top_crop),
                boost::mem_fn (&VideoContent::set_top_crop),
                boost::bind (&VideoPanel::top_crop_changed, this)
                );
@@ -157,7 +157,7 @@ VideoPanel::create ()
                new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(crop_width, -1)),
                VideoContentProperty::CROP,
                &Content::video,
-               boost::mem_fn (&VideoContent::bottom_crop),
+               boost::mem_fn (&VideoContent::requested_bottom_crop),
                boost::mem_fn (&VideoContent::set_bottom_crop),
                boost::bind (&VideoPanel::bottom_crop_changed, this)
                );
@@ -759,7 +759,7 @@ VideoPanel::left_crop_changed ()
        _left_changed_last = true;
        if (_left_right_link->GetValue()) {
                for (auto i: _parent->selected_video()) {
-                       i->video->set_right_crop (i->video->left_crop());
+                       i->video->set_right_crop (i->video->requested_left_crop());
                }
        }
 }
@@ -771,7 +771,7 @@ VideoPanel::right_crop_changed ()
        _left_changed_last = false;
        if (_left_right_link->GetValue()) {
                for (auto i: _parent->selected_video()) {
-                       i->video->set_left_crop (i->video->right_crop());
+                       i->video->set_left_crop (i->video->requested_right_crop());
                }
        }
 }
@@ -783,7 +783,7 @@ VideoPanel::top_crop_changed ()
        _top_changed_last = true;
        if (_top_bottom_link->GetValue()) {
                for (auto i: _parent->selected_video()) {
-                       i->video->set_bottom_crop (i->video->top_crop());
+                       i->video->set_bottom_crop (i->video->requested_top_crop());
                }
        }
 }
@@ -795,10 +795,9 @@ VideoPanel::bottom_crop_changed ()
        _top_changed_last = false;
        if (_top_bottom_link->GetValue()) {
                for (auto i: _parent->selected_video()) {
-                       i->video->set_top_crop (i->video->bottom_crop());
+                       i->video->set_top_crop (i->video->requested_bottom_crop());
                }
        }
 }
 
 
-