expo-image 2.3.2 → 2.4.0-canary-20250709-136b77f

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 (67) hide show
  1. package/CHANGELOG.md +20 -6
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/expo/modules/image/ExpoImageModule.kt +20 -0
  4. package/android/src/main/java/expo/modules/image/ExpoImageViewWrapper.kt +24 -5
  5. package/android/src/main/java/expo/modules/image/blurhash/BlurhashDecoder.kt +1 -10
  6. package/android/src/main/java/expo/modules/image/blurhash/BlurhashEncoder.kt +112 -0
  7. package/android/src/main/java/expo/modules/image/blurhash/BlurhashHelpers.kt +38 -0
  8. package/android/src/main/java/expo/modules/image/okhttp/GlideUrlWrapperLoader.kt +1 -1
  9. package/build/ExpoImage.web.d.ts +1 -1
  10. package/build/ExpoImage.web.d.ts.map +1 -1
  11. package/build/Image.d.ts +3 -2
  12. package/build/Image.d.ts.map +1 -1
  13. package/build/Image.types.d.ts +18 -5
  14. package/build/Image.types.d.ts.map +1 -1
  15. package/build/web/ImageWrapper.d.ts.map +1 -1
  16. package/expo-module.config.json +1 -1
  17. package/ios/ExpoImage.podspec +1 -1
  18. package/ios/ImageModule.swift +24 -11
  19. package/ios/ImageView.swift +8 -1
  20. package/ios/Loaders/PhotoLibraryAssetLoader.swift +15 -1
  21. package/local-maven-repo/BareExpo/expo.modules.image/{2.3.2/expo.modules.image-2.3.2-sources.jar → 2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f-sources.jar} +0 -0
  22. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f-sources.jar.md5 +1 -0
  23. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f-sources.jar.sha1 +1 -0
  24. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f-sources.jar.sha256 +1 -0
  25. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f-sources.jar.sha512 +1 -0
  26. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.aar +0 -0
  27. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.aar.md5 +1 -0
  28. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.aar.sha1 +1 -0
  29. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.aar.sha256 +1 -0
  30. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.aar.sha512 +1 -0
  31. package/local-maven-repo/BareExpo/expo.modules.image/{2.3.2/expo.modules.image-2.3.2.module → 2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.module} +24 -24
  32. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.module.md5 +1 -0
  33. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.module.sha1 +1 -0
  34. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.module.sha256 +1 -0
  35. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.module.sha512 +1 -0
  36. package/local-maven-repo/BareExpo/expo.modules.image/{2.3.2/expo.modules.image-2.3.2.pom → 2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.pom} +2 -2
  37. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.pom.md5 +1 -0
  38. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.pom.sha1 +1 -0
  39. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.pom.sha256 +1 -0
  40. package/local-maven-repo/BareExpo/expo.modules.image/2.4.0-canary-20250709-136b77f/expo.modules.image-2.4.0-canary-20250709-136b77f.pom.sha512 +1 -0
  41. package/local-maven-repo/BareExpo/expo.modules.image/maven-metadata.xml +4 -4
  42. package/local-maven-repo/BareExpo/expo.modules.image/maven-metadata.xml.md5 +1 -1
  43. package/local-maven-repo/BareExpo/expo.modules.image/maven-metadata.xml.sha1 +1 -1
  44. package/local-maven-repo/BareExpo/expo.modules.image/maven-metadata.xml.sha256 +1 -1
  45. package/local-maven-repo/BareExpo/expo.modules.image/maven-metadata.xml.sha512 +1 -1
  46. package/package.json +4 -5
  47. package/src/ExpoImage.web.tsx +2 -1
  48. package/src/Image.tsx +4 -3
  49. package/src/Image.types.ts +19 -5
  50. package/src/web/ImageWrapper.tsx +8 -1
  51. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2-sources.jar.md5 +0 -1
  52. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2-sources.jar.sha1 +0 -1
  53. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2-sources.jar.sha256 +0 -1
  54. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2-sources.jar.sha512 +0 -1
  55. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.aar +0 -0
  56. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.aar.md5 +0 -1
  57. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.aar.sha1 +0 -1
  58. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.aar.sha256 +0 -1
  59. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.aar.sha512 +0 -1
  60. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.module.md5 +0 -1
  61. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.module.sha1 +0 -1
  62. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.module.sha256 +0 -1
  63. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.module.sha512 +0 -1
  64. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.pom.md5 +0 -1
  65. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.pom.sha1 +0 -1
  66. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.pom.sha256 +0 -1
  67. package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.pom.sha512 +0 -1
package/CHANGELOG.md CHANGED
@@ -6,17 +6,27 @@
6
6
 
7
7
  ### 🎉 New features
8
8
 
