forked from mia/Aegisub
Make both source and destination resolution overridable in the resampler
This commit is contained in:
parent
6886436ddc
commit
7e2780f57a
4 changed files with 94 additions and 43 deletions
|
@ -26,6 +26,7 @@
|
||||||
#include "resolution_resampler.h"
|
#include "resolution_resampler.h"
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
|
|
||||||
|
#include <boost/rational.hpp>
|
||||||
#include <wx/checkbox.h>
|
#include <wx/checkbox.h>
|
||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
#include <wx/spinctrl.h>
|
#include <wx/spinctrl.h>
|
||||||
|
@ -47,7 +48,18 @@ DialogResample::DialogResample(agi::Context *c, ResampleSettings &settings)
|
||||||
SetIcon(GETICON(resample_toolbutton_16));
|
SetIcon(GETICON(resample_toolbutton_16));
|
||||||
|
|
||||||
memset(&settings, 0, sizeof(settings));
|
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
|
// Create all controls and set validators
|
||||||
for (size_t i = 0; i < 4; ++i) {
|
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[RIGHT]->Enable(false);
|
||||||
margin_ctrl[BOTTOM]->Enable(false);
|
margin_ctrl[BOTTOM]->Enable(false);
|
||||||
|
|
||||||
res_x = 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);
|
||||||
res_y = 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));
|
source_x->SetValidator(wxGenericValidator(&settings.source_x));
|
||||||
res_y->SetValidator(wxGenericValidator(&settings.script_y));
|
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 = new wxButton(this, -1, _("From &video"));
|
||||||
from_video->Enable(c->videoController->IsLoaded());
|
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->SetValidator(wxGenericValidator(&settings.change_ar));
|
||||||
|
change_ar->Enable(false);
|
||||||
|
|
||||||
// Position the controls
|
// 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->AddSpacer(1);
|
||||||
margin_sizer->Add(margin_ctrl[TOP], wxSizerFlags(1).Expand());
|
margin_sizer->Add(margin_ctrl[TOP], wxSizerFlags(1).Expand());
|
||||||
margin_sizer->AddSpacer(1);
|
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->Add(margin_ctrl[BOTTOM], wxSizerFlags(1).Expand());
|
||||||
margin_sizer->AddSpacer(1);
|
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));
|
margin_box->Add(margin_sizer, wxSizerFlags(1).Expand().Border(wxBOTTOM));
|
||||||
|
|
||||||
wxSizer *res_sizer = new wxBoxSizer(wxHORIZONTAL);
|
auto source_res_sizer = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Source Resolution"));
|
||||||
res_sizer->Add(res_x, wxSizerFlags(1).Border(wxRIGHT).Align(wxALIGN_CENTER_VERTICAL));
|
source_res_sizer->Add(source_x, wxSizerFlags(1).Border(wxRIGHT).Align(wxALIGN_CENTER_VERTICAL));
|
||||||
res_sizer->Add(new wxStaticText(this, -1, _("x")), wxSizerFlags().Center().Border(wxRIGHT));
|
source_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));
|
source_res_sizer->Add(source_y, wxSizerFlags(1).Border(wxRIGHT).Align(wxALIGN_CENTER_VERTICAL));
|
||||||
res_sizer->Add(from_video, wxSizerFlags(1));
|
source_res_sizer->Add(from_script, wxSizerFlags(1));
|
||||||
|
|
||||||
wxSizer *res_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Resolution"));
|
auto dest_res_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
res_box->Add(res_sizer, wxSizerFlags(1).Expand().Border(wxBOTTOM));
|
dest_res_sizer->Add(dest_x, wxSizerFlags(1).Border(wxRIGHT).Align(wxALIGN_CENTER_VERTICAL));
|
||||||
res_box->Add(change_ar);
|
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(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));
|
main_sizer->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL | wxHELP), wxSizerFlags().Expand().Border(wxALL & ~wxTOP));
|
||||||
SetSizerAndFit(main_sizer);
|
SetSizerAndFit(main_sizer);
|
||||||
CenterOnParent();
|
CenterOnParent();
|
||||||
|
@ -108,15 +134,32 @@ DialogResample::DialogResample(agi::Context *c, ResampleSettings &settings)
|
||||||
// Bind events
|
// Bind events
|
||||||
using std::bind;
|
using std::bind;
|
||||||
Bind(wxEVT_BUTTON, bind(&HelpButton::OpenPage, "Resample resolution"), wxID_HELP);
|
Bind(wxEVT_BUTTON, bind(&HelpButton::OpenPage, "Resample resolution"), wxID_HELP);
|
||||||
|
Bind(wxEVT_SPINCTRL, [=](wxCommandEvent&) { UpdateButtons(); });
|
||||||
from_video->Bind(wxEVT_BUTTON, &DialogResample::SetDestFromVideo, this);
|
from_video->Bind(wxEVT_BUTTON, &DialogResample::SetDestFromVideo, this);
|
||||||
|
from_script->Bind(wxEVT_BUTTON, &DialogResample::SetSourceFromScript, this);
|
||||||
symmetrical->Bind(wxEVT_CHECKBOX, &DialogResample::OnSymmetrical, 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[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]));
|
margin_ctrl[TOP]->Bind(wxEVT_SPINCTRL, bind(&DialogResample::OnMarginChange, this, margin_ctrl[TOP], margin_ctrl[BOTTOM]));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogResample::SetDestFromVideo(wxCommandEvent &) {
|
void DialogResample::SetDestFromVideo(wxCommandEvent &) {
|
||||||
res_x->SetValue(c->videoController->GetWidth());
|
dest_x->SetValue(video_w);
|
||||||
res_y->SetValue(c->videoController->GetHeight());
|
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<int> source_ar(source_x->GetValue(), source_y->GetValue());
|
||||||
|
boost::rational<int> dest_ar(dest_x->GetValue(), dest_y->GetValue());
|
||||||
|
change_ar->Enable(source_ar != dest_ar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogResample::OnSymmetrical(wxCommandEvent &) {
|
void DialogResample::OnSymmetrical(wxCommandEvent &) {
|
||||||
|
|
|
@ -32,17 +32,30 @@ struct ResampleSettings;
|
||||||
class DialogResample final : public wxDialog {
|
class DialogResample final : public wxDialog {
|
||||||
agi::Context *c; ///< Project context
|
agi::Context *c; ///< Project context
|
||||||
|
|
||||||
wxSpinCtrl *res_x;
|
int script_w;
|
||||||
wxSpinCtrl *res_y;
|
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 *symmetrical;
|
||||||
|
wxCheckBox *change_ar;
|
||||||
wxSpinCtrl *margin_ctrl[4];
|
wxSpinCtrl *margin_ctrl[4];
|
||||||
|
|
||||||
|
wxButton *from_script;
|
||||||
|
wxButton *from_video;
|
||||||
|
|
||||||
|
void SetSourceFromScript(wxCommandEvent &);
|
||||||
/// Set the destination resolution to the video's resolution
|
/// Set the destination resolution to the video's resolution
|
||||||
void SetDestFromVideo(wxCommandEvent &);
|
void SetDestFromVideo(wxCommandEvent &);
|
||||||
/// Symmetrical checkbox toggle handler
|
/// Symmetrical checkbox toggle handler
|
||||||
void OnSymmetrical(wxCommandEvent &);
|
void OnSymmetrical(wxCommandEvent &);
|
||||||
/// Copy margin values over if symmetrical is enabled
|
/// Copy margin values over if symmetrical is enabled
|
||||||
void OnMarginChange(wxSpinCtrl *src, wxSpinCtrl *dst);
|
void OnMarginChange(wxSpinCtrl *src, wxSpinCtrl *dst);
|
||||||
|
void UpdateButtons();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
|
|
|
@ -153,18 +153,15 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResampleResolution(AssFile *ass, ResampleSettings const& settings) {
|
void ResampleResolution(AssFile *ass, ResampleSettings settings) {
|
||||||
int src_x, src_y;
|
|
||||||
ass->GetResolution(src_x, src_y);
|
|
||||||
|
|
||||||
// Add margins to original resolution
|
// Add margins to original resolution
|
||||||
src_x += settings.margin[LEFT] + settings.margin[RIGHT];
|
settings.source_x += settings.margin[LEFT] + settings.margin[RIGHT];
|
||||||
src_y += settings.margin[TOP] + settings.margin[BOTTOM];
|
settings.source_y += settings.margin[TOP] + settings.margin[BOTTOM];
|
||||||
|
|
||||||
resample_state state = {
|
resample_state state = {
|
||||||
settings.margin,
|
settings.margin,
|
||||||
double(settings.script_x) / double(src_x),
|
double(settings.dest_x) / double(settings.source_x),
|
||||||
double(settings.script_y) / double(src_y),
|
double(settings.dest_y) / double(settings.source_y),
|
||||||
1.0
|
1.0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -176,8 +173,8 @@ void ResampleResolution(AssFile *ass, ResampleSettings const& settings) {
|
||||||
for (auto& line : ass->Events)
|
for (auto& line : ass->Events)
|
||||||
resample_line(&state, line);
|
resample_line(&state, line);
|
||||||
|
|
||||||
ass->SetScriptInfo("PlayResX", std::to_string(settings.script_x));
|
ass->SetScriptInfo("PlayResX", std::to_string(settings.dest_x));
|
||||||
ass->SetScriptInfo("PlayResY", std::to_string(settings.script_y));
|
ass->SetScriptInfo("PlayResY", std::to_string(settings.dest_y));
|
||||||
|
|
||||||
ass->Commit(_("resolution resampling"), AssFile::COMMIT_SCRIPTINFO | AssFile::COMMIT_DIAG_FULL);
|
ass->Commit(_("resolution resampling"), AssFile::COMMIT_SCRIPTINFO | AssFile::COMMIT_DIAG_FULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,17 +18,15 @@ class AssFile;
|
||||||
|
|
||||||
/// Configuration parameters for a resample
|
/// Configuration parameters for a resample
|
||||||
struct ResampleSettings {
|
struct ResampleSettings {
|
||||||
/// Amount to add to each margin
|
int margin[4]; ///< Amount to add to each margin
|
||||||
int margin[4];
|
int source_x; ///< Original X resolution
|
||||||
/// New X resolution
|
int source_y; ///< Original Y resolution
|
||||||
int script_x;
|
int dest_x; ///< New X resolution
|
||||||
/// New Y resolution
|
int dest_y; ///< New Y resolution
|
||||||
int script_y;
|
bool change_ar; ///< Should the aspect ratio of the subs be changed?
|
||||||
/// Should the aspect ratio of the subs be changed?
|
|
||||||
bool change_ar;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Resample the subtitles in the project
|
/// Resample the subtitles in the project
|
||||||
/// @param file Subtitles to resample
|
/// @param file Subtitles to resample
|
||||||
/// @param settings Resample configuration settings
|
/// @param settings Resample configuration settings
|
||||||
void ResampleResolution(AssFile *file, ResampleSettings const& settings);
|
void ResampleResolution(AssFile *file, ResampleSettings settings);
|
||||||
|
|
Loading…
Reference in a new issue