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.
- package/CHANGELOG.md +20 -6
- package/android/build.gradle +1 -1
- package/android/src/main/java/expo/modules/image/ExpoImageModule.kt +20 -0
- package/android/src/main/java/expo/modules/image/ExpoImageViewWrapper.kt +24 -5
- package/android/src/main/java/expo/modules/image/blurhash/BlurhashDecoder.kt +1 -10
- package/android/src/main/java/expo/modules/image/blurhash/BlurhashEncoder.kt +112 -0
- package/android/src/main/java/expo/modules/image/blurhash/BlurhashHelpers.kt +38 -0
- package/android/src/main/java/expo/modules/image/okhttp/GlideUrlWrapperLoader.kt +1 -1
- package/build/ExpoImage.web.d.ts +1 -1
- package/build/ExpoImage.web.d.ts.map +1 -1
- package/build/Image.d.ts +3 -2
- package/build/Image.d.ts.map +1 -1
- package/build/Image.types.d.ts +18 -5
- package/build/Image.types.d.ts.map +1 -1
- package/build/web/ImageWrapper.d.ts.map +1 -1
- package/expo-module.config.json +1 -1
- package/ios/ExpoImage.podspec +1 -1
- package/ios/ImageModule.swift +24 -11
- package/ios/ImageView.swift +8 -1
- package/ios/Loaders/PhotoLibraryAssetLoader.swift +15 -1
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/local-maven-repo/BareExpo/expo.modules.image/maven-metadata.xml +4 -4
- package/local-maven-repo/BareExpo/expo.modules.image/maven-metadata.xml.md5 +1 -1
- package/local-maven-repo/BareExpo/expo.modules.image/maven-metadata.xml.sha1 +1 -1
- package/local-maven-repo/BareExpo/expo.modules.image/maven-metadata.xml.sha256 +1 -1
- package/local-maven-repo/BareExpo/expo.modules.image/maven-metadata.xml.sha512 +1 -1
- package/package.json +4 -5
- package/src/ExpoImage.web.tsx +2 -1
- package/src/Image.tsx +4 -3
- package/src/Image.types.ts +19 -5
- package/src/web/ImageWrapper.tsx +8 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2-sources.jar.md5 +0 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2-sources.jar.sha1 +0 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2-sources.jar.sha256 +0 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2-sources.jar.sha512 +0 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.aar +0 -0
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.aar.md5 +0 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.aar.sha1 +0 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.aar.sha256 +0 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.aar.sha512 +0 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.module.md5 +0 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.module.sha1 +0 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.module.sha256 +0 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.module.sha512 +0 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.pom.md5 +0 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.pom.sha1 +0 -1
- package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.pom.sha256 +0 -1
- 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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
- [
|
|
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
|
|
package/android/build.gradle
CHANGED
|
@@ -8,7 +8,7 @@ android {
|
|
|
8
8
|
namespace "expo.modules.image"
|
|
9
9
|
defaultConfig {
|
|
10
10
|
versionCode 1
|
|
11
|
-
versionName "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
|
-
|
|
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
|
-
|
|
175
|
-
|
|
176
|
-
|
|
182
|
+
private fun setIsAnimating(resource: GifDrawable, setAnimating: Boolean) {
|
|
183
|
+
if (setAnimating) {
|
|
184
|
+
if (resource.isPaused) {
|
|
185
|
+
resource.resume()
|
|
177
186
|
} else {
|
|
178
|
-
resource.
|
|
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
|
)
|
package/build/ExpoImage.web.d.ts
CHANGED
|
@@ -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
|
|
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(
|
|
76
|
+
static generateBlurhashAsync(source: string | ImageRef, numberOfComponents: [number, number] | {
|
|
76
77
|
width: number;
|
|
77
78
|
height: number;
|
|
78
79
|
}): Promise<string | null>;
|
package/build/Image.d.ts.map
CHANGED
|
@@ -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
|
|
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"}
|
package/build/Image.types.d.ts
CHANGED
|
@@ -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 image
|
|
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
|
|
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
|
|
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,
|
|
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"}
|
package/expo-module.config.json
CHANGED
package/ios/ExpoImage.podspec
CHANGED
package/ios/ImageModule.swift
CHANGED
|
@@ -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") { (
|
|
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
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
package/ios/ImageView.swift
CHANGED
|
@@ -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
|
-
|
|
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:
|
|
126
|
+
targetSize: targetSize,
|
|
113
127
|
contentMode: .aspectFit,
|
|
114
128
|
options: options,
|
|
115
129
|
resultHandler: { image, info in
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3a0b848e71aa5eaefb084675eb50c305
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
352aa667f536a581a22180f9d12871019d065320
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
577257f4b8cf651fe9ed849c1250f9f09e6c1854e1f7bb64b629b4b4216c77ee
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
05a1cead66b82e284630207150f467c7ee6d64a9ca2de41f577d350148fa8fe60fbcec54bda5ebc8919abccefa4a55d58870ee4ccfe6961fd606ace3c1c707c6
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ede5ceb6ae9d04e443d6ada39204ea46
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
034f22c314e21aff779c27d6b3318375e53f75fd
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
d37a5801d9bc31976bc07304261903d2f384c37c7ac4d44f87bc761d0c8aa6eb
|
|
@@ -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.
|
|
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
|
+
"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.
|
|
58
|
-
"url": "expo.modules.image-2.
|
|
59
|
-
"size":
|
|
60
|
-
"sha512": "
|
|
61
|
-
"sha256": "
|
|
62
|
-
"sha1": "
|
|
63
|
-
"md5": "
|
|
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.
|
|
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.
|
|
147
|
-
"url": "expo.modules.image-2.
|
|
148
|
-
"size":
|
|
149
|
-
"sha512": "
|
|
150
|
-
"sha256": "
|
|
151
|
-
"sha1": "
|
|
152
|
-
"md5": "
|
|
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.
|
|
167
|
-
"url": "expo.modules.image-2.
|
|
168
|
-
"size":
|
|
169
|
-
"sha512": "
|
|
170
|
-
"sha256": "
|
|
171
|
-
"sha1": "
|
|
172
|
-
"md5": "
|
|
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
|
+
053aece4301f9dc4bf55e98baf457e86
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
a2ec808d3c72fe5b07ef8b9478f7b34fcafde103
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
09a54a93f355d235bfe17c5114155305ee1eaf0d8d42384fa68cba1da36964bf
|
|
@@ -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.
|
|
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.
|
|
55
|
+
<version>2.1.20</version>
|
|
56
56
|
<scope>runtime</scope>
|
|
57
57
|
</dependency>
|
|
58
58
|
<dependency>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4de80a245e8161528cca7c8c74925c4b
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
d55ac1a2b59ccf28bf6dcfc204f3468733d62a1a
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
93724cb41ba9ea118a1ac9b7a2fba5ca4bd244a694b208d9f36b767a2799a954
|
|
@@ -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.
|
|
7
|
-
<release>2.
|
|
6
|
+
<latest>2.4.0-canary-20250709-136b77f</latest>
|
|
7
|
+
<release>2.4.0-canary-20250709-136b77f</release>
|
|
8
8
|
<versions>
|
|
9
|
-
<version>2.
|
|
9
|
+
<version>2.4.0-canary-20250709-136b77f</version>
|
|
10
10
|
</versions>
|
|
11
|
-
<lastUpdated>
|
|
11
|
+
<lastUpdated>20250709123311</lastUpdated>
|
|
12
12
|
</versioning>
|
|
13
13
|
</metadata>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
79100949da845df78c586112149ce73f
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
f3a681b2debb9340295ebefc8c191c4f801f6d83
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
86954d43778efdf5a57e9d3cb1ef077bfc4d0241480420ab1dcc699f80d70f32
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
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.
|
|
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": "
|
|
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
|
}
|
package/src/ExpoImage.web.tsx
CHANGED
|
@@ -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
|
|
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
|
-
|
|
140
|
+
source: string | ImageRef,
|
|
140
141
|
numberOfComponents: [number, number] | { width: number; height: number }
|
|
141
142
|
): Promise<string | null> {
|
|
142
|
-
return
|
|
143
|
+
return ImageModule.generateBlurhashAsync(source, numberOfComponents);
|
|
143
144
|
}
|
|
144
145
|
|
|
145
146
|
/**
|
package/src/Image.types.ts
CHANGED
|
@@ -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 image
|
|
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
|
|
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
|
|
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;
|
package/src/web/ImageWrapper.tsx
CHANGED
|
@@ -44,7 +44,14 @@ const ImageWrapper = React.forwardRef(
|
|
|
44
44
|
events?.onMount?.forEach((e) => e?.());
|
|
45
45
|
}, []);
|
|
46
46
|
|
|
47
|
-
|
|
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);
|
package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2-sources.jar.md5
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
754e5c8b8c3d801d36965a6cf0ec673a
|
package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2-sources.jar.sha1
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
9d61b3b9a11effe5d06c77755eaa06d86da5d422
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
d91f60ce8ec04a24413f687b5596f0165504d5b55d05c380daea5b155e537100
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
4fd35480bc1edafe3727afbfb6b1d9cf69643f30523402e7512a8b2944d17915150373225d5aed1c344b80ad9c9b3fe1ff1050b2c83a13c8faa34956ddef588e
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
5c50faf7e63489ecc2e5d3ab07a2f707
|
package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.aar.sha1
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
af130ea05cd1ce374351bdb409b187b699baeef7
|
package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.aar.sha256
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
5d682f47a7031c3d5403faf294bb898f52299dcc73903682475cc310c39e70ac
|
package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.aar.sha512
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
47c107c9a1134bb50953e5cf037cdc5aef8088d6c1bce906d268f2cf2c6b1a2692dbbd4cf686922d9eded7a78e275fea8038b91267fffd31957fa68b297bdae8
|
package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.module.md5
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
7af4ff2f7c924b72b5d247d1a8e4b595
|
package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.module.sha1
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
ec838d463d942c5f4c7292383a925a84e0aee64a
|
package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.module.sha256
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
4df5ed4d362d6629d7e0f6b8be64e8ba5c7131233e831b6b261da9f7f1e8066c
|
package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.module.sha512
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2df4c319bd63061776f34544f30d204adfb64ffb604a6179cbcf49f63a7194bfa07bf0cd491c40c03111fe2ce6fb9ec46ff321504ee63819681e23773d82f99b
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
63cf17cf173c4f6130d40f99214aa25c
|
package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.pom.sha1
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
52de8ca8a076d145cff287efb578b39c10112171
|
package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.pom.sha256
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
13c3f88c0dff66426230901a9cb1a7cc1c4f1452e6e15e4108062d3a02009c8a
|
package/local-maven-repo/BareExpo/expo.modules.image/2.3.2/expo.modules.image-2.3.2.pom.sha512
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2280a33df6c419059d21badc5bebb4c3fba42d30b50bbca5bddd80cd1895ae12baae65da7cd5d411cd37e1a9db21fd84f61cd6c15b480e5d8421f90b24d06719
|