mirror of
https://github.com/wesnoth/wesnoth
synced 2025-04-16 16:43:18 +00:00
Simplify nearest neighbor rescale (#8240)
This commit is contained in:
parent
c25fc888a7
commit
9f99a4ef7d
|
@ -235,6 +235,10 @@ rng/test_mt_rng_reproducibility5
|
|||
rng/test_mt_rng_reproducibility_coverage
|
||||
rng/validate_get_random_int
|
||||
rng/validate_get_random_int2
|
||||
sdl/test_scale_sharp_nullptr
|
||||
sdl/test_scale_sharp_zero
|
||||
sdl/test_scale_sharp_round
|
||||
sdl/test_scale_sharp_fractional
|
||||
test_serialization_utils_and_unicode/utils_join_test
|
||||
test_serialization_utils_and_unicode/utils_split_test
|
||||
test_serialization_utils_and_unicode/utils_quoted_split_test
|
||||
|
|
|
@ -1211,6 +1211,7 @@
|
|||
<Unit filename="../../src/tests/test_mp_connect.cpp" />
|
||||
<Unit filename="../../src/tests/test_recall_list.cpp" />
|
||||
<Unit filename="../../src/tests/test_rng.cpp" />
|
||||
<Unit filename="../../src/tests/test_sdl.cpp" />
|
||||
<Unit filename="../../src/tests/test_serialization.cpp" />
|
||||
<Unit filename="../../src/tests/test_simple_wml.cpp" />
|
||||
<Unit filename="../../src/tests/test_team.cpp" />
|
||||
|
|
|
@ -628,6 +628,7 @@
|
|||
62114CC61750B99800CA42C7 /* mouse_action_item.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 62114CC41750B99800CA42C7 /* mouse_action_item.cpp */; };
|
||||
62114CC91750B9AF00CA42C7 /* item_palette.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 62114CC71750B9AF00CA42C7 /* item_palette.cpp */; };
|
||||
621DEB8415A7BA1F00FEE18A /* highlighter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 621DEB8215A7BA1F00FEE18A /* highlighter.cpp */; };
|
||||
62714C2FBE84B66CF14E3722 /* test_sdl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D911474D925FA88D5B856A0E /* test_sdl.cpp */; };
|
||||
627F1EDB175AF35C000042E0 /* aspect_advancements.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 627F1ED9175AF35C000042E0 /* aspect_advancements.cpp */; };
|
||||
6295C3B5150FC95C0077D8C5 /* action.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6295C3A7150FC95C0077D8C5 /* action.cpp */; };
|
||||
6295C3B6150FC95C0077D8C5 /* action_label.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6295C3AA150FC95C0077D8C5 /* action_label.cpp */; };
|
||||
|
@ -2706,6 +2707,7 @@
|
|||
C61F473D9AC43768A445E218 /* tod_new_schedule.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = tod_new_schedule.cpp; sourceTree = "<group>"; };
|
||||
C679447D91FD3623CC852FF8 /* edit_pbl_translation.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = edit_pbl_translation.hpp; sourceTree = "<group>"; };
|
||||
D4594633BF3F8A06D6AE752F /* prompt.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = prompt.hpp; sourceTree = "<group>"; };
|
||||
D911474D925FA88D5B856A0E /* test_sdl.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = test_sdl.cpp; path = test_sdl.cpp; sourceTree = "<group>"; };
|
||||
D9A141EAAE90E98B6F6171D6 /* choose_addon.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = choose_addon.hpp; sourceTree = "<group>"; };
|
||||
EC0341DF1ECF46FE000F2E2B /* config_attribute_value.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = config_attribute_value.cpp; sourceTree = "<group>"; };
|
||||
EC0341E01ECF46FE000F2E2B /* config_attribute_value.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = config_attribute_value.hpp; sourceTree = "<group>"; };
|
||||
|
@ -4796,6 +4798,7 @@
|
|||
91E356131CACA6CB00774252 /* test_recall_list.cpp */,
|
||||
91E356141CACA6CB00774252 /* test_rng.cpp */,
|
||||
B597C4AA0FACD42E00CE81F5 /* test_serialization.cpp */,
|
||||
D911474D925FA88D5B856A0E /* test_sdl.cpp */,
|
||||
B597C4A60FACD42E00CE81F5 /* test_team.cpp */,
|
||||
91E356171CACA6CB00774252 /* test_unit_map.cpp */,
|
||||
B597C4A50FACD42E00CE81F5 /* test_util.cpp */,
|
||||
|
@ -6540,6 +6543,7 @@
|
|||
EBB44A70837B84A928CB6424 /* edit_pbl_translation.cpp in Sources */,
|
||||
7BFC4DF5BFF8CF75855BA662 /* prompt.cpp in Sources */,
|
||||
C93048A9AE576B6AD016DFA4 /* tod_new_schedule.cpp in Sources */,
|
||||
62714C2FBE84B66CF14E3722 /* test_sdl.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -6643,15 +6647,15 @@
|
|||
"$(PROJECT_DIR)/Headers/SDL2",
|
||||
"$(PROJECT_DIR)/Headers/harfbuzz",
|
||||
);
|
||||
LD_CLASSIC_1000 = "";
|
||||
LD_CLASSIC_1100 = "";
|
||||
LD_CLASSIC_1200 = "";
|
||||
LD_CLASSIC_1300 = "";
|
||||
LD_CLASSIC_1400 = "";
|
||||
LD_CLASSIC_1500 = "-ld_classic";
|
||||
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/lib";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12;
|
||||
"LD_CLASSIC_1000" = "";
|
||||
"LD_CLASSIC_1100" = "";
|
||||
"LD_CLASSIC_1200" = "";
|
||||
"LD_CLASSIC_1300" = "";
|
||||
"LD_CLASSIC_1400" = "";
|
||||
"LD_CLASSIC_1500" = "-ld_classic";
|
||||
OTHER_LDFLAGS = (
|
||||
"-lz",
|
||||
"-lbz2",
|
||||
|
@ -6717,16 +6721,16 @@
|
|||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = /Applications;
|
||||
LD_CLASSIC_1000 = "";
|
||||
LD_CLASSIC_1100 = "";
|
||||
LD_CLASSIC_1200 = "";
|
||||
LD_CLASSIC_1300 = "";
|
||||
LD_CLASSIC_1400 = "";
|
||||
LD_CLASSIC_1500 = "-ld_classic";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
LLVM_LTO = YES_THIN;
|
||||
OTHER_CFLAGS = "-Wall";
|
||||
OTHER_CPLUSPLUSFLAGS = "-Wall";
|
||||
"LD_CLASSIC_1000" = "";
|
||||
"LD_CLASSIC_1100" = "";
|
||||
"LD_CLASSIC_1200" = "";
|
||||
"LD_CLASSIC_1300" = "";
|
||||
"LD_CLASSIC_1400" = "";
|
||||
"LD_CLASSIC_1500" = "-ld_classic";
|
||||
OTHER_LDFLAGS = (
|
||||
"-lz",
|
||||
"-lbz2",
|
||||
|
@ -7112,15 +7116,15 @@
|
|||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = /Applications;
|
||||
LD_CLASSIC_1000 = "";
|
||||
LD_CLASSIC_1100 = "";
|
||||
LD_CLASSIC_1200 = "";
|
||||
LD_CLASSIC_1300 = "";
|
||||
LD_CLASSIC_1400 = "";
|
||||
LD_CLASSIC_1500 = "-ld_classic";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
OTHER_CFLAGS = "-Wall";
|
||||
OTHER_CPLUSPLUSFLAGS = "-Wall";
|
||||
"LD_CLASSIC_1000" = "";
|
||||
"LD_CLASSIC_1100" = "";
|
||||
"LD_CLASSIC_1200" = "";
|
||||
"LD_CLASSIC_1300" = "";
|
||||
"LD_CLASSIC_1400" = "";
|
||||
"LD_CLASSIC_1500" = "-ld_classic";
|
||||
OTHER_LDFLAGS = (
|
||||
"-lz",
|
||||
"-lbz2",
|
||||
|
@ -7178,16 +7182,16 @@
|
|||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = /Applications;
|
||||
LD_CLASSIC_1000 = "";
|
||||
LD_CLASSIC_1100 = "";
|
||||
LD_CLASSIC_1200 = "";
|
||||
LD_CLASSIC_1300 = "";
|
||||
LD_CLASSIC_1400 = "";
|
||||
LD_CLASSIC_1500 = "-ld_classic";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
LLVM_LTO = YES_THIN;
|
||||
OTHER_CFLAGS = "-Wall";
|
||||
OTHER_CPLUSPLUSFLAGS = "-Wall";
|
||||
"LD_CLASSIC_1000" = "";
|
||||
"LD_CLASSIC_1100" = "";
|
||||
"LD_CLASSIC_1200" = "";
|
||||
"LD_CLASSIC_1300" = "";
|
||||
"LD_CLASSIC_1400" = "";
|
||||
"LD_CLASSIC_1500" = "-ld_classic";
|
||||
OTHER_LDFLAGS = (
|
||||
"-lz",
|
||||
"-lbz2",
|
||||
|
@ -7263,17 +7267,17 @@
|
|||
"$(PROJECT_DIR)/Headers/SDL2",
|
||||
"$(PROJECT_DIR)/Headers/harfbuzz",
|
||||
);
|
||||
LD_CLASSIC_1000 = "";
|
||||
LD_CLASSIC_1100 = "";
|
||||
LD_CLASSIC_1200 = "";
|
||||
LD_CLASSIC_1300 = "";
|
||||
LD_CLASSIC_1400 = "";
|
||||
LD_CLASSIC_1500 = "-ld_classic";
|
||||
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/lib";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CFLAGS = "-Wall";
|
||||
"LD_CLASSIC_1000" = "";
|
||||
"LD_CLASSIC_1100" = "";
|
||||
"LD_CLASSIC_1200" = "";
|
||||
"LD_CLASSIC_1300" = "";
|
||||
"LD_CLASSIC_1400" = "";
|
||||
"LD_CLASSIC_1500" = "-ld_classic";
|
||||
OTHER_LDFLAGS = (
|
||||
"-lz",
|
||||
"-lbz2",
|
||||
|
@ -7318,15 +7322,15 @@
|
|||
"$(PROJECT_DIR)/Headers/SDL2",
|
||||
"$(PROJECT_DIR)/Headers/harfbuzz",
|
||||
);
|
||||
LD_CLASSIC_1000 = "";
|
||||
LD_CLASSIC_1100 = "";
|
||||
LD_CLASSIC_1200 = "";
|
||||
LD_CLASSIC_1300 = "";
|
||||
LD_CLASSIC_1400 = "";
|
||||
LD_CLASSIC_1500 = "-ld_classic";
|
||||
LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = "$(PROJECT_DIR)/lib";
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12;
|
||||
"LD_CLASSIC_1000" = "";
|
||||
"LD_CLASSIC_1100" = "";
|
||||
"LD_CLASSIC_1200" = "";
|
||||
"LD_CLASSIC_1300" = "";
|
||||
"LD_CLASSIC_1400" = "";
|
||||
"LD_CLASSIC_1500" = "-ld_classic";
|
||||
OTHER_LDFLAGS = (
|
||||
"-lz",
|
||||
"-lbz2",
|
||||
|
|
|
@ -19,6 +19,7 @@ tests/test_map_location.cpp
|
|||
tests/test_mp_connect.cpp
|
||||
tests/test_recall_list.cpp
|
||||
tests/test_rng.cpp
|
||||
tests/test_sdl.cpp
|
||||
tests/test_serialization.cpp
|
||||
tests/test_simple_wml.cpp
|
||||
tests/test_team.cpp
|
||||
|
|
|
@ -395,29 +395,28 @@ surface scale_surface_legacy(const surface &surf, int w, int h)
|
|||
surface scale_surface_sharp(const surface& surf, int w, int h)
|
||||
{
|
||||
// Since SDL version 1.1.5 0 is transparent, before 255 was transparent.
|
||||
assert(SDL_ALPHA_TRANSPARENT==0);
|
||||
assert(SDL_ALPHA_TRANSPARENT == 0);
|
||||
|
||||
if(surf == nullptr)
|
||||
if(surf == nullptr) {
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
if(w == surf->w && h == surf->h) {
|
||||
return surf;
|
||||
}
|
||||
|
||||
assert(w >= 0);
|
||||
assert(h >= 0);
|
||||
|
||||
surface dst(w,h);
|
||||
|
||||
if (w == 0 || h ==0) {
|
||||
PLAIN_LOG << "Create an empty image";
|
||||
return dst;
|
||||
}
|
||||
|
||||
if(surf == nullptr || dst == nullptr) {
|
||||
surface dst(w, h);
|
||||
if(dst == nullptr) {
|
||||
PLAIN_LOG << "Could not create surface to scale onto";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(w == 0 || h == 0) {
|
||||
PLAIN_LOG << "Creating an empty image";
|
||||
return dst;
|
||||
}
|
||||
|
||||
{
|
||||
const_surface_lock src_lock(surf);
|
||||
surface_lock dst_lock(dst);
|
||||
|
@ -425,56 +424,18 @@ surface scale_surface_sharp(const surface& surf, int w, int h)
|
|||
const uint32_t* const src_pixels = src_lock.pixels();
|
||||
uint32_t* const dst_pixels = dst_lock.pixels();
|
||||
|
||||
float xratio = static_cast<float>(surf->w) / w;
|
||||
float yratio = static_cast<float>(surf->h) / h;
|
||||
const int src_w = surf->w;
|
||||
const int src_h = surf->h;
|
||||
|
||||
float ysrc = 0.0f;
|
||||
for(int ydst = 0; ydst != h; ++ydst, ysrc += yratio) {
|
||||
float xsrc = 0.0f;
|
||||
for(int xdst = 0; xdst != w; ++xdst, xsrc += xratio) {
|
||||
float red = 0.0f, green = 0.0f, blue = 0.0f, alpha = 0.0f;
|
||||
|
||||
float summation = 0.0f;
|
||||
|
||||
// We now have a rectangle, (xsrc,ysrc,xratio,yratio)
|
||||
// which we want to derive the pixel from
|
||||
for(float xloc = xsrc; xloc < xsrc+xratio; xloc += 1) {
|
||||
const float xsize = std::min<float>(std::floor(xloc+1)-xloc,xsrc+xratio-xloc);
|
||||
|
||||
for(float yloc = ysrc; yloc < ysrc+yratio; yloc += 1) {
|
||||
const int xsrcint = std::max<int>(0,std::min<int>(surf->w-1,static_cast<int>(xsrc)));
|
||||
const int ysrcint = std::max<int>(0,std::min<int>(surf->h-1,static_cast<int>(ysrc)));
|
||||
const float ysize = std::min<float>(std::floor(yloc+1)-yloc,ysrc+yratio-yloc);
|
||||
|
||||
uint8_t r,g,b,a;
|
||||
|
||||
SDL_GetRGBA(src_pixels[ysrcint*surf->w + xsrcint],surf->format,&r,&g,&b,&a);
|
||||
float value = xsize * ysize;
|
||||
summation += value;
|
||||
if (!a) continue;
|
||||
value *= a;
|
||||
alpha += value;
|
||||
red += r * value;
|
||||
green += g * value;
|
||||
blue += b * value;
|
||||
}
|
||||
}
|
||||
|
||||
if (alpha != 0) {
|
||||
red = red / alpha + 0.5f;
|
||||
green = green / alpha + 0.5f;
|
||||
blue = blue / alpha + 0.5f;
|
||||
alpha = alpha / summation + 0.5f;
|
||||
}
|
||||
|
||||
dst_pixels[ydst*dst->w + xdst] = SDL_MapRGBA(
|
||||
dst->format
|
||||
, static_cast<uint8_t>(red)
|
||||
, static_cast<uint8_t>(green)
|
||||
, static_cast<uint8_t>(blue)
|
||||
, static_cast<uint8_t>(alpha));
|
||||
const float xratio = static_cast<float>(src_w) / static_cast<float>(w);
|
||||
const float yratio = static_cast<float>(src_h) / static_cast<float>(h);
|
||||
for(int ydst = 0; ydst != h; ++ydst) {
|
||||
for(int xdst = 0; xdst != w; ++xdst) {
|
||||
// Project dst pixel to a single corresponding src pixel by scale and simply take it
|
||||
const int xsrc = std::floor(static_cast<float>(xdst) * xratio);
|
||||
const int ysrc = std::floor(static_cast<float>(ydst) * yratio);
|
||||
dst_pixels[ydst * dst->w + xdst] = src_pixels[ysrc * src_w + xsrc];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
108
src/tests/test_sdl.cpp
Normal file
108
src/tests/test_sdl.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
Copyright (C) 2023
|
||||
Part of the Battle for Wesnoth Project https://www.wesnoth.org/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY.
|
||||
|
||||
See the COPYING file for more details.
|
||||
*/
|
||||
|
||||
#define GETTEXT_DOMAIN "wesnoth-test"
|
||||
|
||||
#include "sdl/surface.hpp"
|
||||
#include "sdl/utils.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
constexpr uint32_t red = 0xFF'FF'00'00;
|
||||
constexpr uint32_t green = 0xFF'00'FF'00;
|
||||
constexpr uint32_t blue = 0xFF'00'00'FF;
|
||||
constexpr uint32_t yellow = 0xFF'FF'FF'00;
|
||||
constexpr uint32_t white = 0xFF'FF'FF'FF;
|
||||
constexpr uint32_t black = 0xFF'00'00'00;
|
||||
|
||||
constexpr std::array<uint32_t, 16> img_4x4 {
|
||||
red, white, green, black,
|
||||
black, black, black, black,
|
||||
blue, white, yellow, black,
|
||||
black, black, black, black,
|
||||
};
|
||||
|
||||
constexpr std::array<uint32_t, 4> img_4x4_to_2x2_result {
|
||||
red, green,
|
||||
blue, yellow,
|
||||
};
|
||||
|
||||
constexpr std::array<uint32_t, 6> img_4x4_to_3x2_result {
|
||||
red, white, green,
|
||||
blue, white, yellow
|
||||
};
|
||||
|
||||
template<size_t w, size_t h>
|
||||
surface array_to_surface(const std::array<uint32_t, w * h>& arr)
|
||||
{
|
||||
surface surf{w, h};
|
||||
|
||||
{
|
||||
surface_lock surf_lock{surf};
|
||||
uint32_t* const pixels = surf_lock.pixels();
|
||||
for(size_t i = 0; i < w * h; ++i) {
|
||||
pixels[i] = arr[i];
|
||||
}
|
||||
}
|
||||
|
||||
return surf;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> surface_to_vec(const surface& surf)
|
||||
{
|
||||
const_surface_lock lock{surf};
|
||||
const uint32_t* const pixels = lock.pixels();
|
||||
std::vector<uint32_t> pixel_vec;
|
||||
const int surf_size = surf->w * surf->h;
|
||||
std::copy(pixels, pixels + surf_size, std::back_inserter(pixel_vec));
|
||||
return pixel_vec;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(sdl)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_scale_sharp_nullptr)
|
||||
{
|
||||
surface result = scale_surface_sharp(nullptr, 2, 2);
|
||||
BOOST_CHECK_EQUAL(result, nullptr);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_scale_sharp_zero)
|
||||
{
|
||||
surface src = array_to_surface<4, 4>(img_4x4);
|
||||
surface result = scale_surface_sharp(src, 0, 0);
|
||||
BOOST_CHECK_EQUAL(result->w, 0);
|
||||
BOOST_CHECK_EQUAL(result->h, 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_scale_sharp_round)
|
||||
{
|
||||
surface src = array_to_surface<4, 4>(img_4x4);
|
||||
surface result = scale_surface_sharp(src, 2, 2);
|
||||
std::vector<uint32_t> result_pixels = surface_to_vec(result);
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(
|
||||
result_pixels.begin(), result_pixels.end(), img_4x4_to_2x2_result.begin(), img_4x4_to_2x2_result.end());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_scale_sharp_fractional)
|
||||
{
|
||||
surface src = array_to_surface<4, 4>(img_4x4);
|
||||
surface result = scale_surface_sharp(src, 3, 2);
|
||||
std::vector<uint32_t> result_pixels = surface_to_vec(result);
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(
|
||||
result_pixels.begin(), result_pixels.end(), img_4x4_to_3x2_result.begin(), img_4x4_to_3x2_result.end());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
Reference in New Issue
Block a user