From 7e2780f57a66dd1f12d582bd7cdb09cbedbdf07c Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Sun, 8 Sep 2013 08:03:55 -0700 Subject: [PATCH] Make both source and destination resolution overridable in the resampler --- src/dialog_resample.cpp | 87 +++++++++++++++++++++++++++--------- src/dialog_resample.h | 17 ++++++- src/resolution_resampler.cpp | 17 +++---- src/resolution_resampler.h | 16 +++---- 4 files changed, 94 insertions(+), 43 deletions(-) diff --git a/src/dialog_resample.cpp b/src/dialog_resample.cpp index 52bdce081..f94854fc4 100644 --- a/src/dialog_resample.cpp +++ b/src/dialog_resample.cpp @@ -26,6 +26,7 @@ #include "resolution_resampler.h" #include "video_context.h" +#include #include #include #include @@ -47,7 +48,18 @@ DialogResample::DialogResample(agi::Context *c, ResampleSettings &settings) SetIcon(GETICON(resample_toolbutton_16)); memset(&settings, 0, sizeof(settings)); - c->ass->GetResolution(settings.script_x, settings.script_y); + c->ass->GetResolution(script_w, script_h); + settings.source_x = script_w; + settings.source_y = script_h; + + if (c->videoController->IsLoaded()) { + settings.dest_x = video_w = c->videoController->GetWidth(); + settings.dest_y = video_h = c->videoController->GetHeight(); + } + else { + settings.dest_x = script_w; + settings.dest_y = script_h; + } // Create all controls and set validators for (size_t i = 0; i < 4; ++i) { @@ -61,20 +73,27 @@ DialogResample::DialogResample(agi::Context *c, ResampleSettings &settings) margin_ctrl[RIGHT]->Enable(false); margin_ctrl[BOTTOM]->Enable(false); - res_x = new wxSpinCtrl(this, -1, "", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, INT_MAX); - res_y = new wxSpinCtrl(this, -1, "", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, INT_MAX); + source_x = new wxSpinCtrl(this, -1, "", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, INT_MAX); + source_y = new wxSpinCtrl(this, -1, "", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, INT_MAX); + dest_x = new wxSpinCtrl(this, -1, "", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, INT_MAX); + dest_y = new wxSpinCtrl(this, -1, "", wxDefaultPosition, wxSize(50, -1), wxSP_ARROW_KEYS, 1, INT_MAX); - res_x->SetValidator(wxGenericValidator(&settings.script_x)); - res_y->SetValidator(wxGenericValidator(&settings.script_y)); + source_x->SetValidator(wxGenericValidator(&settings.source_x)); + source_y->SetValidator(wxGenericValidator(&settings.source_y)); + dest_x->SetValidator(wxGenericValidator(&settings.dest_x)); + dest_y->SetValidator(wxGenericValidator(&settings.dest_y)); - wxButton *from_video = new wxButton(this, -1, _("From &video")); - from_video->Enable(c->videoController->IsLoaded()); + from_video = new wxButton(this, -1, _("From &video")); + from_video->Enable(false); + from_script = new wxButton(this, -1, _("From s&cript")); + from_script->Enable(false); - wxCheckBox *change_ar = new wxCheckBox(this, -1, _("&Change aspect ratio")); + change_ar = new wxCheckBox(this, -1, _("&Change aspect ratio")); change_ar->SetValidator(wxGenericValidator(&settings.change_ar)); + change_ar->Enable(false); // Position the controls - wxSizer *margin_sizer = new wxGridSizer(3, 3, 5, 5); + auto margin_sizer = new wxGridSizer(3, 3, 5, 5); margin_sizer->AddSpacer(1); margin_sizer->Add(margin_ctrl[TOP], wxSizerFlags(1).Expand()); margin_sizer->AddSpacer(1); @@ -85,22 +104,29 @@ DialogResample::DialogResample(agi::Context *c, ResampleSettings &settings) margin_sizer->Add(margin_ctrl[BOTTOM], wxSizerFlags(1).Expand()); margin_sizer->AddSpacer(1); - wxSizer *margin_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Margin offset")); + auto margin_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Margin offset")); margin_box->Add(margin_sizer, wxSizerFlags(1).Expand().Border(wxBOTTOM)); - wxSizer *res_sizer = new wxBoxSizer(wxHORIZONTAL); - res_sizer->Add(res_x, wxSizerFlags(1).Border(wxRIGHT).Align(wxALIGN_CENTER_VERTICAL)); - res_sizer->Add(new wxStaticText(this, -1, _("x")), wxSizerFlags().Center().Border(wxRIGHT)); - res_sizer->Add(res_y, wxSizerFlags(1).Border(wxRIGHT).Align(wxALIGN_CENTER_VERTICAL)); - res_sizer->Add(from_video, wxSizerFlags(1)); + auto source_res_sizer = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Source Resolution")); + source_res_sizer->Add(source_x, wxSizerFlags(1).Border(wxRIGHT).Align(wxALIGN_CENTER_VERTICAL)); + source_res_sizer->Add(new wxStaticText(this, -1, _("x")), wxSizerFlags().Center().Border(wxRIGHT)); + source_res_sizer->Add(source_y, wxSizerFlags(1).Border(wxRIGHT).Align(wxALIGN_CENTER_VERTICAL)); + source_res_sizer->Add(from_script, wxSizerFlags(1)); - wxSizer *res_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Resolution")); - res_box->Add(res_sizer, wxSizerFlags(1).Expand().Border(wxBOTTOM)); - res_box->Add(change_ar); + auto dest_res_sizer = new wxBoxSizer(wxHORIZONTAL); + dest_res_sizer->Add(dest_x, wxSizerFlags(1).Border(wxRIGHT).Align(wxALIGN_CENTER_VERTICAL)); + dest_res_sizer->Add(new wxStaticText(this, -1, _("x")), wxSizerFlags().Center().Border(wxRIGHT)); + dest_res_sizer->Add(dest_y, wxSizerFlags(1).Border(wxRIGHT).Align(wxALIGN_CENTER_VERTICAL)); + dest_res_sizer->Add(from_video, wxSizerFlags(1)); - wxSizer *main_sizer = new wxBoxSizer(wxVERTICAL); + auto dest_res_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Destination Resolution")); + dest_res_box->Add(dest_res_sizer, wxSizerFlags(1).Expand().Border(wxBOTTOM)); + dest_res_box->Add(change_ar); + + auto main_sizer = new wxBoxSizer(wxVERTICAL); main_sizer->Add(margin_box, wxSizerFlags(1).Expand().Border()); - main_sizer->Add(res_box, wxSizerFlags(0).Expand().Border()); + main_sizer->Add(source_res_sizer, wxSizerFlags(0).Expand().Border()); + main_sizer->Add(dest_res_box, wxSizerFlags(0).Expand().Border()); main_sizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL | wxHELP), wxSizerFlags().Expand().Border(wxALL & ~wxTOP)); SetSizerAndFit(main_sizer); CenterOnParent(); @@ -108,15 +134,32 @@ DialogResample::DialogResample(agi::Context *c, ResampleSettings &settings) // Bind events using std::bind; Bind(wxEVT_BUTTON, bind(&HelpButton::OpenPage, "Resample resolution"), wxID_HELP); + Bind(wxEVT_SPINCTRL, [=](wxCommandEvent&) { UpdateButtons(); }); from_video->Bind(wxEVT_BUTTON, &DialogResample::SetDestFromVideo, this); + from_script->Bind(wxEVT_BUTTON, &DialogResample::SetSourceFromScript, this); symmetrical->Bind(wxEVT_CHECKBOX, &DialogResample::OnSymmetrical, this); margin_ctrl[LEFT]->Bind(wxEVT_SPINCTRL, bind(&DialogResample::OnMarginChange, this, margin_ctrl[LEFT], margin_ctrl[RIGHT])); margin_ctrl[TOP]->Bind(wxEVT_SPINCTRL, bind(&DialogResample::OnMarginChange, this, margin_ctrl[TOP], margin_ctrl[BOTTOM])); } void DialogResample::SetDestFromVideo(wxCommandEvent &) { - res_x->SetValue(c->videoController->GetWidth()); - res_y->SetValue(c->videoController->GetHeight()); + dest_x->SetValue(video_w); + dest_y->SetValue(video_h); +} + +void DialogResample::SetSourceFromScript(wxCommandEvent&) { + source_x->SetValue(script_w); + source_y->SetValue(script_h); +} + +void DialogResample::UpdateButtons() { + from_video->Enable(c->videoController->IsLoaded() && + (dest_x->GetValue() != video_w || dest_y->GetValue() != video_h)); + from_script->Enable(source_x->GetValue() != script_w || source_y->GetValue() != script_h); + + boost::rational source_ar(source_x->GetValue(), source_y->GetValue()); + boost::rational dest_ar(dest_x->GetValue(), dest_y->GetValue()); + change_ar->Enable(source_ar != dest_ar); } void DialogResample::OnSymmetrical(wxCommandEvent &) { diff --git a/src/dialog_resample.h b/src/dialog_resample.h index ce973a64c..5fdc57e41 100644 --- a/src/dialog_resample.h +++ b/src/dialog_resample.h @@ -32,17 +32,30 @@ struct ResampleSettings; class DialogResample final : public wxDialog { agi::Context *c; ///< Project context - wxSpinCtrl *res_x; - wxSpinCtrl *res_y; + int script_w; + int script_h; + int video_w = 0; + int video_h = 0; + + wxSpinCtrl *source_x; + wxSpinCtrl *source_y; + wxSpinCtrl *dest_x; + wxSpinCtrl *dest_y; wxCheckBox *symmetrical; + wxCheckBox *change_ar; wxSpinCtrl *margin_ctrl[4]; + wxButton *from_script; + wxButton *from_video; + + void SetSourceFromScript(wxCommandEvent &); /// Set the destination resolution to the video's resolution void SetDestFromVideo(wxCommandEvent &); /// Symmetrical checkbox toggle handler void OnSymmetrical(wxCommandEvent &); /// Copy margin values over if symmetrical is enabled void OnMarginChange(wxSpinCtrl *src, wxSpinCtrl *dst); + void UpdateButtons(); public: /// Constructor diff --git a/src/resolution_resampler.cpp b/src/resolution_resampler.cpp index e6672d2c3..7220992b5 100644 --- a/src/resolution_resampler.cpp +++ b/src/resolution_resampler.cpp @@ -153,18 +153,15 @@ namespace { } } -void ResampleResolution(AssFile *ass, ResampleSettings const& settings) { - int src_x, src_y; - ass->GetResolution(src_x, src_y); - +void ResampleResolution(AssFile *ass, ResampleSettings settings) { // Add margins to original resolution - src_x += settings.margin[LEFT] + settings.margin[RIGHT]; - src_y += settings.margin[TOP] + settings.margin[BOTTOM]; + settings.source_x += settings.margin[LEFT] + settings.margin[RIGHT]; + settings.source_y += settings.margin[TOP] + settings.margin[BOTTOM]; resample_state state = { settings.margin, - double(settings.script_x) / double(src_x), - double(settings.script_y) / double(src_y), + double(settings.dest_x) / double(settings.source_x), + double(settings.dest_y) / double(settings.source_y), 1.0 }; @@ -176,8 +173,8 @@ void ResampleResolution(AssFile *ass, ResampleSettings const& settings) { for (auto& line : ass->Events) resample_line(&state, line); - ass->SetScriptInfo("PlayResX", std::to_string(settings.script_x)); - ass->SetScriptInfo("PlayResY", std::to_string(settings.script_y)); + ass->SetScriptInfo("PlayResX", std::to_string(settings.dest_x)); + ass->SetScriptInfo("PlayResY", std::to_string(settings.dest_y)); ass->Commit(_("resolution resampling"), AssFile::COMMIT_SCRIPTINFO | AssFile::COMMIT_DIAG_FULL); } diff --git a/src/resolution_resampler.h b/src/resolution_resampler.h index 0e19572c7..8b55b37c7 100644 --- a/src/resolution_resampler.h +++ b/src/resolution_resampler.h @@ -18,17 +18,15 @@ class AssFile; /// Configuration parameters for a resample struct ResampleSettings { - /// Amount to add to each margin - int margin[4]; - /// New X resolution - int script_x; - /// New Y resolution - int script_y; - /// Should the aspect ratio of the subs be changed? - bool change_ar; + int margin[4]; ///< Amount to add to each margin + int source_x; ///< Original X resolution + int source_y; ///< Original Y resolution + int dest_x; ///< New X resolution + int dest_y; ///< New Y resolution + bool change_ar; ///< Should the aspect ratio of the subs be changed? }; /// Resample the subtitles in the project /// @param file Subtitles to resample /// @param settings Resample configuration settings -void ResampleResolution(AssFile *file, ResampleSettings const& settings); +void ResampleResolution(AssFile *file, ResampleSettings settings);