@amazon-devices/expo-image 2.0.1758683737

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 (289) hide show
  1. package/.eslintrc.js +2 -0
  2. package/CHANGELOG.md +285 -0
  3. package/CMakeLists.txt +91 -0
  4. package/LICENSE +7 -0
  5. package/README.kepler.md +123 -0
  6. package/README.md +54 -0
  7. package/THIRD_PARTY_NOTICES.txt +24 -0
  8. package/android/build.gradle +124 -0
  9. package/android/proguard-rules.pro +28 -0
  10. package/android/src/main/AndroidManifest.xml +15 -0
  11. package/android/src/main/java/expo/modules/image/Exceptions.kt +9 -0
  12. package/android/src/main/java/expo/modules/image/ExpoImageAppGlideModule.kt +19 -0
  13. package/android/src/main/java/expo/modules/image/ExpoImageModule.kt +192 -0
  14. package/android/src/main/java/expo/modules/image/ExpoImageView.kt +220 -0
  15. package/android/src/main/java/expo/modules/image/ExpoImageViewWrapper.kt +652 -0
  16. package/android/src/main/java/expo/modules/image/GlideModel.kt +73 -0
  17. package/android/src/main/java/expo/modules/image/ImageUtils.kt +50 -0
  18. package/android/src/main/java/expo/modules/image/ImageViewWrapperTarget.kt +313 -0
  19. package/android/src/main/java/expo/modules/image/ResourceIdHelper.kt +47 -0
  20. package/android/src/main/java/expo/modules/image/ThumbnailRequestCoordinatorExtension.kt +21 -0
  21. package/android/src/main/java/expo/modules/image/YogaUtils.kt +20 -0
  22. package/android/src/main/java/expo/modules/image/blurhash/BlurHashFetcher.kt +32 -0
  23. package/android/src/main/java/expo/modules/image/blurhash/BlurhashDecoder.kt +189 -0
  24. package/android/src/main/java/expo/modules/image/blurhash/BlurhashModelLoader.kt +30 -0
  25. package/android/src/main/java/expo/modules/image/blurhash/BlurhashModelLoaderFactory.kt +14 -0
  26. package/android/src/main/java/expo/modules/image/blurhash/BlurhashModule.kt +17 -0
  27. package/android/src/main/java/expo/modules/image/dataurls/Base64DataFetcher.kt +27 -0
  28. package/android/src/main/java/expo/modules/image/dataurls/Base64ModelLoader.kt +24 -0
  29. package/android/src/main/java/expo/modules/image/dataurls/Base64ModelLoaderFactory.kt +12 -0
  30. package/android/src/main/java/expo/modules/image/dataurls/Base64Module.kt +16 -0
  31. package/android/src/main/java/expo/modules/image/drawing/OutlineProvider.kt +201 -0
  32. package/android/src/main/java/expo/modules/image/enums/ContentFit.kt +89 -0
  33. package/android/src/main/java/expo/modules/image/enums/ImageCacheType.kt +14 -0
  34. package/android/src/main/java/expo/modules/image/enums/Priority.kt +15 -0
  35. package/android/src/main/java/expo/modules/image/events/GlideRequestListener.kt +64 -0
  36. package/android/src/main/java/expo/modules/image/events/OkHttpProgressListener.kt +26 -0
  37. package/android/src/main/java/expo/modules/image/okhttp/ExpoImageOkHttpClientGlideModule.kt +80 -0
  38. package/android/src/main/java/expo/modules/image/okhttp/GlideUrlWrapperLoader.kt +55 -0
  39. package/android/src/main/java/expo/modules/image/records/CachePolicy.kt +10 -0
  40. package/android/src/main/java/expo/modules/image/records/ContentPosition.kt +89 -0
  41. package/android/src/main/java/expo/modules/image/records/ImageTransition.kt +8 -0
  42. package/android/src/main/java/expo/modules/image/records/SourceMap.kt +160 -0
  43. package/android/src/main/java/expo/modules/image/records/events.kt +25 -0
  44. package/android/src/main/java/expo/modules/image/svg/SVGDecoder.kt +33 -0
  45. package/android/src/main/java/expo/modules/image/svg/SVGDrawableTranscoder.kt +37 -0
  46. package/android/src/main/java/expo/modules/image/svg/SVGModule.kt +26 -0
  47. package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashDecoder.kt +365 -0
  48. package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashFetcher.kt +31 -0
  49. package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashModelLoader.kt +26 -0
  50. package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashModelLoaderFactory.kt +14 -0
  51. package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashModule.kt +17 -0
  52. package/build/ExpoImage.d.ts +15 -0
  53. package/build/ExpoImage.d.ts.map +1 -0
  54. package/build/ExpoImage.js +75 -0
  55. package/build/ExpoImage.js.map +1 -0
  56. package/build/ExpoImage.kepler.d.ts +23 -0
  57. package/build/ExpoImage.kepler.d.ts.map +1 -0
  58. package/build/ExpoImage.kepler.js +71 -0
  59. package/build/ExpoImage.kepler.js.map +1 -0
  60. package/build/ExpoImage.web.d.ts +9 -0
  61. package/build/ExpoImage.web.d.ts.map +1 -0
  62. package/build/ExpoImage.web.js +90 -0
  63. package/build/ExpoImage.web.js.map +1 -0
  64. package/build/ExpoImageModules.d.ts +3 -0
  65. package/build/ExpoImageModules.d.ts.map +1 -0
  66. package/build/ExpoImageModules.js +4 -0
  67. package/build/ExpoImageModules.js.map +1 -0
  68. package/build/ExpoImageModules.kepler.d.ts +6 -0
  69. package/build/ExpoImageModules.kepler.d.ts.map +1 -0
  70. package/build/ExpoImageModules.kepler.js +5 -0
  71. package/build/ExpoImageModules.kepler.js.map +1 -0
  72. package/build/Image.d.ts +30 -0
  73. package/build/Image.d.ts.map +1 -0
  74. package/build/Image.js +49 -0
  75. package/build/Image.js.map +1 -0
  76. package/build/Image.types.d.ts +374 -0
  77. package/build/Image.types.d.ts.map +1 -0
  78. package/build/Image.types.js +2 -0
  79. package/build/Image.types.js.map +1 -0
  80. package/build/ImageBackground.d.ts +6 -0
  81. package/build/ImageBackground.d.ts.map +1 -0
  82. package/build/ImageBackground.js +13 -0
  83. package/build/ImageBackground.js.map +1 -0
  84. package/build/ImageViewNativeComponent.d.ts +20 -0
  85. package/build/ImageViewNativeComponent.d.ts.map +1 -0
  86. package/build/ImageViewNativeComponent.js +42 -0
  87. package/build/ImageViewNativeComponent.js.map +1 -0
  88. package/build/NativeImageLoaderKepler.d.ts +18 -0
  89. package/build/NativeImageLoaderKepler.d.ts.map +1 -0
  90. package/build/NativeImageLoaderKepler.js +3 -0
  91. package/build/NativeImageLoaderKepler.js.map +1 -0
  92. package/build/fabric/registerNativeComponent.d.ts +15 -0
  93. package/build/fabric/registerNativeComponent.d.ts.map +1 -0
  94. package/build/fabric/registerNativeComponent.js +47 -0
  95. package/build/fabric/registerNativeComponent.js.map +1 -0
  96. package/build/index.d.ts +4 -0
  97. package/build/index.d.ts.map +1 -0
  98. package/build/index.js +4 -0
  99. package/build/index.js.map +1 -0
  100. package/build/utils/AssetSourceResolver.web.d.ts +24 -0
  101. package/build/utils/AssetSourceResolver.web.d.ts.map +1 -0
  102. package/build/utils/AssetSourceResolver.web.js +67 -0
  103. package/build/utils/AssetSourceResolver.web.js.map +1 -0
  104. package/build/utils/blurhash/base83.d.ts +3 -0
  105. package/build/utils/blurhash/base83.d.ts.map +1 -0
  106. package/build/utils/blurhash/base83.js +103 -0
  107. package/build/utils/blurhash/base83.js.map +1 -0
  108. package/build/utils/blurhash/decode.d.ts +7 -0
  109. package/build/utils/blurhash/decode.d.ts.map +1 -0
  110. package/build/utils/blurhash/decode.js +92 -0
  111. package/build/utils/blurhash/decode.js.map +1 -0
  112. package/build/utils/blurhash/error.d.ts +4 -0
  113. package/build/utils/blurhash/error.d.ts.map +1 -0
  114. package/build/utils/blurhash/error.js +8 -0
  115. package/build/utils/blurhash/error.js.map +1 -0
  116. package/build/utils/blurhash/useBlurhash.d.ts +8 -0
  117. package/build/utils/blurhash/useBlurhash.d.ts.map +1 -0
  118. package/build/utils/blurhash/useBlurhash.js +64 -0
  119. package/build/utils/blurhash/useBlurhash.js.map +1 -0
  120. package/build/utils/blurhash/utils.d.ts +5 -0
  121. package/build/utils/blurhash/utils.d.ts.map +1 -0
  122. package/build/utils/blurhash/utils.js +21 -0
  123. package/build/utils/blurhash/utils.js.map +1 -0
  124. package/build/utils/resolveAssetSource.d.ts +3 -0
  125. package/build/utils/resolveAssetSource.d.ts.map +1 -0
  126. package/build/utils/resolveAssetSource.js +3 -0
  127. package/build/utils/resolveAssetSource.js.map +1 -0
  128. package/build/utils/resolveAssetSource.web.d.ts +9 -0
  129. package/build/utils/resolveAssetSource.web.d.ts.map +1 -0
  130. package/build/utils/resolveAssetSource.web.js +31 -0
  131. package/build/utils/resolveAssetSource.web.js.map +1 -0
  132. package/build/utils/resolveHashString.d.ts +14 -0
  133. package/build/utils/resolveHashString.d.ts.map +1 -0
  134. package/build/utils/resolveHashString.js +31 -0
  135. package/build/utils/resolveHashString.js.map +1 -0
  136. package/build/utils/resolveHashString.web.d.ts +20 -0
  137. package/build/utils/resolveHashString.web.d.ts.map +1 -0
  138. package/build/utils/resolveHashString.web.js +31 -0
  139. package/build/utils/resolveHashString.web.js.map +1 -0
  140. package/build/utils/resolveSources.d.ts +8 -0
  141. package/build/utils/resolveSources.d.ts.map +1 -0
  142. package/build/utils/resolveSources.js +45 -0
  143. package/build/utils/resolveSources.js.map +1 -0
  144. package/build/utils/thumbhash/thumbhash.d.ts +66 -0
  145. package/build/utils/thumbhash/thumbhash.d.ts.map +1 -0
  146. package/build/utils/thumbhash/thumbhash.js +338 -0
  147. package/build/utils/thumbhash/thumbhash.js.map +1 -0
  148. package/build/utils.d.ts +17 -0
  149. package/build/utils.d.ts.map +1 -0
  150. package/build/utils.js +85 -0
  151. package/build/utils.js.map +1 -0
  152. package/build/web/AnimationManager.d.ts +37 -0
  153. package/build/web/AnimationManager.d.ts.map +1 -0
  154. package/build/web/AnimationManager.js +155 -0
  155. package/build/web/AnimationManager.js.map +1 -0
  156. package/build/web/ColorTintFilter.d.ts +12 -0
  157. package/build/web/ColorTintFilter.d.ts.map +1 -0
  158. package/build/web/ColorTintFilter.js +30 -0
  159. package/build/web/ColorTintFilter.js.map +1 -0
  160. package/build/web/ImageWrapper.d.ts +5 -0
  161. package/build/web/ImageWrapper.d.ts.map +1 -0
  162. package/build/web/ImageWrapper.js +44 -0
  163. package/build/web/ImageWrapper.js.map +1 -0
  164. package/build/web/ImageWrapper.types.d.ts +29 -0
  165. package/build/web/ImageWrapper.types.d.ts.map +1 -0
  166. package/build/web/ImageWrapper.types.js +2 -0
  167. package/build/web/ImageWrapper.types.js.map +1 -0
  168. package/build/web/getImageWrapperEventHandler.d.ts +8 -0
  169. package/build/web/getImageWrapperEventHandler.d.ts.map +1 -0
  170. package/build/web/getImageWrapperEventHandler.js +25 -0
  171. package/build/web/getImageWrapperEventHandler.js.map +1 -0
  172. package/build/web/hooks.d.ts +13 -0
  173. package/build/web/hooks.d.ts.map +1 -0
  174. package/build/web/hooks.js +58 -0
  175. package/build/web/hooks.js.map +1 -0
  176. package/build/web/imageStyles.d.ts +2 -0
  177. package/build/web/imageStyles.d.ts.map +1 -0
  178. package/build/web/imageStyles.js +137 -0
  179. package/build/web/imageStyles.js.map +1 -0
  180. package/build/web/positioning.d.ts +11 -0
  181. package/build/web/positioning.d.ts.map +1 -0
  182. package/build/web/positioning.js +35 -0
  183. package/build/web/positioning.js.map +1 -0
  184. package/build/web/useSourceSelection.d.ts +14 -0
  185. package/build/web/useSourceSelection.d.ts.map +1 -0
  186. package/build/web/useSourceSelection.js +98 -0
  187. package/build/web/useSourceSelection.js.map +1 -0
  188. package/expo-module.config.json +9 -0
  189. package/ios/Blurhash.swift +326 -0
  190. package/ios/BlurhashLoader.swift +52 -0
  191. package/ios/ContentFit.swift +55 -0
  192. package/ios/ContentPosition.swift +108 -0
  193. package/ios/ExpoImage.podspec +30 -0
  194. package/ios/ImageCachePolicy.swift +24 -0
  195. package/ios/ImageCacheType.swift +21 -0
  196. package/ios/ImageModule.swift +127 -0
  197. package/ios/ImagePriority.swift +22 -0
  198. package/ios/ImageSource.swift +44 -0
  199. package/ios/ImageTransition.swift +67 -0
  200. package/ios/ImageUtils.swift +227 -0
  201. package/ios/ImageView.swift +469 -0
  202. package/ios/Loaders/PhotoLibraryAssetLoader.swift +146 -0
  203. package/ios/Thumbhash.swift +550 -0
  204. package/ios/ThumbhashLoader.swift +53 -0
  205. package/jest.config.js +3 -0
  206. package/kepler/ExpoImage.cpp +63 -0
  207. package/kepler/ExpoImage.h +29 -0
  208. package/kepler/ExpoImageCacheHandler.cpp +15 -0
  209. package/kepler/ExpoImageCacheHandler.h +28 -0
  210. package/kepler/ExpoImageComponent.cpp +579 -0
  211. package/kepler/ExpoImageComponent.h +199 -0
  212. package/kepler/ImageWrapper/BlurhashImageWrapper.cpp +37 -0
  213. package/kepler/ImageWrapper/BlurhashImageWrapper.h +23 -0
  214. package/kepler/ImageWrapper/CacheImageWrapper.cpp +80 -0
  215. package/kepler/ImageWrapper/CacheImageWrapper.h +41 -0
  216. package/kepler/ImageWrapper/HashImageWrapper.cpp +21 -0
  217. package/kepler/ImageWrapper/HashImageWrapper.h +22 -0
  218. package/kepler/ImageWrapper/ImageWrapper.cpp +24 -0
  219. package/kepler/ImageWrapper/ImageWrapper.h +33 -0
  220. package/kepler/ImageWrapper/LocalImageWrapper.cpp +61 -0
  221. package/kepler/ImageWrapper/LocalImageWrapper.h +30 -0
  222. package/kepler/ImageWrapper/ThumbhashImageWrapper.cpp +33 -0
  223. package/kepler/ImageWrapper/ThumbhashImageWrapper.h +20 -0
  224. package/kepler/KeplerImageViewComponent.h +64 -0
  225. package/kepler/KeplerInit.cpp +35 -0
  226. package/kepler/blurhash/common.h +32 -0
  227. package/kepler/blurhash/decode.cpp +187 -0
  228. package/kepler/blurhash/decode.h +58 -0
  229. package/kepler/contentposition/ImageContentPosition.cpp +86 -0
  230. package/kepler/contentposition/ImageContentPosition.h +48 -0
  231. package/kepler/enums/ImageContentFit.h +17 -0
  232. package/kepler/enums/ImagePriority.h +17 -0
  233. package/kepler/managers/ExpoImageManager.cpp +38 -0
  234. package/kepler/managers/ExpoImageManager.h +23 -0
  235. package/kepler/test/ExpoImage.cpp +73 -0
  236. package/kepler/test/ExpoImageComponent.cpp +290 -0
  237. package/kepler/test/blurhash/decode.cpp +39 -0
  238. package/kepler/test/contentposition/ImageContentPosition.cpp +100 -0
  239. package/kepler/test/managers/ExpoImageManager.cpp +39 -0
  240. package/kepler/test/thumbhash/decode.cpp +18 -0
  241. package/kepler/test/utils/LoaderDelegate.cpp +130 -0
  242. package/kepler/thumbhash/decode.cpp +166 -0
  243. package/kepler/thumbhash/decode.h +22 -0
  244. package/kepler/utils/PlaceholderImageLoaderDelegate.cpp +26 -0
  245. package/kepler/utils/PlaceholderImageLoaderDelegate.h +26 -0
  246. package/kepler/utils/PrefetchImageLoaderDelegate.cpp +55 -0
  247. package/kepler/utils/PrefetchImageLoaderDelegate.h +35 -0
  248. package/kepler/utils/SourceImageLoaderDelegate.cpp +47 -0
  249. package/kepler/utils/SourceImageLoaderDelegate.h +42 -0
  250. package/kepler/utils/SourceImageLoaderDelegateEmitter.cpp +15 -0
  251. package/kepler/utils/SourceImageLoaderDelegateEmitter.h +28 -0
  252. package/kepler-compatibility.json +8 -0
  253. package/package.json +1 -0
  254. package/react-native.config.js +22 -0
  255. package/src/ExpoImage.kepler.tsx +119 -0
  256. package/src/ExpoImage.tsx +119 -0
  257. package/src/ExpoImage.web.tsx +155 -0
  258. package/src/ExpoImageModules.kepler.ts +7 -0
  259. package/src/ExpoImageModules.ts +4 -0
  260. package/src/Image.tsx +82 -0
  261. package/src/Image.types.ts +450 -0
  262. package/src/ImageBackground.tsx +18 -0
  263. package/src/ImageViewNativeComponent.ts +59 -0
  264. package/src/NativeImageLoaderKepler.ts +22 -0
  265. package/src/fabric/registerNativeComponent.ts +70 -0
  266. package/src/index.ts +3 -0
  267. package/src/utils/AssetSourceResolver.web.ts +88 -0
  268. package/src/utils/blurhash/base83.ts +104 -0
  269. package/src/utils/blurhash/decode.ts +114 -0
  270. package/src/utils/blurhash/error.ts +7 -0
  271. package/src/utils/blurhash/useBlurhash.tsx +81 -0
  272. package/src/utils/blurhash/utils.ts +21 -0
  273. package/src/utils/resolveAssetSource.tsx +3 -0
  274. package/src/utils/resolveAssetSource.web.ts +40 -0
  275. package/src/utils/resolveHashString.tsx +36 -0
  276. package/src/utils/resolveHashString.web.tsx +33 -0
  277. package/src/utils/resolveSources.tsx +48 -0
  278. package/src/utils/thumbhash/thumbhash.ts +387 -0
  279. package/src/utils.ts +109 -0
  280. package/src/web/AnimationManager.tsx +224 -0
  281. package/src/web/ColorTintFilter.tsx +36 -0
  282. package/src/web/ImageWrapper.tsx +85 -0
  283. package/src/web/ImageWrapper.types.ts +36 -0
  284. package/src/web/getImageWrapperEventHandler.ts +29 -0
  285. package/src/web/hooks.ts +72 -0
  286. package/src/web/imageStyles.tsx +136 -0
  287. package/src/web/positioning.ts +48 -0
  288. package/src/web/useSourceSelection.ts +151 -0
  289. package/tsconfig.json +9 -0
