diff options
| author | Carl Hetherington <cth@carlh.net> | 2025-03-19 17:20:23 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2025-03-19 21:11:17 +0100 |
| commit | 0692355b1e4d29b1ccb6e4b83554ffec342a74ad (patch) | |
| tree | d5ca5507a01ef9e4cf3f6d496a0ae25876540638 | |
| parent | 51c9af29b6a0b7914e8bfc9e04106887a1514efd (diff) | |
Add --auto-crop option to create CLI (#2968).
| -rw-r--r-- | doc/manual/dcpomatic_create.xml | 1 | ||||
| -rw-r--r-- | src/lib/create_cli.cc | 33 | ||||
| -rw-r--r-- | src/lib/create_cli.h | 1 | ||||
| -rw-r--r-- | test/create_cli_test.cc | 27 |
4 files changed, 60 insertions, 2 deletions
diff --git a/doc/manual/dcpomatic_create.xml b/doc/manual/dcpomatic_create.xml index ba98c878d..516b806ff 100644 --- a/doc/manual/dcpomatic_create.xml +++ b/doc/manual/dcpomatic_create.xml @@ -22,6 +22,7 @@ <listitem><code>--j2k-bandwidth <Mbit/s></code> — J2K bandwidth in Mbit/s</listitem> <listitem><code>--left-eye</code> — next piece of content is for the left eye</listitem> <listitem><code>--right-eye</code> — next piece of content is for the right eye</listitem> +<listitem><code>--auto-crop</code> — next piece of content should be auto-cropped</listitem> <listitem><code>--channel <channel></code> — next piece of content should be mapped to audio channel L, R, C, Lfe, Ls, Rs, BsL, BsR, HI, VI</listitem> <listitem><code>--gain</code> — next piece of content should have the given audio gain (in dB)</listitem> <listitem><code>--cpl <id></code> — CPL ID to use from the next piece of content (which is a DCP)</listitem> diff --git a/src/lib/create_cli.cc b/src/lib/create_cli.cc index c7a49ada9..96a889bc4 100644 --- a/src/lib/create_cli.cc +++ b/src/lib/create_cli.cc @@ -30,6 +30,7 @@ #include "dcpomatic_log.h" #include "film.h" #include "image_content.h" +#include "guess_crop.h" #include "job_manager.h" #include "ratio.h" #include "variant.h" @@ -73,6 +74,7 @@ string CreateCLI::_help = " --j2k-bandwidth <Mbit/s> J2K bandwidth in Mbit/s\n" " --left-eye next piece of content is for the left eye\n" " --right-eye next piece of content is for the right eye\n" + " --auto-crop next piece of content should be auto-cropped\n" " --channel <channel> next piece of content should be mapped to audio channel L, R, C, Lfe, Ls, Rs, BsL, BsR, HI, VI\n" " --gain next piece of content should have the given audio gain (in dB)\n" " --cpl <id> CPL ID to use from the next piece of content (which is a DCP)\n" @@ -165,6 +167,7 @@ CreateCLI::CreateCLI(int argc, char* argv[]) int64_t video_bit_rate_int = 0; optional<int> audio_channels; auto next_frame_type = VideoFrameType::TWO_D; + auto next_auto_crop = false; optional<dcp::Channel> channel; optional<float> gain; optional<boost::filesystem::path> kdm; @@ -201,6 +204,9 @@ CreateCLI::CreateCLI(int argc, char* argv[]) } else if (a == "--right-eye") { next_frame_type = VideoFrameType::THREE_D_RIGHT; claimed = true; + } else if (a == "--auto-crop") { + next_auto_crop = true; + claimed = true; } else if (a == "--twok") { _twok = true; claimed = true; @@ -288,12 +294,14 @@ CreateCLI::CreateCLI(int argc, char* argv[]) Content c; c.path = a; c.frame_type = next_frame_type; + c.auto_crop = next_auto_crop; c.channel = channel; c.gain = gain; c.kdm = kdm; c.cpl = cpl; content.push_back(c); next_frame_type = VideoFrameType::TWO_D; + next_auto_crop = false; channel = {}; gain = {}; } @@ -477,6 +485,31 @@ CreateCLI::make_film(function<void (string)> error) const for (auto film_content: film_content_list) { if (film_content->video) { film_content->video->set_frame_type(cli_content.frame_type); + if (cli_content.auto_crop) { + auto crop = guess_crop_by_brightness( + film, + film_content, + Config::instance()->auto_crop_threshold(), + std::min( + dcpomatic::ContentTime::from_seconds(1), + dcpomatic::ContentTime::from_frames( + film_content->video->length(), + film_content->video_frame_rate().get_value_or(24) + ) + ) + ); + + error(fmt::format( + "Cropped {} to {} left, {} right, {} top and {} bottom", + film_content->path(0).string(), + crop.left, + crop.right, + crop.top, + crop.bottom + )); + + film_content->video->set_crop(crop); + } } if (film_content->audio && cli_content.channel) { for (auto stream: film_content->audio->streams()) { diff --git a/src/lib/create_cli.h b/src/lib/create_cli.h index 1ce345f1b..875fe10c1 100644 --- a/src/lib/create_cli.h +++ b/src/lib/create_cli.h @@ -41,6 +41,7 @@ public: struct Content { boost::filesystem::path path; VideoFrameType frame_type = VideoFrameType::TWO_D; + bool auto_crop = false; boost::optional<dcp::Channel> channel; boost::optional<float> gain; boost::optional<boost::filesystem::path> kdm; diff --git a/test/create_cli_test.cc b/test/create_cli_test.cc index 9716fbef3..6499ef160 100644 --- a/test/create_cli_test.cc +++ b/test/create_cli_test.cc @@ -20,11 +20,14 @@ #include "lib/config.h" +#include "lib/content.h" #include "lib/create_cli.h" +#include "lib/dcp_content_type.h" #include "lib/film.h" #include "lib/ratio.h" -#include "lib/dcp_content_type.h" +#include "lib/video_content.h" #include "test.h" +#include <fmt/format.h> #include <boost/test/unit_test.hpp> #include <boost/tokenizer.hpp> #include <boost/algorithm/string/predicate.hpp> @@ -186,6 +189,26 @@ BOOST_AUTO_TEST_CASE (create_cli_test) BOOST_CHECK_EQUAL(cc._fourk, true); BOOST_CHECK (!cc.error); + cc = run("dcpomatic2_create --auto-crop foo.mp4 bar.mp4 --auto-crop baz.mp4"); + BOOST_REQUIRE_EQUAL(cc.content.size(), 3U); + BOOST_CHECK(cc.content[0].auto_crop); + BOOST_CHECK(!cc.content[1].auto_crop); + BOOST_CHECK(cc.content[2].auto_crop); + + cc = run("dcpomatic2_create --auto-crop foo.mp4 bar.mp4 --auto-crop baz.mp4"); + BOOST_REQUIRE_EQUAL(cc.content.size(), 3U); + BOOST_CHECK(cc.content[0].auto_crop); + BOOST_CHECK(!cc.content[1].auto_crop); + BOOST_CHECK(cc.content[2].auto_crop); + + auto pillarbox = TestPaths::private_data() / "pillarbox.png"; + cc = run("dcpomatic2_create --auto-crop " + pillarbox.string()); + auto film = cc.make_film(error); + BOOST_CHECK_EQUAL(film->content().size(), 1U); + BOOST_CHECK(film->content()[0]->video->actual_crop() == Crop(113, 262, 0, 0)); + BOOST_CHECK_EQUAL(collected_error, fmt::format("Cropped {} to 113 left, 262 right, 0 top and 0 bottom", pillarbox.string())); + collected_error = ""; + cc = run ("dcpomatic2_create --video-bit-rate 120 foo.mp4"); BOOST_REQUIRE_EQUAL (cc.content.size(), 1U); BOOST_CHECK_EQUAL (cc.content[0].path, "foo.mp4"); @@ -203,7 +226,7 @@ BOOST_AUTO_TEST_CASE (create_cli_test) BOOST_CHECK (*cc.content[1].channel == dcp::Channel::RIGHT); BOOST_CHECK_EQUAL (cc.content[2].path, "test/data/Lfe.wav"); BOOST_CHECK (!cc.content[2].channel); - auto film = cc.make_film(out, error); + film = cc.make_film(error); BOOST_CHECK_EQUAL(film->audio_channels(), 6); BOOST_CHECK(collected_error.empty()); |
