@react-native-ohos/react-native-blurhash 2.0.4-rc.1 → 2.0.4-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/harmony/blurhash/index.ets +2 -0
- package/harmony/blurhash/oh-package.json5 +1 -1
- package/harmony/blurhash/src/main/cpp/Blurhash.cpp +171 -77
- package/harmony/blurhash/src/main/cpp/{Blurhash.hpp → Blurhash.h} +5 -2
- package/harmony/blurhash/src/main/cpp/BlurhashNode.cpp +18 -12
- package/harmony/blurhash/src/main/cpp/BlurhashNode.h +3 -2
- package/harmony/blurhash/src/main/cpp/BlurhashPackage.h +23 -12
- package/harmony/blurhash/src/main/cpp/BlurhashViewComponentInstance.cpp +56 -82
- package/harmony/blurhash/src/main/cpp/BlurhashViewComponentInstance.h +8 -5
- package/harmony/blurhash/src/main/cpp/BlurhashViewJSIBinder.h +11 -7
- package/harmony/blurhash/src/main/cpp/ComponentDescriptors.h +4 -2
- package/harmony/blurhash/src/main/cpp/EventEmitters.cpp +9 -8
- package/harmony/blurhash/src/main/cpp/EventEmitters.h +4 -4
- package/harmony/blurhash/src/main/cpp/Props.cpp +11 -10
- package/harmony/blurhash/src/main/cpp/Props.h +19 -13
- package/harmony/blurhash/src/main/cpp/RNBlurhashTurboModule.cpp +16 -10
- package/harmony/blurhash/src/main/cpp/RNBlurhashTurboModule.h +3 -3
- package/harmony/blurhash/src/main/cpp/ShadowNodes.cpp +1 -2
- package/harmony/blurhash/src/main/cpp/ShadowNodes.h +5 -5
- package/harmony/blurhash/src/main/cpp/SparseArray.cpp +7 -4
- package/harmony/blurhash/src/main/cpp/SparseArray.h +2 -2
- package/harmony/blurhash/src/main/cpp/napi_init.cpp +4 -5
- package/harmony/blurhash/src/main/ets/{BlurhashPackage.ts → BlurhashPackage.ets} +3 -2
- package/harmony/blurhash/{ts.ts → ts.ets} +1 -1
- package/harmony/blurhash.har +0 -0
- package/package.json +12 -5
- package/harmony/blurhash/BuildProfile.ets +0 -17
- package/lib/commonjs/index.js +0 -95
- package/lib/commonjs/index.js.map +0 -1
- package/lib/commonjs/specs/NativeBlurhashModule.js +0 -9
- package/lib/commonjs/specs/NativeBlurhashModule.js.map +0 -1
- package/lib/commonjs/specs/NativeBlurhashView.js +0 -10
- package/lib/commonjs/specs/NativeBlurhashView.js.map +0 -1
- package/lib/commonjs/utils.js +0 -56
- package/lib/commonjs/utils.js.map +0 -1
- package/lib/module/index.js +0 -85
- package/lib/module/index.js.map +0 -1
- package/lib/module/specs/NativeBlurhashModule.js +0 -3
- package/lib/module/specs/NativeBlurhashModule.js.map +0 -1
- package/lib/module/specs/NativeBlurhashView.js +0 -3
- package/lib/module/specs/NativeBlurhashView.js.map +0 -1
- package/lib/module/utils.js +0 -48
- package/lib/module/utils.js.map +0 -1
- package/lib/typescript/index.d.ts +0 -90
- package/lib/typescript/specs/NativeBlurhashModule.d.ts +0 -9
- package/lib/typescript/specs/NativeBlurhashView.d.ts +0 -19
- package/lib/typescript/utils.d.ts +0 -22
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* found in the LICENSE file.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
#include "Blurhash.
|
|
7
|
+
#include "Blurhash.h"
|
|
8
8
|
|
|
9
9
|
#include <algorithm>
|
|
10
10
|
#include <array>
|
|
@@ -21,16 +21,58 @@
|
|
|
21
21
|
#include "stb_image_write.h"
|
|
22
22
|
#include "stb_image.h"
|
|
23
23
|
#include <glog/logging.h>
|
|
24
|
+
#define MIN_BLURHASH_SIZE 6
|
|
25
|
+
#define AC_VALUE_MULTIPLIER 166
|
|
26
|
+
#define MIN_COMPONENT 1
|
|
27
|
+
#define MAX_COMPONENT 9
|
|
28
|
+
#define COMPONENT_3 3
|
|
29
|
+
#define CHANNELS_PER_PIXEL 3
|
|
30
|
+
#define CONSTANT_SIZE 2
|
|
31
|
+
#define MAX_PIXEL_VALUE 255
|
|
32
|
+
#define MAX_AC_SIZE 4
|
|
33
|
+
#define MAX_ENCODED_VALUE 82
|
|
34
|
+
#define BASE 83
|
|
35
|
+
#define DEFAULT_CHANNELS 3
|
|
36
|
+
#define LEFT_PADDING_2 2
|
|
37
|
+
#define LEFT_PADDING_4 4
|
|
38
|
+
#define RED_SHIFT 16
|
|
39
|
+
#define GREEN_SHIFT 8
|
|
40
|
+
#define MAX_X 9
|
|
41
|
+
#define HEX_DIGITS_PER_CHAR 2
|
|
42
|
+
#define QUANT_STEP 19
|
|
43
|
+
#define RED_CHANNEL 0
|
|
44
|
+
#define GREEN_CHANNEL 1
|
|
45
|
+
#define BLUE_CHANNEL 2
|
|
46
|
+
#define AC_COMPONENT_SIZE 2
|
|
47
|
+
#define EXPECTEDSIZE 4
|
|
24
48
|
|
|
25
49
|
using namespace std::literals;
|
|
26
50
|
|
|
27
51
|
namespace {
|
|
28
52
|
SparseArray<std::vector<double>> cacheCosinesX;
|
|
29
53
|
SparseArray<std::vector<double>> cacheCosinesY;
|
|
30
|
-
constexpr std::array<char, 84> int_to_b83{
|
|
31
|
-
|
|
32
|
-
|
|
54
|
+
constexpr std::array<char, 84> int_to_b83{
|
|
55
|
+
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~"};
|
|
56
|
+
|
|
57
|
+
inline bool NearEqual(const float left, const float right, const float epsilon)
|
|
58
|
+
{
|
|
59
|
+
return (std::abs(left - right) <= epsilon);
|
|
60
|
+
}
|
|
61
|
+
inline bool NearZero(const float value, const float epsilon)
|
|
62
|
+
{
|
|
63
|
+
return NearEqual(value, 0.0, epsilon);
|
|
64
|
+
}
|
|
65
|
+
inline bool NearZero(const float value)
|
|
66
|
+
{
|
|
67
|
+
constexpr float epsilon = 0.001f;
|
|
68
|
+
return NearZero(value, epsilon);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
std::string leftPad(std::string str, size_t len)
|
|
72
|
+
{
|
|
73
|
+
if (str.size() >= len) {
|
|
33
74
|
return str;
|
|
75
|
+
}
|
|
34
76
|
return str.insert(0, len - str.size(), '0');
|
|
35
77
|
}
|
|
36
78
|
constexpr std::array<int, 255> b83_to_int = []() constexpr {
|
|
@@ -42,122 +84,171 @@ constexpr std::array<int, 255> b83_to_int = []() constexpr {
|
|
|
42
84
|
}
|
|
43
85
|
return a;
|
|
44
86
|
}();
|
|
45
|
-
std::string encode83(int value)
|
|
87
|
+
std::string encode83(int value)
|
|
88
|
+
{
|
|
46
89
|
std::string buffer;
|
|
47
90
|
do {
|
|
48
|
-
buffer += int_to_b83[value %
|
|
49
|
-
} while ((value = value /
|
|
91
|
+
buffer += int_to_b83[value % BASE];
|
|
92
|
+
} while ((value = value / BASE));
|
|
50
93
|
std::reverse(buffer.begin(), buffer.end());
|
|
51
94
|
return buffer;
|
|
52
95
|
}
|
|
53
96
|
struct Components {
|
|
54
97
|
int x, y;
|
|
55
98
|
};
|
|
56
|
-
int packComponents(const Components &c) noexcept
|
|
57
|
-
|
|
58
|
-
|
|
99
|
+
int packComponents(const Components &c) noexcept
|
|
100
|
+
{
|
|
101
|
+
return (c.x - 1) + (c.y - 1) * MAX_X;
|
|
102
|
+
}
|
|
103
|
+
Components unpackComponents(int c) noexcept
|
|
104
|
+
{
|
|
105
|
+
return {c % MAX_X + 1, c / MAX_X + 1};
|
|
106
|
+
}
|
|
107
|
+
int decode83(std::string_view value)
|
|
108
|
+
{
|
|
59
109
|
int temp = 0;
|
|
60
110
|
for (char c : value)
|
|
61
111
|
if (b83_to_int[static_cast<unsigned char>(c)] < 0)
|
|
62
112
|
throw std::invalid_argument("invalid character in blurhash");
|
|
63
113
|
for (char c : value)
|
|
64
|
-
temp = temp *
|
|
114
|
+
temp = temp * BASE + b83_to_int[static_cast<unsigned char>(c)];
|
|
65
115
|
return temp;
|
|
66
116
|
}
|
|
67
|
-
float decodeMaxAC(int quantizedMaxAC) noexcept
|
|
68
|
-
|
|
69
|
-
|
|
117
|
+
float decodeMaxAC(int quantizedMaxAC) noexcept
|
|
118
|
+
{
|
|
119
|
+
return static_cast<float>(quantizedMaxAC + 1) / 166.f;
|
|
120
|
+
}
|
|
121
|
+
float decodeMaxAC(std::string_view maxAC)
|
|
122
|
+
{
|
|
123
|
+
if (maxAC.size() != 1) {
|
|
124
|
+
return 0.0f;
|
|
125
|
+
}
|
|
70
126
|
return decodeMaxAC(decode83(maxAC));
|
|
71
127
|
}
|
|
72
|
-
int encodeMaxAC(float maxAC) noexcept
|
|
73
|
-
|
|
128
|
+
int encodeMaxAC(float maxAC) noexcept
|
|
129
|
+
{
|
|
130
|
+
return std::max(0, std::min(MAX_ENCODED_VALUE, int(maxAC * AC_VALUE_MULTIPLIER - 0.5f)));
|
|
131
|
+
}
|
|
132
|
+
float srgbToLinear(int value) noexcept
|
|
133
|
+
{
|
|
74
134
|
auto srgbToLinearF = [](float x) {
|
|
75
|
-
if (x <= 0.0f)
|
|
135
|
+
if (x <= 0.0f) {
|
|
76
136
|
return 0.0f;
|
|
77
|
-
else if (x >= 1.0f)
|
|
137
|
+
} else if (x >= 1.0f) {
|
|
78
138
|
return 1.0f;
|
|
79
|
-
else if (x < 0.04045f)
|
|
139
|
+
} else if (x < 0.04045f) {
|
|
80
140
|
return x / 12.92f;
|
|
81
|
-
else
|
|
141
|
+
} else {
|
|
82
142
|
return std::pow((x + 0.055f) / 1.055f, 2.4f);
|
|
143
|
+
}
|
|
83
144
|
};
|
|
84
145
|
return srgbToLinearF(static_cast<float>(value) / 255.f);
|
|
85
146
|
}
|
|
86
|
-
int linearToSrgb(float value) noexcept
|
|
147
|
+
int linearToSrgb(float value) noexcept
|
|
148
|
+
{
|
|
87
149
|
auto linearToSrgbF = [](float x) -> float {
|
|
88
|
-
if (x <= 0.0f)
|
|
150
|
+
if (x <= 0.0f) {
|
|
89
151
|
return 0.0f;
|
|
90
|
-
else if (x >= 1.0f)
|
|
152
|
+
} else if (x >= 1.0f) {
|
|
91
153
|
return 1.0f;
|
|
92
|
-
else if (x < 0.0031308f)
|
|
154
|
+
} else if (x < 0.0031308f) {
|
|
93
155
|
return x * 12.92f;
|
|
94
|
-
else
|
|
156
|
+
} else {
|
|
95
157
|
return std::pow(x, 1.0f / 2.4f) * 1.055f - 0.055f;
|
|
158
|
+
}
|
|
96
159
|
};
|
|
97
160
|
return int(linearToSrgbF(value) * 255.f + 0.5f);
|
|
98
161
|
}
|
|
99
162
|
struct Color {
|
|
100
163
|
float r, g, b;
|
|
101
|
-
Color &operator*=(float scale)
|
|
164
|
+
Color &operator*=(float scale)
|
|
165
|
+
{
|
|
102
166
|
r *= scale;
|
|
103
167
|
g *= scale;
|
|
104
168
|
b *= scale;
|
|
105
169
|
return *this;
|
|
106
170
|
}
|
|
107
|
-
friend Color operator*(Color lhs, float rhs)
|
|
108
|
-
|
|
171
|
+
friend Color operator*(Color lhs, float rhs)
|
|
172
|
+
{
|
|
173
|
+
return (lhs *= rhs);
|
|
174
|
+
}
|
|
175
|
+
Color &operator/=(float scale)
|
|
176
|
+
{
|
|
177
|
+
if (NearZero(scale)) {
|
|
178
|
+
return *this;
|
|
179
|
+
}
|
|
109
180
|
r /= scale;
|
|
110
181
|
g /= scale;
|
|
111
182
|
b /= scale;
|
|
112
183
|
return *this;
|
|
113
184
|
}
|
|
114
|
-
Color &operator+=(const Color &rhs)
|
|
185
|
+
Color &operator+=(const Color &rhs)
|
|
186
|
+
{
|
|
115
187
|
r += rhs.r;
|
|
116
188
|
g += rhs.g;
|
|
117
189
|
b += rhs.b;
|
|
118
190
|
return *this;
|
|
119
191
|
}
|
|
120
192
|
};
|
|
121
|
-
Color decodeDC(int value)
|
|
193
|
+
Color decodeDC(int value)
|
|
194
|
+
{
|
|
122
195
|
const int intR = value >> 16;
|
|
123
196
|
const int intG = (value >> 8) & 255;
|
|
124
197
|
const int intB = value & 255;
|
|
125
198
|
return {srgbToLinear(intR), srgbToLinear(intG), srgbToLinear(intB)};
|
|
126
199
|
}
|
|
127
|
-
Color decodeDC(std::string_view value)
|
|
128
|
-
|
|
200
|
+
Color decodeDC(std::string_view value)
|
|
201
|
+
{
|
|
202
|
+
if (value.size() != EXPECTEDSIZE) {
|
|
203
|
+
return Color{0.0f, 0.0f, 0.0f};
|
|
204
|
+
}
|
|
129
205
|
return decodeDC(decode83(value));
|
|
130
206
|
}
|
|
131
|
-
int encodeDC(const Color &c)
|
|
132
|
-
|
|
133
|
-
|
|
207
|
+
int encodeDC(const Color &c)
|
|
208
|
+
{
|
|
209
|
+
return (linearToSrgb(c.r) << RED_SHIFT) + (linearToSrgb(c.g) << GREEN_SHIFT) + linearToSrgb(c.b);
|
|
210
|
+
}
|
|
211
|
+
float signPow(float value, float exp)
|
|
212
|
+
{
|
|
213
|
+
return std::copysign(std::pow(std::abs(value), exp), value);
|
|
214
|
+
}
|
|
215
|
+
int encodeAC(const Color &c, float maximumValue)
|
|
216
|
+
{
|
|
217
|
+
if (maximumValue == 0) {
|
|
218
|
+
return -1;
|
|
219
|
+
}
|
|
134
220
|
auto quantR = int(std::max(0., std::min(18., std::floor(signPow(c.r / maximumValue, 0.5) * 9 + 9.5))));
|
|
135
221
|
auto quantG = int(std::max(0., std::min(18., std::floor(signPow(c.g / maximumValue, 0.5) * 9 + 9.5))));
|
|
136
222
|
auto quantB = int(std::max(0., std::min(18., std::floor(signPow(c.b / maximumValue, 0.5) * 9 + 9.5))));
|
|
137
|
-
return quantR *
|
|
223
|
+
return quantR * QUANT_STEP * QUANT_STEP + quantG * QUANT_STEP + quantB;
|
|
138
224
|
}
|
|
139
|
-
Color decodeAC(int value, float maximumValue)
|
|
140
|
-
|
|
141
|
-
auto
|
|
142
|
-
auto
|
|
143
|
-
|
|
144
|
-
return {signPow((float(quantR) - 9) / 9, 2) * maximumValue,
|
|
225
|
+
Color decodeAC(int value, float maximumValue)
|
|
226
|
+
{
|
|
227
|
+
auto quantR = value / (QUANT_STEP * QUANT_STEP);
|
|
228
|
+
auto quantG = (value / QUANT_STEP) % QUANT_STEP;
|
|
229
|
+
auto quantB = value % QUANT_STEP;
|
|
230
|
+
return {signPow((float(quantR) - 9) / 9, 2) * maximumValue,
|
|
231
|
+
signPow((float(quantG) - 9) / 9, 2) * maximumValue, signPow((float(quantB) - 9) / 9, 2) * maximumValue};
|
|
232
|
+
}
|
|
233
|
+
Color decodeAC(std::string_view value, float maximumValue)
|
|
234
|
+
{
|
|
235
|
+
return decodeAC(decode83(value), maximumValue);
|
|
145
236
|
}
|
|
146
|
-
Color decodeAC(std::string_view value, float maximumValue) { return decodeAC(decode83(value), maximumValue); }
|
|
147
237
|
const float pi = std::acos(-1.0f);
|
|
148
|
-
std::vector<float> bases_for(size_t dimension, size_t components)
|
|
238
|
+
std::vector<float> bases_for(size_t dimension, size_t components)
|
|
239
|
+
{
|
|
149
240
|
std::vector<float> bases(dimension * components);
|
|
150
|
-
|
|
151
241
|
float scale = pi / float(dimension);
|
|
152
|
-
|
|
153
242
|
size_t index = 0;
|
|
154
243
|
std::generate(bases.begin(), bases.end(), [&]() {
|
|
244
|
+
if (components == 0) {
|
|
245
|
+
throw std::invalid_argument("components cannot be zero");
|
|
246
|
+
}
|
|
155
247
|
size_t x = index / components;
|
|
156
248
|
size_t nx = index % components;
|
|
157
249
|
index++;
|
|
158
250
|
return std::cos(scale * float(nx * x));
|
|
159
251
|
});
|
|
160
|
-
|
|
161
252
|
return bases;
|
|
162
253
|
}
|
|
163
254
|
|
|
@@ -178,28 +269,30 @@ std::string path = "/data/storage/el2/base/haps/entry/cache/";
|
|
|
178
269
|
* 如果解码失败,则返回空图像。接着解码最大AC值和平均颜色值。然后解码AC值并将其添加到值向量中。
|
|
179
270
|
* 最后使用解码的值和基础函数计算图像的每个像素的颜色,并将其存储在图像的image数组中。
|
|
180
271
|
*/
|
|
181
|
-
std::string decode(std::string_view blurhash, size_t width, size_t height, float punch, bool useCache) noexcept
|
|
272
|
+
std::string decode(std::string_view blurhash, size_t width, size_t height, float punch, bool useCache) noexcept
|
|
273
|
+
{
|
|
182
274
|
size_t bytesPerPixel = 3;
|
|
183
275
|
Image i{};
|
|
184
|
-
if (blurhash.size() <
|
|
276
|
+
if (blurhash.size() < MIN_BLURHASH_SIZE)
|
|
185
277
|
return "";
|
|
186
278
|
Components components{};
|
|
187
279
|
std::vector<Color> values;
|
|
188
|
-
values.reserve(blurhash.size() /
|
|
280
|
+
values.reserve(blurhash.size() / HEX_DIGITS_PER_CHAR);
|
|
189
281
|
try {
|
|
190
282
|
components = unpackComponents(decode83(blurhash.substr(0, 1)));
|
|
191
|
-
if (components.x < 1 || components.y < 1 ||
|
|
283
|
+
if (components.x < 1 || components.y < 1 ||
|
|
284
|
+
blurhash.size() != size_t(1 + 1 + MAX_AC_SIZE + (components.x * components.y - 1) * AC_COMPONENT_SIZE))
|
|
192
285
|
return {};
|
|
193
286
|
auto maxAC = decodeMaxAC(blurhash.substr(1, 1));
|
|
194
287
|
maxAC *= punch;
|
|
195
288
|
Color average = decodeDC(blurhash.substr(2, 4));
|
|
196
289
|
values.push_back(average);
|
|
197
|
-
for (size_t c = 6; c < blurhash.size(); c +=
|
|
198
|
-
values.push_back(decodeAC(blurhash.substr(c,
|
|
290
|
+
for (size_t c = 6; c < blurhash.size(); c += CONSTANT_SIZE)
|
|
291
|
+
values.push_back(decodeAC(blurhash.substr(c, CONSTANT_SIZE), maxAC));
|
|
199
292
|
} catch (std::invalid_argument &) {
|
|
200
293
|
return {};
|
|
201
294
|
}
|
|
202
|
-
i.image = decltype(i.image)(height * width * bytesPerPixel,
|
|
295
|
+
i.image = decltype(i.image)(height * width * bytesPerPixel, MAX_PIXEL_VALUE);
|
|
203
296
|
std::vector<float> basis_x = bases_for(width, components.x);
|
|
204
297
|
std::vector<float> basis_y = bases_for(height, components.y);
|
|
205
298
|
for (size_t y = 0; y < height; y++) {
|
|
@@ -211,20 +304,18 @@ std::string decode(std::string_view blurhash, size_t width, size_t height, float
|
|
|
211
304
|
c += values[nx + ny * components.x] * basis;
|
|
212
305
|
}
|
|
213
306
|
}
|
|
214
|
-
i.image[(y * width + x) * bytesPerPixel +
|
|
215
|
-
i.image[(y * width + x) * bytesPerPixel +
|
|
216
|
-
i.image[(y * width + x) * bytesPerPixel +
|
|
307
|
+
i.image[(y * width + x) * bytesPerPixel + RED_CHANNEL] = static_cast<unsigned char>(linearToSrgb(c.r));
|
|
308
|
+
i.image[(y * width + x) * bytesPerPixel + GREEN_CHANNEL] = static_cast<unsigned char>(linearToSrgb(c.g));
|
|
309
|
+
i.image[(y * width + x) * bytesPerPixel + BLUE_CHANNEL] = static_cast<unsigned char>(linearToSrgb(c.b));
|
|
217
310
|
}
|
|
218
311
|
}
|
|
219
312
|
i.height = height;
|
|
220
313
|
i.width = width;
|
|
221
314
|
|
|
222
315
|
std::string filename = path + std::string(blurhash) + ".bmp";
|
|
223
|
-
stbi_write_bmp(filename.c_str(), i.width, i.height,
|
|
316
|
+
stbi_write_bmp(filename.c_str(), i.width, i.height, CHANNELS_PER_PIXEL, (void *)i.image.data());
|
|
224
317
|
return filename;
|
|
225
318
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
319
|
/**
|
|
229
320
|
* 对图像进行编码的函数
|
|
230
321
|
* @param image 待编码的图像数据
|
|
@@ -234,15 +325,19 @@ std::string decode(std::string_view blurhash, size_t width, size_t height, float
|
|
|
234
325
|
* @param components_y 在y方向上的分量数
|
|
235
326
|
* @return 编码后的字符串
|
|
236
327
|
*/
|
|
237
|
-
std::string encode(char const *filename, int components_x, int components_y)
|
|
328
|
+
std::string encode(char const *filename, int components_x, int components_y)
|
|
329
|
+
{
|
|
238
330
|
auto start = std::chrono::steady_clock::now();
|
|
239
331
|
auto duration = std::chrono::seconds(5);
|
|
240
|
-
int width
|
|
241
|
-
|
|
242
|
-
|
|
332
|
+
int width;
|
|
333
|
+
int height;
|
|
334
|
+
int n;
|
|
335
|
+
unsigned char *data = stbi_load((path + filename).c_str(), &width, &height, &n, DEFAULT_CHANNELS);
|
|
336
|
+
if (components_x < MIN_COMPONENT || components_x > MAX_COMPONENT ||
|
|
337
|
+
components_y < MIN_COMPONENT || components_y > MAX_COMPONENT)
|
|
243
338
|
return "";
|
|
244
339
|
while (width < 1 || height < 1 || !data) {
|
|
245
|
-
data = stbi_load((path + filename).c_str(), &width, &height, &n,
|
|
340
|
+
data = stbi_load((path + filename).c_str(), &width, &height, &n, COMPONENT_3);
|
|
246
341
|
auto now = std::chrono::steady_clock::now();
|
|
247
342
|
if (now - start >= duration) {
|
|
248
343
|
return "";
|
|
@@ -253,7 +348,8 @@ std::string encode(char const *filename, int components_x, int components_y) {
|
|
|
253
348
|
std::vector<Color> factors(components_x * components_y, Color{});
|
|
254
349
|
for (size_t y = 0; y < height; y++) {
|
|
255
350
|
for (size_t x = 0; x < width; x++) {
|
|
256
|
-
Color linear{srgbToLinear(data[3 * x + 0 + y * width * 3]),
|
|
351
|
+
Color linear{srgbToLinear(data[3 * x + 0 + y * width * 3]),
|
|
352
|
+
srgbToLinear(data[3 * x + 1 + y * width * 3]), srgbToLinear(data[3 * x + 2 + y * width * 3])};
|
|
257
353
|
linear *= 1.f / static_cast<float>(width);
|
|
258
354
|
for (size_t ny = 0; ny < size_t(components_y); ny++) {
|
|
259
355
|
for (size_t nx = 0; nx < size_t(components_x); nx++) {
|
|
@@ -268,7 +364,9 @@ std::string encode(char const *filename, int components_x, int components_y) {
|
|
|
268
364
|
float scale = normalisation / static_cast<float>(height);
|
|
269
365
|
factors[i] *= scale;
|
|
270
366
|
}
|
|
271
|
-
|
|
367
|
+
if (factors.size() <= 0) {
|
|
368
|
+
throw std::runtime_error("Factors array is empty");
|
|
369
|
+
}
|
|
272
370
|
auto dc = factors.front();
|
|
273
371
|
factors.erase(factors.begin());
|
|
274
372
|
std::string h;
|
|
@@ -285,30 +383,26 @@ std::string encode(char const *filename, int components_x, int components_y) {
|
|
|
285
383
|
});
|
|
286
384
|
}
|
|
287
385
|
int quantisedMaximumValue = encodeMaxAC(actualMaximumValue);
|
|
288
|
-
maximumValue = ((float)quantisedMaximumValue + 1) /
|
|
386
|
+
maximumValue = ((float)quantisedMaximumValue + 1) / AC_VALUE_MULTIPLIER;
|
|
289
387
|
h += leftPad(encode83(quantisedMaximumValue), 1);
|
|
290
388
|
} else {
|
|
291
389
|
maximumValue = 1;
|
|
292
390
|
h += leftPad(encode83(0), 1);
|
|
293
391
|
}
|
|
294
|
-
h += leftPad(encode83(encodeDC(dc)),
|
|
392
|
+
h += leftPad(encode83(encodeDC(dc)), LEFT_PADDING_4);
|
|
295
393
|
for (auto ac : factors)
|
|
296
|
-
h += leftPad(encode83(encodeAC(ac, maximumValue)),
|
|
297
|
-
|
|
394
|
+
h += leftPad(encode83(encodeAC(ac, maximumValue)), LEFT_PADDING_2);
|
|
298
395
|
return h;
|
|
299
396
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
void clearCache() {
|
|
303
|
-
|
|
397
|
+
void clearCache()
|
|
398
|
+
{
|
|
304
399
|
DLOG(INFO) << "clearCosineCache:SparseArray<std::vector<double>> Object";
|
|
305
400
|
DLOG(INFO) << "clearCosineCache:SparseArray<std::vector<double>> Object";
|
|
306
401
|
cacheCosinesX.clear();
|
|
307
|
-
cacheCosinesY.clear();
|
|
402
|
+
cacheCosinesY.clear();
|
|
308
403
|
DLOG(INFO) << "clearCosineCache:null";
|
|
309
404
|
DLOG(INFO) << "clearCosineCache:null";
|
|
310
405
|
}
|
|
311
406
|
} // namespace blurhash
|
|
312
|
-
|
|
313
407
|
#ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
|
314
408
|
#endif
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Use of this source code is governed by a MIT license that can be
|
|
4
4
|
* found in the LICENSE file.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
#ifndef BLURHASH_H
|
|
7
|
+
#define BLURHASH_H
|
|
7
8
|
#pragma once
|
|
8
9
|
|
|
9
10
|
#include <__functional/function.h>
|
|
@@ -18,10 +19,12 @@ struct Image {
|
|
|
18
19
|
std::vector<unsigned char> image; // pixels rgb
|
|
19
20
|
};
|
|
20
21
|
|
|
21
|
-
std::string decode(std::string_view blurhash, size_t width = 32,
|
|
22
|
+
std::string decode(std::string_view blurhash, size_t width = 32,
|
|
23
|
+
size_t height = 32, float punch = 1.0, bool useCache = true) noexcept;
|
|
22
24
|
|
|
23
25
|
std::string encode(char const *filename, int components_x, int components_y);
|
|
24
26
|
|
|
25
27
|
void clearCache();
|
|
26
28
|
|
|
27
29
|
} // namespace blurhash
|
|
30
|
+
#endif
|
|
@@ -9,29 +9,32 @@
|
|
|
9
9
|
#include <string_view>
|
|
10
10
|
#include "RNOH/arkui/NativeNodeApi.h"
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
static constexpr ArkUI_NodeEventType IMAGE_NODE_EVENT_TYPES[] = {NODE_IMAGE_ON_COMPLETE,
|
|
13
|
+
NODE_IMAGE_ON_ERROR, NODE_IMAGE_ON_DOWNLOAD_PROGRESS};
|
|
14
14
|
|
|
15
15
|
namespace rnoh {
|
|
16
|
-
|
|
17
16
|
using namespace std::literals;
|
|
18
17
|
constexpr std::string_view ASSET_PREFIX = "asset://"sv;
|
|
19
18
|
const std::string RAWFILE_PREFIX = "resource://RAWFILE/assets/";
|
|
20
19
|
|
|
21
20
|
BlurhashNode::BlurhashNode()
|
|
22
|
-
: ArkUINode(NativeNodeApi::getInstance()->createNode(ArkUI_NodeType::ARKUI_NODE_IMAGE)),
|
|
21
|
+
: ArkUINode(NativeNodeApi::getInstance()->createNode(ArkUI_NodeType::ARKUI_NODE_IMAGE)),
|
|
22
|
+
m_childArkUINodeHandle(nullptr), m_blurhashNodeDelegate(nullptr)
|
|
23
|
+
{
|
|
23
24
|
for (auto eventType : IMAGE_NODE_EVENT_TYPES) {
|
|
24
25
|
maybeThrow(NativeNodeApi::getInstance()->registerNodeEvent(m_nodeHandle, eventType, eventType, this));
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
BlurhashNode::~BlurhashNode()
|
|
29
|
+
BlurhashNode::~BlurhashNode()
|
|
30
|
+
{
|
|
29
31
|
for (auto eventType : IMAGE_NODE_EVENT_TYPES) {
|
|
30
32
|
NativeNodeApi::getInstance()->unregisterNodeEvent(m_nodeHandle, eventType);
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
BlurhashNode &BlurhashNode::setSource(std::string const &uri, std::string prefix)
|
|
36
|
+
BlurhashNode &BlurhashNode::setSource(std::string const &uri, std::string prefix)
|
|
37
|
+
{
|
|
35
38
|
ArkUI_AttributeItem item;
|
|
36
39
|
std::string absolutePath = prefix == "" ? RAWFILE_PREFIX : prefix;
|
|
37
40
|
if (uri.rfind(ASSET_PREFIX, 0) == 0) {
|
|
@@ -44,9 +47,13 @@ BlurhashNode &BlurhashNode::setSource(std::string const &uri, std::string prefix
|
|
|
44
47
|
return *this;
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
void BlurhashNode::setNodeDelegate(BlurhashNodeDelegate *blurhashNodeDelegate)
|
|
50
|
+
void BlurhashNode::setNodeDelegate(BlurhashNodeDelegate *blurhashNodeDelegate)
|
|
51
|
+
{
|
|
52
|
+
m_blurhashNodeDelegate = blurhashNodeDelegate;
|
|
53
|
+
}
|
|
48
54
|
|
|
49
|
-
void BlurhashNode::onNodeEvent(ArkUI_NodeEventType eventType, EventArgs &eventArgs)
|
|
55
|
+
void BlurhashNode::onNodeEvent(ArkUI_NodeEventType eventType, EventArgs &eventArgs)
|
|
56
|
+
{
|
|
50
57
|
if (eventType == ArkUI_NodeEventType::NODE_IMAGE_ON_COMPLETE) {
|
|
51
58
|
if (m_blurhashNodeDelegate != nullptr && eventArgs[0].i32 == 1) {
|
|
52
59
|
m_blurhashNodeDelegate->onComplete();
|
|
@@ -66,7 +73,8 @@ void BlurhashNode::onNodeEvent(ArkUI_NodeEventType eventType, EventArgs &eventAr
|
|
|
66
73
|
}
|
|
67
74
|
}
|
|
68
75
|
|
|
69
|
-
BlurhashNode &BlurhashNode::setResizeMode(facebook::react::ImageResizeMode const &mode)
|
|
76
|
+
BlurhashNode &BlurhashNode::setResizeMode(facebook::react::ImageResizeMode const &mode)
|
|
77
|
+
{
|
|
70
78
|
int32_t val = ARKUI_OBJECT_FIT_COVER;
|
|
71
79
|
if (mode == facebook::react::ImageResizeMode::Cover) {
|
|
72
80
|
val = ARKUI_OBJECT_FIT_COVER;
|
|
@@ -77,11 +85,9 @@ BlurhashNode &BlurhashNode::setResizeMode(facebook::react::ImageResizeMode const
|
|
|
77
85
|
} else if (mode == facebook::react::ImageResizeMode::Center || mode == facebook::react::ImageResizeMode::Repeat) {
|
|
78
86
|
val = ARKUI_OBJECT_FIT_NONE;
|
|
79
87
|
}
|
|
80
|
-
|
|
81
88
|
ArkUI_NumberValue value[] = {{.i32 = val}};
|
|
82
89
|
ArkUI_AttributeItem item = {value, sizeof(value) / sizeof(ArkUI_NumberValue)};
|
|
83
90
|
maybeThrow(NativeNodeApi::getInstance()->setAttribute(m_nodeHandle, NODE_IMAGE_OBJECT_FIT, &item));
|
|
84
91
|
return *this;
|
|
85
92
|
}
|
|
86
|
-
|
|
87
|
-
} // namespace rnoh
|
|
93
|
+
} // namespace rnoh
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
* Use of this source code is governed by a MIT license that can be
|
|
4
4
|
* found in the LICENSE file.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
#ifndef BLURHASHNODE_H
|
|
7
|
+
#define BLURHASHNODE_H
|
|
7
8
|
#pragma once
|
|
8
9
|
#include <cstdint>
|
|
9
10
|
#include <react/renderer/imagemanager/primitives.h>
|
|
10
11
|
#include "RNOH/arkui/ArkUINode.h"
|
|
11
12
|
|
|
12
13
|
namespace rnoh {
|
|
13
|
-
|
|
14
14
|
class BlurhashNodeDelegate {
|
|
15
15
|
public:
|
|
16
16
|
virtual ~BlurhashNodeDelegate() = default;
|
|
@@ -33,3 +33,4 @@ public:
|
|
|
33
33
|
void setNodeDelegate(BlurhashNodeDelegate *blurhashNodeDelegate);
|
|
34
34
|
};
|
|
35
35
|
} // namespace rnoh
|
|
36
|
+
#endif
|
|
@@ -3,20 +3,20 @@
|
|
|
3
3
|
* Use of this source code is governed by a MIT license that can be
|
|
4
4
|
* found in the LICENSE file.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
#ifndef BLURHASHPACKAGE_H
|
|
7
|
+
#define BLURHASHPACKAGE_H
|
|
7
8
|
#include "RNOH/Package.h"
|
|
8
9
|
#include "ComponentDescriptors.h"
|
|
9
10
|
#include "BlurhashViewJSIBinder.h"
|
|
10
11
|
#include "RNBlurhashTurboModule.h"
|
|
11
12
|
#include "BlurhashViewComponentInstance.h"
|
|
12
|
-
|
|
13
|
-
using namespace rnoh;
|
|
13
|
+
namespace rnoh{
|
|
14
14
|
|
|
15
15
|
class BlurhashViewComponentInstanceFactoryDelegate : public ComponentInstanceFactoryDelegate {
|
|
16
16
|
public:
|
|
17
17
|
using ComponentInstanceFactoryDelegate::ComponentInstanceFactoryDelegate;
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
ComponentInstance::Shared create(ComponentInstance::Context ctx) override
|
|
19
|
+
{
|
|
20
20
|
if (ctx.componentName == "BlurhashView") {
|
|
21
21
|
return std::make_shared<BlurhashViewComponentInstance>(std::move(ctx));
|
|
22
22
|
}
|
|
@@ -26,7 +26,8 @@ public:
|
|
|
26
26
|
|
|
27
27
|
class BlurhashTurboModuleFactoryDelegate : public TurboModuleFactoryDelegate {
|
|
28
28
|
public:
|
|
29
|
-
SharedTurboModule createTurboModule(Context ctx, const std::string &name) const override
|
|
29
|
+
SharedTurboModule createTurboModule(Context ctx, const std::string &name) const override
|
|
30
|
+
{
|
|
30
31
|
if (name == "BlurhashModule") {
|
|
31
32
|
return std::make_shared<RNBlurhashTurboModule>(ctx, name);
|
|
32
33
|
}
|
|
@@ -38,16 +39,26 @@ class BlurhashPackage : public Package {
|
|
|
38
39
|
public:
|
|
39
40
|
BlurhashPackage(Package::Context ctx) : Package(ctx) {}
|
|
40
41
|
|
|
41
|
-
std::unique_ptr<TurboModuleFactoryDelegate> createTurboModuleFactoryDelegate() override
|
|
42
|
+
std::unique_ptr<TurboModuleFactoryDelegate> createTurboModuleFactoryDelegate() override
|
|
43
|
+
{
|
|
44
|
+
return std::make_unique<BlurhashTurboModuleFactoryDelegate>();
|
|
45
|
+
}
|
|
42
46
|
|
|
43
|
-
ComponentInstanceFactoryDelegate::Shared createComponentInstanceFactoryDelegate() override
|
|
47
|
+
ComponentInstanceFactoryDelegate::Shared createComponentInstanceFactoryDelegate() override
|
|
48
|
+
{
|
|
44
49
|
return std::make_shared<BlurhashViewComponentInstanceFactoryDelegate>();
|
|
45
50
|
}
|
|
46
51
|
|
|
47
|
-
std::vector<facebook::react::ComponentDescriptorProvider> createComponentDescriptorProviders() override
|
|
48
|
-
|
|
52
|
+
std::vector<facebook::react::ComponentDescriptorProvider> createComponentDescriptorProviders() override
|
|
53
|
+
{
|
|
54
|
+
return {facebook::react::concreteComponentDescriptorProvider<
|
|
55
|
+
facebook::react::BlurhashViewComponentDescriptor>()};
|
|
49
56
|
}
|
|
50
57
|
|
|
51
|
-
ComponentJSIBinderByString createComponentJSIBinderByName() override
|
|
58
|
+
ComponentJSIBinderByString createComponentJSIBinderByName() override
|
|
59
|
+
{
|
|
60
|
+
return {{"BlurhashView", std::make_shared<BlurhashViewJSIBinder>()}};
|
|
61
|
+
}
|
|
52
62
|
};
|
|
53
|
-
// namespace rnoh
|
|
63
|
+
}// namespace rnoh
|
|
64
|
+
#endif
|