Fully extract the resolution resampling logic from DialogResample
This commit is contained in:
parent
ce23d72399
commit
2fdbc73721
10 changed files with 224 additions and 167 deletions
|
@ -209,6 +209,7 @@
|
||||||
<ClInclude Include="$(SrcDir)plugin_manager.h" />
|
<ClInclude Include="$(SrcDir)plugin_manager.h" />
|
||||||
<ClInclude Include="$(SrcDir)preferences.h" />
|
<ClInclude Include="$(SrcDir)preferences.h" />
|
||||||
<ClInclude Include="$(SrcDir)preferences_base.h" />
|
<ClInclude Include="$(SrcDir)preferences_base.h" />
|
||||||
|
<ClInclude Include="$(SrcDir)resolution_resampler.h" />
|
||||||
<ClInclude Include="$(SrcDir)scintilla_text_ctrl.h" />
|
<ClInclude Include="$(SrcDir)scintilla_text_ctrl.h" />
|
||||||
<ClInclude Include="$(SrcDir)scintilla_text_selection_controller.h" />
|
<ClInclude Include="$(SrcDir)scintilla_text_selection_controller.h" />
|
||||||
<ClInclude Include="$(SrcDir)search_replace_engine.h" />
|
<ClInclude Include="$(SrcDir)search_replace_engine.h" />
|
||||||
|
@ -405,6 +406,7 @@
|
||||||
<ClCompile Include="$(SrcDir)plugin_manager.cpp" />
|
<ClCompile Include="$(SrcDir)plugin_manager.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)preferences.cpp" />
|
<ClCompile Include="$(SrcDir)preferences.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)preferences_base.cpp" />
|
<ClCompile Include="$(SrcDir)preferences_base.cpp" />
|
||||||
|
<ClCompile Include="$(SrcDir)resolution_resampler.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)scintilla_text_ctrl.cpp" />
|
<ClCompile Include="$(SrcDir)scintilla_text_ctrl.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)scintilla_text_selection_controller.cpp" />
|
<ClCompile Include="$(SrcDir)scintilla_text_selection_controller.cpp" />
|
||||||
<ClCompile Include="$(SrcDir)search_replace_engine.cpp" />
|
<ClCompile Include="$(SrcDir)search_replace_engine.cpp" />
|
||||||
|
|
|
@ -687,6 +687,9 @@
|
||||||
<ClInclude Include="$(SrcDir)lpeg.h">
|
<ClInclude Include="$(SrcDir)lpeg.h">
|
||||||
<Filter>Automation\Lua</Filter>
|
<Filter>Automation\Lua</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="$(SrcDir)resolution_resampler.h">
|
||||||
|
<Filter>Features\Resolution resampler</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="$(SrcDir)ass_dialogue.cpp">
|
<ClCompile Include="$(SrcDir)ass_dialogue.cpp">
|
||||||
|
@ -1238,6 +1241,9 @@
|
||||||
<ClCompile Include="$(SrcDir)lpeg.c">
|
<ClCompile Include="$(SrcDir)lpeg.c">
|
||||||
<Filter>Automation\Lua</Filter>
|
<Filter>Automation\Lua</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="$(SrcDir)resolution_resampler.cpp">
|
||||||
|
<Filter>Features\Resolution resampler</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="$(SrcDir)res.rc">
|
<ResourceCompile Include="$(SrcDir)res.rc">
|
||||||
|
|
|
@ -204,6 +204,7 @@ SRC += \
|
||||||
plugin_manager.cpp \
|
plugin_manager.cpp \
|
||||||
preferences.cpp \
|
preferences.cpp \
|
||||||
preferences_base.cpp \
|
preferences_base.cpp \
|
||||||
|
resolution_resampler.cpp \
|
||||||
scintilla_text_ctrl.cpp \
|
scintilla_text_ctrl.cpp \
|
||||||
scintilla_text_selection_controller.cpp \
|
scintilla_text_selection_controller.cpp \
|
||||||
search_replace_engine.cpp \
|
search_replace_engine.cpp \
|
||||||
|
|
|
@ -285,34 +285,3 @@ AssEntry *AssDialogue::Clone() const {
|
||||||
*const_cast<int *>(&clone->Id) = Id;
|
*const_cast<int *>(&clone->Id) = Id;
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssDialogueBlockDrawing::TransformCoords(int mx, int my, double x, double y) {
|
|
||||||
// HACK: Implement a proper parser ffs!!
|
|
||||||
// Could use Spline but it'd be slower and this seems to work fine
|
|
||||||
bool is_x = true;
|
|
||||||
std::string final;
|
|
||||||
|
|
||||||
for (auto const& cur : agi::Split(text, ' ')) {
|
|
||||||
if (std::all_of(begin(cur), end(cur), isdigit)) {
|
|
||||||
int val = boost::lexical_cast<int>(agi::str(cur));
|
|
||||||
if (is_x)
|
|
||||||
val = (int)((val + mx) * x + .5);
|
|
||||||
else
|
|
||||||
val = (int)((val + my) * y + .5);
|
|
||||||
final += std::to_string(val);
|
|
||||||
final += ' ';
|
|
||||||
}
|
|
||||||
else if (cur.size() == 1) {
|
|
||||||
char c = tolower(cur[0]);
|
|
||||||
if (c == 'm' || c == 'n' || c == 'l' || c == 'b' || c == 's' || c == 'p' || c == 'c') {
|
|
||||||
is_x = true;
|
|
||||||
final += c;
|
|
||||||
final += ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write back final
|
|
||||||
final.pop_back();
|
|
||||||
text = final;
|
|
||||||
}
|
|
||||||
|
|
|
@ -97,11 +97,11 @@ public:
|
||||||
|
|
||||||
class AssDialogueBlockDrawing : public AssDialogueBlock {
|
class AssDialogueBlockDrawing : public AssDialogueBlock {
|
||||||
public:
|
public:
|
||||||
|
using AssDialogueBlock::text;
|
||||||
int Scale;
|
int Scale;
|
||||||
|
|
||||||
AssBlockType GetType() const override { return AssBlockType::DRAWING; }
|
AssBlockType GetType() const override { return AssBlockType::DRAWING; }
|
||||||
AssDialogueBlockDrawing(std::string const& text, int scale) : AssDialogueBlock(text), Scale(scale) { }
|
AssDialogueBlockDrawing(std::string const& text, int scale) : AssDialogueBlock(text), Scale(scale) { }
|
||||||
void TransformCoords(int trans_x,int trans_y,double mult_x,double mult_y);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AssDialogueBlockOverride : public AssDialogueBlock {
|
class AssDialogueBlockOverride : public AssDialogueBlock {
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
#include "../dialog_translation.h"
|
#include "../dialog_translation.h"
|
||||||
#include "../include/aegisub/context.h"
|
#include "../include/aegisub/context.h"
|
||||||
#include "../options.h"
|
#include "../options.h"
|
||||||
|
#include "../resolution_resampler.h"
|
||||||
#include "../video_context.h"
|
#include "../video_context.h"
|
||||||
|
|
||||||
#include <libaegisub/fs.h>
|
#include <libaegisub/fs.h>
|
||||||
|
|
|
@ -21,20 +21,13 @@
|
||||||
|
|
||||||
#include "dialog_resample.h"
|
#include "dialog_resample.h"
|
||||||
|
|
||||||
#include "ass_dialogue.h"
|
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
#include "ass_style.h"
|
|
||||||
#include "include/aegisub/context.h"
|
#include "include/aegisub/context.h"
|
||||||
#include "help_button.h"
|
#include "help_button.h"
|
||||||
#include "libresrc/libresrc.h"
|
#include "libresrc/libresrc.h"
|
||||||
|
#include "resolution_resampler.h"
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
|
|
||||||
#include <libaegisub/of_type_adaptor.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include <wx/checkbox.h>
|
#include <wx/checkbox.h>
|
||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
#include <wx/spinctrl.h>
|
#include <wx/spinctrl.h>
|
||||||
|
@ -144,113 +137,3 @@ void DialogResample::OnMarginChange(wxSpinCtrl *src, wxSpinCtrl *dst) {
|
||||||
if (symmetrical->IsChecked())
|
if (symmetrical->IsChecked())
|
||||||
dst->SetValue(src->GetValue());
|
dst->SetValue(src->GetValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
|
||||||
struct resample_state {
|
|
||||||
const int *margin;
|
|
||||||
double rx;
|
|
||||||
double ry;
|
|
||||||
double ar;
|
|
||||||
};
|
|
||||||
|
|
||||||
void resample_tags(std::string const& name, AssOverrideParameter *cur, void *ud) {
|
|
||||||
resample_state *state = static_cast<resample_state *>(ud);
|
|
||||||
|
|
||||||
double resizer = 1.0;
|
|
||||||
int shift = 0;
|
|
||||||
|
|
||||||
switch (cur->classification) {
|
|
||||||
case AssParameterClass::ABSOLUTE_SIZE:
|
|
||||||
resizer = state->ry;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AssParameterClass::ABSOLUTE_POS_X:
|
|
||||||
resizer = state->rx;
|
|
||||||
shift = state->margin[LEFT];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AssParameterClass::ABSOLUTE_POS_Y:
|
|
||||||
resizer = state->ry;
|
|
||||||
shift = state->margin[TOP];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AssParameterClass::RELATIVE_SIZE_X:
|
|
||||||
resizer = state->ar;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AssParameterClass::RELATIVE_SIZE_Y:
|
|
||||||
//resizer = ry;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AssParameterClass::DRAWING: {
|
|
||||||
AssDialogueBlockDrawing block(cur->Get<std::string>(), 1);
|
|
||||||
block.TransformCoords(state->margin[LEFT], state->margin[TOP], state->rx, state->ry);
|
|
||||||
cur->Set(block.GetText());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
VariableDataType curType = cur->GetType();
|
|
||||||
if (curType == VariableDataType::FLOAT)
|
|
||||||
cur->Set((cur->Get<double>() + shift) * resizer);
|
|
||||||
else if (curType == VariableDataType::INT)
|
|
||||||
cur->Set<int>((cur->Get<int>() + shift) * resizer + 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
void resample_line(resample_state *state, AssEntry &line) {
|
|
||||||
AssDialogue *diag = dynamic_cast<AssDialogue*>(&line);
|
|
||||||
if (diag && !(diag->Comment && (boost::starts_with(diag->Effect.get(), "template") || boost::starts_with(diag->Effect.get(), "code")))) {
|
|
||||||
boost::ptr_vector<AssDialogueBlock> blocks(diag->ParseTags());
|
|
||||||
|
|
||||||
for (auto block : blocks | agi::of_type<AssDialogueBlockOverride>())
|
|
||||||
block->ProcessParameters(resample_tags, state);
|
|
||||||
|
|
||||||
for (auto drawing : blocks | agi::of_type<AssDialogueBlockDrawing>())
|
|
||||||
drawing->TransformCoords(state->margin[LEFT], state->margin[TOP], state->rx, state->ry);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 3; ++i)
|
|
||||||
diag->Margin[i] = int((diag->Margin[i] + state->margin[i]) * (i < 2 ? state->rx : state->ry) + 0.5);
|
|
||||||
|
|
||||||
diag->UpdateText(blocks);
|
|
||||||
}
|
|
||||||
else if (AssStyle *style = dynamic_cast<AssStyle*>(&line)) {
|
|
||||||
style->fontsize = int(style->fontsize * state->ry + 0.5);
|
|
||||||
style->outline_w *= state->ry;
|
|
||||||
style->shadow_w *= state->ry;
|
|
||||||
style->spacing *= state->rx;
|
|
||||||
style->scalex *= state->ar;
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
style->Margin[i] = int((style->Margin[i] + state->margin[i]) * (i < 2 ? state->rx : state->ry) + 0.5);
|
|
||||||
style->UpdateData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResampleResolution(AssFile *ass, ResampleSettings const& settings) {
|
|
||||||
int src_x, src_y;
|
|
||||||
ass->GetResolution(src_x, src_y);
|
|
||||||
|
|
||||||
// Add margins to original resolution
|
|
||||||
src_x += settings.margin[LEFT] + settings.margin[RIGHT];
|
|
||||||
src_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),
|
|
||||||
1.0
|
|
||||||
};
|
|
||||||
|
|
||||||
if (settings.change_ar)
|
|
||||||
state.ar = state.rx / state.ry;
|
|
||||||
|
|
||||||
for_each(ass->Line.begin(), ass->Line.end(), std::bind(resample_line, &state, std::placeholders::_1));
|
|
||||||
|
|
||||||
ass->SetScriptInfo("PlayResX", std::to_string(settings.script_x));
|
|
||||||
ass->SetScriptInfo("PlayResY", std::to_string(settings.script_y));
|
|
||||||
|
|
||||||
ass->Commit(_("resolution resampling"), AssFile::COMMIT_SCRIPTINFO | AssFile::COMMIT_DIAG_FULL);
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,23 +23,7 @@ namespace agi { struct Context; }
|
||||||
class AssFile;
|
class AssFile;
|
||||||
class wxCheckBox;
|
class wxCheckBox;
|
||||||
class wxSpinCtrl;
|
class wxSpinCtrl;
|
||||||
|
struct ResampleSettings;
|
||||||
/// 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Resample the subtitles in the project
|
|
||||||
/// @param file Subtitles to resample
|
|
||||||
/// @param settings Resample configuration settings
|
|
||||||
void ResampleResolution(AssFile *file, ResampleSettings const& settings);
|
|
||||||
|
|
||||||
/// @class DialogResample
|
/// @class DialogResample
|
||||||
/// @brief Configuration dialog for resolution resampling
|
/// @brief Configuration dialog for resolution resampling
|
||||||
|
|
177
aegisub/src/resolution_resampler.cpp
Normal file
177
aegisub/src/resolution_resampler.cpp
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
// Copyright (c) 2013, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
//
|
||||||
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "resolution_resampler.h"
|
||||||
|
|
||||||
|
#include "ass_dialogue.h"
|
||||||
|
#include "ass_file.h"
|
||||||
|
#include "ass_style.h"
|
||||||
|
|
||||||
|
#include <libaegisub/of_type_adaptor.h>
|
||||||
|
#include <libaegisub/split.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
LEFT = 0,
|
||||||
|
RIGHT = 1,
|
||||||
|
TOP = 2,
|
||||||
|
BOTTOM = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::string transform_drawing(std::string const& drawing, int shift_x, int shift_y, double scale_x, double scale_y) {
|
||||||
|
bool is_x = true;
|
||||||
|
std::string final;
|
||||||
|
final.reserve(drawing.size());
|
||||||
|
|
||||||
|
for (auto const& cur : agi::Split(drawing, ' ')) {
|
||||||
|
if (std::all_of(begin(cur), end(cur), isdigit)) {
|
||||||
|
int val = boost::lexical_cast<int>(agi::str(cur));
|
||||||
|
if (is_x)
|
||||||
|
val = (int)((val + shift_x) * scale_x + .5);
|
||||||
|
else
|
||||||
|
val = (int)((val + shift_y) * scale_y + .5);
|
||||||
|
final += std::to_string(val);
|
||||||
|
final += ' ';
|
||||||
|
}
|
||||||
|
else if (cur.size() == 1) {
|
||||||
|
char c = tolower(cur[0]);
|
||||||
|
if (c == 'm' || c == 'n' || c == 'l' || c == 'b' || c == 's' || c == 'p' || c == 'c') {
|
||||||
|
is_x = true;
|
||||||
|
final += c;
|
||||||
|
final += ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final.pop_back();
|
||||||
|
return final;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct resample_state {
|
||||||
|
const int *margin;
|
||||||
|
double rx;
|
||||||
|
double ry;
|
||||||
|
double ar;
|
||||||
|
};
|
||||||
|
|
||||||
|
void resample_tags(std::string const& name, AssOverrideParameter *cur, void *ud) {
|
||||||
|
resample_state *state = static_cast<resample_state *>(ud);
|
||||||
|
|
||||||
|
double resizer = 1.0;
|
||||||
|
int shift = 0;
|
||||||
|
|
||||||
|
switch (cur->classification) {
|
||||||
|
case AssParameterClass::ABSOLUTE_SIZE:
|
||||||
|
resizer = state->ry;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssParameterClass::ABSOLUTE_POS_X:
|
||||||
|
resizer = state->rx;
|
||||||
|
shift = state->margin[LEFT];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssParameterClass::ABSOLUTE_POS_Y:
|
||||||
|
resizer = state->ry;
|
||||||
|
shift = state->margin[TOP];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssParameterClass::RELATIVE_SIZE_X:
|
||||||
|
resizer = state->ar;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssParameterClass::RELATIVE_SIZE_Y:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AssParameterClass::DRAWING: {
|
||||||
|
cur->Set(transform_drawing(
|
||||||
|
cur->Get<std::string>(),
|
||||||
|
state->margin[LEFT], state->margin[TOP], state->rx, state->ry));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VariableDataType curType = cur->GetType();
|
||||||
|
if (curType == VariableDataType::FLOAT)
|
||||||
|
cur->Set((cur->Get<double>() + shift) * resizer);
|
||||||
|
else if (curType == VariableDataType::INT)
|
||||||
|
cur->Set<int>((cur->Get<int>() + shift) * resizer + 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resample_line(resample_state *state, AssEntry &line) {
|
||||||
|
AssDialogue *diag = dynamic_cast<AssDialogue*>(&line);
|
||||||
|
if (diag && !(diag->Comment && (boost::starts_with(diag->Effect.get(), "template") || boost::starts_with(diag->Effect.get(), "code")))) {
|
||||||
|
boost::ptr_vector<AssDialogueBlock> blocks(diag->ParseTags());
|
||||||
|
|
||||||
|
for (auto block : blocks | agi::of_type<AssDialogueBlockOverride>())
|
||||||
|
block->ProcessParameters(resample_tags, state);
|
||||||
|
|
||||||
|
for (auto drawing : blocks | agi::of_type<AssDialogueBlockDrawing>())
|
||||||
|
drawing->text = transform_drawing(drawing->text, state->margin[LEFT], state->margin[TOP], state->rx, state->ry);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 3; ++i)
|
||||||
|
diag->Margin[i] = int((diag->Margin[i] + state->margin[i]) * (i < 2 ? state->rx : state->ry) + 0.5);
|
||||||
|
|
||||||
|
diag->UpdateText(blocks);
|
||||||
|
}
|
||||||
|
else if (AssStyle *style = dynamic_cast<AssStyle*>(&line)) {
|
||||||
|
style->fontsize = int(style->fontsize * state->ry + 0.5);
|
||||||
|
style->outline_w *= state->ry;
|
||||||
|
style->shadow_w *= state->ry;
|
||||||
|
style->spacing *= state->rx;
|
||||||
|
style->scalex *= state->ar;
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
style->Margin[i] = int((style->Margin[i] + state->margin[i]) * (i < 2 ? state->rx : state->ry) + 0.5);
|
||||||
|
style->UpdateData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResampleResolution(AssFile *ass, ResampleSettings const& settings) {
|
||||||
|
int src_x, src_y;
|
||||||
|
ass->GetResolution(src_x, src_y);
|
||||||
|
|
||||||
|
// Add margins to original resolution
|
||||||
|
src_x += settings.margin[LEFT] + settings.margin[RIGHT];
|
||||||
|
src_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),
|
||||||
|
1.0
|
||||||
|
};
|
||||||
|
|
||||||
|
if (settings.change_ar)
|
||||||
|
state.ar = state.rx / state.ry;
|
||||||
|
|
||||||
|
for (auto& line : ass->Line)
|
||||||
|
resample_line(&state, line);
|
||||||
|
|
||||||
|
ass->SetScriptInfo("PlayResX", std::to_string(settings.script_x));
|
||||||
|
ass->SetScriptInfo("PlayResY", std::to_string(settings.script_y));
|
||||||
|
|
||||||
|
ass->Commit(_("resolution resampling"), AssFile::COMMIT_SCRIPTINFO | AssFile::COMMIT_DIAG_FULL);
|
||||||
|
}
|
34
aegisub/src/resolution_resampler.h
Normal file
34
aegisub/src/resolution_resampler.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright (c) 2013, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
//
|
||||||
|
// Aegisub Project http://www.aegisub.org/
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Resample the subtitles in the project
|
||||||
|
/// @param file Subtitles to resample
|
||||||
|
/// @param settings Resample configuration settings
|
||||||
|
void ResampleResolution(AssFile *file, ResampleSettings const& settings);
|
Loading…
Reference in a new issue