@@ -0,0 +1,166 @@
1
+ /*
2
+ * Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * PROPRIETARY/CONFIDENTIAL
5
+ *
6
+ * Use is subject to license terms.
7
+ */
8
+
9
+ #include "decode.h"
10
+
11
+ #include <mbedtls/base64.h>
12
+
13
+ #include <cmath>
14
+ #include <string>
15
+ #include <unordered_map>
16
+ #include <vector>
17
+
18
+ // Inspired by https://github.com/evanw/thumbhash/blob/main/java/com/madebyevan/thumbhash/ThumbHash.java
19
+
20
+ namespace {
21
+
22
+ std::string base64_decode(const std::string& in) {
23
+ size_t bufferSize;
24
+
25
+ mbedtls_base64_decode(nullptr, 0, &bufferSize, reinterpret_cast<const unsigned char*>(in.data()), in.size());
26
+
27
+ std::string buffer(bufferSize, ' ');
28
+
29
+ mbedtls_base64_decode(
30
+ reinterpret_cast<unsigned char*>(buffer.data()),
31
+ bufferSize,
32
+ &bufferSize,
33
+ reinterpret_cast<const unsigned char*>(in.data()),
34
+ in.size());
35
+
36
+ return buffer;
37
+ }
38
+
39
+ double thumbHashToApproximateAspectRatio(const std::string& hash) {
40
+ int header = hash[3];
41
+ bool hasAlpha = hash[2] & 0x80;
42
+ bool isLandscape = hash[4] & 0x80;
43
+ int lx = isLandscape ? hasAlpha ? 5 : 7 : header & 7;
44
+ int ly = isLandscape ? header & 7 : hasAlpha ? 5 : 7;
45
+ return double(lx) / double(ly);
46
+ }
47
+
48
+ } // namespace
49
+
50
+ const int HEADER_SIZE = 6;
51
+ DecodedThumbhash decodeThumbhash(const std::string& hash) {
52
+ // Decode hash to readable vector
53
+ std::string decodedHash = base64_decode(hash);
54
+ if (decodedHash.size() < HEADER_SIZE) return (DecodedThumbhash){0, 0, std::make_unique<uint8_t[]>(0)};
55
+
56
+ // Read the constants
57
+ int header24 = int(decodedHash[0]) | (int(decodedHash[1]) << 8) | (int(decodedHash[2]) << 16);
58
+ int header16 = int(decodedHash[3]) | (int(decodedHash[4]) << 8);
59
+ double l_dc = double(header24 & 63) / 63.0;
60
+ double p_dc = double((header24 >> 6) & 63) / 31.5 - 1.0;
61
+ double q_dc = double((header24 >> 12) & 63) / 31.5 - 1.0;
62
+ double l_scale = double((header24 >> 18) & 31) / 31.0;
63
+ bool hasAlpha = header24 >> 23;
64
+ double p_scale = double((header16 >> 3) & 63) / 63.0;
65
+ double q_scale = ((header16 >> 9) & 63) / 63.0;
66
+ bool isLandscape = header16 >> 15;
67
+ int lx = std::max(3, isLandscape ? hasAlpha ? 5 : 7 : header16 & 7);
68
+ int ly = std::max(3, isLandscape ? header16 & 7 : hasAlpha ? 5 : 7);
69
+ double a_dc = hasAlpha ? double(decodedHash[5] & 15) / 15.0 : 1.0;
70
+ double a_scale = double(decodedHash[5] >> 4) / 15.0;
71
+
72
+ // Read the varying factors (boost saturation by 1.25x to compensate for quantization)
73
+ int ac_start = hasAlpha ? 6 : 5;
74
+ int ac_index = 0;
75
+
76
+ auto decodeChannel = [&](int nx, int ny, double scale) {
77
+ std::vector<double> ac;
78
+ ac.reserve(nx * ny);
79
+ for (int cy = 0; cy < ny; ++cy) {
80
+ for (int cx = cy != 0 ? 0 : 1; cx * ny < nx * (ny - cy); ++cx) {
81
+ ac.push_back(
82
+ (double((decodedHash[ac_start + (ac_index >> 1)] >> ((ac_index++ & 1) << 2)) & 15) / 7.5 -
83
+ 1.0) *
84
+ scale);
85
+ }
86
+ }
87
+ return ac;
88
+ };
89
+ auto l_ac = decodeChannel(lx, ly, l_scale);
90
+ auto p_ac = decodeChannel(3, 3, p_scale * 1.25);
91
+ auto q_ac = decodeChannel(3, 3, q_scale * 1.25);
92
+ std::vector<double> a_ac;
93
+ if (hasAlpha) {
94
+ a_ac = decodeChannel(5, 5, a_scale);
95
+ }
96
+
97
+ // Decode using the DCT into RGB
98
+ double ratio = thumbHashToApproximateAspectRatio(decodedHash);
99
+ int w = int(round(ratio > 1.0 ? 32.0 : 32.0 * ratio));
100
+ int h = int(round(ratio > 1.0 ? 32.0 / ratio : 32.0));
101
+ auto rgba = std::make_unique<uint8_t[]>(w * h * 4);
102
+ int n1 = std::max(lx, hasAlpha ? 5 : 3);
103
+ int n2 = std::max(ly, hasAlpha ? 5 : 3);
104
+ std::vector<double> fx(n1, 0);
105
+ std::vector<double> fy(n2, 0);
106
+
107
+ for (int y = 0, i = 0; y < h; ++y) {
108
+ for (int x = 0; x < w; ++x, i += 4) {
109
+ double l = l_dc;
110
+ double p = p_dc;
111
+ double q = q_dc;
112
+ double a = a_dc;
113
+
114
+ // Precompute the coefficients d
115
+ for (int cx = 0; cx < n1; ++cx) {
116
+ fx[cx] = cos(M_PI / w * (double(x) + 0.5) * double(cx));
117
+ }
118
+
119
+ for (int cy = 0; cy < n2; ++cy) {
120
+ fy[cy] = cos(M_PI / h * (double(y) + 0.5) * double(cy));
121
+ }
122
+
123
+ // Decode L
124
+
125
+ for (int cy = 0, j = 0; cy < ly; ++cy) {
126
+ for (int cx = cy != 0 ? 0 : 1; cx * ly < lx * (ly - cy); ++cx, ++j) {
127
+ double fy2 = fy[cy] * 2.0;
128
+ l += l_ac[j] * fx[cx] * fy2;
129
+ }
130
+ }
131
+
132
+ // Decode P and Q
133
+ for (int cy = 0, j = 0; cy < 3; ++cy) {
134
+ for (int cx = cy != 0 ? 0 : 1; cx < 3 - cy; ++cx, ++j) {
135
+ double fy2 = fy[cy] * 2.0;
136
+ double f = fx[cx] * fy2;
137
+ p += p_ac[j] * f;
138
+ q += q_ac[j] * f;
139
+ }
140
+ }
141
+
142
+ // Decode A
143
+ if (hasAlpha) {
144
+ for (int cy = 0, j = 0; cy < 5; ++cy) {
145
+ for (int cx = cy != 0 ? 0 : 1; cx < 5 - cy; ++cx, ++j) {
146
+ double fy2 = fy[cy] * 2.0;
147
+ a += a_ac[j] * fx[cx] * fy2;
148
+ }
149
+ }
150
+ }
151
+
152
+ // Convert to RGB
153
+ double b = l - 2.0 / 3.0 * p;
154
+ double r = (3.0 * l - b + q) / 2.0;
155
+ double g = r - q;
156
+ rgba[i] = uint8_t(std::max(0.0, 255.0 * std::min(1.0, r)));
157
+ rgba[i + 1] = uint8_t(std::max(0.0, 255.0 * std::min(1.0, g)));
158
+ rgba[i + 2] = uint8_t(std::max(0.0, 255.0 * std::min(1.0, b)));
159
+ rgba[i + 3] = uint8_t(std::max(0.0, 255.0 * std::min(1.0, a)));
160
+ }
161
+ }
162
+
163
+ DecodedThumbhash result = {.width = w, .height = h, .pixelArray = std::move(rgba)};
164
+
165
+ return result;
166
+ }
@@ -0,0 +1,22 @@
1
+ /*
2
+ * Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * PROPRIETARY/CONFIDENTIAL
5
+ *
6
+ * Use is subject to license terms.
7
+ */
8
+
9
+ #pragma once
10
+
11
+ #include <cstdint>
12
+ #include <memory>
13
+
14
+ // Inspired by https://github.com/evanw/thumbhash/blob/main/java/com/madebyevan/thumbhash/ThumbHash.java
15
+
16
+ struct DecodedThumbhash {
17
+ int width;
18
+ int height;
19
+ std::unique_ptr<uint8_t[]> pixelArray;
20
+ };
21
+
22
+ DecodedThumbhash decodeThumbhash(const std::string& thumbhash);
@@ -0,0 +1,26 @@
1
+ /*
2
+ * Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * PROPRIETARY/CONFIDENTIAL
5
+ *
6
+ * Use is subject to license terms.
7
+ */
8
+
9
+ #include "PlaceholderImageLoaderDelegate.h"
10
+
11
+ PlaceholderImageLoaderDelegate::PlaceholderImageLoaderDelegate(std::function<void()> onLoad) : onLoad_(onLoad){};
12
+
13
+ void PlaceholderImageLoaderDelegate::notifyImageLoadStart(){};
14
+
15
+ void PlaceholderImageLoaderDelegate::notifyImageLoadProgress(float progress) {}
16
+
17
+ void PlaceholderImageLoaderDelegate::notifyImageLoadSuccess(volta::graphics::Image) {
18
+ onLoad_();
19
+ }
20
+ void PlaceholderImageLoaderDelegate::notifyImageLoadSuccess(volta::image::ImageRef) {
21
+ onLoad_();
22
+ }
23
+
24
+ void PlaceholderImageLoaderDelegate::notifyImageLoadFailure(volta::ImageLoadError) {
25
+ onLoad_();
26
+ }
@@ -0,0 +1,26 @@
1
+ /*
2
+ * Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * PROPRIETARY/CONFIDENTIAL
5
+ *
6
+ * Use is subject to license terms.
7
+ */
8
+
9
+ #pragma once
10
+
11
+ #include <KeplerScript/utils/image/KeplerScriptImageLoaderDelegate.h>
12
+ #include <Volta/utils/Image.h>
13
+
14
+ class PlaceholderImageLoaderDelegate : public volta::IImageLoaderDelegate {
15
+ public:
16
+ PlaceholderImageLoaderDelegate(std::function<void()> onLoad);
17
+
18
+ void notifyImageLoadStart() override;
19
+ void notifyImageLoadProgress(float progress) override;
20
+ void notifyImageLoadSuccess(volta::graphics::Image) override;
21
+ void notifyImageLoadSuccess(volta::image::ImageRef) override;
22
+ void notifyImageLoadFailure(volta::ImageLoadError) override;
23
+
24
+ private:
25
+ std::function<void()> onLoad_;
26
+ };
@@ -0,0 +1,55 @@
1
+ /*
2
+ * Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * PROPRIETARY/CONFIDENTIAL
5
+ *
6
+ * Use is subject to license terms.
7
+ */
8
+
9
+ #include "PrefetchImageLoaderDelegate.h"
10
+
11
+ #include <KeplerScript/appinit/KeplerScriptApplication.h>
12
+ #include <KeplerScript/logger/KPLog.h>
13
+
14
+ PrefetchImageLoaderDelegate::PrefetchImageLoaderDelegate(int imagesToLoad, const std::function<void(bool)>& onFinish) :
15
+ imagesToLoad_(imagesToLoad),
16
+ onFinish_(onFinish){};
17
+
18
+ void PrefetchImageLoaderDelegate::notifyImageLoadStart() {
19
+ volta::react::KPLog.debug("ExpoImage :: prefetch LoadStart");
20
+ };
21
+
22
+ void PrefetchImageLoaderDelegate::notifyImageLoadProgress(float progress) {
23
+ volta::react::KPLog.debug("ExpoImage :: prefetch LoadProgress {}", progress);
24
+ }
25
+
26
+ void PrefetchImageLoaderDelegate::notifyImageLoadSuccess(volta::graphics::Image) {
27
+ volta::react::KPLog.debug("ExpoImage :: prefetch LoadSuccess");
28
+ imageLoaded();
29
+ }
30
+ void PrefetchImageLoaderDelegate::notifyImageLoadSuccess(volta::image::ImageRef) {
31
+ volta::react::KPLog.debug("ExpoImage :: prefetch LoadSuccess");
32
+ imageLoaded();
33
+ }
34
+
35
+ void PrefetchImageLoaderDelegate::notifyImageLoadFailure(volta::ImageLoadError) {
36
+ volta::react::KPLog.debug("ExpoImage :: prefetch LoadFailure");
37
+ imageErrored();
38
+ }
39
+
40
+ void PrefetchImageLoaderDelegate::onFinish(bool success) {
41
+ volta::react::KPLog.debug("ExpoImage :: onFinish {} {}", success, isResolved_);
42
+ if (!isResolved_) {
43
+ isResolved_ = true;
44
+ onFinish_(success);
45
+ }
46
+ }
47
+
48
+ void PrefetchImageLoaderDelegate::imageLoaded() {
49
+ imagesLoaded_++;
50
+ if (imagesLoaded_ == imagesToLoad_) onFinish(true);
51
+ }
52
+
53
+ void PrefetchImageLoaderDelegate::imageErrored() {
54
+ onFinish(false);
55
+ }
@@ -0,0 +1,35 @@
1
+ /*
2
+ * Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * PROPRIETARY/CONFIDENTIAL
5
+ *
6
+ * Use is subject to license terms.
7
+ */
8
+
9
+ #pragma once
10
+
11
+ #include <KeplerScript/components/KeplerViewComponentEventEmitter.h>
12
+ #include <KeplerScript/utils/image/KeplerScriptImageLoaderDelegate.h>
13
+ #include <Volta/utils/Image.h>
14
+
15
+ #include <memory>
16
+
17
+ class PrefetchImageLoaderDelegate : public volta::IImageLoaderDelegate {
18
+ public:
19
+ PrefetchImageLoaderDelegate(int imagesToLoad, const std::function<void(bool)>& onFinish);
20
+ void notifyImageLoadStart() override;
21
+ void notifyImageLoadProgress(float progress) override;
22
+ void notifyImageLoadSuccess(volta::graphics::Image) override;
23
+ void notifyImageLoadSuccess(volta::image::ImageRef) override;
24
+ void notifyImageLoadFailure(volta::ImageLoadError) override;
25
+
26
+ private:
27
+ void imageLoaded();
28
+ void imageErrored();
29
+ void onFinish(bool success);
30
+
31
+ std::function<void(bool)> onFinish_;
32
+ int imagesToLoad_ = 0;
33
+ int imagesLoaded_ = 0;
34
+ bool isResolved_ = false;
35
+ };
@@ -0,0 +1,47 @@
1
+ /*
2
+ * Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * PROPRIETARY/CONFIDENTIAL
5
+ *
6
+ * Use is subject to license terms.
7
+ */
8
+
9
+ #include "SourceImageLoaderDelegate.h"
10
+
11
+ #include <KeplerScript/components/EventPayloadBuilder.h>
12
+
13
+ SourceImageLoaderDelegate::SourceImageLoaderDelegate(
14
+ const std::shared_ptr<volta::react::KeplerViewComponentEventEmitter>& eventEmitter,
15
+ const std::function<void()>& onLoad) :
16
+ eventEmitter_(std::make_unique<SourceImageLoaderDelegateEmitter>(eventEmitter)),
17
+ onLoad_(onLoad){};
18
+
19
+ void SourceImageLoaderDelegate::notifyImageLoadStart() {
20
+ eventEmitter_->emit("loadStart");
21
+ };
22
+
23
+ void SourceImageLoaderDelegate::notifyImageLoadProgress(float progress) {
24
+ constexpr int32_t total = 10000;
25
+
26
+ eventEmitter_->emit("progress", [progress](volta::react::EventPayloadBuilder& eventPayloadBuilder) {
27
+ eventPayloadBuilder.insert("loaded", static_cast<int>(progress * total));
28
+ eventPayloadBuilder.insert("total", total);
29
+ });
30
+ }
31
+
32
+ void SourceImageLoaderDelegate::notifyImageLoadSuccess(volta::graphics::Image) {
33
+ eventEmitter_->emit("load");
34
+ eventEmitter_->emit("loadEnd");
35
+ onLoad_();
36
+ }
37
+ void SourceImageLoaderDelegate::notifyImageLoadSuccess(volta::image::ImageRef) {
38
+ eventEmitter_->emit("load");
39
+ eventEmitter_->emit("loadEnd");
40
+ onLoad_();
41
+ }
42
+
43
+ void SourceImageLoaderDelegate::notifyImageLoadFailure(volta::ImageLoadError) {
44
+ eventEmitter_->emit("error");
45
+ eventEmitter_->emit("loadEnd");
46
+ onLoad_();
47
+ }
@@ -0,0 +1,42 @@
1
+ /*
2
+ * Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * PROPRIETARY/CONFIDENTIAL
5
+ *
6
+ * Use is subject to license terms.
7
+ */
8
+
9
+ #pragma once
10
+
11
+ #include <KeplerScript/components/EventPayloadBuilder.h>
12
+ #include <KeplerScript/components/KeplerViewComponentEventEmitter.h>
13
+ #include <KeplerScript/utils/image/KeplerScriptImageLoaderDelegate.h>
14
+ #include <Volta/utils/Image.h>
15
+
16
+ #include "SourceImageLoaderDelegateEmitter.h"
17
+
18
+ #include <memory>
19
+
20
+
21
+ class SourceImageLoaderDelegate : public volta::IImageLoaderDelegate {
22
+ public:
23
+ SourceImageLoaderDelegate(
24
+ const std::shared_ptr<volta::react::KeplerViewComponentEventEmitter>& eventEmitter,
25
+ const std::function<void()>& onLoad);
26
+
27
+ #ifdef UNIT_TEST
28
+ SourceImageLoaderDelegate(
29
+ std::unique_ptr<ISourceImageLoaderDelegateEmitter>&& emitter,
30
+ const std::function<void()>& onLoad) : eventEmitter_{std::move(emitter)}, onLoad_{onLoad} {}
31
+ #endif
32
+
33
+ void notifyImageLoadStart() override;
34
+ void notifyImageLoadProgress(float progress) override;
35
+ void notifyImageLoadSuccess(volta::graphics::Image) override;
36
+ void notifyImageLoadSuccess(volta::image::ImageRef) override;
37
+ void notifyImageLoadFailure(volta::ImageLoadError) override;
38
+
39
+ private:
40
+ std::unique_ptr<ISourceImageLoaderDelegateEmitter> eventEmitter_;
41
+ std::function<void()> onLoad_;
42
+ };
@@ -0,0 +1,15 @@
1
+ #include "SourceImageLoaderDelegateEmitter.h"
2
+
3
+ SourceImageLoaderDelegateEmitter::SourceImageLoaderDelegateEmitter(
4
+ const std::shared_ptr<volta::react::KeplerViewComponentEventEmitter>& eventEmitter) :
5
+ eventEmitter_{eventEmitter} {}
6
+
7
+ void SourceImageLoaderDelegateEmitter::emit(const std::string& eventName) const {
8
+ eventEmitter_->emit(eventName);
9
+ }
10
+
11
+ void SourceImageLoaderDelegateEmitter::emit(
12
+ const std::string& eventName,
13
+ const std::function<void(volta::react::EventPayloadBuilder&)>& builderFunc) const {
14
+ eventEmitter_->emit(eventName, builderFunc);
15
+ }
@@ -0,0 +1,28 @@
1
+ #pragma once
2
+
3
+ #include <KeplerScript/components/EventPayloadBuilder.h>
4
+ #include <KeplerScript/components/KeplerViewComponentEventEmitter.h>
5
+
6
+ class ISourceImageLoaderDelegateEmitter {
7
+ public:
8
+ virtual ~ISourceImageLoaderDelegateEmitter() = default;
9
+
10
+ virtual void emit(const std::string& eventName) const = 0;
11
+
12
+ virtual void emit(
13
+ const std::string& eventName,
14
+ const std::function<void(volta::react::EventPayloadBuilder&)>& builderFunc) const = 0;
15
+ };
16
+
17
+ class SourceImageLoaderDelegateEmitter : public ISourceImageLoaderDelegateEmitter {
18
+ public:
19
+ explicit SourceImageLoaderDelegateEmitter(
20
+ const std::shared_ptr<volta::react::KeplerViewComponentEventEmitter>& eventEmitter);
21
+
22
+ void emit(const std::string& eventName) const override;
23
+
24
+ void emit(const std::string& eventName, const std::function<void(volta::react::EventPayloadBuilder&)>& builderFunc) const override;
25
+
26
+ private:
27
+ std::shared_ptr<volta::react::KeplerViewComponentEventEmitter> eventEmitter_;
28
+ };
@@ -0,0 +1,8 @@
1
+ {
2
+ "versions": {
3
+ "2.0.0": "/com.amazon.kepler.expo_image_2@IExpoImage_0",
4
+ "2.0.1756403551": "/com.amazon.kepler.expo_image_2@IExpoImage_0",
5
+ "2.0.1758654000": "/com.amazon.kepler.expo_image_2@IExpoImage_0",
6
+ "2.0.1758683737": "/com.amazon.kepler.expo_image_2@IExpoImage_0"
7
+ }
8
+ }
package/package.json ADDED
@@ -0,0 +1 @@
1
+ {"name": "@amazon-devices/expo-image", "title": "Expo Image", "version": "2.0.1758683737+1.6.0", "description": "A cross-platform, performant image component for React Native and Expo with Web support", "main": "build/index.js", "types": "build/index.d.ts", "sideEffects": false, "scripts": {"build": "expo-module build", "clean": "expo-module clean", "lint": "expo-module lint", "test": "expo-module test", "expo-module": "expo-module"}, "homepage": "https://docs.expo.dev/versions/latest/sdk/image/", "repository": {"type": "git", "url": "https://github.com/expo/expo.git", "directory": "packages/expo-image"}, "kepler": {"temporary-alias-for-package": {"name": "expo-image", "version": "1.6.0"}}, "keywords": ["react-native"], "author": "650 Industries, Inc.", "license": "See license in LICENSE", "dependencies": {"@amazon-devices/keplerscript-turbomodule-api": "^1.0.0"}, "devDependencies": {"expo-module-scripts": "^3.0.0"}, "peerDependencies": {"expo": "*"}}
@@ -0,0 +1,22 @@
1
+ module.exports = {
2
+ dependencies: {
3
+ '@amazon-devices/react-native-kepler': {
4
+ platforms: {
5
+ kepler: null, // do not use platform definition from @react-native-kepler
6
+ },
7
+ },
8
+ },
9
+ dependency: {
10
+ platforms: {
11
+ kepler: {
12
+ autolink: {
13
+ ExpoImageLib: {
14
+ provider: 'system',
15
+ turbomodules: ['ExpoImage'],
16
+ components: ['ExpoImageComponent'],
17
+ },
18
+ },
19
+ },
20
+ },
21
+ },
22
+ };
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Copyright (c) 2024 Amazon.com, Inc. or its affiliates. All rights reserved.
3
+ *
4
+ * PROPRIETARY/CONFIDENTIAL. USE IS SUBJECT TO LICENSE TERMS.
5
+ *
6
+ * @flow
7
+ * @format
8
+ */
9
+
10
+ import * as React from 'react';
11
+ import { NativeSyntheticEvent, StyleSheet, ViewProps, processColor } from 'react-native';
12
+
13
+ import { ExpoImageModule } from './ExpoImageModules';
14
+ import {
15
+ ImageErrorEventData,
16
+ ImageLoadEventData,
17
+ ImageNativeProps,
18
+ ImageProgressEventData,
19
+ } from './Image.types';
20
+ import ImageViewNativeComponent, {
21
+ ImageViewNativeComponentProps,
22
+ } from './ImageViewNativeComponent';
23
+
24
+ type ImageOnlyProps = Omit<ImageViewNativeComponentProps, keyof ViewProps> & {
25
+ accessibilityLabel?: string | undefined;
26
+ };
27
+
28
+
29
+
30
+ function withDeprecatedNativeEvent<NativeEvent>(
31
+ event: NativeSyntheticEvent<NativeEvent>
32
+ ): NativeEvent {
33
+ Object.defineProperty(event.nativeEvent, 'nativeEvent', {
34
+ get() {
35
+ console.warn(
36
+ '[expo-image]: Accessing event payload through "nativeEvent" is deprecated, it is now part of the event object itself'
37
+ );
38
+ return event.nativeEvent;
39
+ },
40
+ });
41
+ return event.nativeEvent;
42
+ }
43
+
44
+ class ExpoImage extends React.PureComponent<ImageNativeProps> {
45
+ onLoadStart = () => {
46
+ this.props.onLoadStart?.();
47
+ };
48
+
49
+ onLoad = (event: NativeSyntheticEvent<ImageLoadEventData>) => {
50
+ this.props.onLoad?.(withDeprecatedNativeEvent(event));
51
+ };
52
+
53
+ onProgress = (event: NativeSyntheticEvent<ImageProgressEventData>) => {
54
+ this.props.onProgress?.(withDeprecatedNativeEvent(event));
55
+ };
56
+
57
+ onError = (event: NativeSyntheticEvent<ImageErrorEventData>) => {
58
+ this.props.onError?.(withDeprecatedNativeEvent(event));
59
+ };
60
+
61
+ onLoadEnd = () => {
62
+ this.props.onLoadEnd?.();
63
+ };
64
+
65
+ render() {
66
+ const {
67
+ style,
68
+ allowDownscaling,
69
+ alt,
70
+ accessibilityLabel,
71
+ blurRadius,
72
+ cachePolicy,
73
+ contentFit,
74
+ contentPosition,
75
+ placeholderContentFit,
76
+ priority,
77
+ recyclingKey,
78
+ source,
79
+ transition,
80
+ placeholder,
81
+ tintColor,
82
+ ...props
83
+ } = this.props;
84
+
85
+ delete props.defaultSource;
86
+ delete props.fadeDuration;
87
+ delete props.resizeMode;
88
+ delete props.loadingIndicatorSource;
89
+
90
+ const resolvedStyle = StyleSheet.flatten(style);
91
+
92
+ const imageProps: ImageOnlyProps = {
93
+ allowDownscaling: allowDownscaling ?? true,
94
+ alt,
95
+ accessibilityLabel: accessibilityLabel ?? alt,
96
+ blurRadius,
97
+ cachePolicy,
98
+ contentFit,
99
+ contentPosition,
100
+ onError: this.onError,
101
+ onLoadStart: this.onLoadStart,
102
+ onLoad: this.onLoad,
103
+ onProgress: this.onProgress,
104
+ onLoadEnd: this.onLoadEnd,
105
+ placeholder,
106
+ placeholderContentFit,
107
+ priority,
108
+ tintColor: processColor(tintColor || resolvedStyle.tintColor),
109
+ recyclingKey,
110
+ source,
111
+ transition,
112
+ };
113
+
114
+ return <ImageViewNativeComponent {...props} {...imageProps} style={style} />;
115
+ }
116
+ }
117
+
118
+ export { ExpoImageModule };
119
+ export default ExpoImage;