Accept percentage arguments in scaling IPFs (#8217)
This commit is contained in:
parent
309abc7a21
commit
855f01728a
2 changed files with 43 additions and 28 deletions
|
@ -470,17 +470,15 @@ surface scale_modification::operator()(const surface& src) const
|
|||
point size = target_size_;
|
||||
|
||||
if(size.x <= 0) {
|
||||
if(size.x < 0) {
|
||||
ERR_DP << "width of " << fn_ << " is negative - resetting to original width";
|
||||
}
|
||||
size.x = src->w;
|
||||
} else if(flags_ & X_BY_FACTOR) {
|
||||
size.x = src->w * (static_cast<double>(size.x) / 100);
|
||||
}
|
||||
|
||||
if(size.y <= 0) {
|
||||
if(size.y < 0) {
|
||||
ERR_DP << "height of " << fn_ << " is negative - resetting to original height";
|
||||
}
|
||||
size.y = src->h;
|
||||
} else if(flags_ & Y_BY_FACTOR) {
|
||||
size.y = src->h * (static_cast<double>(size.y) / 100);
|
||||
}
|
||||
|
||||
if(flags_ & PRESERVE_ASPECT_RATIO) {
|
||||
|
@ -1047,24 +1045,44 @@ REGISTER_MOD_PARSER(L, args)
|
|||
|
||||
namespace
|
||||
{
|
||||
std::pair<int, bool> parse_scale_value(std::string_view arg)
|
||||
{
|
||||
if(const std::size_t pos = arg.rfind('%'); pos != std::string_view::npos) {
|
||||
return { utils::from_chars<int>(arg.substr(0, pos)).value_or(0), true };
|
||||
} else {
|
||||
return { utils::from_chars<int>(arg).value_or(0), false };
|
||||
}
|
||||
}
|
||||
|
||||
/** Common helper function to parse scaling IPF inputs. */
|
||||
std::optional<point> parse_scale_args(std::string_view args)
|
||||
std::optional<std::pair<point, uint8_t>> parse_scale_args(std::string_view args)
|
||||
{
|
||||
const auto scale_params = utils::split_view(args, ',', utils::STRIP_SPACES);
|
||||
const std::size_t s = scale_params.size();
|
||||
const std::size_t num_args = scale_params.size();
|
||||
|
||||
if(s == 0 || (s == 1 && scale_params[0].empty())) {
|
||||
if(num_args == 0 || (num_args == 1 && scale_params[0].empty())) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
point size{0, 0};
|
||||
size.x = utils::from_chars<int>(scale_params[0]).value_or(0);
|
||||
uint8_t flags = 0;
|
||||
std::array<int, 2> parsed_sizes{0,0};
|
||||
|
||||
if(s > 1) {
|
||||
size.y = utils::from_chars<int>(scale_params[1]).value_or(0);
|
||||
for(unsigned i = 0; i < std::min<unsigned>(2, num_args); ++i) {
|
||||
const auto& [size, relative] = parse_scale_value(scale_params[i]);
|
||||
|
||||
if(size < 0) {
|
||||
ERR_DP << "Negative size passed to scaling IPF. Original image dimension will be used instead";
|
||||
continue;
|
||||
}
|
||||
|
||||
parsed_sizes[i] = size;
|
||||
|
||||
if(relative) {
|
||||
flags |= (i == 0 ? scale_modification::X_BY_FACTOR : scale_modification::Y_BY_FACTOR);
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
return std::pair{point{parsed_sizes[0], parsed_sizes[1]}, flags};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -1072,9 +1090,9 @@ std::optional<point> parse_scale_args(std::string_view args)
|
|||
// Scale
|
||||
REGISTER_MOD_PARSER(SCALE, args)
|
||||
{
|
||||
if(auto size = parse_scale_args(args)) {
|
||||
if(auto params = parse_scale_args(args)) {
|
||||
constexpr uint8_t mode = scale_modification::SCALE_LINEAR | scale_modification::FIT_TO_SIZE;
|
||||
return std::make_unique<scale_modification>(*size, "SCALE", mode);
|
||||
return std::make_unique<scale_modification>(params->first, mode | params->second);
|
||||
} else {
|
||||
ERR_DP << "no arguments passed to the ~SCALE() function";
|
||||
return nullptr;
|
||||
|
@ -1083,9 +1101,9 @@ REGISTER_MOD_PARSER(SCALE, args)
|
|||
|
||||
REGISTER_MOD_PARSER(SCALE_SHARP, args)
|
||||
{
|
||||
if(auto size = parse_scale_args(args)) {
|
||||
if(auto params = parse_scale_args(args)) {
|
||||
constexpr uint8_t mode = scale_modification::SCALE_SHARP | scale_modification::FIT_TO_SIZE;
|
||||
return std::make_unique<scale_modification>(*size, "SCALE_SHARP", mode);
|
||||
return std::make_unique<scale_modification>(params->first, mode | params->second);
|
||||
} else {
|
||||
ERR_DP << "no arguments passed to the ~SCALE_SHARP() function";
|
||||
return nullptr;
|
||||
|
@ -1094,9 +1112,9 @@ REGISTER_MOD_PARSER(SCALE_SHARP, args)
|
|||
|
||||
REGISTER_MOD_PARSER(SCALE_INTO, args)
|
||||
{
|
||||
if(auto size = parse_scale_args(args)) {
|
||||
if(auto params = parse_scale_args(args)) {
|
||||
constexpr uint8_t mode = scale_modification::SCALE_LINEAR | scale_modification::PRESERVE_ASPECT_RATIO;
|
||||
return std::make_unique<scale_modification>(*size, "SCALE_INTO", mode);
|
||||
return std::make_unique<scale_modification>(params->first, mode | params->second);
|
||||
} else {
|
||||
ERR_DP << "no arguments passed to the ~SCALE_INTO() function";
|
||||
return nullptr;
|
||||
|
@ -1105,9 +1123,9 @@ REGISTER_MOD_PARSER(SCALE_INTO, args)
|
|||
|
||||
REGISTER_MOD_PARSER(SCALE_INTO_SHARP, args)
|
||||
{
|
||||
if(auto size = parse_scale_args(args)) {
|
||||
if(auto params = parse_scale_args(args)) {
|
||||
constexpr uint8_t mode = scale_modification::SCALE_SHARP | scale_modification::PRESERVE_ASPECT_RATIO;
|
||||
return std::make_unique<scale_modification>(*size, "SCALE_INTO_SHARP", mode);
|
||||
return std::make_unique<scale_modification>(params->first, mode | params->second);
|
||||
} else {
|
||||
ERR_DP << "no arguments passed to the ~SCALE_INTO_SHARP() function";
|
||||
return nullptr;
|
||||
|
@ -1125,8 +1143,6 @@ REGISTER_MOD_PARSER(XBRZ, args)
|
|||
return std::make_unique<xbrz_modification>(z);
|
||||
}
|
||||
|
||||
// scale
|
||||
|
||||
// Gaussian-like blur
|
||||
REGISTER_MOD_PARSER(BL, args)
|
||||
{
|
||||
|
|
|
@ -447,12 +447,13 @@ public:
|
|||
SCALE_SHARP = 0b00001,
|
||||
FIT_TO_SIZE = 0b00010,
|
||||
PRESERVE_ASPECT_RATIO = 0b00100,
|
||||
X_BY_FACTOR = 0b01000,
|
||||
Y_BY_FACTOR = 0b10000,
|
||||
};
|
||||
|
||||
scale_modification(point target_size, const std::string& fn, uint8_t flags)
|
||||
scale_modification(point target_size, uint8_t flags)
|
||||
: target_size_(target_size)
|
||||
, flags_(flags)
|
||||
, fn_(fn)
|
||||
{}
|
||||
|
||||
virtual surface operator()(const surface& src) const;
|
||||
|
@ -464,8 +465,6 @@ private:
|
|||
point target_size_{0,0};
|
||||
|
||||
uint8_t flags_ = SCALE_LINEAR | FIT_TO_SIZE;
|
||||
|
||||
const std::string fn_ = "";
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue