diff options
| author | Carl Hetherington <cth@carlh.net> | 2018-07-08 00:19:42 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2018-07-08 00:19:42 +0100 |
| commit | 85bd14f4e7dcbfb2005969575788dbfb303bf846 (patch) | |
| tree | bd3d938a75e7a2e7ffedad845dfc2dfde459682a | |
| parent | ba5915461f1622715a69fa25579e5e27e64fb079 (diff) | |
Basic interop bitmap writing.
| -rw-r--r-- | src/interop_subtitle_asset.cc | 16 | ||||
| -rw-r--r-- | src/object.h | 2 | ||||
| -rw-r--r-- | src/subtitle.h | 4 | ||||
| -rw-r--r-- | src/subtitle_asset.cc | 10 | ||||
| -rw-r--r-- | src/subtitle_asset_internal.cc | 54 | ||||
| -rw-r--r-- | src/subtitle_asset_internal.h | 27 | ||||
| -rw-r--r-- | src/subtitle_string.h | 4 | ||||
| -rw-r--r-- | test/data/sub.png | bin | 0 -> 44935 bytes | |||
| -rw-r--r-- | test/data/write_interop_subtitle_test3.xml | 2 | ||||
| -rw-r--r-- | test/write_subtitle_test.cc | 41 |
10 files changed, 136 insertions, 24 deletions
diff --git a/src/interop_subtitle_asset.cc b/src/interop_subtitle_asset.cc index 7d3114c3..02e2d75b 100644 --- a/src/interop_subtitle_asset.cc +++ b/src/interop_subtitle_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -33,11 +33,13 @@ #include "interop_subtitle_asset.h" #include "interop_load_font_node.h" +#include "subtitle_asset_internal.h" #include "xml.h" #include "raw_convert.h" #include "util.h" #include "font_asset.h" #include "dcp_assert.h" +#include "subtitle_image.h" #include <libxml++/libxml++.h> #include <boost/foreach.hpp> #include <cmath> @@ -63,7 +65,7 @@ InteropSubtitleAsset::InteropSubtitleAsset (boost::filesystem::path file) _reel_number = xml->string_child ("ReelNumber"); _language = xml->string_child ("Language"); _movie_title = xml->string_child ("MovieTitle"); - _load_font_nodes = type_children<dcp::InteropLoadFontNode> (xml, "LoadFont"); + _load_font_nodes = type_children<InteropLoadFontNode> (xml, "LoadFont"); /* Now we need to drop down to xmlpp */ @@ -174,6 +176,16 @@ InteropSubtitleAsset::write (boost::filesystem::path p) const _file = p; + /* Image subtitles */ + int n = 0; + BOOST_FOREACH (shared_ptr<dcp::Subtitle> i, _subtitles) { + shared_ptr<dcp::SubtitleImage> im = dynamic_pointer_cast<dcp::SubtitleImage> (i); + if (im) { + im->png_image().write (p.parent_path() / image_subtitle_file (n++)); + } + } + + /* Fonts */ BOOST_FOREACH (shared_ptr<InteropLoadFontNode> i, _load_font_nodes) { boost::filesystem::path file = p.parent_path() / i->uri; FILE* f = fopen_boost (file, "wb"); diff --git a/src/object.h b/src/object.h index 50817051..b2d0ad35 100644 --- a/src/object.h +++ b/src/object.h @@ -43,6 +43,7 @@ class write_interop_subtitle_test; class write_interop_subtitle_test2; +class write_interop_subtitle_test3; class write_smpte_subtitle_test; class write_smpte_subtitle_test2; @@ -66,6 +67,7 @@ public: protected: friend struct ::write_interop_subtitle_test; friend struct ::write_interop_subtitle_test2; + friend struct ::write_interop_subtitle_test3; friend struct ::write_smpte_subtitle_test; friend struct ::write_smpte_subtitle_test2; diff --git a/src/subtitle.h b/src/subtitle.h index 8dba299d..ed63983f 100644 --- a/src/subtitle.h +++ b/src/subtitle.h @@ -113,11 +113,11 @@ public: _v_position = p; } - void set_fade_up_time (dcp::Time t) { + void set_fade_up_time (Time t) { _fade_up_time = t; } - void set_fade_down_time (dcp::Time t) { + void set_fade_down_time (Time t) { _fade_down_time = t; } diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc index 3ecd16a7..f93ffa85 100644 --- a/src/subtitle_asset.cc +++ b/src/subtitle_asset.cc @@ -549,7 +549,6 @@ SubtitleAsset::subtitles_as_xml (xmlpp::Element* xml_root, int time_code_rate, S } shared_ptr<SubtitleString> is = dynamic_pointer_cast<SubtitleString>(i); - if (is) { if (!text || last_h_align != is->h_align() || @@ -571,7 +570,13 @@ SubtitleAsset::subtitles_as_xml (xmlpp::Element* xml_root, int time_code_rate, S text->children.push_back (shared_ptr<order::String> (new order::String (text, order::Font (is, standard), is->text()))); } - /* XXX: image */ + shared_ptr<SubtitleImage> ii = dynamic_pointer_cast<SubtitleImage>(i); + if (ii) { + text.reset (); + subtitle->children.push_back ( + shared_ptr<order::Image> (new order::Image (subtitle, ii->png_image(), ii->h_align(), ii->h_position(), ii->v_align(), ii->v_position())) + ); + } } /* Pull font changes as high up the hierarchy as we can */ @@ -584,6 +589,7 @@ SubtitleAsset::subtitles_as_xml (xmlpp::Element* xml_root, int time_code_rate, S context.time_code_rate = time_code_rate; context.standard = standard; context.spot_number = 1; + context.image_number = 0; root->write_xml (xml_root, context); } diff --git a/src/subtitle_asset_internal.cc b/src/subtitle_asset_internal.cc index c525256d..13bdf6ab 100644 --- a/src/subtitle_asset_internal.cc +++ b/src/subtitle_asset_internal.cc @@ -33,6 +33,7 @@ #include "subtitle_asset_internal.h" #include "subtitle_string.h" +#include "compose.hpp" #include <cmath> using std::string; @@ -145,38 +146,36 @@ order::Part::write_xml (xmlpp::Element* parent, order::Context& context) const } } -xmlpp::Element* -order::Text::as_xml (xmlpp::Element* parent, Context& context) const +static void +position_align (xmlpp::Element* e, order::Context& context, HAlign h_align, float h_position, VAlign v_align, float v_position) { - xmlpp::Element* e = parent->add_child ("Text", context.xmlns()); - - if (_h_align != HALIGN_CENTER) { + if (h_align != HALIGN_CENTER) { if (context.standard == SMPTE) { - e->set_attribute ("Halign", halign_to_string (_h_align)); + e->set_attribute ("Halign", halign_to_string (h_align)); } else { - e->set_attribute ("HAlign", halign_to_string (_h_align)); + e->set_attribute ("HAlign", halign_to_string (h_align)); } } - if (fabs(_h_position) > ALIGN_EPSILON) { + if (fabs(h_position) > ALIGN_EPSILON) { if (context.standard == SMPTE) { - e->set_attribute ("Hposition", raw_convert<string> (_h_position * 100, 6)); + e->set_attribute ("Hposition", raw_convert<string> (h_position * 100, 6)); } else { - e->set_attribute ("HPosition", raw_convert<string> (_h_position * 100, 6)); + e->set_attribute ("HPosition", raw_convert<string> (h_position * 100, 6)); } } if (context.standard == SMPTE) { - e->set_attribute ("Valign", valign_to_string (_v_align)); + e->set_attribute ("Valign", valign_to_string (v_align)); } else { - e->set_attribute ("VAlign", valign_to_string (_v_align)); + e->set_attribute ("VAlign", valign_to_string (v_align)); } - if (fabs(_v_position) > ALIGN_EPSILON) { + if (fabs(v_position) > ALIGN_EPSILON) { if (context.standard == SMPTE) { - e->set_attribute ("Vposition", raw_convert<string> (_v_position * 100, 6)); + e->set_attribute ("Vposition", raw_convert<string> (v_position * 100, 6)); } else { - e->set_attribute ("VPosition", raw_convert<string> (_v_position * 100, 6)); + e->set_attribute ("VPosition", raw_convert<string> (v_position * 100, 6)); } } else { if (context.standard == SMPTE) { @@ -185,6 +184,14 @@ order::Text::as_xml (xmlpp::Element* parent, Context& context) const e->set_attribute ("VPosition", "0"); } } +} + +xmlpp::Element* +order::Text::as_xml (xmlpp::Element* parent, Context& context) const +{ + xmlpp::Element* e = parent->add_child ("Text", context.xmlns()); + + position_align (e, context, _h_align, _h_position, _v_align, _v_position); /* Interop only supports "horizontal" or "vertical" for direction, so only write this for SMPTE. @@ -224,3 +231,20 @@ order::Font::clear () { _values.clear (); } + +xmlpp::Element * +order::Image::as_xml (xmlpp::Element* parent, Context& context) const +{ + xmlpp::Element* e = parent->add_child ("Image", context.xmlns()); + + position_align (e, context, _h_align, _h_position, _v_align, _v_position); + e->add_child_text (image_subtitle_file (context.image_number++)); + + return e; +} + +string +dcp::image_subtitle_file (int n) +{ + return String::compose ("sub_%1.png", n); +} diff --git a/src/subtitle_asset_internal.h b/src/subtitle_asset_internal.h index fad65a91..e2b1602e 100644 --- a/src/subtitle_asset_internal.h +++ b/src/subtitle_asset_internal.h @@ -37,6 +37,7 @@ #include "raw_convert.h" #include "types.h" #include "dcp_time.h" +#include "data.h" #include <libxml++/libxml++.h> #include <boost/foreach.hpp> @@ -59,6 +60,7 @@ struct Context int time_code_rate; Standard standard; int spot_number; + int image_number; }; class Font @@ -163,7 +165,32 @@ private: Time _fade_down; }; +class Image : public Part +{ +public: + Image (boost::shared_ptr<Part> parent, Data png_data, HAlign h_align, float h_position, VAlign v_align, float v_position) + : Part (parent) + , _png_data (png_data) + , _h_align (h_align) + , _h_position (h_position) + , _v_align (v_align) + , _v_position (v_position) + {} + + xmlpp::Element* as_xml (xmlpp::Element* parent, Context& context) const; + +private: + Data _png_data; + HAlign _h_align; + float _h_position; + VAlign _v_align; + float _v_position; +}; + } + +std::string image_subtitle_file (int n); + } #endif diff --git a/src/subtitle_string.h b/src/subtitle_string.h index 08e4da5d..c274152b 100644 --- a/src/subtitle_string.h +++ b/src/subtitle_string.h @@ -137,7 +137,7 @@ public: _text = t; } - void set_colour (dcp::Colour c) { + void set_colour (Colour c) { _colour = c; } @@ -145,7 +145,7 @@ public: _effect = e; } - void set_effect_colour (dcp::Colour c) { + void set_effect_colour (Colour c) { _effect_colour = c; } diff --git a/test/data/sub.png b/test/data/sub.png Binary files differnew file mode 100644 index 00000000..89b53cf2 --- /dev/null +++ b/test/data/sub.png diff --git a/test/data/write_interop_subtitle_test3.xml b/test/data/write_interop_subtitle_test3.xml new file mode 100644 index 00000000..e92685b8 --- /dev/null +++ b/test/data/write_interop_subtitle_test3.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<DCSubtitle Version="1.0"><SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID><MovieTitle>Test</MovieTitle><ReelNumber>1</ReelNumber><Language>EN</Language><Subtitle SpotNumber="1" TimeIn="00:04:09:229" TimeOut="00:04:11:229" FadeUpTime="0" FadeDownTime="0"><Image VAlign="top" VPosition="80">sub_0.png</Image></Subtitle></DCSubtitle> diff --git a/test/write_subtitle_test.cc b/test/write_subtitle_test.cc index c8f8fc57..dec815c0 100644 --- a/test/write_subtitle_test.cc +++ b/test/write_subtitle_test.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2015-2016 Carl Hetherington <cth@carlh.net> + Copyright (C) 2015-2018 Carl Hetherington <cth@carlh.net> This file is part of libdcp. @@ -20,8 +20,10 @@ #include "interop_subtitle_asset.h" #include "smpte_subtitle_asset.h" #include "subtitle_string.h" +#include "subtitle_image.h" #include "subtitle_asset_internal.h" #include "test.h" +#include "util.h" #include <boost/test/unit_test.hpp> using std::list; @@ -307,6 +309,43 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test2) ); } +/* Write some subtitle content as Interop XML using bitmaps and check that it is right */ +BOOST_AUTO_TEST_CASE (write_interop_subtitle_test3) +{ + dcp::InteropSubtitleAsset c; + c.set_reel_number ("1"); + c.set_language ("EN"); + c.set_movie_title ("Test"); + + c.add ( + shared_ptr<dcp::Subtitle> ( + new dcp::SubtitleImage ( + dcp::Data ("test/data/sub.png"), + dcp::Time (0, 4, 9, 22, 24), + dcp::Time (0, 4, 11, 22, 24), + 0, + dcp::HALIGN_CENTER, + 0.8, + dcp::VALIGN_TOP, + dcp::Time (0, 0, 0, 0, 24), + dcp::Time (0, 0, 0, 0, 24) + ) + ) + ); + + c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6"; + + boost::filesystem::create_directories ("build/test/write_interop_subtitle_test3"); + c.write ("build/test/write_interop_subtitle_test3/subs.xml"); + + check_xml ( + dcp::file_to_string("test/data/write_interop_subtitle_test3.xml"), + dcp::file_to_string("build/test/write_interop_subtitle_test3/subs.xml"), + list<string>() + ); + check_file ("build/test/write_interop_subtitle_test3/sub_0.png", "test/data/sub.png"); +} + /* Write some subtitle content as SMPTE XML and check that it is right */ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test) { |
