@amazon-devices/expo-image 2.0.9000000000 → 3.0.0

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 (92) hide show
  1. package/CMakeLists.txt +80 -58
  2. package/README.kepler.md +1 -0
  3. package/build/ExpoImageModules.kepler.d.ts.map +1 -1
  4. package/build/ExpoImageModules.kepler.js +1 -1
  5. package/build/ExpoImageModules.kepler.js.map +1 -1
  6. package/build/ImageViewNativeComponent.js +1 -1
  7. package/build/ImageViewNativeComponent.js.map +1 -1
  8. package/kepler/AutoLinkInit.cpp +17 -0
  9. package/kepler/Constants.h +21 -0
  10. package/kepler/ExpoImage/ExpoImageTurboModule.cpp +148 -0
  11. package/kepler/ExpoImage/ExpoImageTurboModule.h +41 -0
  12. package/kepler/ExpoImage/PrefetchListener.cpp +45 -0
  13. package/kepler/ExpoImage/PrefetchListener.h +40 -0
  14. package/kepler/ExpoImageComponent/AccessibilityDelegate.cpp +33 -0
  15. package/kepler/ExpoImageComponent/AccessibilityDelegate.h +30 -0
  16. package/kepler/ExpoImageComponent/ExpoImageComponentViewManager.cpp +132 -0
  17. package/kepler/ExpoImageComponent/ExpoImageComponentViewManager.h +66 -0
  18. package/kepler/ExpoImageComponent/ExpoImageStore.h +102 -0
  19. package/kepler/ExpoImageComponent/ExpoImageView.cpp +556 -0
  20. package/kepler/ExpoImageComponent/ExpoImageView.h +186 -0
  21. package/kepler/ExpoImageComponent/HashImageDecoder.cpp +91 -0
  22. package/kepler/ExpoImageComponent/HashImageDecoder.h +18 -0
  23. package/kepler/ExpoImageComponent/ImageLoadListeners.cpp +73 -0
  24. package/kepler/ExpoImageComponent/ImageLoadListeners.h +52 -0
  25. package/kepler/ExpoImageComponent/TransitionAnimator.cpp +113 -0
  26. package/kepler/ExpoImageComponent/TransitionAnimator.h +32 -0
  27. package/kepler/ImageSourceInfo.h +21 -0
  28. package/kepler/ViewManagerFactory.cpp +36 -0
  29. package/kepler/ViewManagerFactory.h +29 -0
  30. package/kepler/blurhash/common.h +11 -10
  31. package/kepler/blurhash/decode.cpp +26 -16
  32. package/kepler/contentposition/ImageContentPosition.cpp +50 -69
  33. package/kepler/contentposition/ImageContentPosition.h +36 -26
  34. package/kepler/enums/ImageContentFit.h +47 -15
  35. package/kepler/enums/ImagePriority.h +12 -13
  36. package/kepler/test/blurhash/decode.cpp +36 -27
  37. package/kepler/test/contentposition/ImageContentPosition.cpp +70 -76
  38. package/kepler/test/thumbhash/decode.cpp +18 -10
  39. package/kepler/test/utils/Base64.cpp +73 -0
  40. package/kepler/test/utils/ColorUtils.cpp +53 -0
  41. package/kepler/test/utils/SourceSelection.cpp +87 -0
  42. package/kepler/thumbhash/decode.cpp +7 -16
  43. package/kepler/utils/Base64.cpp +85 -0
  44. package/kepler/utils/Base64.h +36 -0
  45. package/kepler/utils/ColorUtils.h +26 -0
  46. package/kepler/utils/SourceSelection.cpp +80 -0
  47. package/kepler/utils/SourceSelection.h +65 -0
  48. package/lib/aarch64-release/com.amazon.kepler.uitoolkit.react.expoimageapp.so +0 -0
  49. package/lib/aarch64-release/libexpo-image-3.so +0 -0
  50. package/lib/armv7-release/com.amazon.kepler.uitoolkit.react.expoimageapp.so +0 -0
  51. package/lib/armv7-release/libexpo-image-3.so +0 -0
  52. package/lib/x86_64-release/com.amazon.kepler.uitoolkit.react.expoimageapp.so +0 -0
  53. package/lib/x86_64-release/libexpo-image-3.so +0 -0
  54. package/package.json +1 -1
  55. package/react-native.config.js +12 -4
  56. package/src/ExpoImageModules.kepler.ts +1 -1
  57. package/src/ImageViewNativeComponent.ts +1 -1
  58. package/kepler/ExpoImage.cpp +0 -63
  59. package/kepler/ExpoImage.h +0 -29
  60. package/kepler/ExpoImageCacheHandler.cpp +0 -15
  61. package/kepler/ExpoImageCacheHandler.h +0 -28
  62. package/kepler/ExpoImageComponent.cpp +0 -579
  63. package/kepler/ExpoImageComponent.h +0 -199
  64. package/kepler/ImageWrapper/BlurhashImageWrapper.cpp +0 -37
  65. package/kepler/ImageWrapper/BlurhashImageWrapper.h +0 -23
  66. package/kepler/ImageWrapper/CacheImageWrapper.cpp +0 -80
  67. package/kepler/ImageWrapper/CacheImageWrapper.h +0 -41
  68. package/kepler/ImageWrapper/HashImageWrapper.cpp +0 -21
  69. package/kepler/ImageWrapper/HashImageWrapper.h +0 -22
  70. package/kepler/ImageWrapper/ImageWrapper.cpp +0 -24
  71. package/kepler/ImageWrapper/ImageWrapper.h +0 -33
  72. package/kepler/ImageWrapper/LocalImageWrapper.cpp +0 -61
  73. package/kepler/ImageWrapper/LocalImageWrapper.h +0 -30
  74. package/kepler/ImageWrapper/ThumbhashImageWrapper.cpp +0 -33
  75. package/kepler/ImageWrapper/ThumbhashImageWrapper.h +0 -20
  76. package/kepler/KeplerImageViewComponent.h +0 -64
  77. package/kepler/KeplerInit.cpp +0 -35
  78. package/kepler/managers/ExpoImageManager.cpp +0 -38
  79. package/kepler/managers/ExpoImageManager.h +0 -23
  80. package/kepler/test/ExpoImage.cpp +0 -73
  81. package/kepler/test/ExpoImageComponent.cpp +0 -304
  82. package/kepler/test/managers/ExpoImageManager.cpp +0 -39
  83. package/kepler/test/utils/LoaderDelegate.cpp +0 -130
  84. package/kepler/utils/PlaceholderImageLoaderDelegate.cpp +0 -26
  85. package/kepler/utils/PlaceholderImageLoaderDelegate.h +0 -26
  86. package/kepler/utils/PrefetchImageLoaderDelegate.cpp +0 -55
  87. package/kepler/utils/PrefetchImageLoaderDelegate.h +0 -35
  88. package/kepler/utils/SourceImageLoaderDelegate.cpp +0 -47
  89. package/kepler/utils/SourceImageLoaderDelegate.h +0 -42
  90. package/kepler/utils/SourceImageLoaderDelegateEmitter.cpp +0 -15
  91. package/kepler/utils/SourceImageLoaderDelegateEmitter.h +0 -28
  92. package/kepler-compatibility.json +0 -6
