@react-native-ohos/react-native-blurhash 2.0.4-rc.1

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.
Files changed (72) hide show
  1. package/LICENSE +21 -0
  2. package/README.OpenSource +11 -0
  3. package/README.md +13 -0
  4. package/harmony/blurhash/BuildProfile.ets +17 -0
  5. package/harmony/blurhash/build-profile.json5 +9 -0
  6. package/harmony/blurhash/hvigorfile.ts +2 -0
  7. package/harmony/blurhash/index.ets +2 -0
  8. package/harmony/blurhash/oh-package.json5 +13 -0
  9. package/harmony/blurhash/src/main/cpp/Blurhash.cpp +314 -0
  10. package/harmony/blurhash/src/main/cpp/Blurhash.hpp +27 -0
  11. package/harmony/blurhash/src/main/cpp/BlurhashNode.cpp +87 -0
  12. package/harmony/blurhash/src/main/cpp/BlurhashNode.h +35 -0
  13. package/harmony/blurhash/src/main/cpp/BlurhashPackage.h +53 -0
  14. package/harmony/blurhash/src/main/cpp/BlurhashViewComponentInstance.cpp +137 -0
  15. package/harmony/blurhash/src/main/cpp/BlurhashViewComponentInstance.h +34 -0
  16. package/harmony/blurhash/src/main/cpp/BlurhashViewJSIBinder.h +34 -0
  17. package/harmony/blurhash/src/main/cpp/CMakeLists.txt +13 -0
  18. package/harmony/blurhash/src/main/cpp/ComponentDescriptors.h +18 -0
  19. package/harmony/blurhash/src/main/cpp/EventEmitters.cpp +36 -0
  20. package/harmony/blurhash/src/main/cpp/EventEmitters.h +40 -0
  21. package/harmony/blurhash/src/main/cpp/Props.cpp +25 -0
  22. package/harmony/blurhash/src/main/cpp/Props.h +73 -0
  23. package/harmony/blurhash/src/main/cpp/RNBlurhashTurboModule.cpp +42 -0
  24. package/harmony/blurhash/src/main/cpp/RNBlurhashTurboModule.h +19 -0
  25. package/harmony/blurhash/src/main/cpp/ShadowNodes.cpp +15 -0
  26. package/harmony/blurhash/src/main/cpp/ShadowNodes.h +27 -0
  27. package/harmony/blurhash/src/main/cpp/SparseArray.cpp +28 -0
  28. package/harmony/blurhash/src/main/cpp/SparseArray.h +26 -0
  29. package/harmony/blurhash/src/main/cpp/napi_init.cpp +68 -0
  30. package/harmony/blurhash/src/main/cpp/stb_image.h +7656 -0
  31. package/harmony/blurhash/src/main/cpp/stb_image_write.h +1724 -0
  32. package/harmony/blurhash/src/main/cpp/types/libblurhash/Index.d.ts +1 -0
  33. package/harmony/blurhash/src/main/cpp/types/libblurhash/oh-package.json5 +6 -0
  34. package/harmony/blurhash/src/main/ets/BlurhashPackage.ts +58 -0
  35. package/harmony/blurhash/src/main/ets/BlurhashTurboModule.ts +49 -0
  36. package/harmony/blurhash/src/main/ets/BlurhashView.ets +107 -0
  37. package/harmony/blurhash/src/main/ets/Logger.ts +64 -0
  38. package/harmony/blurhash/src/main/ets/RNCBlurhashView.ts +157 -0
  39. package/harmony/blurhash/src/main/ets/RNCSpecs.ts +163 -0
  40. package/harmony/blurhash/src/main/ets/TMSpecs.ts +33 -0
  41. package/harmony/blurhash/src/main/module.json5 +7 -0
  42. package/harmony/blurhash/src/main/resources/base/element/string.json +8 -0
  43. package/harmony/blurhash/src/main/resources/en_US/element/string.json +8 -0
  44. package/harmony/blurhash/src/main/resources/zh_CN/element/string.json +8 -0
  45. package/harmony/blurhash/ts.ts +26 -0
  46. package/harmony/blurhash.har +0 -0
  47. package/lib/commonjs/index.js +95 -0
  48. package/lib/commonjs/index.js.map +1 -0
  49. package/lib/commonjs/specs/NativeBlurhashModule.js +9 -0
  50. package/lib/commonjs/specs/NativeBlurhashModule.js.map +1 -0
  51. package/lib/commonjs/specs/NativeBlurhashView.js +10 -0
  52. package/lib/commonjs/specs/NativeBlurhashView.js.map +1 -0
  53. package/lib/commonjs/utils.js +56 -0
  54. package/lib/commonjs/utils.js.map +1 -0
  55. package/lib/module/index.js +85 -0
  56. package/lib/module/index.js.map +1 -0
  57. package/lib/module/specs/NativeBlurhashModule.js +3 -0
  58. package/lib/module/specs/NativeBlurhashModule.js.map +1 -0
  59. package/lib/module/specs/NativeBlurhashView.js +3 -0
  60. package/lib/module/specs/NativeBlurhashView.js.map +1 -0
  61. package/lib/module/utils.js +48 -0
  62. package/lib/module/utils.js.map +1 -0
  63. package/lib/typescript/index.d.ts +90 -0
  64. package/lib/typescript/specs/NativeBlurhashModule.d.ts +9 -0
  65. package/lib/typescript/specs/NativeBlurhashView.d.ts +19 -0
  66. package/lib/typescript/utils.d.ts +22 -0
  67. package/package.json +113 -0
  68. package/react-native-blurhash.podspec +34 -0
  69. package/src/index.tsx +131 -0
  70. package/src/specs/NativeBlurhashModule.ts +9 -0
  71. package/src/specs/NativeBlurhashView.ts +19 -0
  72. package/src/utils.ts +147 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Marc Rousavy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,11 @@
