speed up blurhash decode a bit

This commit is contained in:
Nicolas Werner 2021-10-20 15:19:04 +02:00
parent 2902bbb7e7
commit 5bce8fd915
No known key found for this signature in database
GPG key ID: C8D75E610773F2D9
2 changed files with 17 additions and 18 deletions

View file

@ -6,10 +6,6 @@
#include <cmath> #include <cmath>
#include <stdexcept> #include <stdexcept>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest.h> #include <doctest.h>
#endif #endif
@ -17,6 +13,9 @@
using namespace std::literals; using namespace std::literals;
namespace { namespace {
template<class T>
T pi = 3.14159265358979323846;
constexpr std::array<char, 84> int_to_b83{ constexpr std::array<char, 84> int_to_b83{
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~"}; "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~"};
@ -62,13 +61,13 @@ struct Components
}; };
int int
packComponents(const Components &c) packComponents(const Components &c) noexcept
{ {
return (c.x - 1) + (c.y - 1) * 9; return (c.x - 1) + (c.y - 1) * 9;
} }
Components Components
unpackComponents(int c) unpackComponents(int c) noexcept
{ {
return {c % 9 + 1, c / 9 + 1}; return {c % 9 + 1, c / 9 + 1};
} }
@ -88,7 +87,7 @@ decode83(std::string_view value)
} }
float float
decodeMaxAC(int quantizedMaxAC) decodeMaxAC(int quantizedMaxAC) noexcept
{ {
return (quantizedMaxAC + 1) / 166.; return (quantizedMaxAC + 1) / 166.;
} }
@ -101,13 +100,13 @@ decodeMaxAC(std::string_view maxAC)
} }
int int
encodeMaxAC(float maxAC) encodeMaxAC(float maxAC) noexcept
{ {
return std::max(0, std::min(82, int(maxAC * 166 - 0.5))); return std::max(0, std::min(82, int(maxAC * 166 - 0.5f)));
} }
float float
srgbToLinear(int value) srgbToLinear(int value) noexcept
{ {
auto srgbToLinearF = [](float x) { auto srgbToLinearF = [](float x) {
if (x <= 0.0f) if (x <= 0.0f)
@ -124,7 +123,7 @@ srgbToLinear(int value)
} }
int int
linearToSrgb(float value) linearToSrgb(float value) noexcept
{ {
auto linearToSrgbF = [](float x) -> float { auto linearToSrgbF = [](float x) -> float {
if (x <= 0.0f) if (x <= 0.0f)
@ -137,7 +136,7 @@ linearToSrgb(float value)
return std::pow(x, 1.0f / 2.4f) * 1.055f - 0.055f; return std::pow(x, 1.0f / 2.4f) * 1.055f - 0.055f;
}; };
return int(linearToSrgbF(value) * 255.f + 0.5); return int(linearToSrgbF(value) * 255.f + 0.5f);
} }
struct Color struct Color
@ -235,8 +234,8 @@ multiplyBasisFunction(Components components, int width, int height, unsigned cha
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
float basis = std::cos(M_PI * components.x * x / float(width)) * float basis = std::cos(pi<float> * components.x * x / float(width)) *
std::cos(M_PI * components.y * y / float(height)); std::cos(pi<float> * components.y * y / float(height));
c.r += basis * srgbToLinear(pixels[3 * x + 0 + y * width * 3]); c.r += basis * srgbToLinear(pixels[3 * x + 0 + y * width * 3]);
c.g += basis * srgbToLinear(pixels[3 * x + 1 + y * width * 3]); c.g += basis * srgbToLinear(pixels[3 * x + 1 + y * width * 3]);
c.b += basis * srgbToLinear(pixels[3 * x + 2 + y * width * 3]); c.b += basis * srgbToLinear(pixels[3 * x + 2 + y * width * 3]);
@ -251,7 +250,7 @@ multiplyBasisFunction(Components components, int width, int height, unsigned cha
namespace blurhash { namespace blurhash {
Image Image
decode(std::string_view blurhash, size_t width, size_t height, size_t bytesPerPixel) decode(std::string_view blurhash, size_t width, size_t height, size_t bytesPerPixel) noexcept
{ {
Image i{}; Image i{};
@ -287,8 +286,8 @@ decode(std::string_view blurhash, size_t width, size_t height, size_t bytesPerPi
for (size_t nx = 0; nx < size_t(components.x); nx++) { for (size_t nx = 0; nx < size_t(components.x); nx++) {
for (size_t ny = 0; ny < size_t(components.y); ny++) { for (size_t ny = 0; ny < size_t(components.y); ny++) {
float basis = float basis =
std::cos(M_PI * float(x) * float(nx) / float(width)) * std::cos(pi<float> * float(nx * x) / float(width)) *
std::cos(M_PI * float(y) * float(ny) / float(height)); std::cos(pi<float> * float(ny * y) / float(height));
c += values[nx + ny * components.x] * basis; c += values[nx + ny * components.x] * basis;
} }
} }

View file

@ -13,7 +13,7 @@ struct Image
// Decode a blurhash to an image with size width*height // Decode a blurhash to an image with size width*height
Image Image
decode(std::string_view blurhash, size_t width, size_t height, size_t bytesPerPixel = 3); decode(std::string_view blurhash, size_t width, size_t height, size_t bytesPerPixel = 3) noexcept;
// Encode an image of rgb pixels (without padding) with size width*height into a blurhash with x*y // Encode an image of rgb pixels (without padding) with size width*height into a blurhash with x*y
// components // components