diff options
| author | Carl Hetherington <cth@carlh.net> | 2012-10-11 21:54:52 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2012-10-11 21:54:52 +0100 |
| commit | f78ce22dc46e42e4f041ebf877fd7199232e4856 (patch) | |
| tree | 0e2a4a2c3cd3618ca32d14696437993b21d9c23b /src | |
| parent | a8b56b931203f984ae7e3f66bc5b9e66d0942199 (diff) | |
Basic sub offset support.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/film.cc | 14 | ||||
| -rw-r--r-- | src/lib/film.h | 12 | ||||
| -rw-r--r-- | src/lib/film_state.cc | 6 | ||||
| -rw-r--r-- | src/lib/film_state.h | 7 | ||||
| -rw-r--r-- | src/wx/film_editor.cc | 53 | ||||
| -rw-r--r-- | src/wx/film_editor.h | 4 | ||||
| -rw-r--r-- | src/wx/film_viewer.cc | 38 |
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; } |