@@ -11,22 +11,23 @@
11
11
 
12
12
  #include <cmath>
13
13
 
14
- int linearTosRGB(float value) {
14
+ inline int linearTosRGB(float value) {
15
15
  float v = fmaxf(0, fminf(1, value));
16
- if (v <= 0.0031308)
16
+ if (v <= 0.0031308) {
17
17
  return v * 12.92 * 255 + 0.5;
18
- else
19
- return (1.055 * powf(v, 1 / 2.4) - 0.055) * 255 + 0.5;
18
+ }
19
+
20
+ return (1.055 * powf(v, 1 / 2.4) - 0.055) * 255 + 0.5;
20
21
  }
21
22
 
22
- float sRGBToLinear(int value) {
23
- float v = (float) value / 255;
24
- if (v <= 0.04045)
23
+ inline float sRGBToLinear(int value) {
24
+ float v = static_cast<float>(value) / 255;
25
+ if (v <= 0.04045) {
25
26
  return v / 12.92;
26
- else
27
- return powf((v + 0.055) / 1.055, 2.4);
27
+ }
28
+ return powf((v + 0.055) / 1.055, 2.4);
28
29
  }
29
30
 
30
- float signPow(float value, float exp) {
31
+ inline float signPow(float value, float exp) {
31
32
  return copysignf(powf(fabsf(value), exp), value);
32
33
  }
@@ -7,6 +7,10 @@
7
7
  */
8
8
 
9
9
  // Source: https://github.com/woltapp/blurhash/blob/master/C/decode.c
10
+
11
+ #include <vector>
12
+ #include <array>
13
+
10
14
  #include "decode.h"
11
15
 
12
16
  #include <unordered_map>
@@ -66,7 +70,7 @@ int decodeToInt(const std::string& string, int start, int end) {
66
70
 
67
71
  Size getImageSize(const std::string& blurhash) {
68
72
  int sizeFlag = decodeToInt(blurhash, 0); // Get size from first character
69
- int numY = (int) floorf(sizeFlag / 9) + 1;
73
+ int numY = static_cast<int>(floorf(sizeFlag / 9)) + 1;
70
74
  int numX = (sizeFlag % 9) + 1;
71
75
 
72
76
  return Size{numY, numX};
@@ -79,8 +83,7 @@ bool isValidBlurhash(const std::string& blurhash) {
79
83
  if (hashLength < MINIMAL_HASH_LENGTH) return false;
80
84
  auto size = getImageSize(blurhash);
81
85
 
82
- if (hashLength != 4 + 2 * size.x * size.y) return false;
83
- return true;
86
+ return hashLength == 4 + 2 * size.x * size.y;
84
87
  }
85
88
 
86
89
  Color decodeDC(int value) {
@@ -97,9 +100,9 @@ Color decodeAC(int value, float maximumValue) {
97
100
  int quantB = (int) value % 19;
98
101
 
99
102
  return std::make_tuple(
100
- signPow(((float) quantR - 9) / 9, 2.0) * maximumValue,
101
- signPow(((float) quantG - 9) / 9, 2.0) * maximumValue,
102
- signPow(((float) quantB - 9) / 9, 2.0) * maximumValue);
103
+ signPow((static_cast<float>(quantR) - 9) / 9, 2.0) * maximumValue,
104
+ signPow((static_cast<float>(quantG) - 9) / 9, 2.0) * maximumValue,
105
+ signPow((static_cast<float>(quantB) - 9) / 9, 2.0) * maximumValue);
103
106
  }
104
107
 
105
108
  int decodeToArray(
@@ -117,21 +120,23 @@ int decodeToArray(
117
120
  int quantizedMaxValue = decodeToInt(blurhash, 1);
118
121
  if (quantizedMaxValue == -1) return -1;
119
122
 
120
- float maxValue = ((float) (quantizedMaxValue + 1)) / 166;
123
+ float maxValue = (static_cast<float>(quantizedMaxValue + 1)) / 166;
121
124
 
122
- int colors_size = size.x * size.y;
123
- float colors[colors_size][3];
125
+ int colorsSize = size.x * size.y;
126
+ std::vector<std::array<float, 3>> colors(colorsSize);
124
127
 
125
- for (int iter = 0; iter < colors_size; ++iter) {
126
- float r = 0, g = 0, b = 0;
128
+ for (int iter = 0; iter < colorsSize; ++iter) {
129
+ float r = 0;
130
+ float g = 0;
131
+ float b = 0;
127
132
  if (iter == 0) {
128
133
  int value = decodeToInt(blurhash, 2, 6);
129
- if (value == -1) return -1;
134
+ if (value == -1) { return -1;}
130
135
  std::tie(r, g, b) = decodeDC(value);
131
136
 
132
137
  } else {
133
138
  int value = decodeToInt(blurhash, 4 + iter * 2, 6 + iter * 2);
134
- if (value == -1) return -1;
139
+ if (value == -1) { return -1;}
135
140
  std::tie(r, g, b) = decodeAC(value, maxValue * punch);
136
141
  }
137
142
  colors[iter][0] = r;
@@ -140,11 +145,15 @@ int decodeToArray(
140
145
  }
141
146
 
142
147
  int bytesPerRow = width * nChannels;
143
- int intR = 0, intG = 0, intB = 0;
148
+ int intR = 0;
149
+ int intG = 0;
150
+ int intB = 0;
144
151
 
145
152
  for (int y = 0; y < height; ++y) {
146
153
  for (int x = 0; x < width; ++x) {
147
- float r = 0, g = 0, b = 0;
154
+ float r = 0;
155
+ float g = 0;
156
+ float b = 0;
148
157
 
149
158
  for (int j = 0; j < size.y; ++j) {
150
159
  for (int i = 0; i < size.x; ++i) {
@@ -164,9 +173,10 @@ int decodeToArray(
164
173
  pixelArray[nChannels * x + 1 + y * bytesPerRow] = clampToUByte(intG);
165
174
  pixelArray[nChannels * x + 2 + y * bytesPerRow] = clampToUByte(intB);
166
175
 
167
- if (nChannels == 4)
176
+ if (nChannels == 4) {
168
177
  pixelArray[nChannels * x + 3 + y * bytesPerRow] =
169
178
  255; // If nChannels=4, treat each pixel as RGBA instead of RGB
179
+ }
170
180
  }
171
181
  }
172
182
 
@@ -1,86 +1,67 @@
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
1
  #include "ImageContentPosition.h"
10
2
 
11
- #include <JsonContainer/JsonContainer.h>
3
+ #include <apmf/iface/com/amazon/kepler/uitoolkit/react/JsType.h>
4
+
5
+ #include "../utils/SourceSelection.h"
6
+
7
+ namespace expoimage {
12
8
 
13
- float calcTranslation(
14
- float value,
15
- float imageRefValue,
16
- float viewRefValue,
17
- bool isPercentage = false,
18
- bool isReverse = false) {
9
+ using apmf::iface::com::amazon::kepler::uitoolkit::react::JsType;
10
+
11
+ namespace {
12
+
13
+ float calcTranslation(float value, float imageVal, float viewVal, bool isPercentage, bool isReverse) {
19
14
  if (isPercentage) {
20
- float finalPercentage = isReverse ? 100.0f - value : value;
21
- return (finalPercentage / 100.0f) * (viewRefValue - imageRefValue);
15
+ float pct = isReverse ? 100.0f - value : value;
16
+ return (pct / 100.0f) * (viewVal - imageVal);
22
17
  }
23
-
24
- return isReverse ? viewRefValue - imageRefValue - value : value;
18
+ return isReverse ? viewVal - imageVal - value : value;
25
19
  }
26
20
 
27
- float calcXTranslation(
28
- float value,
29
- const volta::graphics::Size& imageRect,
30
- const volta::graphics::Size& viewRect,
31
- bool isPercentage = false,
32
- bool isReverse = false) {
33
- return calcTranslation(value, imageRect.width(), viewRect.width(), isPercentage, isReverse);
21
+ float calcX(float value, const Size& imageRect, const Size& viewRect, bool isPercentage, bool isReverse) {
22
+ return calcTranslation(value, imageRect.width, viewRect.width, isPercentage, isReverse);
34
23
  }
35
24
 
36
- float calcYTranslation(
37
- float value,
38
- const volta::graphics::Size& imageRect,
39
- const volta::graphics::Size& viewRect,
40
- bool isPercentage = false,
41
- bool isReverse = false) {
42
- return calcTranslation(value, imageRect.height(), viewRect.height(), isPercentage, isReverse);
25
+ float calcY(float value, const Size& imageRect, const Size& viewRect, bool isPercentage, bool isReverse) {
26
+ return calcTranslation(value, imageRect.height, viewRect.height, isPercentage, isReverse);
43
27
  }
44
28
 
45
- ImageContentPositionValue::ImageContentPositionValue() : value_(std::nullopt), isPercentage_(true) {}
29
+ } // namespace
46
30
 
47
- ImageContentPositionValue::ImageContentPositionValue(float value, bool isPercentage) :
48
- value_(value),
49
- isPercentage_(isPercentage) {}
50
-
51
- std::optional<float> ImageContentPositionValue::calcOffset(
52
- bool isReverse,
53
- const volta::graphics::Size& imageRect,
54
- const volta::graphics::Size& viewRect,
55
- std::function<float(float, const volta::graphics::Size&, const volta::graphics::Size&, bool, bool)>
56
- calcAxisOffset) {
57
- return value_ ? calcAxisOffset(value_.value(), imageRect, viewRect, isPercentage_, isReverse) : value_;
31
+ float ImageContentPosition::offsetX(const Size& imageRect, const Size& viewRect) const {
32
+ return left_.calcOffset(false, imageRect, viewRect, &calcX)
33
+ .value_or(right_.calcOffset(true, imageRect, viewRect, &calcX)
34
+ .value_or(calcX(50.0f, imageRect, viewRect, true, false)));
58
35
  }
59
36
 
60
- ImageContentPosition::ImageContentPosition() :
61
- top_(ImageContentPositionValue()),
62
- bottom_(ImageContentPositionValue()),
63
- right_(ImageContentPositionValue()),
64
- left_(ImageContentPositionValue()) {}
65
-
66
- ImageContentPosition::ImageContentPosition(
67
- ImageContentPositionValue top,
68
- ImageContentPositionValue bottom,
69
- ImageContentPositionValue right,
70
- ImageContentPositionValue left) :
71
- top_(top),
72
- bottom_(bottom),
73
- right_(right),
74
- left_(left) {}
75
-
76
- float ImageContentPosition::offsetX(const volta::graphics::Size& imageRect, const volta::graphics::Size& viewRect) {
77
- return left_.calcOffset(false, imageRect, viewRect, &calcXTranslation)
78
- .value_or(right_.calcOffset(true, imageRect, viewRect, &calcXTranslation)
79
- .value_or(calcXTranslation(50.0f, imageRect, viewRect, true)));
37
+ float ImageContentPosition::offsetY(const Size& imageRect, const Size& viewRect) const {
38
+ return top_.calcOffset(false, imageRect, viewRect, &calcY)
39
+ .value_or(bottom_.calcOffset(true, imageRect, viewRect, &calcY)
40
+ .value_or(calcY(50.0f, imageRect, viewRect, true, false)));
80
41
  }
81
42
 
82
- float ImageContentPosition::offsetY(const volta::graphics::Size& imageRect, const volta::graphics::Size& viewRect) {
83
- return top_.calcOffset(false, imageRect, viewRect, &calcYTranslation)
84
- .value_or(bottom_.calcOffset(true, imageRect, viewRect, &calcYTranslation)
85
- .value_or(calcYTranslation(50.0f, imageRect, viewRect, true)));
43
+ ImageContentPositionValue parsePositionValue(View<IJsObject> obj, const std::string& key) {
44
+ ImageContentPositionValue result;
45
+ auto keys = obj->getAllKeys();
46
+ if (!hasKey(keys, key)) return result;
47
+ auto type = obj->getElementValueType(key);
48
+ if (type.value == JsType::STRING.value) {
49
+ std::string val = obj->getString(key);
50
+ if (!val.empty() && val.back() == '%') {
51
+ try {
52
+ result.value = std::stof(val);
53
+ result.isPercentage = true;
54
+ } catch (...) {
55
+ }
56
+ }
57
+ } else if (type.value == JsType::DOUBLE.value) {
58
+ result.value = static_cast<float>(obj->getDouble(key));
59
+ result.isPercentage = false;
60
+ } else if (type.value == JsType::INT.value) {
61
+ result.value = static_cast<float>(obj->getInt(key));
62
+ result.isPercentage = false;
63
+ }
64
+ return result;
86
65
  }
66
+
67
+ } // namespace expoimage
@@ -7,42 +7,52 @@
7
7
  */
8
8
 
9
9
  #pragma once
10
- #include <Volta/graphics/Size.h>
10
+
11
+ #include <apmf/iface/com/amazon/kepler/uitoolkit/graphics/Size.h>
12
+ #include <apmf/iface/com/amazon/kepler/uitoolkit/react/IJsObject.h>
11
13
 
12
14
  #include <functional>
13
15
  #include <optional>
14
16
  #include <string>
15
17
 
16
- class ImageContentPositionValue {
17
- public:
18
- std::optional<float> value_;
19
- bool isPercentage_;
20
- ImageContentPositionValue();
21
- ImageContentPositionValue(float value, bool isPercentage);
18
+ namespace expoimage {
19
+
20
+ using Size = apmf::iface::com::amazon::kepler::uitoolkit::graphics::Size;
21
+ using apmf::detail::View;
22
+ using apmf::iface::com::amazon::kepler::uitoolkit::react::IJsObject;
23
+
24
+ struct ImageContentPositionValue {
25
+ std::optional<float> value;
26
+ bool isPercentage{true};
27
+
28
+ ImageContentPositionValue() = default;
29
+ ImageContentPositionValue(float v, bool pct) : value(v), isPercentage(pct) {}
30
+
22
31
  std::optional<float> calcOffset(
23
- bool isReverse,
24
- const volta::graphics::Size& imageRect,
25
- const volta::graphics::Size& viewRect,
26
- std::function<float(float, const volta::graphics::Size&, const volta::graphics::Size&, bool, bool)>
27
- calcAxisOffset);
32
+ bool isReverse, const Size& imageSize, const Size& viewSize,
33
+ std::function<float(float, const Size&, const Size&, bool, bool)> calc) const {
34
+ if (value) {
35
+ return calc(*value, imageSize, viewSize, isPercentage, isReverse);
36
+ }
37
+ return std::nullopt;
38
+ }
28
39
  };
29
40
 
30
41
  class ImageContentPosition {
31
42
  public:
32
- ImageContentPosition();
43
+ ImageContentPosition() = default;
33
44
  ImageContentPosition(
34
- ImageContentPositionValue top,
35
- ImageContentPositionValue bottom,
36
- ImageContentPositionValue right,
37
- ImageContentPositionValue left);
38
- float offsetX(const volta::graphics::Size& imageRect, const volta::graphics::Size& viewRect);
39
- float offsetY(const volta::graphics::Size& imageRect, const volta::graphics::Size& viewRect);
40
-
41
- #ifndef UNIT_TEST
45
+ ImageContentPositionValue top, ImageContentPositionValue bottom,
46
+ ImageContentPositionValue right, ImageContentPositionValue left)
47
+ : top_(top), bottom_(bottom), right_(right), left_(left) {}
48
+
49
+ float offsetX(const Size& imageRect, const Size& viewRect) const;
50
+ float offsetY(const Size& imageRect, const Size& viewRect) const;
51
+
42
52
  private:
43
- #endif
44
- ImageContentPositionValue top_;
45
- ImageContentPositionValue bottom_;
46
- ImageContentPositionValue right_;
47
- ImageContentPositionValue left_;
53
+ ImageContentPositionValue top_, bottom_, right_, left_;
48
54
  };
55
+
56
+ ImageContentPositionValue parsePositionValue(View<IJsObject> obj, const std::string& key);
57
+
58
+ } // namespace expoimage
@@ -1,17 +1,49 @@
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
1
  #pragma once
10
2
 
11
- enum ImageContentFit {
12
- Cover,
13
- Contain,
14
- Fill,
15
- None,
16
- ScaleDown,
17
- };
3
+ #include <apmf/iface/com/amazon/kepler/uitoolkit/graphics/Size.h>
4
+ #include <apmf/iface/com/amazon/kepler/uitoolkit/view/Fit.h>
5
+
6
+ #include <string>
7
+
8
+ namespace expoimage {
9
+
10
+ using apmf::iface::com::amazon::kepler::uitoolkit::view::Fit;
11
+
12
+ enum class ImageContentFit { Cover, Contain, Fill, None, ScaleDown };
13
+
14
+ inline ImageContentFit parseContentFit(const std::string& value, ImageContentFit defaultFit = ImageContentFit::Cover) {
15
+ if (value == "contain") return ImageContentFit::Contain;
16
+ if (value == "fill") return ImageContentFit::Fill;
17
+ if (value == "scale-down") return ImageContentFit::ScaleDown;
18
+ if (value == "none") return ImageContentFit::None;
19
+ if (value == "cover") return ImageContentFit::Cover;
20
+ return defaultFit;
21
+ }
22
+
23
+ /** Maps ImageContentFit to stable Fit enum. All modes have direct platform support. */
24
+ inline Fit toFit(ImageContentFit contentFit) {
25
+ switch (contentFit) {
26
+ case ImageContentFit::Cover: return Fit::COVER;
27
+ case ImageContentFit::Contain: return Fit::CONTAIN;
28
+ case ImageContentFit::Fill: return Fit::STRETCH;
29
+ case ImageContentFit::ScaleDown: return Fit::SCALE_DOWN;
30
+ case ImageContentFit::None: return Fit::NONE;
31
+ }
32
+ return Fit::COVER;
33
+ }
34
+
35
+ inline Fit resolveNativeFit(
36
+ ImageContentFit fit,
37
+ bool allowDownscaling,
38
+ apmf::iface::com::amazon::kepler::uitoolkit::graphics::Size imageSize,
39
+ apmf::iface::com::amazon::kepler::uitoolkit::graphics::Size viewSize) {
40
+ if (!allowDownscaling) return Fit::NONE;
41
+ if (fit != ImageContentFit::ScaleDown) return toFit(fit);
42
+ const bool imageSizeKnown = imageSize.width > 0 && imageSize.height > 0;
43
+ if (!imageSizeKnown) return Fit::CONTAIN;
44
+ const bool imageFitsInView =
45
+ imageSize.width <= viewSize.width && imageSize.height <= viewSize.height;
46
+ return imageFitsInView ? Fit::NONE : Fit::CONTAIN;
47
+ }
48
+
49
+ } // namespace expoimage
@@ -1,17 +1,16 @@
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
1
  #pragma once
10
2
 
11
3
  #include <cstdint>
4
+ #include <string>
5
+
6
+ namespace expoimage {
7
+
8
+ enum class ImagePriority : uint8_t { Low = 1, Normal = 2, High = 3 };
9
+
10
+ inline ImagePriority parsePriority(const std::string& value) {
11
+ if (value == "low") return ImagePriority::Low;
12
+ if (value == "high") return ImagePriority::High;
13
+ return ImagePriority::Normal;
14
+ }
12
15
 
13
- enum class ImagePriority : uint8_t {
14
- Low,
15
- Normal,
16
- High
17
- };
16
+ } // namespace expoimage
@@ -1,39 +1,48 @@
1
1
  #include "../../blurhash/decode.h"
2
2
 
3
- #include <gmock/gmock-actions.h>
4
- #include <gmock/gmock.h>
5
3
  #include <gtest/gtest.h>
6
4
 
7
- #include "catch.hpp"
5
+ namespace expoimage {
6
+ namespace {
8
7
 
9
- TEST_CASE("blurhash") {
10
- std::string validBlurHash = "LGF5]+Yk^6#M@-5c,1J5@[or[Q6.";
11
- std::string invalidBlurHash = "some invalid blurhash";
12
- std::string pureBlackHash = "L0006Mp2p2p2fRfRfRfRfQfQfQfQ";
8
+ TEST(BlurhashDecode, IsValidBlurhashAcceptsWellFormed) {
9
+ const std::string validBlurHash = "LGF5]+Yk^6#M@-5c,1J5@[or[Q6.";
10
+ EXPECT_TRUE(isValidBlurhash(validBlurHash));
11
+ }
13
12
 
14
- SECTION("decodeBlurHash") {
15
- const int channels = 3;
16
- const int width = 32;
17
- const int height = 32;
13
+ TEST(BlurhashDecode, IsValidBlurhashRejectsGarbage) {
14
+ EXPECT_FALSE(isValidBlurhash("some invalid blurhash"));
15
+ EXPECT_FALSE(isValidBlurhash(""));
16
+ }
18
17
 
19
- auto decoded = decodeBlurhash(pureBlackHash, width, height, 1, channels);
18
+ TEST(BlurhashDecode, DecodeProducesExpectedBufferSize) {
19
+ const std::string nearBlackHash = "L0006Mp2p2p2fRfRfRfRfQfQfQfQ";
20
+ const int channels = 3;
21
+ const int width = 32;
22
+ const int height = 32;
20
23
 
21
- // channels times pixels
22
- int bytesPerRow = 32 * channels;
24
+ constexpr int kNearBlackThreshold = 64;
23
25
 
24
- for (int i = 0; i < height; i++) {
25
- for (int j = 0; j < width; j++) {
26
- for (int ch = 0; i < channels; i++) {
27
- int part = decoded.get()[channels * j + ch + i * bytesPerRow];
28
- // expect each channel to be close to 0
29
- CHECK(part < 10);
30
- }
31
- }
32
- }
33
- }
26
+ auto decoded = decodeBlurhash(nearBlackHash, width, height, 1, channels);
27
+ ASSERT_NE(decoded, nullptr);
34
28
 
35
- SECTION("isValidBlurHash") {
36
- EXPECT_TRUE(isValidBlurhash(validBlurHash));
37
- EXPECT_FALSE(isValidBlurhash(invalidBlurHash));
29
+ const int totalBytes = width * height * channels;
30
+ int maxByte = 0;
31
+ for (int i = 0; i < totalBytes; ++i) {
32
+ int byte = decoded.get()[i];
33
+ if (byte > maxByte) maxByte = byte;
38
34
  }
35
+ EXPECT_LT(maxByte, kNearBlackThreshold)
36
+ << "Decoded buffer unexpectedly bright for near-black hash; "
37
+ "brightest byte was "
38
+ << maxByte;
39
39
  }
40
+
41
+ TEST(BlurhashDecode, DecodeReturnsNonNullForValidHash) {
42
+ const std::string validBlurHash = "LGF5]+Yk^6#M@-5c,1J5@[or[Q6.";
43
+ auto decoded = decodeBlurhash(validBlurHash, 16, 16, 1, 3);
44
+ EXPECT_NE(decoded, nullptr);
45
+ }
46
+
47
+ } // namespace
48
+ } // namespace expoimage