summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2012-10-11 21:54:52 +0100
committerCarl Hetherington <cth@carlh.net>2012-10-11 21:54:52 +0100
commitf78ce22dc46e42e4f041ebf877fd7199232e4856 (patch)
tree0e2a4a2c3cd3618ca32d14696437993b21d9c23b /src
parenta8b56b931203f984ae7e3f66bc5b9e66d0942199 (diff)
Basic sub offset support.
Diffstat (limited to 'src')
-rw-r--r--src/lib/film.cc14
-rw-r--r--src/lib/film.h12
-rw-r--r--src/lib/film_state.cc6
-rw-r--r--src/lib/film_state.h7
-rw-r--r--src/wx/film_editor.cc53
-rw-r--r--src/wx/film_editor.h4
-rw-r--r--src/wx/film_viewer.cc38
7 files changed, 127 insertions, 7 deletions
diff --git a/src/lib/film.cc b/src/lib/film.cc
index 08ef938d1..e4155c9f6 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -670,6 +670,20 @@ Film::set_with_subtitles (bool w)
signal_changed (WITH_SUBTITLES);
}
+void
+Film::set_subtitle_offset (int o)
+{
+ _state.subtitle_offset = o;
+ signal_changed (SUBTITLE_OFFSET);
+}
+
+void
+Film::set_subtitle_scale (float s)
+{
+ _state.subtitle_scale = s;
+ signal_changed (SUBTITLE_SCALE);
+}
+
list<pair<Position, string> >
Film::thumb_subtitles (int n) const
{
diff --git a/src/lib/film.h b/src/lib/film.h
index 1e01747a2..c006eae36 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -123,6 +123,14 @@ public:
bool with_subtitles () const {
return _state.with_subtitles;
}
+
+ int subtitle_offset () const {
+ return _state.subtitle_offset;
+ }
+
+ float subtitle_scale () const {
+ return _state.subtitle_scale;
+ }
void set_filters (std::vector<Filter const *> const &);
@@ -149,6 +157,8 @@ public:
void set_audio_delay (int);
void set_still_duration (int);
void set_with_subtitles (bool);
+ void set_subtitle_offset (int);
+ void set_subtitle_scale (float);
/** @return size, in pixels, of the source (ignoring cropping) */
Size size () const {
@@ -230,6 +240,8 @@ public:
AUDIO_SAMPLE_RATE,
STILL_DURATION,
WITH_SUBTITLES,
+ SUBTITLE_OFFSET,
+ SUBTITLE_SCALE
};
boost::shared_ptr<FilmState> state_copy () const;
diff --git a/src/lib/film_state.cc b/src/lib/film_state.cc
index 610362dcd..a4d88d0e0 100644
--- a/src/lib/film_state.cc
+++ b/src/lib/film_state.cc
@@ -81,6 +81,8 @@ FilmState::write_metadata (ofstream& f) const
f << "audio_delay " << audio_delay << "\n";
f << "still_duration " << still_duration << "\n";
f << "with_subtitles " << with_subtitles << "\n";
+ f << "subtitle_offset " << subtitle_offset << "\n";
+ f << "subtitle_scale " << subtitle_scale << "\n";
/* Cached stuff; this is information about our content; we could
look it up each time, but that's slow.
@@ -146,6 +148,10 @@ FilmState::read_metadata (string k, string v)
still_duration = atoi (v.c_str ());
} else if (k == "with_subtitles") {
with_subtitles = (v == "1");
+ } else if (k == "subtitle_offset") {
+ subtitle_offset = atoi (v.c_str ());
+ } else if (k == "subtitle_scale") {
+ subtitle_scale = atof (v.c_str ());
}
/* Cached stuff */
diff --git a/src/lib/film_state.h b/src/lib/film_state.h
index 5b3ef8367..d53c6a969 100644
--- a/src/lib/film_state.h
+++ b/src/lib/film_state.h
@@ -63,6 +63,8 @@ public:
, audio_delay (0)
, still_duration (10)
, with_subtitles (false)
+ , subtitle_offset (0)
+ , subtitle_scale (1)
, length (0)
, audio_channels (0)
, audio_sample_rate (0)
@@ -130,6 +132,11 @@ public:
/** Duration to make still-sourced films (in seconds) */
int still_duration;
bool with_subtitles;
+ /** y offset for placing subtitles, in source pixels; +ve is further down
+ the frame, -ve is further up.
+ */
+ int subtitle_offset;
+ float subtitle_scale;
/* Data which is cached to speed things up */
diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc
index 97a98e54d..ae1557c3e 100644
--- a/src/wx/film_editor.cc
+++ b/src/wx/film_editor.cc
@@ -135,6 +135,14 @@ FilmEditor::FilmEditor (Film* f, wxWindow* parent)
_sizer->Add (_with_subtitles, 1);
_sizer->AddSpacer (0);
+ video_control (add_label_to_sizer (_sizer, this, "Subtitle Offset"));
+ _subtitle_offset = new wxSpinCtrl (this);
+ _sizer->Add (video_control (_subtitle_offset), 1);
+
+ video_control (add_label_to_sizer (_sizer, this, "Subtitle Scale"));
+ _subtitle_scale = new wxSpinCtrl (this);
+ _sizer->Add (video_control (_subtitle_scale), 1);
+
video_control (add_label_to_sizer (_sizer, this, "Frames Per Second"));
_frames_per_second = new wxStaticText (this, wxID_ANY, wxT (""));
_sizer->Add (video_control (_frames_per_second), 1, wxALIGN_CENTER_VERTICAL);
@@ -186,6 +194,7 @@ FilmEditor::FilmEditor (Film* f, wxWindow* parent)
_audio_gain->SetRange (-60, 60);
_audio_delay->SetRange (-1000, 1000);
_still_duration->SetRange (0, 60 * 60);
+ _subtitle_offset->SetRange (-1024, 1024);
vector<DCPContentType const *> const ct = DCPContentType::all ();
for (vector<DCPContentType const *>::const_iterator i = ct.begin(); i != ct.end(); ++i) {
@@ -220,6 +229,8 @@ FilmEditor::FilmEditor (Film* f, wxWindow* parent)
_still_duration->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::still_duration_changed), 0, this);
_change_dcp_range_button->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::change_dcp_range_clicked), 0, this);
_with_subtitles->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::with_subtitles_toggled), 0, this);
+ _subtitle_offset->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_offset_changed), 0, this);
+ _subtitle_scale->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_scale_changed), 0, this);
setup_visibility ();
setup_formats ();
@@ -327,6 +338,31 @@ FilmEditor::name_changed (wxCommandEvent &)
_ignore_changes = Film::NONE;
}
+void
+FilmEditor::subtitle_offset_changed (wxCommandEvent &)
+{
+ if (!_film) {
+ return;
+ }
+
+ _ignore_changes = Film::SUBTITLE_OFFSET;
+ _film->set_subtitle_offset (_subtitle_offset->GetValue ());
+ _ignore_changes = Film::NONE;
+}
+
+void
+FilmEditor::subtitle_scale_changed (wxCommandEvent &)
+{
+ if (!_film) {
+ return;
+ }
+
+ _ignore_changes = Film::SUBTITLE_OFFSET;
+ _film->set_subtitle_scale (_subtitle_scale->GetValue ());
+ _ignore_changes = Film::NONE;
+}
+
+
/** Called when the metadata stored in the Film object has changed;
* so that we can update the GUI.
* @param p Property of the Film that has changed.
@@ -447,6 +483,14 @@ FilmEditor::film_changed (Film::Property p)
break;
case Film::WITH_SUBTITLES:
_with_subtitles->SetValue (_film->with_subtitles ());
+ _subtitle_scale->Enable (_film->with_subtitles ());
+ _subtitle_offset->Enable (_film->with_subtitles ());
+ break;
+ case Film::SUBTITLE_OFFSET:
+ _subtitle_offset->SetValue (_film->subtitle_offset ());
+ break;
+ case Film::SUBTITLE_SCALE:
+ _subtitle_scale->SetValue (_film->subtitle_scale ());
break;
}
}
@@ -520,6 +564,9 @@ FilmEditor::set_film (Film* f)
film_changed (Film::AUDIO_GAIN);
film_changed (Film::AUDIO_DELAY);
film_changed (Film::STILL_DURATION);
+ film_changed (Film::WITH_SUBTITLES);
+ film_changed (Film::SUBTITLE_OFFSET);
+ film_changed (Film::SUBTITLE_SCALE);
}
/** Updates the sensitivity of lots of widgets to a given value.
@@ -546,6 +593,9 @@ FilmEditor::set_things_sensitive (bool s)
_audio_gain_calculate_button->Enable (s);
_audio_delay->Enable (s);
_still_duration->Enable (s);
+ _with_subtitles->Enable (s);
+ _subtitle_offset->Enable (s);
+ _subtitle_scale->Enable (s);
}
/** Called when the `Edit filters' button has been clicked */
@@ -724,6 +774,9 @@ FilmEditor::with_subtitles_toggled (wxCommandEvent &)
_ignore_changes = Film::WITH_SUBTITLES;
_film->set_with_subtitles (_with_subtitles->GetValue ());
_ignore_changes = Film::NONE;
+
+ _subtitle_scale->Enable (_film->with_subtitles ());
+ _subtitle_offset->Enable (_film->with_subtitles ());
}
void
diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h
index 720e71902..31d8ad39b 100644
--- a/src/wx/film_editor.h
+++ b/src/wx/film_editor.h
@@ -59,6 +59,8 @@ private:
void audio_gain_calculate_button_clicked (wxCommandEvent &);
void audio_delay_changed (wxCommandEvent &);
void with_subtitles_toggled (wxCommandEvent &);
+ void subtitle_offset_changed (wxCommandEvent &);
+ void subtitle_scale_changed (wxCommandEvent &);
void still_duration_changed (wxCommandEvent &);
/* Handle changes to the model */
@@ -106,6 +108,8 @@ private:
/** The Film's audio delay */
wxSpinCtrl* _audio_delay;
wxCheckBox* _with_subtitles;
+ wxSpinCtrl* _subtitle_offset;
+ wxSpinCtrl* _subtitle_scale;
/** The Film's DCP content type */
wxComboBox* _dcp_content_type;
/** The Film's frames per second */
diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc
index cd043b04e..85632075c 100644
--- a/src/wx/film_viewer.cc
+++ b/src/wx/film_viewer.cc
@@ -42,6 +42,10 @@ public:
ThumbPanel (wxPanel* parent, Film* film)
: wxPanel (parent)
, _film (film)
+ , _current_index (-1)
+ , _pending_index (-1)
+ , _current_subtitle_offset (0)
+ , _pending_subtitle_offset (0)
{
}
@@ -67,6 +71,11 @@ public:
setup ();
}
+ if (_current_subtitle_offset != _pending_subtitle_offset) {
+ _current_subtitle_offset = _pending_subtitle_offset;
+ setup ();
+ }
+
wxPaintDC dc (this);
if (_bitmap) {
dc.DrawBitmap (*_bitmap, 0, 0, false);
@@ -103,6 +112,12 @@ public:
Refresh ();
}
+ void set_subtitle_offset (int o)
+ {
+ _pending_subtitle_offset = o;
+ Refresh ();
+ }
+
void set_film (Film* f)
{
_film = f;
@@ -162,21 +177,25 @@ private:
if ((float (vw) / vh) > target) {
/* view is longer (horizontally) than the ratio; fit height */
_cropped_image.Rescale (vh * target, vh, wxIMAGE_QUALITY_HIGH);
- x_scale = vh * target / _image->GetWidth ();
- y_scale = float (vh) / _image->GetHeight ();
+ x_scale = vh * target / cropped.w;
+ y_scale = float (vh) / cropped.h;
} else {
/* view is shorter (horizontally) than the ratio; fit width */
_cropped_image.Rescale (vw, vw / target, wxIMAGE_QUALITY_HIGH);
- x_scale = float (vw) / _image->GetWidth ();
- y_scale = (vw / target) / _image->GetHeight ();
+ x_scale = float (vw) / cropped.w;
+ y_scale = (vw / target) / cropped.h;
}
_bitmap.reset (new wxBitmap (_cropped_image));
for (list<SubtitleView>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
- Rectangle sub_rect (i->position.x, i->position.y, i->image.GetWidth(), i->image.GetHeight());
+
+ /* Area of the subtitle graphic within the (uncropped) picture frame */
+ Rectangle sub_rect (i->position.x, i->position.y + _current_subtitle_offset, i->image.GetWidth(), i->image.GetHeight());
+ /* Hence the subtitle graphic after it has been cropped */
Rectangle cropped_sub_rect = sub_rect.intersection (cropped);
+ /* Get the cropped version of the subtitle image */
i->cropped_image = i->image.GetSubImage (
wxRect (
cropped_sub_rect.x - sub_rect.x,
@@ -185,12 +204,12 @@ private:
cropped_sub_rect.h
)
);
-
+
i->cropped_image.Rescale (cropped_sub_rect.w * x_scale, cropped_sub_rect.h * y_scale, wxIMAGE_QUALITY_HIGH);
i->cropped_position = Position (
cropped_sub_rect.x * x_scale,
- cropped_sub_rect.y * y_scale
+ (cropped_sub_rect.y - _current_crop.top) * y_scale
);
i->bitmap.reset (new wxBitmap (i->cropped_image));
@@ -206,6 +225,8 @@ private:
shared_ptr<wxBitmap> _bitmap;
Crop _current_crop;
Crop _pending_crop;
+ int _current_subtitle_offset;
+ int _pending_subtitle_offset;
struct SubtitleView
{
@@ -294,6 +315,9 @@ FilmViewer::film_changed (Film::Property p)
case Film::WITH_SUBTITLES:
_thumb_panel->Refresh ();
break;
+ case Film::SUBTITLE_OFFSET:
+ _thumb_panel->set_subtitle_offset (_film->subtitle_offset ());
+ break;
default:
break;
}