9
+ - Add support for `ImageRef` source in `generateBlurhashAsync` ([#37901](https://github.com/expo/expo/pull/37901) by [@Wenszel](https://github.com/Wenszel))
10
+ - [Android] Add generateBlurhashAsync ([#37817](https://github.com/expo/expo/pull/37817) by [@Wenszel](https://github.com/Wenszel))
11
+ - [iOS] Add a new prop - `enforceEarlyResizing` to reduce the memory usage of the image view. ([#37909](https://github.com/expo/expo/pull/37909) by [@lukmccall](https://github.com/lukmccall))
12
+
9
13
  ### 🐛 Bug fixes
10
14
 
15
+ - [iOS] Speed up displaying local assets. ([#37795](https://github.com/expo/expo/pull/37795) by [@aleqsio](https://github.com/aleqsio))
16
+ - [Android] Fix animation resuming by casting image to GifDrawable. ([#37363](https://github.com/expo/expo/pull/37363) by [@Wenszel](https://github.com/Wenszel))
17
+ - [Web] Fix `alt` as an alias for `accessibilityLabel` ([#37682](https://github.com/expo/expo/pull/37682) by [@huextrat](https://github.com/huextrat))
18
+
11
19
  ### 💡 Others
12
20
 
13
- ## 2.3.2 2025-07-01
21
+ ### 📚 3rd party library updates
22
+
23
+ ## 2.3.2 - 2025-07-01
14
24
 
15
25
  ### 🐛 Bug fixes
16
26
 
17
27
  - [iOS] Use specified cache type when no transformation is applied ([#37777](https://github.com/expo/expo/pull/37777) by [@jakex7](https://github.com/jakex7))
18
28
 
19
- ## 2.3.1 2025-07-01
29
+ ## 2.3.1 - 2025-07-01
20
30
 
21
31
  ### 🐛 Bug fixes
22
32
 
@@ -26,17 +36,21 @@
26
36
 
27
37
  - [Android] Bumped GIF Glide plugin to 3.0.5 for Android 16KB page size support. ([#37454](https://github.com/expo/expo/pull/37454) by [@kudo](https://github.com/kudo))
28
38
 
29
- ## 2.3.0 2025-06-11
39
+ ## 2.3.0 - 2025-06-11
30
40
 
31
41
  ### 🛠 Breaking changes
32
42
 
33
43
  - [iOS] `useAppleWebpCodec` has been moved from the source object to the component's prop to make it usable with the local assets. ([#37300](https://github.com/expo/expo/pull/37300) by [@tsapeta](https://github.com/tsapeta))
34
44
 
35
- ## 2.2.1 2025-06-10
45
+ ### 🐛 Bug fixes
46
+
47
+ - [iOS] Fix blurry images when using `tintColor` by scaling `imageThumbnailPixelSize` with screen density. ([#37235](https://github.com/expo/expo/pull/37235) by [@hirbod](https://github.com/hirbod))
48
+
49
+ ## 2.2.1 - 2025-06-10
36
50
 
37
51
  _This version does not introduce any user-facing changes._
38
52
 
39
- ## 2.2.0 2025-06-04
53
+ ## 2.2.0 - 2025-06-04
40
54
 
41
55
  ### 🎉 New features
42
56
 
@@ -47,7 +61,7 @@ _This version does not introduce any user-facing changes._
47
61
  - Fix React Server Components support. ([#36801](https://github.com/expo/expo/pull/36801) by [@EvanBacon](https://github.com/EvanBacon))
48
62
  - [iOS] Fix PhotoLibrary assets being scaled twice. ([#36776](https://github.com/expo/expo/pull/36776) by [@alanjhughes](https://github.com/alanjhughes))
49
63
  - [iOS] Don't add transformers when unnecessary. ([#36884](https://github.com/expo/expo/pull/36884) by [@jakex7](https://github.com/jakex7))
50
- - [iOS] Fix blurry images when using `tintColor` by scaling `imageThumbnailPixelSize` with screen density. ([#37235](https://github.com/expo/expo/pull/37235) by [@hirbod](https://github.com/hirbod))
64
+ - [Web] Fix `tintColor` in React 19. ([#37133](https://github.com/expo/expo/pull/37133) by [@bradleyayers](https://github.com/bradleyayers))
51
65
 
52
66
  ## 2.1.7 — 2025-05-06
53
67
 
@@ -8,7 +8,7 @@ android {
8
8
  namespace "expo.modules.image"
9
9
  defaultConfig {
10
10
  versionCode 1
11
- versionName "2.3.2"
11
+ versionName "2.4.0-canary-20250709-136b77f"
12
12
  consumerProguardFiles("proguard-rules.pro")
13
13
 
14
14
  buildConfigField("boolean", "ALLOW_GLIDE_LOGS", project.properties.get("EXPO_ALLOW_GLIDE_LOGS", "false"))
@@ -5,6 +5,7 @@ package expo.modules.image
5
5
  import android.graphics.Bitmap
6
6
  import android.graphics.drawable.BitmapDrawable
7
7
  import android.graphics.drawable.Drawable
8
+ import androidx.core.graphics.drawable.toBitmap
8
9
  import androidx.core.graphics.drawable.toBitmapOrNull
9
10
  import androidx.core.view.doOnDetach
10
11
  import com.bumptech.glide.Glide
@@ -19,6 +20,7 @@ import com.bumptech.glide.request.target.Target
19
20
  import com.github.penfeizhou.animation.apng.APNGDrawable
20
21
  import com.github.penfeizhou.animation.gif.GifDrawable
21
22
  import com.github.penfeizhou.animation.webp.WebPDrawable
23
+ import expo.modules.image.blurhash.BlurhashEncoder
22
24
  import expo.modules.image.enums.ContentFit
23
25
  import expo.modules.image.enums.Priority
24
26
  import expo.modules.image.records.CachePolicy
@@ -36,8 +38,12 @@ import expo.modules.kotlin.functions.Queues
36
38
  import expo.modules.kotlin.modules.Module
37
39
  import expo.modules.kotlin.modules.ModuleDefinition
38
40
  import expo.modules.kotlin.sharedobjects.SharedRef
41
+ import expo.modules.kotlin.types.Either
39
42
  import expo.modules.kotlin.types.EitherOfThree
40
43
  import expo.modules.kotlin.types.toKClass
44
+ import kotlinx.coroutines.Dispatchers
45
+ import kotlinx.coroutines.withContext
46
+ import java.net.URL
41
47
 
42
48
  class ExpoImageModule : Module() {
43
49
  override fun definition() = ModuleDefinition {
@@ -112,6 +118,20 @@ class ExpoImageModule : Module() {
112
118
  ImageLoadTask(appContext, source, options ?: ImageLoadOptions()).load()
113
119
  }
114
120
 
121
+ AsyncFunction("generateBlurhashAsync") Coroutine { source: Either<URL, Image>, numberOfComponents: Pair<Int, Int> ->
122
+ val image = source.let {
123
+ if (it.`is`(Image::class)) {
124
+ it.get(Image::class)
125
+ } else {
126
+ ImageLoadTask(appContext, SourceMap(uri = it.get(URL::class).toString()), ImageLoadOptions()).load()
127
+ }
128
+ }
129
+ val blurHash = withContext(Dispatchers.Default) {
130
+ BlurhashEncoder.encode(image.ref.toBitmap(), numberOfComponents)
131
+ }
132
+ blurHash
133
+ }
134
+
115
135
  Class(Image::class) {
116
136
  Property("width") { image: Image ->
117
137
  image.ref.intrinsicWidth
@@ -18,6 +18,7 @@ import com.bumptech.glide.RequestManager
18
18
  import com.bumptech.glide.load.engine.DiskCacheStrategy
19
19
  import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
20
20
  import com.bumptech.glide.request.RequestOptions
21
+ import com.github.penfeizhou.animation.gif.GifDrawable
21
22
  import expo.modules.image.enums.ContentFit
22
23
  import expo.modules.image.enums.Priority
23
24
  import expo.modules.image.events.GlideRequestListener
@@ -169,14 +170,32 @@ class ExpoImageViewWrapper(context: Context, appContext: AppContext) : ExpoView(
169
170
  internal var cachePolicy: CachePolicy = CachePolicy.DISK
170
171
 
171
172
  fun setIsAnimating(setAnimating: Boolean) {
172
- val resource = activeView.drawable
173
+ // Animatable animations always start from the beginning when resumed.
174
+ // So we check first if the resource is a GifDrawable, because it can continue
175
+ // from where it was paused.
176
+ when (val resource = activeView.drawable) {
177
+ is GifDrawable -> setIsAnimating(resource, setAnimating)
178
+ is Animatable -> setIsAnimating(resource, setAnimating)
179
+ }
180
+ }
173
181
 
174
- if (resource is Animatable) {
175
- if (setAnimating) {
176
- resource.start()
182
+ private fun setIsAnimating(resource: GifDrawable, setAnimating: Boolean) {
183
+ if (setAnimating) {
184
+ if (resource.isPaused) {
185
+ resource.resume()
177
186
  } else {
178
- resource.stop()
187
+ resource.start()
179
188
  }
189
+ } else {
190
+ resource.pause()
191
+ }
192
+ }
193
+
194
+ private fun setIsAnimating(resource: Animatable, setAnimating: Boolean) {
195
+ if (setAnimating) {
196
+ resource.start()
197
+ } else {
198
+ resource.stop()
180
199
  }
181
200
  }
182
201
 
@@ -74,16 +74,7 @@ object BlurhashDecoder {
74
74
  val r = colorEnc shr 16
75
75
  val g = (colorEnc shr 8) and 255
76
76
  val b = colorEnc and 255
77
- return floatArrayOf(srgbToLinear(r), srgbToLinear(g), srgbToLinear(b))
78
- }
79
-
80
- private fun srgbToLinear(colorEnc: Int): Float {
81
- val v = colorEnc / 255f
82
- return if (v <= 0.04045f) {
83
- (v / 12.92f)
84
- } else {
85
- ((v + 0.055f) / 1.055f).pow(2.4f)
86
- }
77
+ return floatArrayOf(BlurhashHelpers.srgbToLinear(r), BlurhashHelpers.srgbToLinear(g), BlurhashHelpers.srgbToLinear(b))
87
78
  }
88
79
 
89
80
  private fun decodeAc(value: Int, maxAc: Float): FloatArray {
@@ -0,0 +1,112 @@
1
+ package expo.modules.image.blurhash
2
+
3
+ import android.graphics.Bitmap
4
+ import android.graphics.Color
5
+ import kotlin.math.*
6
+
7
+ /**
8
+ * Rewritten in kotlin from https://github.com/woltapp/blurhash/blob/master/Swift/BlurHashEncode.swift
9
+ */
10
+ object BlurhashEncoder {
11
+ fun encode(image: Bitmap, numberOfComponents: Pair<Int, Int>): String {
12
+ val pixels = IntArray(image.width * image.height)
13
+ image.getPixels(pixels, 0, image.width, 0, 0, image.width, image.height)
14
+
15
+ val factors = calculateBlurFactors(pixels, image.width, image.height, numberOfComponents)
16
+
17
+ val dc = factors.first()
18
+ val ac = factors.drop(1)
19
+ val hashBuilder = StringBuilder()
20
+
21
+ encodeFlag(numberOfComponents, hashBuilder)
22
+ val maximumValue = encodeMaximumValue(ac, hashBuilder)
23
+ hashBuilder.append(encode83(encodeDC(dc), 4))
24
+ for (factor in ac) {
25
+ hashBuilder.append(encode83(encodeAC(factor, maximumValue), 2))
26
+ }
27
+
28
+ return hashBuilder.toString()
29
+ }
30
+
31
+ private fun encodeFlag(numberOfComponents: Pair<Int, Int>, hashBuilder: StringBuilder) {
32
+ val sizeFlag = (numberOfComponents.first - 1) + (numberOfComponents.second - 1) * 9
33
+ hashBuilder.append(encode83(sizeFlag, 1))
34
+ }
35
+
36
+ private fun encodeMaximumValue(ac: List<Triple<Float, Float, Float>>, hash: StringBuilder): Float {
37
+ val maximumValue: Float
38
+ if (ac.isNotEmpty()) {
39
+ val actualMaximumValue = ac.maxOf { t -> max(max(abs(t.first), abs(t.second)), abs(t.third)) }
40
+ val quantisedMaximumValue = max(0f, min(82f, floor(actualMaximumValue * 166f - 0.5f))).toInt()
41
+ maximumValue = (quantisedMaximumValue + 1).toFloat() / 166f
42
+ hash.append(encode83(quantisedMaximumValue, 1))
43
+ } else {
44
+ maximumValue = 1f
45
+ hash.append(encode83(0, 1))
46
+ }
47
+ return maximumValue
48
+ }
49
+
50
+ private fun calculateBlurFactors(pixels: IntArray, width: Int, height: Int, numberOfComponents: Pair<Int, Int>): List<Triple<Float, Float, Float>> {
51
+ val factors = mutableListOf<Triple<Float, Float, Float>>()
52
+ for (y in 0 until numberOfComponents.second) {
53
+ for (x in 0 until numberOfComponents.first) {
54
+ val normalisation = if (x == 0 && y == 0) 1f else 2f
55
+ val factor = multiplyBasisFunction(pixels, width, height, x, y, normalisation)
56
+ factors.add(factor)
57
+ }
58
+ }
59
+ return factors
60
+ }
61
+
62
+ private fun encode83(value: Int, length: Int): String {
63
+ var result = ""
64
+ for (i in 1..length) {
65
+ val digit = (value / 83f.pow((length - i).toFloat())) % 83f
66
+ result += ENCODE_CHARACTERS[digit.toInt()]
67
+ }
68
+ return result
69
+ }
70
+
71
+ private const val ENCODE_CHARACTERS =
72
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~"
73
+
74
+ private fun encodeDC(value: Triple<Float, Float, Float>): Int {
75
+ val roundedR = BlurhashHelpers.linearTosRGB(value.first)
76
+ val roundedG = BlurhashHelpers.linearTosRGB(value.second)
77
+ val roundedB = BlurhashHelpers.linearTosRGB(value.third)
78
+ return (roundedR shl 16) + (roundedG shl 8) + roundedB
79
+ }
80
+
81
+ private fun encodeAC(value: Triple<Float, Float, Float>, maximumValue: Float): Int {
82
+ val quantR = max(0f, min(18f, floor(BlurhashHelpers.signPow(value.first / maximumValue, 0.5f) * 9f + 9.5f)))
83
+ val quantG = max(0f, min(18f, floor(BlurhashHelpers.signPow(value.second / maximumValue, 0.5f) * 9f + 9.5f)))
84
+ val quantB = max(0f, min(18f, floor(BlurhashHelpers.signPow(value.third / maximumValue, 0.5f) * 9f + 9.5f)))
85
+
86
+ return (quantR * 19f * 19f + quantG * 19f + quantB).toInt()
87
+ }
88
+
89
+ private fun multiplyBasisFunction(pixels: IntArray, width: Int, height: Int, x: Int, y: Int, normalisation: Float): Triple<Float, Float, Float> {
90
+ var r = 0f
91
+ var g = 0f
92
+ var b = 0f
93
+
94
+ for (j in 0 until height) {
95
+ for (i in 0 until width) {
96
+ val basis = normalisation * cos(PI.toFloat() * x * i / width) * cos(PI.toFloat() * y * j / height)
97
+
98
+ val pixel = pixels[i + j * width]
99
+ val pr = BlurhashHelpers.srgbToLinear(Color.red(pixel))
100
+ val pg = BlurhashHelpers.srgbToLinear(Color.green(pixel))
101
+ val pb = BlurhashHelpers.srgbToLinear(Color.blue(pixel))
102
+
103
+ r += basis * pr
104
+ g += basis * pg
105
+ b += basis * pb
106
+ }
107
+ }
108
+
109
+ val scale = 1f / (width * height)
110
+ return Triple(r * scale, g * scale, b * scale)
111
+ }
112
+ }
@@ -0,0 +1,38 @@
1
+ package expo.modules.image.blurhash
2
+
3
+ import android.graphics.Bitmap
4
+ import kotlin.math.*
5
+
6
+ object BlurhashHelpers {
7
+ fun srgbToLinear(colorEnc: Int): Float {
8
+ val v = colorEnc / 255f
9
+ return if (v <= 0.04045f) {
10
+ (v / 12.92f)
11
+ } else {
12
+ ((v + 0.055f) / 1.055f).pow(2.4f)
13
+ }
14
+ }
15
+
16
+ fun linearTosRGB(value: Float): Int {
17
+ val v = max(0f, min(1f, value))
18
+ return if (v <= 0.0031308) {
19
+ (v * 12.92 * 255 + 0.5).toInt()
20
+ } else {
21
+ (1.055 * (v.pow(1f / 2.4f) - 0.055) * 255 + 0.5).toInt()
22
+ }
23
+ }
24
+
25
+ fun signPow(value: Float, exp: Float): Float {
26
+ return abs(value).pow(exp) * sign(value)
27
+ }
28
+
29
+ fun getBitsPerPixel(bitmap: Bitmap): Int {
30
+ return when (bitmap.config) {
31
+ Bitmap.Config.ARGB_8888 -> 32
32
+ Bitmap.Config.RGB_565 -> 16
33
+ Bitmap.Config.ALPHA_8 -> 8
34
+ Bitmap.Config.ARGB_4444 -> 16
35
+ else -> 0
36
+ }
37
+ }
38
+ }
@@ -28,7 +28,7 @@ class GlideUrlWrapperLoader(
28
28
  originalResponse
29
29
  .newBuilder()
30
30
  .body(
31
- ProgressResponseBody(originalResponse.body) { bytesWritten, contentLength, done ->
31
+ ProgressResponseBody(requireNotNull(originalResponse.body)) { bytesWritten, contentLength, done ->
32
32
  model.progressListener?.onProgress(bytesWritten, contentLength, done)
33
33
  }
34
34
  )
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import type { ImageNativeProps } from './Image.types';
3
- export default function ExpoImage({ source, placeholder, contentFit, contentPosition, placeholderContentFit, cachePolicy, onLoad, transition, onError, responsivePolicy, onLoadEnd, onDisplay, priority, blurRadius, recyclingKey, style, nativeViewRef, accessibilityLabel, tintColor, containerViewRef, ...props }: ImageNativeProps): React.JSX.Element;
3
+ export default function ExpoImage({ source, placeholder, contentFit, contentPosition, placeholderContentFit, cachePolicy, onLoad, transition, onError, responsivePolicy, onLoadEnd, onDisplay, priority, blurRadius, recyclingKey, style, nativeViewRef, accessibilityLabel, alt, tintColor, containerViewRef, ...props }: ImageNativeProps): React.JSX.Element;
4
4
  //# sourceMappingURL=ExpoImage.web.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoImage.web.d.ts","sourceRoot":"","sources":["../src/ExpoImage.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,gBAAgB,EAA6C,MAAM,eAAe,CAAC;AAsDjG,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAChC,MAAM,EACN,WAAW,EACX,UAAU,EACV,eAAe,EACf,qBAAqB,EACrB,WAAW,EACX,MAAM,EACN,UAAU,EACV,OAAO,EACP,gBAAgB,EAChB,SAAS,EACT,SAAS,EACT,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,KAAK,EACL,aAAa,EACb,kBAAkB,EAClB,SAAS,EACT,gBAAgB,EAChB,GAAG,KAAK,EACT,EAAE,gBAAgB,qBA0FlB"}
1
+ {"version":3,"file":"ExpoImage.web.d.ts","sourceRoot":"","sources":["../src/ExpoImage.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,gBAAgB,EAA6C,MAAM,eAAe,CAAC;AAsDjG,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAChC,MAAM,EACN,WAAW,EACX,UAAU,EACV,eAAe,EACf,qBAAqB,EACrB,WAAW,EACX,MAAM,EACN,UAAU,EACV,OAAO,EACP,gBAAgB,EAChB,SAAS,EACT,SAAS,EACT,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,KAAK,EACL,aAAa,EACb,kBAAkB,EAClB,GAAG,EACH,SAAS,EACT,gBAAgB,EAChB,GAAG,KAAK,EACT,EAAE,gBAAgB,qBA0FlB"}
package/build/Image.d.ts CHANGED
@@ -66,13 +66,14 @@ export declare class Image extends React.PureComponent<ImageProps> {
66
66
  static getCachePathAsync(cacheKey: string): Promise<string | null>;
67
67
  /**
68
68
  * Asynchronously generates a [Blurhash](https://blurha.sh) from an image.
69
- * @param url - The URL of the image to generate a blurhash from.
69
+ * @param source - The image source, either a URL (string) or an ImageRef
70
70
  * @param numberOfComponents - The number of components to encode the blurhash with.
71
71
  * Must be between 1 and 9. Defaults to `[4, 3]`.
72
+ * @platform android
72
73
  * @platform ios
73
74
  * @return A promise resolving to the blurhash string.
74
75
  */
75
- static generateBlurhashAsync(url: string, numberOfComponents: [number, number] | {
76
+ static generateBlurhashAsync(source: string | ImageRef, numberOfComponents: [number, number] | {
76
77
  width: number;
77
78
  height: number;
78
79
  }): Promise<string | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../src/Image.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,SAAS,MAAM,aAAa,CAAC;AACpC,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,UAAU,EACV,QAAQ,EACR,WAAW,EACZ,MAAM,eAAe,CAAC;AAQvB,qBAAa,KAAM,SAAQ,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC;IACxD,aAAa,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IACjD,gBAAgB,EAAE,KAAK,CAAC,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;gBAEnC,KAAK,EAAE,UAAU;IAO7B,gBAAgB,2BAMd;IAEF;;OAEG;IACH,MAAM,CAAC,KAAK,kBAAqB;IAEjC;;;;;;;;;;OAUG;WACU,QAAQ,CACnB,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,WAAW,CAAC,EAAE,oBAAoB,CAAC,aAAa,CAAC,GAChD,OAAO,CAAC,OAAO,CAAC;IACnB;;;;;;;;;;OAUG;WACU,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBhG;;;;;;;OAOG;WACU,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAIjD;;;;;;;OAOG;WACU,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/C;;;;;;;;;OASG;WACU,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIxE;;;;;;;OAOG;WACU,qBAAqB,CAChC,GAAG,EAAE,MAAM,EACX,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GACvE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIzB;;;;OAIG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrC;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAIpC;;;;OAIG;IACG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxC;;;;OAIG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI1C;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAIlC;;;;;;OAMG;WACU,SAAS,CACpB,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG,MAAM,EACrC,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,QAAQ,CAAC;IAKpB,MAAM;CA6CP"}
1
+ {"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../src/Image.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,SAAS,MAAM,aAAa,CAAC;AACpC,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,UAAU,EACV,QAAQ,EACR,WAAW,EACZ,MAAM,eAAe,CAAC;AAQvB,qBAAa,KAAM,SAAQ,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC;IACxD,aAAa,EAAE,KAAK,CAAC,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IACjD,gBAAgB,EAAE,KAAK,CAAC,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;gBAEnC,KAAK,EAAE,UAAU;IAO7B,gBAAgB,2BAMd;IAEF;;OAEG;IACH,MAAM,CAAC,KAAK,kBAAqB;IAEjC;;;;;;;;;;OAUG;WACU,QAAQ,CACnB,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,WAAW,CAAC,EAAE,oBAAoB,CAAC,aAAa,CAAC,GAChD,OAAO,CAAC,OAAO,CAAC;IACnB;;;;;;;;;;OAUG;WACU,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBhG;;;;;;;OAOG;WACU,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAIjD;;;;;;;OAOG;WACU,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/C;;;;;;;;;OASG;WACU,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIxE;;;;;;;;OAQG;WACU,qBAAqB,CAChC,MAAM,EAAE,MAAM,GAAG,QAAQ,EACzB,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GACvE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIzB;;;;OAIG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrC;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAIpC;;;;OAIG;IACG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxC;;;;OAIG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI1C;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAIlC;;;;;;OAMG;WACU,SAAS,CACpB,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG,MAAM,EACrC,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,QAAQ,CAAC;IAKpB,MAAM;CA6CP"}
@@ -140,7 +140,7 @@ export interface ImageProps extends Omit<ViewProps, 'style' | 'children'> {
140
140
  blurRadius?: number;
141
141
  /**
142
142
  * A color used to tint template images (a bitmap image where only the opacity matters).
143
- * The color is applied to every non-transparent pixel, causing the images shape to adopt that color.
143
+ * The color is applied to every non-transparent pixel, causing the image's shape to adopt that color.
144
144
  * This effect is not applied to placeholders.
145
145
  * @default null
146
146
  */
@@ -264,12 +264,12 @@ export interface ImageProps extends Omit<ViewProps, 'style' | 'children'> {
264
264
  */
265
265
  accessible?: boolean;
266
266
  /**
267
- * The text that's read by the screen reader when the user interacts with the image. Sets the the `alt` tag on web which is used for web crawlers and link traversal.
267
+ * The text that's read by the screen reader when the user interacts with the image. Sets the `alt` tag on web which is used for web crawlers and link traversal.
268
268
  * @default undefined
269
269
  */
270
270
  accessibilityLabel?: string;
271
271
  /**
272
- * The text that's read by the screen reader when the user interacts with the image. Sets the the `alt` tag on web which is used for web crawlers and link traversal. Is an alias for `accessibilityLabel`.
272
+ * The text that's read by the screen reader when the user interacts with the image. Sets the `alt` tag on web which is used for web crawlers and link traversal. Is an alias for `accessibilityLabel`.
273
273
  *
274
274
  * @alias accessibilityLabel
275
275
  * @default undefined
@@ -313,6 +313,15 @@ export interface ImageProps extends Omit<ViewProps, 'style' | 'children'> {
313
313
  * @platform ios
314
314
  */
315
315
  useAppleWebpCodec?: boolean;
316
+ /**
317
+ * Force early resizing of the image to match the container size.
318
+ * This option helps to reduce the memory usage of the image view, especially when the image is larger than the container.
319
+ * It may affect the `resizeType` and `contentPosition` properties when the image view is resized dynamically.
320
+ *
321
+ * @default false
322
+ * @platform ios
323
+ */
324
+ enforceEarlyResizing?: boolean;
316
325
  }
317
326
  /**
318
327
  * It narrows down some props to types expected by the native/web side.
@@ -375,10 +384,14 @@ export type ImageContentPosition =
375
384
  bottom?: ImageContentPositionValue;
376
385
  left?: ImageContentPositionValue;
377
386
  } | ImageContentPositionString;
387
+ /**
388
+ * It allows you to use an image as a background while rendering other content on top of it.
389
+ * It extends all `Image` props but provides separate styling controls for the container and the background image itself.
390
+ */
378
391
  export interface ImageBackgroundProps extends Omit<ImageProps, 'style'> {
379
- /** The style of the image container */
392
+ /** The style of the image container. */
380
393
  style?: StyleProp<ViewStyle> | undefined;
381
- /** Style object for the image */
394
+ /** Style object for the image. */
382
395
  imageStyle?: StyleProp<RNImageStyle> | undefined;
383
396
  /** @hidden */
384
397
  children?: React.ReactNode | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"Image.types.d.ts","sourceRoot":"","sources":["../src/Image.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Image.types.d.ts","sourceRoot":"","sources":["../src/Image.types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ImageWrapper.d.ts","sourceRoot":"","sources":["../../src/web/ImageWrapper.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAGrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAqBzD,QAAA,MAAM,YAAY,4FA4DjB,CAAC;AAEF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"ImageWrapper.d.ts","sourceRoot":"","sources":["../../src/web/ImageWrapper.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAGrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAqBzD,QAAA,MAAM,YAAY,4FAmEjB,CAAC;AAEF,eAAe,YAAY,CAAC"}
@@ -8,7 +8,7 @@
8
8
  "publication": {
9
9
  "groupId": "BareExpo",
10
10
  "artifactId": "expo.modules.image",
11
- "version": "2.3.2",
11
+ "version": "2.4.0-canary-20250709-136b77f",
12
12
  "repository": "local-maven-repo"
13
13
  }
14
14
  }
@@ -14,7 +14,7 @@ Pod::Spec.new do |s|
14
14
  :ios => '15.1',
15
15
  :tvos => '15.1'
16
16
  }
17
- s.swift_version = '5.4'
17
+ s.swift_version = '5.9'
18
18
  s.source = { git: 'https://github.com/expo/expo.git' }
19
19
  s.static_framework = true
20
20
 
@@ -111,6 +111,10 @@ public final class ImageModule: Module {
111
111
  view.useAppleWebpCodec = useAppleWebpCodec
112
112
  }
113
113
 
114
+ Prop("enforceEarlyResizing", false) { (view, enforceEarlyResizing: Bool) in
115
+ view.enforceEarlyResizing = enforceEarlyResizing
116
+ }
117
+
114
118
  AsyncFunction("startAnimating") { (view: ImageView) in
115
119
  view.sdImageView.startAnimating()
116
120
  }
@@ -166,19 +170,28 @@ public final class ImageModule: Module {
166
170
  }
167
171
  }
168
172
 
169
- AsyncFunction("generateBlurhashAsync") { (url: URL, numberOfComponents: CGSize, promise: Promise) in
173
+ AsyncFunction("generateBlurhashAsync") { (source: Either<Image, URL>, numberOfComponents: CGSize, promise: Promise) in
170
174
  let downloader = SDWebImageDownloader()
171
- let parsedNumberOfComponents = (Int(numberOfComponents.width), Int(numberOfComponents.height))
172
- downloader.downloadImage(with: url, progress: nil, completed: { image, _, _, _ in
173
- DispatchQueue.global().async {
174
- if let downloadedImage = image {
175
- let blurhashString = blurhash(fromImage: downloadedImage, numberOfComponents: parsedNumberOfComponents)
176
- promise.resolve(blurhashString)
177
- } else {
178
- promise.reject(BlurhashGenerationException())
179
- }
175
+ let parsedNumberOfComponents = (width: Int(numberOfComponents.width), height: Int(numberOfComponents.height))
176
+
177
+ if let image: Image = source.get() {
178
+ if let blurhashString = blurhash(fromImage: image.ref, numberOfComponents: parsedNumberOfComponents) {
179
+ promise.resolve(blurhashString)
180
+ } else {
181
+ promise.reject(BlurhashGenerationException())
180
182
  }
181
- })
183
+ } else if let url: URL = source.get() {
184
+ downloader.downloadImage(with: url, progress: nil, completed: { image, _, _, _ in
185
+ DispatchQueue.global().async {
186
+ if let downloadedImage = image {
187
+ let blurhashString = blurhash(fromImage: downloadedImage, numberOfComponents: parsedNumberOfComponents)
188
+ promise.resolve(blurhashString)
189
+ } else {
190
+ promise.reject(BlurhashGenerationException())
191
+ }
192
+ }
193
+ })
194
+ }
182
195
  }
183
196
 
184
197
  AsyncFunction("clearMemoryCache") { () -> Bool in
@@ -12,6 +12,8 @@ typealias SDWebImageContext = [SDWebImageContextOption: Any]
12
12
  public final class ImageView: ExpoView {
13
13
  static let contextSourceKey = SDWebImageContextOption(rawValue: "source")
14
14
  static let screenScaleKey = SDWebImageContextOption(rawValue: "screenScale")
15
+ static let contentFitKey = SDWebImageContextOption(rawValue: "contentFit")
16
+ static let frameSizeKey = SDWebImageContextOption(rawValue: "frameSize")
15
17
 
16
18
  let sdImageView = SDAnimatedImageView(frame: .zero)
17
19
 
@@ -58,6 +60,8 @@ public final class ImageView: ExpoView {
58
60
 
59
61
  var lockResource: Bool = false
60
62
 
63
+ var enforceEarlyResizing: Bool = false
64
+
61
65
  var recyclingKey: String? {
62
66
  didSet {
63
67
  if oldValue != nil && recyclingKey != oldValue {
@@ -161,7 +165,8 @@ public final class ImageView: ExpoView {
161
165
 
162
166
  // It seems that `UIImageView` can't tint some vector graphics. If the `tintColor` prop is specified,
163
167
  // we tell the SVG coder to decode to a bitmap instead. This will become useless when we switch to SVGNative coder.
164
- if imageTintColor != nil {
168
+ let shouldEarlyResize = imageTintColor != nil || enforceEarlyResizing
169
+ if shouldEarlyResize {
165
170
  context[.imagePreserveAspectRatio] = true
166
171
  context[.imageThumbnailPixelSize] = CGSize(
167
172
  width: sdImageView.bounds.size.width * screenScale,
@@ -171,6 +176,8 @@ public final class ImageView: ExpoView {
171
176
 
172
177
  // Some loaders (e.g. PhotoLibraryAssetLoader) may need to know the screen scale.
173
178
  context[ImageView.screenScaleKey] = screenScale
179
+ context[ImageView.frameSizeKey] = frame.size
180
+ context[ImageView.contentFitKey] = contentFit
174
181
 
175
182
  // Do it here so we don't waste resources trying to fetch from a remote URL
176
183
  if maybeRenderLocalAsset(from: source) {
@@ -107,9 +107,23 @@ private func requestAsset(
107
107
  }
108
108
  }
109
109
 
110
+ var targetSize = PHImageManagerMaximumSize
111
+
112
+ // We compute the minimal size required to display the image to avoid having to downsample it later
113
+ if let scale = context?[ImageView.screenScaleKey] as? Double,
114
+ let containerSize = context?[ImageView.frameSizeKey] as? CGSize,
115
+ let contentFit = context?[ImageView.contentFitKey] as? ContentFit {
116
+ let targetSize = idealSize(
117
+ contentPixelSize: CGSize(width: asset.pixelWidth, height: asset.pixelHeight),
118
+ containerSize: containerSize,
119
+ scale: scale,
120
+ contentFit: contentFit
121
+ ).rounded(.up) * scale
122
+ }
123
+
110
124
  return PHImageManager.default().requestImage(
111
125
  for: asset,
112
- targetSize: PHImageManagerMaximumSize,
126
+ targetSize: targetSize,
113
127
  contentMode: .aspectFit,
114
128
  options: options,
115
129
  resultHandler: { image, info in
@@ -0,0 +1 @@
1
+ 05a1cead66b82e284630207150f467c7ee6d64a9ca2de41f577d350148fa8fe60fbcec54bda5ebc8919abccefa4a55d58870ee4ccfe6961fd606ace3c1c707c6
@@ -0,0 +1 @@
1
+ 13b6a7e526fc661313b603d3032aa875fecaadf27dc0a763d817e899e30be579a9ba7549a57589e9b3bca7ff3ea36aab4f55bd1790cb0ab3c5a65fcca1a23a8a
@@ -3,14 +3,14 @@
3
3
  "component": {
4
4
  "group": "BareExpo",
5
5
  "module": "expo.modules.image",
6
- "version": "2.3.2",
6
+ "version": "2.4.0-canary-20250709-136b77f",
7
7
  "attributes": {
8
8
  "org.gradle.status": "release"
9
9
  }
10
10
  },
11
11
  "createdBy": {
12
12
  "gradle": {
13
- "version": "8.13"
13
+ "version": "8.14"
14
14
  }
15
15
  },
16
16
  "variants": [
@@ -54,13 +54,13 @@
54
54
  ],
55
55
  "files": [
56
56
  {
57
- "name": "expo.modules.image-2.3.2.aar",
58
- "url": "expo.modules.image-2.3.2.aar",
59
- "size": 279544,
60
- "sha512": "47c107c9a1134bb50953e5cf037cdc5aef8088d6c1bce906d268f2cf2c6b1a2692dbbd4cf686922d9eded7a78e275fea8038b91267fffd31957fa68b297bdae8",
61
- "sha256": "5d682f47a7031c3d5403faf294bb898f52299dcc73903682475cc310c39e70ac",
62
- "sha1": "af130ea05cd1ce374351bdb409b187b699baeef7",
63
- "md5": "5c50faf7e63489ecc2e5d3ab07a2f707"
57
+ "name": "expo.modules.image-2.4.0-canary-20250709-136b77f.aar",
58
+ "url": "expo.modules.image-2.4.0-canary-20250709-136b77f.aar",
59
+ "size": 293614,
60
+ "sha512": "13b6a7e526fc661313b603d3032aa875fecaadf27dc0a763d817e899e30be579a9ba7549a57589e9b3bca7ff3ea36aab4f55bd1790cb0ab3c5a65fcca1a23a8a",
61
+ "sha256": "d37a5801d9bc31976bc07304261903d2f384c37c7ac4d44f87bc761d0c8aa6eb",
62
+ "sha1": "034f22c314e21aff779c27d6b3318375e53f75fd",
63
+ "md5": "ede5ceb6ae9d04e443d6ada39204ea46"
64
64
  }
65
65
  ]
66
66
  },
@@ -77,7 +77,7 @@
77
77
  "group": "org.jetbrains.kotlin",
78
78
  "module": "kotlin-stdlib-jdk7",
79
79
  "version": {
80
- "requires": "2.0.21"
80
+ "requires": "2.1.20"
81
81
  }
82
82
  },
83
83
  {
@@ -143,13 +143,13 @@
143
143
  ],
144
144
  "files": [
145
145
  {
146
- "name": "expo.modules.image-2.3.2.aar",
147
- "url": "expo.modules.image-2.3.2.aar",
148
- "size": 279544,
149
- "sha512": "47c107c9a1134bb50953e5cf037cdc5aef8088d6c1bce906d268f2cf2c6b1a2692dbbd4cf686922d9eded7a78e275fea8038b91267fffd31957fa68b297bdae8",
150
- "sha256": "5d682f47a7031c3d5403faf294bb898f52299dcc73903682475cc310c39e70ac",
151
- "sha1": "af130ea05cd1ce374351bdb409b187b699baeef7",
152
- "md5": "5c50faf7e63489ecc2e5d3ab07a2f707"
146
+ "name": "expo.modules.image-2.4.0-canary-20250709-136b77f.aar",
147
+ "url": "expo.modules.image-2.4.0-canary-20250709-136b77f.aar",
148
+ "size": 293614,
149
+ "sha512": "13b6a7e526fc661313b603d3032aa875fecaadf27dc0a763d817e899e30be579a9ba7549a57589e9b3bca7ff3ea36aab4f55bd1790cb0ab3c5a65fcca1a23a8a",
150
+ "sha256": "d37a5801d9bc31976bc07304261903d2f384c37c7ac4d44f87bc761d0c8aa6eb",
151
+ "sha1": "034f22c314e21aff779c27d6b3318375e53f75fd",
152
+ "md5": "ede5ceb6ae9d04e443d6ada39204ea46"
153
153
  }
154
154
  ]
155
155
  },
@@ -163,13 +163,13 @@
163
163
  },
164
164
  "files": [
165
165
  {
166
- "name": "expo.modules.image-2.3.2-sources.jar",
167
- "url": "expo.modules.image-2.3.2-sources.jar",
168
- "size": 64200,
169
- "sha512": "4fd35480bc1edafe3727afbfb6b1d9cf69643f30523402e7512a8b2944d17915150373225d5aed1c344b80ad9c9b3fe1ff1050b2c83a13c8faa34956ddef588e",
170
- "sha256": "d91f60ce8ec04a24413f687b5596f0165504d5b55d05c380daea5b155e537100",
171
- "sha1": "9d61b3b9a11effe5d06c77755eaa06d86da5d422",
172
- "md5": "754e5c8b8c3d801d36965a6cf0ec673a"
166
+ "name": "expo.modules.image-2.4.0-canary-20250709-136b77f-sources.jar",
167
+ "url": "expo.modules.image-2.4.0-canary-20250709-136b77f-sources.jar",
168
+ "size": 66715,
169
+ "sha512": "05a1cead66b82e284630207150f467c7ee6d64a9ca2de41f577d350148fa8fe60fbcec54bda5ebc8919abccefa4a55d58870ee4ccfe6961fd606ace3c1c707c6",
170
+ "sha256": "577257f4b8cf651fe9ed849c1250f9f09e6c1854e1f7bb64b629b4b4216c77ee",
171
+ "sha1": "352aa667f536a581a22180f9d12871019d065320",
172
+ "md5": "3a0b848e71aa5eaefb084675eb50c305"
173
173
  }
174
174
  ]
175
175
  }
@@ -0,0 +1 @@
1
+ 01a52b8c9a218146e47fafecd23748e28bf183f13fb2a61cb23b0dd363729c227a1520cc2ba5e3bf8923c1d316e05478d0b08d42819ba04b6085c1309d3ccbb5
@@ -9,7 +9,7 @@
9
9
  <modelVersion>4.0.0</modelVersion>
10
10
  <groupId>BareExpo</groupId>
11
11
  <artifactId>expo.modules.image</artifactId>
12
- <version>2.3.2</version>
12
+ <version>2.4.0-canary-20250709-136b77f</version>
13
13
  <packaging>aar</packaging>
14
14
  <name>expo.modules.image</name>
15
15
  <url>https://github.com/expo/expo</url>
@@ -52,7 +52,7 @@
52
52
  <dependency>
53
53
  <groupId>org.jetbrains.kotlin</groupId>
54
54
  <artifactId>kotlin-stdlib-jdk7</artifactId>
55
- <version>2.0.21</version>
55
+ <version>2.1.20</version>
56
56
  <scope>runtime</scope>
57
57
  </dependency>
58
58
  <dependency>
@@ -0,0 +1 @@
1
+ feae52ca8fb6026beeef51acc6b8f4889f9994c94f891343e0733a4415a0b50db2d7cd80bd019dea54fb287f9104ae1873d2a0e65dab3acf49a968cb84375051
@@ -3,11 +3,11 @@
3
3
  <groupId>BareExpo</groupId>
4
4
  <artifactId>expo.modules.image</artifactId>
5
5
  <versioning>
6
- <latest>2.3.2</latest>
7
- <release>2.3.2</release>
6
+ <latest>2.4.0-canary-20250709-136b77f</latest>
7
+ <release>2.4.0-canary-20250709-136b77f</release>
8
8
  <versions>
9
- <version>2.3.2</version>
9
+ <version>2.4.0-canary-20250709-136b77f</version>
10
10
  </versions>
11
- <lastUpdated>20250701155759</lastUpdated>
11
+ <lastUpdated>20250709123311</lastUpdated>
12
12
  </versioning>
13
13
  </metadata>
@@ -1 +1 @@
1
- 4ad31226fb6dfe828d50ead85bca40b4
1
+ 79100949da845df78c586112149ce73f
@@ -1 +1 @@
1
- e8165ce2412191e00e0188eb7e066c9e2454a7f8
1
+ f3a681b2debb9340295ebefc8c191c4f801f6d83
@@ -1 +1 @@
1
- 024e30b789f8aec85dd5e0fb878211d0f3a991ba08f925f639024edb51317e4f
1
+ 86954d43778efdf5a57e9d3cb1ef077bfc4d0241480420ab1dcc699f80d70f32
@@ -1 +1 @@
1
- 09ad0049527394985a358ee97cabaa55f7a0fcdacc994d0347a3c38c829136fb816932373c718d0fca25951c5676facd59980da58e36e61daa5e08585bdd8532
1
+ a69168ee5e6f21ac5b064b227c32d148e1fb8082158c4a93880a222452291d6a895673f4f525478b956a7c59b3d3fca18453ce6ef4ff73dd2dd5ec1820c45f94
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "expo-image",
3
3
  "title": "Expo Image",
4
- "version": "2.3.2",
4
+ "version": "2.4.0-canary-20250709-136b77f",
5
5
  "description": "A cross-platform, performant image component for React Native and Expo with Web support",
6
6
  "main": "src/index.ts",
7
7
  "types": "build/index.d.ts",
@@ -29,10 +29,10 @@
29
29
  "license": "MIT",
30
30
  "dependencies": {},
31
31
  "devDependencies": {
32
- "expo-module-scripts": "^4.1.8"
32
+ "expo-module-scripts": "4.1.10-canary-20250709-136b77f"
33
33
  },
34
34
  "peerDependencies": {
35
- "expo": "*",
35
+ "expo": "54.0.0-canary-20250709-136b77f",
36
36
  "react": "*",
37
37
  "react-native": "*",
38
38
  "react-native-web": "*"
@@ -44,6 +44,5 @@
44
44
  },
45
45
  "jest": {
46
46
  "preset": "expo-module-scripts"
47
- },
48
- "gitHead": "34824ca1e6fb52d70d5488d32fe790234f3c3100"
47
+ }
49
48
  }
@@ -75,6 +75,7 @@ export default function ExpoImage({
75
75
  style,
76
76
  nativeViewRef,
77
77
  accessibilityLabel,
78
+ alt,
78
79
  tintColor,
79
80
  containerViewRef,
80
81
  ...props
@@ -114,7 +115,7 @@ export default function ExpoImage({
114
115
  contentPosition={{ left: '50%', top: '50%' }}
115
116
  hashPlaceholderContentPosition={contentPosition}
116
117
  hashPlaceholderStyle={imageHashStyle}
117
- accessibilityLabel={accessibilityLabel}
118
+ accessibilityLabel={accessibilityLabel ?? alt}
118
119
  cachePolicy={cachePolicy}
119
120
  priority={priority}
120
121
  tintColor={tintColor}
package/src/Image.tsx CHANGED
@@ -129,17 +129,18 @@ export class Image extends React.PureComponent<ImageProps> {
129
129
 
130
130
  /**
131
131
  * Asynchronously generates a [Blurhash](https://blurha.sh) from an image.
132
- * @param url - The URL of the image to generate a blurhash from.
132
+ * @param source - The image source, either a URL (string) or an ImageRef
133
133
  * @param numberOfComponents - The number of components to encode the blurhash with.
134
134
  * Must be between 1 and 9. Defaults to `[4, 3]`.
135
+ * @platform android
135
136
  * @platform ios
136
137
  * @return A promise resolving to the blurhash string.
137
138
  */
138
139
  static async generateBlurhashAsync(
139
- url: string,
140
+ source: string | ImageRef,
140
141
  numberOfComponents: [number, number] | { width: number; height: number }
141
142
  ): Promise<string | null> {
142
- return await ImageModule.generateBlurhashAsync(url, numberOfComponents);
143
+ return ImageModule.generateBlurhashAsync(source, numberOfComponents);
143
144
  }
144
145
 
145
146
  /**
@@ -164,7 +164,7 @@ export interface ImageProps extends Omit<ViewProps, 'style' | 'children'> {
164
164
 
165
165
  /**
166
166
  * A color used to tint template images (a bitmap image where only the opacity matters).
167
- * The color is applied to every non-transparent pixel, causing the images shape to adopt that color.
167
+ * The color is applied to every non-transparent pixel, causing the image's shape to adopt that color.
168
168
  * This effect is not applied to placeholders.
169
169
  * @default null
170
170
  */
@@ -308,13 +308,13 @@ export interface ImageProps extends Omit<ViewProps, 'style' | 'children'> {
308
308
  accessible?: boolean;
309
309
 
310
310
  /**
311
- * The text that's read by the screen reader when the user interacts with the image. Sets the the `alt` tag on web which is used for web crawlers and link traversal.
311
+ * The text that's read by the screen reader when the user interacts with the image. Sets the `alt` tag on web which is used for web crawlers and link traversal.
312
312
  * @default undefined
313
313
  */
314
314
  accessibilityLabel?: string;
315
315
 
316
316
  /**
317
- * The text that's read by the screen reader when the user interacts with the image. Sets the the `alt` tag on web which is used for web crawlers and link traversal. Is an alias for `accessibilityLabel`.
317
+ * The text that's read by the screen reader when the user interacts with the image. Sets the `alt` tag on web which is used for web crawlers and link traversal. Is an alias for `accessibilityLabel`.
318
318
  *
319
319
  * @alias accessibilityLabel
320
320
  * @default undefined
@@ -362,6 +362,16 @@ export interface ImageProps extends Omit<ViewProps, 'style' | 'children'> {
362
362
  * @platform ios
363
363
  */
364
364
  useAppleWebpCodec?: boolean;
365
+
366
+ /**
367
+ * Force early resizing of the image to match the container size.
368
+ * This option helps to reduce the memory usage of the image view, especially when the image is larger than the container.
369
+ * It may affect the `resizeType` and `contentPosition` properties when the image view is resized dynamically.
370
+ *
371
+ * @default false
372
+ * @platform ios
373
+ */
374
+ enforceEarlyResizing?: boolean;
365
375
  }
366
376
 
367
377
  /**
@@ -429,10 +439,14 @@ export type ImageContentPosition =
429
439
  }
430
440
  | ImageContentPositionString;
431
441
 
442
+ /**
443
+ * It allows you to use an image as a background while rendering other content on top of it.
444
+ * It extends all `Image` props but provides separate styling controls for the container and the background image itself.
445
+ */
432
446
  export interface ImageBackgroundProps extends Omit<ImageProps, 'style'> {
433
- /** The style of the image container */
447
+ /** The style of the image container. */
434
448
  style?: StyleProp<ViewStyle> | undefined;
435
- /** Style object for the image */
449
+ /** Style object for the image. */
436
450
  imageStyle?: StyleProp<RNImageStyle> | undefined;
437
451
  /** @hidden */
438
452
  children?: React.ReactNode | undefined;
@@ -44,7 +44,14 @@ const ImageWrapper = React.forwardRef(
44
44
  events?.onMount?.forEach((e) => e?.());
45
45
  }, []);
46
46
 
47
- const tintId = useId();
47
+ // Use a unique ID for the SVG filter so that multiple <Image> can be used
48
+ // on the same page with different tint colors without conflicts.
49
+ const tintId = useId()
50
+ // Make it safe for use as an SVG ID. SVG IDs are most strict than HTML
51
+ // IDs. They must be compliant with https://www.w3.org/TR/xml/#NT-Name.
52
+ // React 19 changed useId() to include « and ». These must be removed or
53
+ // the SVG filter will not work (e.g. in Safari which enforces the spec).
54
+ .replace(/[«»]/g, '_');
48
55
 
49
56
  // Thumbhash uri always has to start with 'thumbhash:/'
50
57
  const { resolvedSource, isImageHash } = useImageHashes(source);
@@ -1 +0,0 @@
1
- 9d61b3b9a11effe5d06c77755eaa06d86da5d422
@@ -1 +0,0 @@
1
- d91f60ce8ec04a24413f687b5596f0165504d5b55d05c380daea5b155e537100
@@ -1 +0,0 @@
1
- 4fd35480bc1edafe3727afbfb6b1d9cf69643f30523402e7512a8b2944d17915150373225d5aed1c344b80ad9c9b3fe1ff1050b2c83a13c8faa34956ddef588e
@@ -1 +0,0 @@
1
- 5c50faf7e63489ecc2e5d3ab07a2f707
@@ -1 +0,0 @@
1
- af130ea05cd1ce374351bdb409b187b699baeef7
@@ -1 +0,0 @@
1
- 5d682f47a7031c3d5403faf294bb898f52299dcc73903682475cc310c39e70ac
@@ -1 +0,0 @@
1
- 47c107c9a1134bb50953e5cf037cdc5aef8088d6c1bce906d268f2cf2c6b1a2692dbbd4cf686922d9eded7a78e275fea8038b91267fffd31957fa68b297bdae8
@@ -1 +0,0 @@
1
- 7af4ff2f7c924b72b5d247d1a8e4b595
@@ -1 +0,0 @@
1
- ec838d463d942c5f4c7292383a925a84e0aee64a
@@ -1 +0,0 @@
1
- 4df5ed4d362d6629d7e0f6b8be64e8ba5c7131233e831b6b261da9f7f1e8066c
@@ -1 +0,0 @@
1
- 2df4c319bd63061776f34544f30d204adfb64ffb604a6179cbcf49f63a7194bfa07bf0cd491c40c03111fe2ce6fb9ec46ff321504ee63819681e23773d82f99b
@@ -1 +0,0 @@
1
- 63cf17cf173c4f6130d40f99214aa25c
@@ -1 +0,0 @@
1
- 52de8ca8a076d145cff287efb578b39c10112171
@@ -1 +0,0 @@
1
- 13c3f88c0dff66426230901a9cb1a7cc1c4f1452e6e15e4108062d3a02009c8a
@@ -1 +0,0 @@
1
- 2280a33df6c419059d21badc5bebb4c3fba42d30b50bbca5bddd80cd1895ae12baae65da7cd5d411cd37e1a9db21fd84f61cd6c15b480e5d8421f90b24d06719