+2016-02-26 Carl Hetherington <cth@carlh.net>
+
+ * Allow changes to colours of subtitles embedded
+ into video files (#795).
+
2016-02-25 Carl Hetherington <cth@carlh.net>
* Plot all video and subtitle content on single tracks
p.push_back (UserProperty (_("Video"), _("Bits per pixel"), raw_convert<string> (_bits_per_pixel.get ())));
}
}
+
+/** Our subtitle streams have colour maps, which can be changed, but
+ * they have no way of signalling that change. As a hack, we have this
+ * method which callers can use when they've modified one of our subtitle
+ * streams.
+ */
+void
+FFmpegContent::signal_subtitle_stream_changed ()
+{
+ signal_changed (FFmpegContentProperty::SUBTITLE_STREAM);
+}
{
public:
static int const SUBTITLE_STREAMS;
+ /** The chosen subtitle stream, or something about it */
static int const SUBTITLE_STREAM;
static int const FILTERS;
};
std::list<ContentTimePeriod> image_subtitles_during (ContentTimePeriod, bool starting) const;
std::list<ContentTimePeriod> text_subtitles_during (ContentTimePeriod, bool starting) const;
+ void signal_subtitle_stream_changed ();
+
protected:
void add_properties (std::list<UserProperty> &) const;
using std::min;
using std::pair;
using std::max;
+using std::map;
using boost::shared_ptr;
using boost::is_any_of;
using boost::split;
(i.e. first byte B, second G, third R, fourth A)
*/
uint32_t const * palette = (uint32_t *) rect->pict.data[1];
+ /* And the stream has a map of those palette colours to colours
+ chosen by the user; created a `mapped' palette from those settings.
+ */
+ map<RGBA, RGBA> colour_map = ffmpeg_content()->subtitle_stream()->colours ();
+ vector<RGBA> mapped_palette (rect->nb_colors);
+ for (int i = 0; i < rect->nb_colors; ++i) {
+ RGBA c ((palette[i] & 0xff0000) >> 16, (palette[i] & 0xff00) >> 8, palette[i] & 0xff, (palette[i] & 0xff000000) >> 24);
+ DCPOMATIC_ASSERT (colour_map.find(c) != colour_map.end());
+ mapped_palette[i] = colour_map[c];
+ }
+
/* Start of the output data */
uint32_t* out_p = (uint32_t *) image->data()[0];
uint8_t* sub_line_p = sub_p;
uint32_t* out_line_p = out_p;
for (int x = 0; x < rect->w; ++x) {
- uint32_t const p = palette[*sub_line_p++];
- *out_line_p++ = ((p & 0xff) << 16) | (p & 0xff00) | ((p & 0xff0000) >> 16) | (p & 0xff000000);
+ RGBA const p = mapped_palette[*sub_line_p++];
+ /* XXX: this seems to be wrong to me (isn't the output image RGBA?) but it looks right on screen */
+ *out_line_p++ = (p.a << 24) | (p.r << 16) | (p.g << 8) | p.b;
}
sub_p += rect->pict.linesize[0];
out_p += image->stride()[0] / sizeof (uint32_t);
_last_subtitle_start[stream] = SubtitleStart (id, image, period.from);
}
}
+
+ for (unsigned int i = 0; i < sub.num_rects; ++i) {
+ if (sub.rects[i]->type == SUBTITLE_BITMAP) {
+ uint32_t* palette = (uint32_t *) sub.rects[i]->pict.data[1];
+ for (int j = 0; j < sub.rects[i]->nb_colors; ++j) {
+ RGBA rgba (
+ (palette[j] & 0x00ff0000) >> 16,
+ (palette[j] & 0x0000ff00) >> 8,
+ (palette[j] & 0x000000ff) >> 0,
+ (palette[j] & 0xff000000) >> 24
+ );
+
+ stream->set_colour (rgba, rgba);
+ }
+ }
+ }
+
avsubtitle_free (&sub);
}
}
/*
- Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
using std::map;
using std::list;
using std::cout;
+using std::make_pair;
/** Construct a SubtitleStream from a value returned from to_string().
* @param t String returned from to_string().
)
);
}
+
+ BOOST_FOREACH (cxml::NodePtr i, node->node_children ("Colour")) {
+ _colours[RGBA(i->node_child("From"))] = RGBA (i->node_child("To"));
+ }
}
}
as_xml (root, _image_subtitles, "ImageSubtitle");
as_xml (root, _text_subtitles, "TextSubtitle");
+
+ for (map<RGBA, RGBA>::const_iterator i = _colours.begin(); i != _colours.end(); ++i) {
+ xmlpp::Node* node = root->add_child("Colour");
+ i->first.as_xml (node->add_child("From"));
+ i->second.as_xml (node->add_child("To"));
+ }
}
void
i->second.to += offset;
}
}
+
+map<RGBA, RGBA>
+FFmpegSubtitleStream::colours () const
+{
+ return _colours;
+}
+
+void
+FFmpegSubtitleStream::set_colour (RGBA from, RGBA to)
+{
+ _colours[from] = to;
+}
*/
#include "dcpomatic_time.h"
+#include "rgba.h"
#include "ffmpeg_stream.h"
class FFmpegSubtitleStream : public FFmpegStream
std::list<ContentTimePeriod> text_subtitles_during (ContentTimePeriod period, bool starting) const;
ContentTime find_subtitle_to (std::string id) const;
void add_offset (ContentTime offset);
+ void set_colour (RGBA from, RGBA to);
bool has_image_subtitles () const {
return !_image_subtitles.empty ();
bool has_text_subtitles () const {
return !_text_subtitles.empty ();
}
+ std::map<RGBA, RGBA> colours () const;
private:
PeriodMap _image_subtitles;
PeriodMap _text_subtitles;
+ std::map<RGBA, RGBA> _colours;
};
property == DCPContentProperty::CAN_BE_PLAYED ||
property == TextSubtitleContentProperty::TEXT_SUBTITLE_COLOUR ||
property == TextSubtitleContentProperty::TEXT_SUBTITLE_OUTLINE ||
- property == TextSubtitleContentProperty::TEXT_SUBTITLE_OUTLINE_COLOUR
+ property == TextSubtitleContentProperty::TEXT_SUBTITLE_OUTLINE_COLOUR ||
+ property == FFmpegContentProperty::SUBTITLE_STREAM
) {
_have_valid_pieces = false;
--- /dev/null
+/*
+ Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "rgba.h"
+#include <libxml++/libxml++.h>
+#include <boost/lexical_cast.hpp>
+
+using std::string;
+using boost::lexical_cast;
+
+RGBA::RGBA (cxml::ConstNodePtr node)
+{
+ r = node->number_child<int> ("R");
+ g = node->number_child<int> ("G");
+ b = node->number_child<int> ("B");
+ a = node->number_child<int> ("A");
+}
+
+void
+RGBA::as_xml (xmlpp::Node* parent) const
+{
+ parent->add_child("R")->add_child_text (lexical_cast<string> (int (r)));
+ parent->add_child("G")->add_child_text (lexical_cast<string> (int (g)));
+ parent->add_child("B")->add_child_text (lexical_cast<string> (int (b)));
+ parent->add_child("A")->add_child_text (lexical_cast<string> (int (a)));
+}
+
+bool
+RGBA::operator< (RGBA const & other) const
+{
+ if (r != other.r) {
+ return r < other.r;
+ }
+
+ if (g != other.g) {
+ return g < other.g;
+ }
+
+ if (b != other.b) {
+ return b < other.b;
+ }
+
+ return a < other.a;
+}
--- /dev/null
+/*
+ Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef DCPOMATIC_RGBA_H
+#define DCPOMATIC_RGBA_H
+
+#include <libcxml/cxml.h>
+#include <stdint.h>
+
+/** @class RGBA
+ * @brief A 32-bit RGBA colour.
+ */
+
+class RGBA
+{
+public:
+ RGBA ()
+ : r (0)
+ , g (0)
+ , b (0)
+ , a (0)
+ {}
+
+ RGBA (uint8_t r_, uint8_t g_, uint8_t b_, uint8_t a_)
+ : r (r_)
+ , g (g_)
+ , b (b_)
+ , a (a_)
+ {}
+
+ RGBA (cxml::ConstNodePtr node);
+
+ void as_xml (xmlpp::Node* parent) const;
+
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+ uint8_t a;
+
+ bool operator< (RGBA const & other) const;
+};
+
+#endif
reel_writer.cc
render_subtitles.cc
resampler.cc
+ rgba.cc
safe_stringstream.cc
scoped_temporary.cc
scp_uploader.cc
--- /dev/null
+/*
+ Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "image_subtitle_colour_dialog.h"
+#include "rgba_colour_picker.h"
+#include "lib/ffmpeg_subtitle_stream.h"
+#include "lib/ffmpeg_content.h"
+
+using std::map;
+using std::cout;
+using boost::shared_ptr;
+
+ImageSubtitleColourDialog::ImageSubtitleColourDialog (wxWindow* parent, shared_ptr<FFmpegContent> content, shared_ptr<FFmpegSubtitleStream> stream)
+ : TableDialog (parent, _("Subtitle colours"), 2, 1, true)
+ , _content (content)
+ , _stream (stream)
+{
+ map<RGBA, RGBA> colours = _stream->colours ();
+
+ wxStaticText* t = new wxStaticText (this, wxID_ANY, "");
+ t->SetLabelMarkup (_("<b>Original colour</b>"));
+ add (t);
+ t = new wxStaticText (this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL);
+ t->SetLabelMarkup (_("<b>New colour</b>"));
+ add (t, 1, wxALIGN_CENTER);
+
+ for (map<RGBA, RGBA>::const_iterator i = colours.begin(); i != colours.end(); ++i) {
+ wxPanel* from = new wxPanel (this, wxID_ANY);
+ from->SetBackgroundColour (wxColour (i->first.r, i->first.g, i->first.b, i->first.a));
+ add (from);
+ RGBAColourPicker* to = new RGBAColourPicker (this, i->second);
+ add (to);
+ _pickers[i->first] = to;
+ }
+
+ layout ();
+}
+
+void
+ImageSubtitleColourDialog::apply ()
+{
+ for (map<RGBA, RGBAColourPicker*>::const_iterator i = _pickers.begin(); i != _pickers.end(); ++i) {
+ _stream->set_colour (i->first, i->second->colour ());
+ }
+
+ _content->signal_subtitle_stream_changed ();
+}
--- /dev/null
+/*
+ Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "table_dialog.h"
+#include "lib/rgba.h"
+#include <map>
+
+class RGBAColourPicker;
+class FFmpegContent;
+class FFmpegSubtitleStream;
+
+class ImageSubtitleColourDialog : public TableDialog
+{
+public:
+ ImageSubtitleColourDialog (wxWindow* parent, boost::shared_ptr<FFmpegContent> content, boost::shared_ptr<FFmpegSubtitleStream> stream);
+
+ void apply ();
+
+private:
+ boost::shared_ptr<FFmpegContent> _content;
+ boost::shared_ptr<FFmpegSubtitleStream> _stream;
+ std::map<RGBA, RGBAColourPicker*> _pickers;
+};
--- /dev/null
+/*
+ Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "rgba_colour_picker.h"
+#include "wx_util.h"
+#include <wx/clrpicker.h>
+
+RGBAColourPicker::RGBAColourPicker (wxWindow* parent, RGBA colour)
+ : wxPanel (parent, wxID_ANY)
+{
+ wxBoxSizer* sizer = new wxBoxSizer (wxHORIZONTAL);
+
+ _picker = new wxColourPickerCtrl (this, wxID_ANY);
+ _picker->SetColour (wxColour (colour.r, colour.g, colour.b));
+ sizer->Add (_picker, 1, wxEXPAND | wxALL, DCPOMATIC_SIZER_X_GAP);
+ sizer->Add (new wxStaticText (this, wxID_ANY, _("Alpha 0")), 0, wxALIGN_CENTRE_VERTICAL);
+ _alpha = new wxSlider (this, wxID_ANY, colour.a, 0, 255);
+ sizer->Add (_alpha, 1, wxEXPAND | wxALL, DCPOMATIC_SIZER_X_GAP);
+ sizer->Add (new wxStaticText (this, wxID_ANY, _("255")), 0, wxALIGN_CENTRE_VERTICAL);
+
+ SetSizer (sizer);
+}
+
+RGBA
+RGBAColourPicker::colour () const
+{
+ wxColour const c = _picker->GetColour ();
+ return RGBA (c.Red(), c.Green(), c.Blue(), _alpha->GetValue());
+}
--- /dev/null
+/*
+ Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "lib/rgba.h"
+#include <wx/wx.h>
+
+class wxColourPickerCtrl;
+class wxSlider;
+
+class RGBAColourPicker : public wxPanel
+{
+public:
+ RGBAColourPicker (wxWindow* parent, RGBA colour);
+
+ RGBA colour () const;
+
+private:
+ wxColourPickerCtrl* _picker;
+ wxSlider* _alpha;
+};
#include "content_panel.h"
#include "fonts_dialog.h"
#include "text_subtitle_appearance_dialog.h"
+#include "image_subtitle_colour_dialog.h"
#include "lib/ffmpeg_content.h"
#include "lib/text_subtitle_content.h"
#include "lib/ffmpeg_subtitle_stream.h"
_stream->Enable (!reference && ffmpeg_subs == 1);
_subtitle_view_button->Enable (!reference && (text_subs == 1 || dcp_subs == 1));
_fonts_dialog_button->Enable (!reference && (text_subs == 1 || dcp_subs == 1));
- _appearance_dialog_button->Enable (!reference && text_subs == 1);
+ _appearance_dialog_button->Enable (!reference && (ffmpeg_subs == 1 || text_subs == 1));
}
void
DCPOMATIC_ASSERT (c.size() == 1);
shared_ptr<TextSubtitleContent> sr = dynamic_pointer_cast<TextSubtitleContent> (c.front ());
- DCPOMATIC_ASSERT (sr);
-
- TextSubtitleAppearanceDialog* d = new TextSubtitleAppearanceDialog (this, sr);
- if (d->ShowModal () == wxID_OK) {
- d->apply ();
+ if (sr) {
+ TextSubtitleAppearanceDialog* d = new TextSubtitleAppearanceDialog (this, sr);
+ if (d->ShowModal () == wxID_OK) {
+ d->apply ();
+ }
+ d->Destroy ();
+ } else {
+ shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (c.front ());
+ DCPOMATIC_ASSERT (fc);
+ ImageSubtitleColourDialog* d = new ImageSubtitleColourDialog (this, fc, fc->subtitle_stream ());
+ if (d->ShowModal() == wxID_OK) {
+ d->apply ();
+ }
+ d->Destroy ();
}
- d->Destroy ();
}
class wxSpinCtrl;
class SubtitleView;
class FontsDialog;
-class SubtitleAppearanceDialog;
class SubtitlePanel : public ContentSubPanel
{
protected:
template<class T>
- T* add (T* w) {
- _table->Add (w, 1, wxEXPAND);
+ T* add (T* w, int proportion = 1, int flag = wxEXPAND) {
+ _table->Add (w, proportion, flag);
return w;
}
dcp_panel.cc
email_dialog.cc
image_sequence_dialog.cc
+ image_subtitle_colour_dialog.cc
isdcf_metadata_dialog.cc
dir_picker_ctrl.cc
dolby_doremi_certificate_panel.cc
preset_colour_conversion_dialog.cc
repeat_dialog.cc
report_problem_dialog.cc
+ rgba_colour_picker.cc
screen_dialog.cc
screens_panel.cc
self_dkdm_dialog.cc