1
+ [
2
+ {
3
+ "Name": "react-native-blurhash",
4
+ "License": "MIT License",
5
+ "License File": "https://github.com/mrousavy/react-native-blurhash/blob/master/LICENSE",
6
+ "Version Number": "2.0.3",
7
+ "Owner" : "xiafeng@huawei.com",
8
+ "Upstream URL": "https://github.com/mrousavy/react-native-blurhash",
9
+ "Description": "🖼 Blurhash is a compact representation of a placeholder for an image. This is a Native UI Module for React Native to asynchronously wrap the Blurhash implementations and make them usable in React Native. Also supports encoding!"
10
+ }
11
+ ]
package/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # @react-native-ohos/react-native-blurhash
2
+
3
+ 本项目基于 [react-native-blurhash](https://github.com/TiHxdvt/react-native-blurhash)
4
+
5
+ ## 文档地址 / Documentation URL
6
+
7
+ [中文 / Chinese](https://gitee.com/react-native-oh-library/usage-docs/blob/master/zh-cn/react-native-blurhash.md)
8
+
9
+ [英文 / English](https://gitee.com/react-native-oh-library/usage-docs/blob/master/zh-en/react-native-blurhash.md)
10
+
11
+ ## 请悉知 / Acknowledgements
12
+
13
+ 本项目基于 [The MIT License (MIT)](https://github.com/mrousavy/react-native-blurhash/blob/master/LICENSE) ,请自由地享受和参与开源。
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Use these variables when you tailor your ArkTS code. They must be of the const type.
3
+ */
4
+ export const HAR_VERSION = '2.0.3-0.0.2';
5
+ export const BUILD_MODE_NAME = 'debug';
6
+ export const DEBUG = true;
7
+ export const TARGET_NAME = 'default';
8
+
9
+ /**
10
+ * BuildProfile Class is used only for compatibility purposes.
11
+ */
12
+ export default class BuildProfile {
13
+ static readonly HAR_VERSION = HAR_VERSION;
14
+ static readonly BUILD_MODE_NAME = BUILD_MODE_NAME;
15
+ static readonly DEBUG = DEBUG;
16
+ static readonly TARGET_NAME = TARGET_NAME;
17
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "apiType": "stageMode",
3
+ "targets": [
4
+ {
5
+ "name": "default",
6
+ "runtimeOS": "HarmonyOS"
7
+ }
8
+ ]
9
+ }
@@ -0,0 +1,2 @@
1
+ // Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
2
+ export { harTasks } from '@ohos/hvigor-ohos-plugin';
@@ -0,0 +1,2 @@
1
+ export * from './ts'
2
+ // export * from './src/main/ets/BlurhashView'
@@ -0,0 +1,13 @@
1
+ {
2
+ license: 'ISC',
3
+ types: '',
4
+ name: '@react-native-ohos/react-native-blurhash',
5
+ description: '',
6
+ main: 'index.ets',
7
+ type: 'module',
8
+ version: '2.0.4-rc.1',
9
+ dependencies: {
10
+ "@rnoh/react-native-openharmony": 'file:../react_native_openharmony',
11
+ "librnoh_blurhash.so": "file:./src/main/cpp/types/libblurhash"
12
+ },
13
+ }
@@ -0,0 +1,314 @@
1
+ /*
2
+ * Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved
3
+ * Use of this source code is governed by a MIT license that can be
4
+ * found in the LICENSE file.
5
+ */
6
+
7
+ #include "Blurhash.hpp"
8
+
9
+ #include <algorithm>
10
+ #include <array>
11
+ #include <cassert>
12
+ #include <cmath>
13
+ #include <stdexcept>
14
+ #include <string>
15
+ #ifdef __clang__
16
+ #define STBIWDEF static inline
17
+ #endif
18
+ #define STB_IMAGE_WRITE_STATIC
19
+ #define STB_IMAGE_WRITE_IMPLEMENTATION
20
+ #define STB_IMAGE_IMPLEMENTATION
21
+ #include "stb_image_write.h"
22
+ #include "stb_image.h"
23
+ #include <glog/logging.h>
24
+
25
+ using namespace std::literals;
26
+
27
+ namespace {
28
+ SparseArray<std::vector<double>> cacheCosinesX;
29
+ SparseArray<std::vector<double>> cacheCosinesY;
30
+ constexpr std::array<char, 84> int_to_b83{"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~"};
31
+ std::string leftPad(std::string str, size_t len) {
32
+ if (str.size() >= len)
33
+ return str;
34
+ return str.insert(0, len - str.size(), '0');
35
+ }
36
+ constexpr std::array<int, 255> b83_to_int = []() constexpr {
37
+ std::array<int, 255> a{};
38
+ for (auto &e : a)
39
+ e = -1;
40
+ for (int i = 0; i < 83; i++) {
41
+ a[static_cast<unsigned char>(int_to_b83[i])] = i;
42
+ }
43
+ return a;
44
+ }();
45
+ std::string encode83(int value) {
46
+ std::string buffer;
47
+ do {
48
+ buffer += int_to_b83[value % 83];
49
+ } while ((value = value / 83));
50
+ std::reverse(buffer.begin(), buffer.end());
51
+ return buffer;
52
+ }
53
+ struct Components {
54
+ int x, y;
55
+ };
56
+ int packComponents(const Components &c) noexcept { return (c.x - 1) + (c.y - 1) * 9; }
57
+ Components unpackComponents(int c) noexcept { return {c % 9 + 1, c / 9 + 1}; }
58
+ int decode83(std::string_view value) {
59
+ int temp = 0;
60
+ for (char c : value)
61
+ if (b83_to_int[static_cast<unsigned char>(c)] < 0)
62
+ throw std::invalid_argument("invalid character in blurhash");
63
+ for (char c : value)
64
+ temp = temp * 83 + b83_to_int[static_cast<unsigned char>(c)];
65
+ return temp;
66
+ }
67
+ float decodeMaxAC(int quantizedMaxAC) noexcept { return static_cast<float>(quantizedMaxAC + 1) / 166.f; }
68
+ float decodeMaxAC(std::string_view maxAC) {
69
+ assert(maxAC.size() == 1);
70
+ return decodeMaxAC(decode83(maxAC));
71
+ }
72
+ int encodeMaxAC(float maxAC) noexcept { return std::max(0, std::min(82, int(maxAC * 166 - 0.5f))); }
73
+ float srgbToLinear(int value) noexcept {
74
+ auto srgbToLinearF = [](float x) {
75
+ if (x <= 0.0f)
76
+ return 0.0f;
77
+ else if (x >= 1.0f)
78
+ return 1.0f;
79
+ else if (x < 0.04045f)
80
+ return x / 12.92f;
81
+ else
82
+ return std::pow((x + 0.055f) / 1.055f, 2.4f);
83
+ };
84
+ return srgbToLinearF(static_cast<float>(value) / 255.f);
85
+ }
86
+ int linearToSrgb(float value) noexcept {
87
+ auto linearToSrgbF = [](float x) -> float {
88
+ if (x <= 0.0f)
89
+ return 0.0f;
90
+ else if (x >= 1.0f)
91
+ return 1.0f;
92
+ else if (x < 0.0031308f)
93
+ return x * 12.92f;
94
+ else
95
+ return std::pow(x, 1.0f / 2.4f) * 1.055f - 0.055f;
96
+ };
97
+ return int(linearToSrgbF(value) * 255.f + 0.5f);
98
+ }
99
+ struct Color {
100
+ float r, g, b;
101
+ Color &operator*=(float scale) {
102
+ r *= scale;
103
+ g *= scale;
104
+ b *= scale;
105
+ return *this;
106
+ }
107
+ friend Color operator*(Color lhs, float rhs) { return (lhs *= rhs); }
108
+ Color &operator/=(float scale) {
109
+ r /= scale;
110
+ g /= scale;
111
+ b /= scale;
112
+ return *this;
113
+ }
114
+ Color &operator+=(const Color &rhs) {
115
+ r += rhs.r;
116
+ g += rhs.g;
117
+ b += rhs.b;
118
+ return *this;
119
+ }
120
+ };
121
+ Color decodeDC(int value) {
122
+ const int intR = value >> 16;
123
+ const int intG = (value >> 8) & 255;
124
+ const int intB = value & 255;
125
+ return {srgbToLinear(intR), srgbToLinear(intG), srgbToLinear(intB)};
126
+ }
127
+ Color decodeDC(std::string_view value) {
128
+ assert(value.size() == 4);
129
+ return decodeDC(decode83(value));
130
+ }
131
+ int encodeDC(const Color &c) { return (linearToSrgb(c.r) << 16) + (linearToSrgb(c.g) << 8) + linearToSrgb(c.b); }
132
+ float signPow(float value, float exp) { return std::copysign(std::pow(std::abs(value), exp), value); }
133
+ int encodeAC(const Color &c, float maximumValue) {
134
+ auto quantR = int(std::max(0., std::min(18., std::floor(signPow(c.r / maximumValue, 0.5) * 9 + 9.5))));
135
+ auto quantG = int(std::max(0., std::min(18., std::floor(signPow(c.g / maximumValue, 0.5) * 9 + 9.5))));
136
+ auto quantB = int(std::max(0., std::min(18., std::floor(signPow(c.b / maximumValue, 0.5) * 9 + 9.5))));
137
+ return quantR * 19 * 19 + quantG * 19 + quantB;
138
+ }
139
+ Color decodeAC(int value, float maximumValue) {
140
+ auto quantR = value / (19 * 19);
141
+ auto quantG = (value / 19) % 19;
142
+ auto quantB = value % 19;
143
+
144
+ return {signPow((float(quantR) - 9) / 9, 2) * maximumValue, signPow((float(quantG) - 9) / 9, 2) * maximumValue, signPow((float(quantB) - 9) / 9, 2) * maximumValue};
145
+ }
146
+ Color decodeAC(std::string_view value, float maximumValue) { return decodeAC(decode83(value), maximumValue); }
147
+ const float pi = std::acos(-1.0f);
148
+ std::vector<float> bases_for(size_t dimension, size_t components) {
149
+ std::vector<float> bases(dimension * components);
150
+
151
+ float scale = pi / float(dimension);
152
+
153
+ size_t index = 0;
154
+ std::generate(bases.begin(), bases.end(), [&]() {
155
+ size_t x = index / components;
156
+ size_t nx = index % components;
157
+ index++;
158
+ return std::cos(scale * float(nx * x));
159
+ });
160
+
161
+ return bases;
162
+ }
163
+
164
+
165
+ } // namespace
166
+ namespace blurhash {
167
+ std::string path = "/data/storage/el2/base/haps/entry/cache/";
168
+ /**
169
+ * @brief 解码Blurhash为图像
170
+ * @param blurhash 待解码的Blurhash字符串
171
+ * @param width 图像宽度
172
+ * @param height 图像高度
173
+ * @param bytesPerPixel 每个像素的字节数
174
+ * @param useCache 是否使用缓存
175
+ * @return 解码后的图像
176
+ * @note
177
+ * 此函数首先检查Blurhash的长度,如果长度小于6,则返回空图像。然后尝试解码Blurhash的组件,
178
+ * 如果解码失败,则返回空图像。接着解码最大AC值和平均颜色值。然后解码AC值并将其添加到值向量中。
179
+ * 最后使用解码的值和基础函数计算图像的每个像素的颜色,并将其存储在图像的image数组中。
180
+ */
181
+ std::string decode(std::string_view blurhash, size_t width, size_t height, float punch, bool useCache) noexcept {
182
+ size_t bytesPerPixel = 3;
183
+ Image i{};
184
+ if (blurhash.size() < 6)
185
+ return "";
186
+ Components components{};
187
+ std::vector<Color> values;
188
+ values.reserve(blurhash.size() / 2);
189
+ try {
190
+ components = unpackComponents(decode83(blurhash.substr(0, 1)));
191
+ if (components.x < 1 || components.y < 1 || blurhash.size() != size_t(1 + 1 + 4 + (components.x * components.y - 1) * 2))
192
+ return {};
193
+ auto maxAC = decodeMaxAC(blurhash.substr(1, 1));
194
+ maxAC *= punch;
195
+ Color average = decodeDC(blurhash.substr(2, 4));
196
+ values.push_back(average);
197
+ for (size_t c = 6; c < blurhash.size(); c += 2)
198
+ values.push_back(decodeAC(blurhash.substr(c, 2), maxAC));
199
+ } catch (std::invalid_argument &) {
200
+ return {};
201
+ }
202
+ i.image = decltype(i.image)(height * width * bytesPerPixel, 255);
203
+ std::vector<float> basis_x = bases_for(width, components.x);
204
+ std::vector<float> basis_y = bases_for(height, components.y);
205
+ for (size_t y = 0; y < height; y++) {
206
+ for (size_t x = 0; x < width; x++) {
207
+ Color c{};
208
+ for (size_t nx = 0; nx < size_t(components.x); nx++) {
209
+ for (size_t ny = 0; ny < size_t(components.y); ny++) {
210
+ float basis = basis_x[x * components.x + nx] * basis_y[y * components.y + ny];
211
+ c += values[nx + ny * components.x] * basis;
212
+ }
213
+ }
214
+ i.image[(y * width + x) * bytesPerPixel + 0] = static_cast<unsigned char>(linearToSrgb(c.r));
215
+ i.image[(y * width + x) * bytesPerPixel + 1] = static_cast<unsigned char>(linearToSrgb(c.g));
216
+ i.image[(y * width + x) * bytesPerPixel + 2] = static_cast<unsigned char>(linearToSrgb(c.b));
217
+ }
218
+ }
219
+ i.height = height;
220
+ i.width = width;
221
+
222
+ std::string filename = path + std::string(blurhash) + ".bmp";
223
+ stbi_write_bmp(filename.c_str(), i.width, i.height, 3, (void *)i.image.data());
224
+ return filename;
225
+ }
226
+
227
+
228
+ /**
229
+ * 对图像进行编码的函数
230
+ * @param image 待编码的图像数据
231
+ * @param width 图像的宽度
232
+ * @param height 图像的高度
233
+ * @param components_x 在x方向上的分量数
234
+ * @param components_y 在y方向上的分量数
235
+ * @return 编码后的字符串
236
+ */
237
+ std::string encode(char const *filename, int components_x, int components_y) {
238
+ auto start = std::chrono::steady_clock::now();
239
+ auto duration = std::chrono::seconds(5);
240
+ int width, height, n;
241
+ unsigned char *data = stbi_load((path + filename).c_str(), &width, &height, &n, 3);
242
+ if (components_x < 1 || components_x > 9 || components_y < 1 || components_y > 9)
243
+ return "";
244
+ while (width < 1 || height < 1 || !data) {
245
+ data = stbi_load((path + filename).c_str(), &width, &height, &n, 3);
246
+ auto now = std::chrono::steady_clock::now();
247
+ if (now - start >= duration) {
248
+ return "";
249
+ }
250
+ }
251
+ std::vector<float> basis_x = bases_for(width, components_x);
252
+ std::vector<float> basis_y = bases_for(height, components_y);
253
+ std::vector<Color> factors(components_x * components_y, Color{});
254
+ for (size_t y = 0; y < height; y++) {
255
+ for (size_t x = 0; x < width; x++) {
256
+ Color linear{srgbToLinear(data[3 * x + 0 + y * width * 3]), srgbToLinear(data[3 * x + 1 + y * width * 3]), srgbToLinear(data[3 * x + 2 + y * width * 3])};
257
+ linear *= 1.f / static_cast<float>(width);
258
+ for (size_t ny = 0; ny < size_t(components_y); ny++) {
259
+ for (size_t nx = 0; nx < size_t(components_x); nx++) {
260
+ float basis = basis_x[x * size_t(components_x) + nx] * basis_y[y * size_t(components_y) + ny];
261
+ factors[ny * components_x + nx] += linear * basis;
262
+ }
263
+ }
264
+ }
265
+ }
266
+ for (size_t i = 0; i < factors.size(); i++) {
267
+ float normalisation = (i == 0) ? 1 : 2;
268
+ float scale = normalisation / static_cast<float>(height);
269
+ factors[i] *= scale;
270
+ }
271
+ assert(factors.size() > 0);
272
+ auto dc = factors.front();
273
+ factors.erase(factors.begin());
274
+ std::string h;
275
+ h += leftPad(encode83(packComponents({components_x, components_y})), 1);
276
+ float maximumValue;
277
+ if (!factors.empty()) {
278
+ float actualMaximumValue = 0;
279
+ for (auto ac : factors) {
280
+ actualMaximumValue = std::max({
281
+ std::abs(ac.r),
282
+ std::abs(ac.g),
283
+ std::abs(ac.b),
284
+ actualMaximumValue,
285
+ });
286
+ }
287
+ int quantisedMaximumValue = encodeMaxAC(actualMaximumValue);
288
+ maximumValue = ((float)quantisedMaximumValue + 1) / 166;
289
+ h += leftPad(encode83(quantisedMaximumValue), 1);
290
+ } else {
291
+ maximumValue = 1;
292
+ h += leftPad(encode83(0), 1);
293
+ }
294
+ h += leftPad(encode83(encodeDC(dc)), 4);
295
+ for (auto ac : factors)
296
+ h += leftPad(encode83(encodeAC(ac, maximumValue)), 2);
297
+
298
+ return h;
299
+ }
300
+
301
+
302
+ void clearCache() {
303
+
304
+ DLOG(INFO) << "clearCosineCache:SparseArray<std::vector<double>> Object";
305
+ DLOG(INFO) << "clearCosineCache:SparseArray<std::vector<double>> Object";
306
+ cacheCosinesX.clear();
307
+ cacheCosinesY.clear();
308
+ DLOG(INFO) << "clearCosineCache:null";
309
+ DLOG(INFO) << "clearCosineCache:null";
310
+ }
311
+ } // namespace blurhash
312
+
313
+ #ifdef DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
314
+ #endif
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved
3
+ * Use of this source code is governed by a MIT license that can be
4
+ * found in the LICENSE file.
5
+ */
6
+
7
+ #pragma once
8
+
9
+ #include <__functional/function.h>
10
+ #include <string>
11
+ #include <string_view>
12
+ #include <vector>
13
+ #include "SparseArray.h"
14
+
15
+ namespace blurhash {
16
+ struct Image {
17
+ size_t width, height;
18
+ std::vector<unsigned char> image; // pixels rgb
19
+ };
20
+
21
+ std::string decode(std::string_view blurhash, size_t width = 32, size_t height = 32, float punch = 1.0, bool useCache = true) noexcept;
22
+
23
+ std::string encode(char const *filename, int components_x, int components_y);
24
+
25
+ void clearCache();
26
+
27
+ } // namespace blurhash
@@ -0,0 +1,87 @@
1
+ /*
2
+ * Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved
3
+ * Use of this source code is governed by a MIT license that can be
4
+ * found in the LICENSE file.
5
+ */
6
+
7
+ #include "BlurhashNode.h"
8
+
9
+ #include <string_view>
10
+ #include "RNOH/arkui/NativeNodeApi.h"
11
+
12
+
13
+ static constexpr ArkUI_NodeEventType IMAGE_NODE_EVENT_TYPES[] = {NODE_IMAGE_ON_COMPLETE, NODE_IMAGE_ON_ERROR, NODE_IMAGE_ON_DOWNLOAD_PROGRESS};
14
+
15
+ namespace rnoh {
16
+
17
+ using namespace std::literals;
18
+ constexpr std::string_view ASSET_PREFIX = "asset://"sv;
19
+ const std::string RAWFILE_PREFIX = "resource://RAWFILE/assets/";
20
+
21
+ BlurhashNode::BlurhashNode()
22
+ : ArkUINode(NativeNodeApi::getInstance()->createNode(ArkUI_NodeType::ARKUI_NODE_IMAGE)), m_childArkUINodeHandle(nullptr), m_blurhashNodeDelegate(nullptr) {
23
+ for (auto eventType : IMAGE_NODE_EVENT_TYPES) {
24
+ maybeThrow(NativeNodeApi::getInstance()->registerNodeEvent(m_nodeHandle, eventType, eventType, this));
25
+ }
26
+ }
27
+
28
+ BlurhashNode::~BlurhashNode() {
29
+ for (auto eventType : IMAGE_NODE_EVENT_TYPES) {
30
+ NativeNodeApi::getInstance()->unregisterNodeEvent(m_nodeHandle, eventType);
31
+ }
32
+ }
33
+
34
+ BlurhashNode &BlurhashNode::setSource(std::string const &uri, std::string prefix) {
35
+ ArkUI_AttributeItem item;
36
+ std::string absolutePath = prefix == "" ? RAWFILE_PREFIX : prefix;
37
+ if (uri.rfind(ASSET_PREFIX, 0) == 0) {
38
+ absolutePath += uri.substr(ASSET_PREFIX.size());
39
+ item = {.string = absolutePath.c_str()};
40
+ } else {
41
+ item = {.string = uri.c_str()};
42
+ }
43
+ maybeThrow(NativeNodeApi::getInstance()->setAttribute(m_nodeHandle, NODE_IMAGE_SRC, &item));
44
+ return *this;
45
+ }
46
+
47
+ void BlurhashNode::setNodeDelegate(BlurhashNodeDelegate *blurhashNodeDelegate) { m_blurhashNodeDelegate = blurhashNodeDelegate; }
48
+
49
+ void BlurhashNode::onNodeEvent(ArkUI_NodeEventType eventType, EventArgs &eventArgs){
50
+ if (eventType == ArkUI_NodeEventType::NODE_IMAGE_ON_COMPLETE) {
51
+ if (m_blurhashNodeDelegate != nullptr && eventArgs[0].i32 == 1) {
52
+ m_blurhashNodeDelegate->onComplete();
53
+ }
54
+ }
55
+
56
+ if (eventType == ArkUI_NodeEventType::NODE_IMAGE_ON_ERROR) {
57
+ if (m_blurhashNodeDelegate != nullptr) {
58
+ m_blurhashNodeDelegate->onError(eventArgs[0].i32);
59
+ }
60
+ }
61
+
62
+ if (eventType == ArkUI_NodeEventType::NODE_IMAGE_ON_DOWNLOAD_PROGRESS) {
63
+ if (m_blurhashNodeDelegate != nullptr) {
64
+ m_blurhashNodeDelegate->onProgress(eventArgs[0].u32, eventArgs[1].u32);
65
+ }
66
+ }
67
+ }
68
+
69
+ BlurhashNode &BlurhashNode::setResizeMode(facebook::react::ImageResizeMode const &mode) {
70
+ int32_t val = ARKUI_OBJECT_FIT_COVER;
71
+ if (mode == facebook::react::ImageResizeMode::Cover) {
72
+ val = ARKUI_OBJECT_FIT_COVER;
73
+ } else if (mode == facebook::react::ImageResizeMode::Contain) {
74
+ val = ARKUI_OBJECT_FIT_CONTAIN;
75
+ } else if (mode == facebook::react::ImageResizeMode::Stretch) {
76
+ val = ARKUI_OBJECT_FIT_FILL;
77
+ } else if (mode == facebook::react::ImageResizeMode::Center || mode == facebook::react::ImageResizeMode::Repeat) {
78
+ val = ARKUI_OBJECT_FIT_NONE;
79
+ }
80
+
81
+ ArkUI_NumberValue value[] = {{.i32 = val}};
82
+ ArkUI_AttributeItem item = {value, sizeof(value) / sizeof(ArkUI_NumberValue)};
83
+ maybeThrow(NativeNodeApi::getInstance()->setAttribute(m_nodeHandle, NODE_IMAGE_OBJECT_FIT, &item));
84
+ return *this;
85
+ }
86
+
87
+ } // namespace rnoh
@@ -0,0 +1,35 @@
1
+ /*
2
+ * Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved
3
+ * Use of this source code is governed by a MIT license that can be
4
+ * found in the LICENSE file.
5
+ */
6
+
7
+ #pragma once
8
+ #include <cstdint>
9
+ #include <react/renderer/imagemanager/primitives.h>
10
+ #include "RNOH/arkui/ArkUINode.h"
11
+
12
+ namespace rnoh {
13
+
14
+ class BlurhashNodeDelegate {
15
+ public:
16
+ virtual ~BlurhashNodeDelegate() = default;
17
+ virtual void onComplete(){};
18
+ virtual void onError(int32_t errorCode){};
19
+ virtual void onProgress(uint32_t loaded, uint32_t total){};
20
+ };
21
+
22
+ class BlurhashNode : public ArkUINode {
23
+ protected:
24
+ ArkUI_NodeHandle m_childArkUINodeHandle;
25
+ BlurhashNodeDelegate *m_blurhashNodeDelegate;
26
+
27
+ public:
28
+ BlurhashNode();
29
+ ~BlurhashNode();
30
+ BlurhashNode &setSource(std::string const &uri, std::string prefix = "");
31
+ BlurhashNode &setResizeMode(facebook::react::ImageResizeMode const &mode);
32
+ void onNodeEvent(ArkUI_NodeEventType eventType, EventArgs &eventArgs) override;
33
+ void setNodeDelegate(BlurhashNodeDelegate *blurhashNodeDelegate);
34
+ };
35
+ } // namespace rnoh
@@ -0,0 +1,53 @@
1
+ /*
2
+ * Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved
3
+ * Use of this source code is governed by a MIT license that can be
4
+ * found in the LICENSE file.
5
+ */
6
+
7
+ #include "RNOH/Package.h"
8
+ #include "ComponentDescriptors.h"
9
+ #include "BlurhashViewJSIBinder.h"
10
+ #include "RNBlurhashTurboModule.h"
11
+ #include "BlurhashViewComponentInstance.h"
12
+
13
+ using namespace rnoh;
14
+
15
+ class BlurhashViewComponentInstanceFactoryDelegate : public ComponentInstanceFactoryDelegate {
16
+ public:
17
+ using ComponentInstanceFactoryDelegate::ComponentInstanceFactoryDelegate;
18
+
19
+ ComponentInstance::Shared create(ComponentInstance::Context ctx) override {
20
+ if (ctx.componentName == "BlurhashView") {
21
+ return std::make_shared<BlurhashViewComponentInstance>(std::move(ctx));
22
+ }
23
+ return nullptr;
24
+ }
25
+ };
26
+
27
+ class BlurhashTurboModuleFactoryDelegate : public TurboModuleFactoryDelegate {
28
+ public:
29
+ SharedTurboModule createTurboModule(Context ctx, const std::string &name) const override {
30
+ if (name == "BlurhashModule") {
31
+ return std::make_shared<RNBlurhashTurboModule>(ctx, name);
32
+ }
33
+ return nullptr;
34
+ }
35
+ };
36
+
37
+ class BlurhashPackage : public Package {
38
+ public:
39
+ BlurhashPackage(Package::Context ctx) : Package(ctx) {}
40
+
41
+ std::unique_ptr<TurboModuleFactoryDelegate> createTurboModuleFactoryDelegate() override { return std::make_unique<BlurhashTurboModuleFactoryDelegate>(); }
42
+
43
+ ComponentInstanceFactoryDelegate::Shared createComponentInstanceFactoryDelegate() override {
44
+ return std::make_shared<BlurhashViewComponentInstanceFactoryDelegate>();
45
+ }
46
+
47
+ std::vector<facebook::react::ComponentDescriptorProvider> createComponentDescriptorProviders() override {
48
+ return {facebook::react::concreteComponentDescriptorProvider<facebook::react::BlurhashViewComponentDescriptor>()};
49
+ }
50
+
51
+ ComponentJSIBinderByString createComponentJSIBinderByName() override { return {{"BlurhashView", std::make_shared<BlurhashViewJSIBinder>()}}; }
52
+ };
53
+ // namespace rnoh