From: Carl Hetherington Date: Tue, 15 Oct 2013 14:26:04 +0000 (+0100) Subject: Allow no-stretch scaling of video content. X-Git-Tag: v2.0.48~1277 X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=45f9912aa850546e319e32a4052517d67f4e3d8f Allow no-stretch scaling of video content. --- diff --git a/ChangeLog b/ChangeLog index a066ce19d..addda9eea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-10-15 Carl Hetherington + + * Allow no-stretch scaling like in DVD-o-matic. + 2013-10-14 Carl Hetherington * Add Rec. 709 colour conversion preset using diff --git a/src/lib/image.cc b/src/lib/image.cc index 9a3aa8d45..d56b8763a 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -155,10 +155,7 @@ Image::post_process (string pp, bool aligned) const shared_ptr Image::crop (Crop crop, bool aligned) const { - libdcp::Size cropped_size = size (); - cropped_size.width -= crop.left + crop.right; - cropped_size.height -= crop.top + crop.bottom; - + libdcp::Size cropped_size = crop.apply (size ()); shared_ptr out (new Image (pixel_format(), cropped_size, aligned)); for (int c = 0; c < components(); ++c) { diff --git a/src/lib/player.cc b/src/lib/player.cc index 70d6fa877..03c5dc322 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -103,7 +103,7 @@ Player::Player (shared_ptr f, shared_ptr p) _playlist_changed_connection = _playlist->Changed.connect (bind (&Player::playlist_changed, this)); _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2, _3)); _film_changed_connection = _film->Changed.connect (bind (&Player::film_changed, this, _1)); - set_video_container_size (_film->container()->size (_film->full_frame ())); + set_video_container_size (fit_ratio_within (_film->container()->ratio (), _film->full_frame ())); } void @@ -256,7 +256,8 @@ Player::process_video (weak_ptr weak_piece, shared_ptr image work_image = work_image->crop (content->crop(), true); - libdcp::Size const image_size = content->ratio()->size (_video_container_size); + float const ratio = content->ratio() ? content->ratio()->ratio() : content->video_size_after_crop().ratio(); + libdcp::Size image_size = fit_ratio_within (ratio, _video_container_size); work_image = work_image->scale (image_size, _film->scaler(), PIX_FMT_RGB24, true); diff --git a/src/lib/ratio.cc b/src/lib/ratio.cc index 5988b3418..41abbb760 100644 --- a/src/lib/ratio.cc +++ b/src/lib/ratio.cc @@ -19,6 +19,7 @@ #include #include "ratio.h" +#include "util.h" #include "i18n.h" @@ -28,19 +29,6 @@ using std::vector; vector Ratio::_ratios; -libdcp::Size -Ratio::size (libdcp::Size full_frame) const -{ - if (_ratio < static_cast(full_frame.width) / full_frame.height) { - return libdcp::Size (full_frame.height * _ratio, full_frame.height); - } else { - return libdcp::Size (full_frame.width, full_frame.width / _ratio); - } - - return libdcp::Size (); -} - - void Ratio::setup_ratios () { diff --git a/src/lib/ratio.h b/src/lib/ratio.h index c331edabe..f3354f1b6 100644 --- a/src/lib/ratio.h +++ b/src/lib/ratio.h @@ -34,8 +34,6 @@ public: , _dci_name (d) {} - libdcp::Size size (libdcp::Size) const; - std::string id () const { return _id; } diff --git a/src/lib/types.h b/src/lib/types.h index 01560ba81..d4d66387d 100644 --- a/src/lib/types.h +++ b/src/lib/types.h @@ -87,6 +87,21 @@ struct Crop int top; /** Number of pixels to remove from the bottom */ int bottom; + + libdcp::Size apply (libdcp::Size s, int minimum = 4) const { + s.width -= left + right; + s.height -= top + bottom; + + if (s.width < minimum) { + s.width = minimum; + } + + if (s.height < minimum) { + s.height = minimum; + } + + return s; + } }; extern bool operator== (Crop const & a, Crop const & b); diff --git a/src/lib/util.cc b/src/lib/util.cc index b13d905bf..1c4347233 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -882,3 +882,12 @@ make_signer () return shared_ptr (new libdcp::Signer (chain, signer_key)); } +libdcp::Size +fit_ratio_within (float ratio, libdcp::Size full_frame) +{ + if (ratio < full_frame.ratio ()) { + return libdcp::Size (full_frame.height * ratio, full_frame.height); + } + + return libdcp::Size (full_frame.width, full_frame.width / ratio); +} diff --git a/src/lib/util.h b/src/lib/util.h index 377b3b785..b8ea6ebec 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -75,7 +75,8 @@ extern bool valid_image_file (boost::filesystem::path); extern boost::filesystem::path mo_path (); #endif extern std::string tidy_for_filename (std::string); -boost::shared_ptr make_signer (); +extern boost::shared_ptr make_signer (); +extern libdcp::Size fit_ratio_within (float ratio, libdcp::Size); struct FrameRateConversion { diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc index af0c3e12c..23ef2cf89 100644 --- a/src/lib/video_content.cc +++ b/src/lib/video_content.cc @@ -66,6 +66,7 @@ VideoContent::VideoContent (shared_ptr f, boost::filesystem::path p) VideoContent::VideoContent (shared_ptr f, shared_ptr node) : Content (f, node) + , _ratio (0) { _video_length = node->number_child ("VideoLength"); _video_size.width = node->number_child ("VideoWidth"); @@ -139,7 +140,7 @@ VideoContent::information () const _("%1x%2 pixels (%3:1)"), video_size().width, video_size().height, - setprecision (3), float (video_size().width) / video_size().height + setprecision (3), video_size().ratio () ); return s.str (); @@ -281,3 +282,10 @@ VideoContent::set_colour_conversion (ColourConversion c) signal_changed (VideoContentProperty::COLOUR_CONVERSION); } + +/** @return Video size after 3D split and crop */ +libdcp::Size +VideoContent::video_size_after_crop () const +{ + return crop().apply (video_size_after_3d_split ()); +} diff --git a/src/lib/video_content.h b/src/lib/video_content.h index 81325516d..369209776 100644 --- a/src/lib/video_content.h +++ b/src/lib/video_content.h @@ -87,6 +87,7 @@ public: void set_ratio (Ratio const *); + /** @return ratio to scale to, or 0 if the content's own ratio should be preserved. */ Ratio const * ratio () const { boost::mutex::scoped_lock lm (_mutex); return _ratio; @@ -98,6 +99,7 @@ public: } libdcp::Size video_size_after_3d_split () const; + libdcp::Size video_size_after_crop () const; protected: void take_from_video_examiner (boost::shared_ptr); diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 5e8fb5b7a..968cd1505 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -80,7 +80,7 @@ Writer::Writer (shared_ptr f, shared_ptr j) } _picture_asset->set_edit_rate (_film->video_frame_rate ()); - _picture_asset->set_size (_film->container()->size (_film->full_frame ())); + _picture_asset->set_size (fit_ratio_within (_film->container()->ratio(), _film->full_frame ())); if (_film->encrypted ()) { _picture_asset->set_key (_film->key ()); diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 3ba7ee7ce..69cd276e1 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -239,7 +239,7 @@ FilmViewer::calculate_sizes () Ratio const * container = _film->container (); - float const panel_ratio = static_cast (_panel_size.width) / _panel_size.height; + float const panel_ratio = _panel_size.ratio (); float const film_ratio = container ? container->ratio () : 1.78; if (panel_ratio < film_ratio) { diff --git a/src/wx/video_panel.cc b/src/wx/video_panel.cc index bb8476d63..a643832e8 100644 --- a/src/wx/video_panel.cc +++ b/src/wx/video_panel.cc @@ -23,6 +23,7 @@ #include "lib/ffmpeg_content.h" #include "lib/colour_conversion.h" #include "lib/config.h" +#include "lib/util.h" #include "filter_dialog.h" #include "video_panel.h" #include "wx_util.h" @@ -128,6 +129,7 @@ VideoPanel::VideoPanel (FilmEditor* e) for (vector::iterator i = ratios.begin(); i != ratios.end(); ++i) { _ratio->Append (std_to_wx ((*i)->nickname ())); } + _ratio->Append (_("No stretch")); _frame_type->Append (_("2D")); _frame_type->Append (_("3D left/right")); @@ -230,7 +232,7 @@ VideoPanel::film_content_changed (shared_ptr c, int property) } if (i == ratios.end()) { - checked_set (_ratio, -1); + checked_set (_ratio, ratios.size ()); } else { checked_set (_ratio, n); } @@ -293,45 +295,45 @@ VideoPanel::setup_description () if (vc->video_size().width && vc->video_size().height) { d << wxString::Format ( _("Content video is %dx%d (%.2f:1)\n"), - vc->video_size_after_3d_split().width, vc->video_size_after_3d_split().height, - float (vc->video_size_after_3d_split().width) / vc->video_size_after_3d_split().height + vc->video_size_after_3d_split().width, + vc->video_size_after_3d_split().height, + vc->video_size_after_3d_split().ratio () ); ++lines; } Crop const crop = vc->crop (); if ((crop.left || crop.right || crop.top || crop.bottom) && vc->video_size() != libdcp::Size (0, 0)) { - libdcp::Size cropped = vc->video_size_after_3d_split (); - cropped.width -= crop.left + crop.right; - cropped.height -= crop.top + crop.bottom; + libdcp::Size cropped = vc->video_size_after_crop (); d << wxString::Format ( _("Cropped to %dx%d (%.2f:1)\n"), cropped.width, cropped.height, - float (cropped.width) / cropped.height + cropped.ratio () ); ++lines; } Ratio const * ratio = vc->ratio (); - if (ratio) { - libdcp::Size container_size = _editor->film()->container()->size (_editor->film()->full_frame ()); - - libdcp::Size const scaled = ratio->size (container_size); + libdcp::Size container_size = fit_ratio_within (_editor->film()->container()->ratio (), _editor->film()->full_frame ()); + float const ratio_value = ratio ? ratio->ratio() : vc->video_size_after_crop().ratio (); + + /* We have a specified ratio to scale to */ + libdcp::Size const scaled = fit_ratio_within (ratio_value, container_size); + + d << wxString::Format ( + _("Scaled to %dx%d (%.2f:1)\n"), + scaled.width, scaled.height, + scaled.ratio () + ); + ++lines; + + if (scaled != container_size) { d << wxString::Format ( - _("Scaled to %dx%d (%.2f:1)\n"), - scaled.width, scaled.height, - float (scaled.width) / scaled.height + _("Padded with black to %dx%d (%.2f:1)\n"), + container_size.width, container_size.height, + container_size.ratio () ); ++lines; - - if (scaled != container_size) { - d << wxString::Format ( - _("Padded with black to %dx%d (%.2f:1)\n"), - container_size.width, container_size.height, - float (container_size.width) / container_size.height - ); - ++lines; - } } d << wxString::Format (_("Content frame rate %.4f\n"), vc->video_frame_rate ()); @@ -361,8 +363,11 @@ VideoPanel::ratio_changed () int const n = _ratio->GetSelection (); if (n >= 0) { vector ratios = Ratio::all (); - assert (n < int (ratios.size())); - vc->set_ratio (ratios[n]); + if (n < int (ratios.size ())) { + vc->set_ratio (ratios[n]); + } else { + vc->set_ratio (0); + } } } diff --git a/test/ratio_test.cc b/test/ratio_test.cc index 11517ed11..1a39040fb 100644 --- a/test/ratio_test.cc +++ b/test/ratio_test.cc @@ -21,6 +21,7 @@ #include #include #include "lib/ratio.h" +#include "lib/util.h" using std::ostream; @@ -41,38 +42,38 @@ BOOST_AUTO_TEST_CASE (ratio_test) Ratio const * r = Ratio::from_id ("119"); BOOST_CHECK (r); - BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1285, 1080)); + BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), libdcp::Size (2048, 1080)), libdcp::Size (1285, 1080)); r = Ratio::from_id ("133"); BOOST_CHECK (r); - BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1436, 1080)); + BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), libdcp::Size (2048, 1080)), libdcp::Size (1436, 1080)); r = Ratio::from_id ("137"); BOOST_CHECK (r); - BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1480, 1080)); + BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), libdcp::Size (2048, 1080)), libdcp::Size (1480, 1080)); r = Ratio::from_id ("138"); BOOST_CHECK (r); - BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1485, 1080)); + BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), libdcp::Size (2048, 1080)), libdcp::Size (1485, 1080)); r = Ratio::from_id ("166"); BOOST_CHECK (r); - BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1793, 1080)); + BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), libdcp::Size (2048, 1080)), libdcp::Size (1793, 1080)); r = Ratio::from_id ("178"); BOOST_CHECK (r); - BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1920, 1080)); + BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), libdcp::Size (2048, 1080)), libdcp::Size (1920, 1080)); r = Ratio::from_id ("185"); BOOST_CHECK (r); - BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (1998, 1080)); + BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), libdcp::Size (2048, 1080)), libdcp::Size (1998, 1080)); r = Ratio::from_id ("239"); BOOST_CHECK (r); - BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (2048, 858)); + BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), libdcp::Size (2048, 1080)), libdcp::Size (2048, 858)); r = Ratio::from_id ("full-frame"); BOOST_CHECK (r); - BOOST_CHECK_EQUAL (r->size(libdcp::Size (2048, 1080)), libdcp::Size (2048, 1080)); + BOOST_CHECK_EQUAL (fit_ratio_within (r->ratio(), libdcp::Size (2048, 1080)), libdcp::Size (2048, 1080)); }