move image scaling functions to their own unit, as -O2
This commit is contained in:
parent
9da08e898d
commit
6b49f382e3
@ -41,6 +41,7 @@ SET (star_core_HEADERS
|
||||
StarIdMap.hpp
|
||||
StarImage.hpp
|
||||
StarImageProcessing.hpp
|
||||
StarImageScaling.hpp
|
||||
StarInputEvent.hpp
|
||||
StarInterpolation.hpp
|
||||
StarRefPtr.hpp
|
||||
@ -152,6 +153,7 @@ SET (star_core_SOURCES
|
||||
StarIODevice.cpp
|
||||
StarImage.cpp
|
||||
StarImageProcessing.cpp
|
||||
StarImageScaling.cpp
|
||||
StarInputEvent.cpp
|
||||
StarJson.cpp
|
||||
StarJsonBuilder.cpp
|
||||
@ -229,6 +231,10 @@ IF(STAR_PRECOMPILED_HEADERS)
|
||||
TARGET_PRECOMPILE_HEADERS (star_core PUBLIC StarPch.hpp)
|
||||
ENDIF()
|
||||
|
||||
IF(STAR_COMPILER STREQUAL "gnu")
|
||||
SET_SOURCE_FILES_PROPERTIES(StarImageScaling.cpp PROPERTIES COMPILE_FLAGS "-O2")
|
||||
ENDIF()
|
||||
|
||||
IF(STAR_USE_JEMALLOC AND JEMALLOC_IS_PREFIXED)
|
||||
SET_SOURCE_FILES_PROPERTIES(StarMemory.cpp PROPERTIES
|
||||
COMPILE_DEFINITIONS STAR_JEMALLOC_IS_PREFIXED
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "StarImageProcessing.hpp"
|
||||
#include "StarImageScaling.hpp"
|
||||
#include "StarMatrix3.hpp"
|
||||
#include "StarInterpolation.hpp"
|
||||
#include "StarLexicalCast.hpp"
|
||||
@ -10,104 +11,6 @@
|
||||
|
||||
namespace Star {
|
||||
|
||||
Image scaleNearest(Image const& srcImage, Vec2F const& scale) {
|
||||
Vec2U srcSize = srcImage.size();
|
||||
Vec2U destSize = Vec2U::round(vmult(Vec2F(srcSize), scale));
|
||||
destSize[0] = max(destSize[0], 1u);
|
||||
destSize[1] = max(destSize[1], 1u);
|
||||
|
||||
Image destImage(destSize, srcImage.pixelFormat());
|
||||
|
||||
for (unsigned y = 0; y < destSize[1]; ++y) {
|
||||
for (unsigned x = 0; x < destSize[0]; ++x)
|
||||
destImage.set({x, y}, srcImage.clamp(Vec2I::round(vdiv(Vec2F(x, y), scale))));
|
||||
}
|
||||
return destImage;
|
||||
}
|
||||
|
||||
#pragma GCC push_options
|
||||
#pragma GCC optimize("-fno-unsafe-math-optimizations", "-ffloat-store")
|
||||
Image scaleBilinear(Image const& srcImage, Vec2F const& scale) {
|
||||
Vec2U srcSize = srcImage.size();
|
||||
Vec2U destSize = Vec2U::round(vmult(Vec2F(srcSize), scale));
|
||||
destSize[0] = max(destSize[0], 1u);
|
||||
destSize[1] = max(destSize[1], 1u);
|
||||
|
||||
Image destImage(destSize, srcImage.pixelFormat());
|
||||
|
||||
auto lerpVec = [](float const& offset, Vec4F f0, Vec4F f1) {
|
||||
return f0 * (1 - offset) + f1 * (offset);
|
||||
};
|
||||
|
||||
for (unsigned y = 0; y < destSize[1]; ++y) {
|
||||
for (unsigned x = 0; x < destSize[0]; ++x) {
|
||||
auto pos = vdiv(Vec2F(x, y), scale);
|
||||
auto ipart = Vec2I::floor(pos);
|
||||
auto fpart = pos - Vec2F(ipart);
|
||||
|
||||
auto result = lerpVec(fpart[1], lerpVec(fpart[0], Vec4F(srcImage.clamp(ipart[0], ipart[1])), Vec4F(srcImage.clamp(ipart[0] + 1, ipart[1]))), lerpVec(fpart[0],
|
||||
Vec4F(srcImage.clamp(ipart[0], ipart[1] + 1)), Vec4F(srcImage.clamp(ipart[0] + 1, ipart[1] + 1))));
|
||||
|
||||
destImage.set({x, y}, Vec4B(result));
|
||||
}
|
||||
}
|
||||
|
||||
return destImage;
|
||||
}
|
||||
|
||||
Image scaleBicubic(Image const& srcImage, Vec2F const& scale) {
|
||||
Vec2U srcSize = srcImage.size();
|
||||
Vec2U destSize = Vec2U::round(vmult(Vec2F(srcSize), scale));
|
||||
destSize[0] = max(destSize[0], 1u);
|
||||
destSize[1] = max(destSize[1], 1u);
|
||||
|
||||
Image destImage(destSize, srcImage.pixelFormat());
|
||||
|
||||
for (unsigned y = 0; y < destSize[1]; ++y) {
|
||||
for (unsigned x = 0; x < destSize[0]; ++x) {
|
||||
auto pos = vdiv(Vec2F(x, y), scale);
|
||||
auto ipart = Vec2I::floor(pos);
|
||||
auto fpart = pos - Vec2F(ipart);
|
||||
|
||||
Vec4F a = cubic4(fpart[0],
|
||||
Vec4F(srcImage.clamp(ipart[0], ipart[1])),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 1, ipart[1])),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 2, ipart[1])),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 3, ipart[1])));
|
||||
|
||||
Vec4F b = cubic4(fpart[0],
|
||||
Vec4F(srcImage.clamp(ipart[0], ipart[1] + 1)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 1, ipart[1] + 1)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 2, ipart[1] + 1)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 3, ipart[1] + 1)));
|
||||
|
||||
Vec4F c = cubic4(fpart[0],
|
||||
Vec4F(srcImage.clamp(ipart[0], ipart[1] + 2)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 1, ipart[1] + 2)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 2, ipart[1] + 2)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 3, ipart[1] + 2)));
|
||||
|
||||
Vec4F d = cubic4(fpart[0],
|
||||
Vec4F(srcImage.clamp(ipart[0], ipart[1] + 3)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 1, ipart[1] + 3)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 2, ipart[1] + 3)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 3, ipart[1] + 3)));
|
||||
|
||||
auto result = cubic4(fpart[1], a, b, c, d);
|
||||
|
||||
destImage.set({x, y}, Vec4B(
|
||||
clamp(result[0], 0.0f, 255.0f),
|
||||
clamp(result[1], 0.0f, 255.0f),
|
||||
clamp(result[2], 0.0f, 255.0f),
|
||||
clamp(result[3], 0.0f, 255.0f)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return destImage;
|
||||
}
|
||||
#pragma GCC pop_options
|
||||
|
||||
StringList colorDirectivesFromConfig(JsonArray const& directives) {
|
||||
List<String> result;
|
||||
|
||||
|
@ -10,10 +10,6 @@ STAR_CLASS(Image);
|
||||
|
||||
STAR_EXCEPTION(ImageOperationException, StarException);
|
||||
|
||||
Image scaleNearest(Image const& srcImage, Vec2F const& scale);
|
||||
Image scaleBilinear(Image const& srcImage, Vec2F const& scale);
|
||||
Image scaleBicubic(Image const& srcImage, Vec2F const& scale);
|
||||
|
||||
StringList colorDirectivesFromConfig(JsonArray const& directives);
|
||||
String paletteSwapDirectivesFromConfig(Json const& swaps);
|
||||
|
||||
|
98
source/core/StarImageScaling.cpp
Normal file
98
source/core/StarImageScaling.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
#include "StarImage.hpp"
|
||||
#include "StarImageScaling.hpp"
|
||||
#include "StarInterpolation.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
Image scaleNearest(Image const& srcImage, Vec2F const& scale) {
|
||||
Vec2U srcSize = srcImage.size();
|
||||
Vec2U destSize = Vec2U::round(vmult(Vec2F(srcSize), scale));
|
||||
destSize[0] = max(destSize[0], 1u);
|
||||
destSize[1] = max(destSize[1], 1u);
|
||||
|
||||
Image destImage(destSize, srcImage.pixelFormat());
|
||||
|
||||
for (unsigned y = 0; y < destSize[1]; ++y) {
|
||||
for (unsigned x = 0; x < destSize[0]; ++x)
|
||||
destImage.set({x, y}, srcImage.clamp(Vec2I::round(vdiv(Vec2F(x, y), scale))));
|
||||
}
|
||||
return destImage;
|
||||
}
|
||||
|
||||
Image scaleBilinear(Image const& srcImage, Vec2F const& scale) {
|
||||
Vec2U srcSize = srcImage.size();
|
||||
Vec2U destSize = Vec2U::round(vmult(Vec2F(srcSize), scale));
|
||||
destSize[0] = max(destSize[0], 1u);
|
||||
destSize[1] = max(destSize[1], 1u);
|
||||
|
||||
Image destImage(destSize, srcImage.pixelFormat());
|
||||
|
||||
for (unsigned y = 0; y < destSize[1]; ++y) {
|
||||
for (unsigned x = 0; x < destSize[0]; ++x) {
|
||||
auto pos = vdiv(Vec2F(x, y), scale);
|
||||
auto ipart = Vec2I::floor(pos);
|
||||
auto fpart = pos - Vec2F(ipart);
|
||||
|
||||
auto result = lerp(fpart[1], lerp(fpart[0], Vec4F(srcImage.clamp(ipart[0], ipart[1])), Vec4F(srcImage.clamp(ipart[0] + 1, ipart[1]))), lerp(fpart[0],
|
||||
Vec4F(srcImage.clamp(ipart[0], ipart[1] + 1)), Vec4F(srcImage.clamp(ipart[0] + 1, ipart[1] + 1))));
|
||||
|
||||
destImage.set({x, y}, Vec4B(result));
|
||||
}
|
||||
}
|
||||
|
||||
return destImage;
|
||||
}
|
||||
|
||||
Image scaleBicubic(Image const& srcImage, Vec2F const& scale) {
|
||||
Vec2U srcSize = srcImage.size();
|
||||
Vec2U destSize = Vec2U::round(vmult(Vec2F(srcSize), scale));
|
||||
destSize[0] = max(destSize[0], 1u);
|
||||
destSize[1] = max(destSize[1], 1u);
|
||||
|
||||
Image destImage(destSize, srcImage.pixelFormat());
|
||||
|
||||
for (unsigned y = 0; y < destSize[1]; ++y) {
|
||||
for (unsigned x = 0; x < destSize[0]; ++x) {
|
||||
auto pos = vdiv(Vec2F(x, y), scale);
|
||||
auto ipart = Vec2I::floor(pos);
|
||||
auto fpart = pos - Vec2F(ipart);
|
||||
|
||||
Vec4F a = cubic4(fpart[0],
|
||||
Vec4F(srcImage.clamp(ipart[0], ipart[1])),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 1, ipart[1])),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 2, ipart[1])),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 3, ipart[1])));
|
||||
|
||||
Vec4F b = cubic4(fpart[0],
|
||||
Vec4F(srcImage.clamp(ipart[0], ipart[1] + 1)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 1, ipart[1] + 1)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 2, ipart[1] + 1)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 3, ipart[1] + 1)));
|
||||
|
||||
Vec4F c = cubic4(fpart[0],
|
||||
Vec4F(srcImage.clamp(ipart[0], ipart[1] + 2)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 1, ipart[1] + 2)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 2, ipart[1] + 2)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 3, ipart[1] + 2)));
|
||||
|
||||
Vec4F d = cubic4(fpart[0],
|
||||
Vec4F(srcImage.clamp(ipart[0], ipart[1] + 3)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 1, ipart[1] + 3)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 2, ipart[1] + 3)),
|
||||
Vec4F(srcImage.clamp(ipart[0] + 3, ipart[1] + 3)));
|
||||
|
||||
auto result = cubic4(fpart[1], a, b, c, d);
|
||||
|
||||
destImage.set({x, y}, Vec4B(
|
||||
clamp(result[0], 0.0f, 255.0f),
|
||||
clamp(result[1], 0.0f, 255.0f),
|
||||
clamp(result[2], 0.0f, 255.0f),
|
||||
clamp(result[3], 0.0f, 255.0f)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return destImage;
|
||||
}
|
||||
|
||||
}
|
8
source/core/StarImageScaling.hpp
Normal file
8
source/core/StarImageScaling.hpp
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Star {
|
||||
|
||||
STAR_CLASS(Image);
|
||||
Image scaleNearest(Image const& srcImage, Vec2F const& scale);
|
||||
Image scaleBilinear(Image const& srcImage, Vec2F const& scale);
|
||||
Image scaleBicubic(Image const& srcImage, Vec2F const& scale);
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user