@amazon-devices/expo-image 2.0.1758683737
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +2 -0
- package/CHANGELOG.md +285 -0
- package/CMakeLists.txt +91 -0
- package/LICENSE +7 -0
- package/README.kepler.md +123 -0
- package/README.md +54 -0
- package/THIRD_PARTY_NOTICES.txt +24 -0
- package/android/build.gradle +124 -0
- package/android/proguard-rules.pro +28 -0
- package/android/src/main/AndroidManifest.xml +15 -0
- package/android/src/main/java/expo/modules/image/Exceptions.kt +9 -0
- package/android/src/main/java/expo/modules/image/ExpoImageAppGlideModule.kt +19 -0
- package/android/src/main/java/expo/modules/image/ExpoImageModule.kt +192 -0
- package/android/src/main/java/expo/modules/image/ExpoImageView.kt +220 -0
- package/android/src/main/java/expo/modules/image/ExpoImageViewWrapper.kt +652 -0
- package/android/src/main/java/expo/modules/image/GlideModel.kt +73 -0
- package/android/src/main/java/expo/modules/image/ImageUtils.kt +50 -0
- package/android/src/main/java/expo/modules/image/ImageViewWrapperTarget.kt +313 -0
- package/android/src/main/java/expo/modules/image/ResourceIdHelper.kt +47 -0
- package/android/src/main/java/expo/modules/image/ThumbnailRequestCoordinatorExtension.kt +21 -0
- package/android/src/main/java/expo/modules/image/YogaUtils.kt +20 -0
- package/android/src/main/java/expo/modules/image/blurhash/BlurHashFetcher.kt +32 -0
- package/android/src/main/java/expo/modules/image/blurhash/BlurhashDecoder.kt +189 -0
- package/android/src/main/java/expo/modules/image/blurhash/BlurhashModelLoader.kt +30 -0
- package/android/src/main/java/expo/modules/image/blurhash/BlurhashModelLoaderFactory.kt +14 -0
- package/android/src/main/java/expo/modules/image/blurhash/BlurhashModule.kt +17 -0
- package/android/src/main/java/expo/modules/image/dataurls/Base64DataFetcher.kt +27 -0
- package/android/src/main/java/expo/modules/image/dataurls/Base64ModelLoader.kt +24 -0
- package/android/src/main/java/expo/modules/image/dataurls/Base64ModelLoaderFactory.kt +12 -0
- package/android/src/main/java/expo/modules/image/dataurls/Base64Module.kt +16 -0
- package/android/src/main/java/expo/modules/image/drawing/OutlineProvider.kt +201 -0
- package/android/src/main/java/expo/modules/image/enums/ContentFit.kt +89 -0
- package/android/src/main/java/expo/modules/image/enums/ImageCacheType.kt +14 -0
- package/android/src/main/java/expo/modules/image/enums/Priority.kt +15 -0
- package/android/src/main/java/expo/modules/image/events/GlideRequestListener.kt +64 -0
- package/android/src/main/java/expo/modules/image/events/OkHttpProgressListener.kt +26 -0
- package/android/src/main/java/expo/modules/image/okhttp/ExpoImageOkHttpClientGlideModule.kt +80 -0
- package/android/src/main/java/expo/modules/image/okhttp/GlideUrlWrapperLoader.kt +55 -0
- package/android/src/main/java/expo/modules/image/records/CachePolicy.kt +10 -0
- package/android/src/main/java/expo/modules/image/records/ContentPosition.kt +89 -0
- package/android/src/main/java/expo/modules/image/records/ImageTransition.kt +8 -0
- package/android/src/main/java/expo/modules/image/records/SourceMap.kt +160 -0
- package/android/src/main/java/expo/modules/image/records/events.kt +25 -0
- package/android/src/main/java/expo/modules/image/svg/SVGDecoder.kt +33 -0
- package/android/src/main/java/expo/modules/image/svg/SVGDrawableTranscoder.kt +37 -0
- package/android/src/main/java/expo/modules/image/svg/SVGModule.kt +26 -0
- package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashDecoder.kt +365 -0
- package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashFetcher.kt +31 -0
- package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashModelLoader.kt +26 -0
- package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashModelLoaderFactory.kt +14 -0
- package/android/src/main/java/expo/modules/image/thumbhash/ThumbhashModule.kt +17 -0
- package/build/ExpoImage.d.ts +15 -0
- package/build/ExpoImage.d.ts.map +1 -0
- package/build/ExpoImage.js +75 -0
- package/build/ExpoImage.js.map +1 -0
- package/build/ExpoImage.kepler.d.ts +23 -0
- package/build/ExpoImage.kepler.d.ts.map +1 -0
- package/build/ExpoImage.kepler.js +71 -0
- package/build/ExpoImage.kepler.js.map +1 -0
- package/build/ExpoImage.web.d.ts +9 -0
- package/build/ExpoImage.web.d.ts.map +1 -0
- package/build/ExpoImage.web.js +90 -0
- package/build/ExpoImage.web.js.map +1 -0
- package/build/ExpoImageModules.d.ts +3 -0
- package/build/ExpoImageModules.d.ts.map +1 -0
- package/build/ExpoImageModules.js +4 -0
- package/build/ExpoImageModules.js.map +1 -0
- package/build/ExpoImageModules.kepler.d.ts +6 -0
- package/build/ExpoImageModules.kepler.d.ts.map +1 -0
- package/build/ExpoImageModules.kepler.js +5 -0
- package/build/ExpoImageModules.kepler.js.map +1 -0
- package/build/Image.d.ts +30 -0
- package/build/Image.d.ts.map +1 -0
- package/build/Image.js +49 -0
- package/build/Image.js.map +1 -0
- package/build/Image.types.d.ts +374 -0
- package/build/Image.types.d.ts.map +1 -0
- package/build/Image.types.js +2 -0
- package/build/Image.types.js.map +1 -0
- package/build/ImageBackground.d.ts +6 -0
- package/build/ImageBackground.d.ts.map +1 -0
- package/build/ImageBackground.js +13 -0
- package/build/ImageBackground.js.map +1 -0
- package/build/ImageViewNativeComponent.d.ts +20 -0
- package/build/ImageViewNativeComponent.d.ts.map +1 -0
- package/build/ImageViewNativeComponent.js +42 -0
- package/build/ImageViewNativeComponent.js.map +1 -0
- package/build/NativeImageLoaderKepler.d.ts +18 -0
- package/build/NativeImageLoaderKepler.d.ts.map +1 -0
- package/build/NativeImageLoaderKepler.js +3 -0
- package/build/NativeImageLoaderKepler.js.map +1 -0
- package/build/fabric/registerNativeComponent.d.ts +15 -0
- package/build/fabric/registerNativeComponent.d.ts.map +1 -0
- package/build/fabric/registerNativeComponent.js +47 -0
- package/build/fabric/registerNativeComponent.js.map +1 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +4 -0
- package/build/index.js.map +1 -0
- package/build/utils/AssetSourceResolver.web.d.ts +24 -0
- package/build/utils/AssetSourceResolver.web.d.ts.map +1 -0
- package/build/utils/AssetSourceResolver.web.js +67 -0
- package/build/utils/AssetSourceResolver.web.js.map +1 -0
- package/build/utils/blurhash/base83.d.ts +3 -0
- package/build/utils/blurhash/base83.d.ts.map +1 -0
- package/build/utils/blurhash/base83.js +103 -0
- package/build/utils/blurhash/base83.js.map +1 -0
- package/build/utils/blurhash/decode.d.ts +7 -0
- package/build/utils/blurhash/decode.d.ts.map +1 -0
- package/build/utils/blurhash/decode.js +92 -0
- package/build/utils/blurhash/decode.js.map +1 -0
- package/build/utils/blurhash/error.d.ts +4 -0
- package/build/utils/blurhash/error.d.ts.map +1 -0
- package/build/utils/blurhash/error.js +8 -0
- package/build/utils/blurhash/error.js.map +1 -0
- package/build/utils/blurhash/useBlurhash.d.ts +8 -0
- package/build/utils/blurhash/useBlurhash.d.ts.map +1 -0
- package/build/utils/blurhash/useBlurhash.js +64 -0
- package/build/utils/blurhash/useBlurhash.js.map +1 -0
- package/build/utils/blurhash/utils.d.ts +5 -0
- package/build/utils/blurhash/utils.d.ts.map +1 -0
- package/build/utils/blurhash/utils.js +21 -0
- package/build/utils/blurhash/utils.js.map +1 -0
- package/build/utils/resolveAssetSource.d.ts +3 -0
- package/build/utils/resolveAssetSource.d.ts.map +1 -0
- package/build/utils/resolveAssetSource.js +3 -0
- package/build/utils/resolveAssetSource.js.map +1 -0
- package/build/utils/resolveAssetSource.web.d.ts +9 -0
- package/build/utils/resolveAssetSource.web.d.ts.map +1 -0
- package/build/utils/resolveAssetSource.web.js +31 -0
- package/build/utils/resolveAssetSource.web.js.map +1 -0
- package/build/utils/resolveHashString.d.ts +14 -0
- package/build/utils/resolveHashString.d.ts.map +1 -0
- package/build/utils/resolveHashString.js +31 -0
- package/build/utils/resolveHashString.js.map +1 -0
- package/build/utils/resolveHashString.web.d.ts +20 -0
- package/build/utils/resolveHashString.web.d.ts.map +1 -0
- package/build/utils/resolveHashString.web.js +31 -0
- package/build/utils/resolveHashString.web.js.map +1 -0
- package/build/utils/resolveSources.d.ts +8 -0
- package/build/utils/resolveSources.d.ts.map +1 -0
- package/build/utils/resolveSources.js +45 -0
- package/build/utils/resolveSources.js.map +1 -0
- package/build/utils/thumbhash/thumbhash.d.ts +66 -0
- package/build/utils/thumbhash/thumbhash.d.ts.map +1 -0
- package/build/utils/thumbhash/thumbhash.js +338 -0
- package/build/utils/thumbhash/thumbhash.js.map +1 -0
- package/build/utils.d.ts +17 -0
- package/build/utils.d.ts.map +1 -0
- package/build/utils.js +85 -0
- package/build/utils.js.map +1 -0
- package/build/web/AnimationManager.d.ts +37 -0
- package/build/web/AnimationManager.d.ts.map +1 -0
- package/build/web/AnimationManager.js +155 -0
- package/build/web/AnimationManager.js.map +1 -0
- package/build/web/ColorTintFilter.d.ts +12 -0
- package/build/web/ColorTintFilter.d.ts.map +1 -0
- package/build/web/ColorTintFilter.js +30 -0
- package/build/web/ColorTintFilter.js.map +1 -0
- package/build/web/ImageWrapper.d.ts +5 -0
- package/build/web/ImageWrapper.d.ts.map +1 -0
- package/build/web/ImageWrapper.js +44 -0
- package/build/web/ImageWrapper.js.map +1 -0
- package/build/web/ImageWrapper.types.d.ts +29 -0
- package/build/web/ImageWrapper.types.d.ts.map +1 -0
- package/build/web/ImageWrapper.types.js +2 -0
- package/build/web/ImageWrapper.types.js.map +1 -0
- package/build/web/getImageWrapperEventHandler.d.ts +8 -0
- package/build/web/getImageWrapperEventHandler.d.ts.map +1 -0
- package/build/web/getImageWrapperEventHandler.js +25 -0
- package/build/web/getImageWrapperEventHandler.js.map +1 -0
- package/build/web/hooks.d.ts +13 -0
- package/build/web/hooks.d.ts.map +1 -0
- package/build/web/hooks.js +58 -0
- package/build/web/hooks.js.map +1 -0
- package/build/web/imageStyles.d.ts +2 -0
- package/build/web/imageStyles.d.ts.map +1 -0
- package/build/web/imageStyles.js +137 -0
- package/build/web/imageStyles.js.map +1 -0
- package/build/web/positioning.d.ts +11 -0
- package/build/web/positioning.d.ts.map +1 -0
- package/build/web/positioning.js +35 -0
- package/build/web/positioning.js.map +1 -0
- package/build/web/useSourceSelection.d.ts +14 -0
- package/build/web/useSourceSelection.d.ts.map +1 -0
- package/build/web/useSourceSelection.js +98 -0
- package/build/web/useSourceSelection.js.map +1 -0
- package/expo-module.config.json +9 -0
- package/ios/Blurhash.swift +326 -0
- package/ios/BlurhashLoader.swift +52 -0
- package/ios/ContentFit.swift +55 -0
- package/ios/ContentPosition.swift +108 -0
- package/ios/ExpoImage.podspec +30 -0
- package/ios/ImageCachePolicy.swift +24 -0
- package/ios/ImageCacheType.swift +21 -0
- package/ios/ImageModule.swift +127 -0
- package/ios/ImagePriority.swift +22 -0
- package/ios/ImageSource.swift +44 -0
- package/ios/ImageTransition.swift +67 -0
- package/ios/ImageUtils.swift +227 -0
- package/ios/ImageView.swift +469 -0
- package/ios/Loaders/PhotoLibraryAssetLoader.swift +146 -0
- package/ios/Thumbhash.swift +550 -0
- package/ios/ThumbhashLoader.swift +53 -0
- package/jest.config.js +3 -0
- package/kepler/ExpoImage.cpp +63 -0
- package/kepler/ExpoImage.h +29 -0
- package/kepler/ExpoImageCacheHandler.cpp +15 -0
- package/kepler/ExpoImageCacheHandler.h +28 -0
- package/kepler/ExpoImageComponent.cpp +579 -0
- package/kepler/ExpoImageComponent.h +199 -0
- package/kepler/ImageWrapper/BlurhashImageWrapper.cpp +37 -0
- package/kepler/ImageWrapper/BlurhashImageWrapper.h +23 -0
- package/kepler/ImageWrapper/CacheImageWrapper.cpp +80 -0
- package/kepler/ImageWrapper/CacheImageWrapper.h +41 -0
- package/kepler/ImageWrapper/HashImageWrapper.cpp +21 -0
- package/kepler/ImageWrapper/HashImageWrapper.h +22 -0
- package/kepler/ImageWrapper/ImageWrapper.cpp +24 -0
- package/kepler/ImageWrapper/ImageWrapper.h +33 -0
- package/kepler/ImageWrapper/LocalImageWrapper.cpp +61 -0
- package/kepler/ImageWrapper/LocalImageWrapper.h +30 -0
- package/kepler/ImageWrapper/ThumbhashImageWrapper.cpp +33 -0
- package/kepler/ImageWrapper/ThumbhashImageWrapper.h +20 -0
- package/kepler/KeplerImageViewComponent.h +64 -0
- package/kepler/KeplerInit.cpp +35 -0
- package/kepler/blurhash/common.h +32 -0
- package/kepler/blurhash/decode.cpp +187 -0
- package/kepler/blurhash/decode.h +58 -0
- package/kepler/contentposition/ImageContentPosition.cpp +86 -0
- package/kepler/contentposition/ImageContentPosition.h +48 -0
- package/kepler/enums/ImageContentFit.h +17 -0
- package/kepler/enums/ImagePriority.h +17 -0
- package/kepler/managers/ExpoImageManager.cpp +38 -0
- package/kepler/managers/ExpoImageManager.h +23 -0
- package/kepler/test/ExpoImage.cpp +73 -0
- package/kepler/test/ExpoImageComponent.cpp +290 -0
- package/kepler/test/blurhash/decode.cpp +39 -0
- package/kepler/test/contentposition/ImageContentPosition.cpp +100 -0
- package/kepler/test/managers/ExpoImageManager.cpp +39 -0
- package/kepler/test/thumbhash/decode.cpp +18 -0
- package/kepler/test/utils/LoaderDelegate.cpp +130 -0
- package/kepler/thumbhash/decode.cpp +166 -0
- package/kepler/thumbhash/decode.h +22 -0
- package/kepler/utils/PlaceholderImageLoaderDelegate.cpp +26 -0
- package/kepler/utils/PlaceholderImageLoaderDelegate.h +26 -0
- package/kepler/utils/PrefetchImageLoaderDelegate.cpp +55 -0
- package/kepler/utils/PrefetchImageLoaderDelegate.h +35 -0
- package/kepler/utils/SourceImageLoaderDelegate.cpp +47 -0
- package/kepler/utils/SourceImageLoaderDelegate.h +42 -0
- package/kepler/utils/SourceImageLoaderDelegateEmitter.cpp +15 -0
- package/kepler/utils/SourceImageLoaderDelegateEmitter.h +28 -0
- package/kepler-compatibility.json +8 -0
- package/package.json +1 -0
- package/react-native.config.js +22 -0
- package/src/ExpoImage.kepler.tsx +119 -0
- package/src/ExpoImage.tsx +119 -0
- package/src/ExpoImage.web.tsx +155 -0
- package/src/ExpoImageModules.kepler.ts +7 -0
- package/src/ExpoImageModules.ts +4 -0
- package/src/Image.tsx +82 -0
- package/src/Image.types.ts +450 -0
- package/src/ImageBackground.tsx +18 -0
- package/src/ImageViewNativeComponent.ts +59 -0
- package/src/NativeImageLoaderKepler.ts +22 -0
- package/src/fabric/registerNativeComponent.ts +70 -0
- package/src/index.ts +3 -0
- package/src/utils/AssetSourceResolver.web.ts +88 -0
- package/src/utils/blurhash/base83.ts +104 -0
- package/src/utils/blurhash/decode.ts +114 -0
- package/src/utils/blurhash/error.ts +7 -0
- package/src/utils/blurhash/useBlurhash.tsx +81 -0
- package/src/utils/blurhash/utils.ts +21 -0
- package/src/utils/resolveAssetSource.tsx +3 -0
- package/src/utils/resolveAssetSource.web.ts +40 -0
- package/src/utils/resolveHashString.tsx +36 -0
- package/src/utils/resolveHashString.web.tsx +33 -0
- package/src/utils/resolveSources.tsx +48 -0
- package/src/utils/thumbhash/thumbhash.ts +387 -0
- package/src/utils.ts +109 -0
- package/src/web/AnimationManager.tsx +224 -0
- package/src/web/ColorTintFilter.tsx +36 -0
- package/src/web/ImageWrapper.tsx +85 -0
- package/src/web/ImageWrapper.types.ts +36 -0
- package/src/web/getImageWrapperEventHandler.ts +29 -0
- package/src/web/hooks.ts +72 -0
- package/src/web/imageStyles.tsx +136 -0
- package/src/web/positioning.ts +48 -0
- package/src/web/useSourceSelection.ts +151 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
// The blurhash algorithm was entirely created by Wolt Enterprises.
|
|
2
|
+
// This implementation was inspired by:
|
|
3
|
+
// - https://github.com/woltapp/blurhash/blob/master/Swift/BlurHashDecode.swift
|
|
4
|
+
// - https://github.com/woltapp/blurhash/blob/master/Swift/BlurHashEncode.swift
|
|
5
|
+
// See https://blurha.sh for more details about the blurhash.
|
|
6
|
+
|
|
7
|
+
import UIKit
|
|
8
|
+
|
|
9
|
+
// swiftlint:disable force_unwrapping
|
|
10
|
+
|
|
11
|
+
internal func image(fromBlurhash blurhash: String, size: CGSize, punch: Float = 1.0) -> CGImage? {
|
|
12
|
+
guard blurhash.count >= 6 else {
|
|
13
|
+
return nil
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let sizeFlag = decode83(String(blurhash[0]))
|
|
17
|
+
let numY = (sizeFlag / 9) + 1
|
|
18
|
+
let numX = (sizeFlag % 9) + 1
|
|
19
|
+
|
|
20
|
+
let quantisedMaximumValue = decode83(String(blurhash[1]))
|
|
21
|
+
let maximumValue = Float(quantisedMaximumValue + 1) / 166
|
|
22
|
+
|
|
23
|
+
guard blurhash.count == 4 + 2 * numX * numY else {
|
|
24
|
+
return nil
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let colors: [(Float, Float, Float)] = (0 ..< numX * numY).map { i in
|
|
28
|
+
if i == 0 {
|
|
29
|
+
let value = decode83(String(blurhash[2 ..< 6]))
|
|
30
|
+
return decodeDC(value)
|
|
31
|
+
} else {
|
|
32
|
+
let value = decode83(String(blurhash[4 + i * 2 ..< 4 + i * 2 + 2]))
|
|
33
|
+
return decodeAC(value, maximumValue: maximumValue * punch)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let width = Int(size.width)
|
|
38
|
+
let height = Int(size.height)
|
|
39
|
+
let bytesPerRow = width * 3
|
|
40
|
+
|
|
41
|
+
guard let data = CFDataCreateMutable(kCFAllocatorDefault, bytesPerRow * height) else {
|
|
42
|
+
return nil
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
CFDataSetLength(data, bytesPerRow * height)
|
|
46
|
+
|
|
47
|
+
guard let pixels = CFDataGetMutableBytePtr(data) else {
|
|
48
|
+
return nil
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
for y in 0 ..< height {
|
|
52
|
+
for x in 0 ..< width {
|
|
53
|
+
var r: Float = 0
|
|
54
|
+
var g: Float = 0
|
|
55
|
+
var b: Float = 0
|
|
56
|
+
|
|
57
|
+
for j in 0 ..< numY {
|
|
58
|
+
for i in 0 ..< numX {
|
|
59
|
+
let basis = cos(Float.pi * Float(x) * Float(i) / Float(width)) * cos(Float.pi * Float(y) * Float(j) / Float(height))
|
|
60
|
+
let color = colors[i + j * numX]
|
|
61
|
+
r += color.0 * basis
|
|
62
|
+
g += color.1 * basis
|
|
63
|
+
b += color.2 * basis
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let intR = UInt8(linearTosRGB(r))
|
|
68
|
+
let intG = UInt8(linearTosRGB(g))
|
|
69
|
+
let intB = UInt8(linearTosRGB(b))
|
|
70
|
+
|
|
71
|
+
pixels[3 * x + 0 + y * bytesPerRow] = intR
|
|
72
|
+
pixels[3 * x + 1 + y * bytesPerRow] = intG
|
|
73
|
+
pixels[3 * x + 2 + y * bytesPerRow] = intB
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue)
|
|
78
|
+
|
|
79
|
+
guard let provider = CGDataProvider(data: data), let cgImage = CGImage(
|
|
80
|
+
width: width,
|
|
81
|
+
height: height,
|
|
82
|
+
bitsPerComponent: 8,
|
|
83
|
+
bitsPerPixel: 24,
|
|
84
|
+
bytesPerRow: bytesPerRow,
|
|
85
|
+
space: CGColorSpaceCreateDeviceRGB(),
|
|
86
|
+
bitmapInfo: bitmapInfo,
|
|
87
|
+
provider: provider,
|
|
88
|
+
decode: nil,
|
|
89
|
+
shouldInterpolate: true,
|
|
90
|
+
intent: .defaultIntent
|
|
91
|
+
) else {
|
|
92
|
+
return nil
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return cgImage
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
internal func blurhash(fromImage image: UIImage, numberOfComponents components: (Int, Int)) -> String? {
|
|
99
|
+
let size = image.size
|
|
100
|
+
let scale = image.scale
|
|
101
|
+
|
|
102
|
+
let pixelWidth = Int(round(size.width * scale))
|
|
103
|
+
let pixelHeight = Int(round(size.height * scale))
|
|
104
|
+
|
|
105
|
+
let context = CGContext(
|
|
106
|
+
data: nil,
|
|
107
|
+
width: pixelWidth,
|
|
108
|
+
height: pixelHeight,
|
|
109
|
+
bitsPerComponent: 8,
|
|
110
|
+
bytesPerRow: pixelWidth * 4,
|
|
111
|
+
space: CGColorSpace(name: CGColorSpace.sRGB)!,
|
|
112
|
+
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue
|
|
113
|
+
)!
|
|
114
|
+
context.scaleBy(x: scale, y: -scale)
|
|
115
|
+
context.translateBy(x: 0, y: -size.height)
|
|
116
|
+
|
|
117
|
+
UIGraphicsPushContext(context)
|
|
118
|
+
image.draw(at: .zero)
|
|
119
|
+
UIGraphicsPopContext()
|
|
120
|
+
|
|
121
|
+
guard let cgImage = context.makeImage(),
|
|
122
|
+
let dataProvider = cgImage.dataProvider,
|
|
123
|
+
let data = dataProvider.data,
|
|
124
|
+
let pixels = CFDataGetBytePtr(data) else {
|
|
125
|
+
assertionFailure("Unexpected error!")
|
|
126
|
+
return nil
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let width = cgImage.width
|
|
130
|
+
let height = cgImage.height
|
|
131
|
+
let bytesPerRow = cgImage.bytesPerRow
|
|
132
|
+
|
|
133
|
+
var factors: [(Float, Float, Float)] = []
|
|
134
|
+
for y in 0 ..< components.1 {
|
|
135
|
+
for x in 0 ..< components.0 {
|
|
136
|
+
let normalisation: Float = (x == 0 && y == 0) ? 1 : 2
|
|
137
|
+
let factor = multiplyBasisFunction(
|
|
138
|
+
pixels: pixels,
|
|
139
|
+
width: width,
|
|
140
|
+
height: height,
|
|
141
|
+
bytesPerRow: bytesPerRow,
|
|
142
|
+
bytesPerPixel: cgImage.bitsPerPixel / 8,
|
|
143
|
+
pixelOffset: 0
|
|
144
|
+
) {
|
|
145
|
+
normalisation * cos(Float.pi * Float(x) * $0 / Float(width)) as Float * cos(Float.pi * Float(y) * $1 / Float(height)) as Float
|
|
146
|
+
}
|
|
147
|
+
factors.append(factor)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let dc = factors.first!
|
|
152
|
+
let ac = factors.dropFirst()
|
|
153
|
+
|
|
154
|
+
var hash = ""
|
|
155
|
+
|
|
156
|
+
let sizeFlag = (components.0 - 1) + (components.1 - 1) * 9
|
|
157
|
+
hash += encode83(sizeFlag, length: 1)
|
|
158
|
+
|
|
159
|
+
let maximumValue: Float
|
|
160
|
+
if !ac.isEmpty {
|
|
161
|
+
let actualMaximumValue = ac.map({ max(abs($0.0), abs($0.1), abs($0.2)) }).max()!
|
|
162
|
+
let quantisedMaximumValue = Int(max(0, min(82, floor(actualMaximumValue * 166 - 0.5))))
|
|
163
|
+
maximumValue = Float(quantisedMaximumValue + 1) / 166
|
|
164
|
+
hash += encode83(quantisedMaximumValue, length: 1)
|
|
165
|
+
} else {
|
|
166
|
+
maximumValue = 1
|
|
167
|
+
hash += encode83(0, length: 1)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
hash += encode83(encodeDC(dc), length: 4)
|
|
171
|
+
|
|
172
|
+
for factor in ac {
|
|
173
|
+
hash += encode83(encodeAC(factor, maximumValue: maximumValue), length: 2)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return hash
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
internal func isBlurhash(_ str: String) -> Bool {
|
|
180
|
+
return str.allSatisfy { char in decodeCharacters[char] != nil }
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// MARK: - Encode
|
|
184
|
+
|
|
185
|
+
// swiftlint:disable:next function_parameter_count
|
|
186
|
+
private func multiplyBasisFunction(
|
|
187
|
+
pixels: UnsafePointer<UInt8>,
|
|
188
|
+
width: Int,
|
|
189
|
+
height: Int,
|
|
190
|
+
bytesPerRow: Int,
|
|
191
|
+
bytesPerPixel: Int,
|
|
192
|
+
pixelOffset: Int,
|
|
193
|
+
basisFunction: (Float, Float) -> Float
|
|
194
|
+
) -> (Float, Float, Float) {
|
|
195
|
+
var r: Float = 0
|
|
196
|
+
var g: Float = 0
|
|
197
|
+
var b: Float = 0
|
|
198
|
+
|
|
199
|
+
let buffer = UnsafeBufferPointer(start: pixels, count: height * bytesPerRow)
|
|
200
|
+
|
|
201
|
+
for x in 0 ..< width {
|
|
202
|
+
for y in 0 ..< height {
|
|
203
|
+
let basis = basisFunction(Float(x), Float(y))
|
|
204
|
+
r += basis * sRGBToLinear(buffer[bytesPerPixel * x + pixelOffset + 0 + y * bytesPerRow])
|
|
205
|
+
g += basis * sRGBToLinear(buffer[bytesPerPixel * x + pixelOffset + 1 + y * bytesPerRow])
|
|
206
|
+
b += basis * sRGBToLinear(buffer[bytesPerPixel * x + pixelOffset + 2 + y * bytesPerRow])
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
let scale = 1 / Float(width * height)
|
|
211
|
+
|
|
212
|
+
return (r * scale, g * scale, b * scale)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
private let encodeCharacters: [Character] = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~")
|
|
216
|
+
|
|
217
|
+
private func encodeDC(_ value: (Float, Float, Float)) -> Int {
|
|
218
|
+
let roundedR = linearTosRGB(value.0)
|
|
219
|
+
let roundedG = linearTosRGB(value.1)
|
|
220
|
+
let roundedB = linearTosRGB(value.2)
|
|
221
|
+
return (roundedR << 16) + (roundedG << 8) + roundedB
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
private func encodeAC(_ value: (Float, Float, Float), maximumValue: Float) -> Int {
|
|
225
|
+
let quantR = Int(max(0, min(18, floor(signPow(value.0 / maximumValue, 0.5) * 9 + 9.5))))
|
|
226
|
+
let quantG = Int(max(0, min(18, floor(signPow(value.1 / maximumValue, 0.5) * 9 + 9.5))))
|
|
227
|
+
let quantB = Int(max(0, min(18, floor(signPow(value.2 / maximumValue, 0.5) * 9 + 9.5))))
|
|
228
|
+
|
|
229
|
+
return quantR * 19 * 19 + quantG * 19 + quantB
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
private func encode83(_ value: Int, length: Int) -> String {
|
|
233
|
+
var result = ""
|
|
234
|
+
for i in 1 ... length {
|
|
235
|
+
let digit = (value / pow(83, length - i)) % 83
|
|
236
|
+
result += String(encodeCharacters[Int(digit)])
|
|
237
|
+
}
|
|
238
|
+
return result
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// MARK: - Decode
|
|
242
|
+
|
|
243
|
+
private func decodeDC(_ value: Int) -> (Float, Float, Float) {
|
|
244
|
+
let intR = value >> 16
|
|
245
|
+
let intG = (value >> 8) & 255
|
|
246
|
+
let intB = value & 255
|
|
247
|
+
return (sRGBToLinear(intR), sRGBToLinear(intG), sRGBToLinear(intB))
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
private func decodeAC(_ value: Int, maximumValue: Float) -> (Float, Float, Float) {
|
|
251
|
+
let quantR = value / (19 * 19)
|
|
252
|
+
let quantG = (value / 19) % 19
|
|
253
|
+
let quantB = value % 19
|
|
254
|
+
|
|
255
|
+
let rgb = (
|
|
256
|
+
signPow((Float(quantR) - 9) / 9, 2) * maximumValue,
|
|
257
|
+
signPow((Float(quantG) - 9) / 9, 2) * maximumValue,
|
|
258
|
+
signPow((Float(quantB) - 9) / 9, 2) * maximumValue
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
return rgb
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
private let decodeCharacters: [Character: Int] = {
|
|
265
|
+
var dict: [Character: Int] = [:]
|
|
266
|
+
for (index, character) in encodeCharacters.enumerated() {
|
|
267
|
+
dict[character] = index
|
|
268
|
+
}
|
|
269
|
+
return dict
|
|
270
|
+
}()
|
|
271
|
+
|
|
272
|
+
private func decode83(_ str: String) -> Int {
|
|
273
|
+
var value: Int = 0
|
|
274
|
+
for character in str {
|
|
275
|
+
if let digit = decodeCharacters[character] {
|
|
276
|
+
value = value * 83 + digit
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return value
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// MARK: - Helpers
|
|
283
|
+
|
|
284
|
+
private func signPow(_ value: Float, _ exp: Float) -> Float {
|
|
285
|
+
return copysign(pow(abs(value), exp), value)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
private func linearTosRGB(_ value: Float) -> Int {
|
|
289
|
+
let v = max(0, min(1, value))
|
|
290
|
+
if v <= 0.0031308 {
|
|
291
|
+
return Int(v * 12.92 * 255 + 0.5)
|
|
292
|
+
} else {
|
|
293
|
+
return Int((1.055 * pow(v, 1 / 2.4) - 0.055) * 255 + 0.5)
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
private func sRGBToLinear<Type: BinaryInteger>(_ value: Type) -> Float {
|
|
298
|
+
let v = Float(Int64(value)) / 255
|
|
299
|
+
if v <= 0.04045 {
|
|
300
|
+
return v / 12.92
|
|
301
|
+
} else {
|
|
302
|
+
return pow((v + 0.055) / 1.055, 2.4)
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
private func pow(_ base: Int, _ exponent: Int) -> Int {
|
|
307
|
+
return (0 ..< exponent).reduce(1) { value, _ in value * base }
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
private extension String {
|
|
311
|
+
subscript (offset: Int) -> Character {
|
|
312
|
+
return self[index(startIndex, offsetBy: offset)]
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
subscript (bounds: CountableClosedRange<Int>) -> Substring {
|
|
316
|
+
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
|
317
|
+
let end = index(startIndex, offsetBy: bounds.upperBound)
|
|
318
|
+
return self[start...end]
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
subscript (bounds: CountableRange<Int>) -> Substring {
|
|
322
|
+
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
|
323
|
+
let end = index(startIndex, offsetBy: bounds.upperBound)
|
|
324
|
+
return self[start..<end]
|
|
325
|
+
}
|
|
326
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import SDWebImage
|
|
2
|
+
import ExpoModulesCore
|
|
3
|
+
|
|
4
|
+
class BlurhashLoader: NSObject, SDImageLoader {
|
|
5
|
+
// MARK: - SDImageLoader
|
|
6
|
+
|
|
7
|
+
func canRequestImage(for url: URL?) -> Bool {
|
|
8
|
+
return url?.scheme == "blurhash"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
func requestImage(
|
|
12
|
+
with url: URL?,
|
|
13
|
+
options: SDWebImageOptions = [],
|
|
14
|
+
context: [SDWebImageContextOption: Any]?,
|
|
15
|
+
progress progressBlock: SDImageLoaderProgressBlock?,
|
|
16
|
+
completed completedBlock: SDImageLoaderCompletedBlock? = nil
|
|
17
|
+
) -> SDWebImageOperation? {
|
|
18
|
+
guard let url = url else {
|
|
19
|
+
let error = makeNSError(description: "URL provided to BlurhashLoader is missing")
|
|
20
|
+
completedBlock?(nil, nil, error, false)
|
|
21
|
+
return nil
|
|
22
|
+
}
|
|
23
|
+
guard let source = context?[ImageView.contextSourceKey] as? ImageSource else {
|
|
24
|
+
let error = makeNSError(description: "Image source was not provided to the context")
|
|
25
|
+
completedBlock?(nil, nil, error, false)
|
|
26
|
+
return nil
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// The URI looks like this: blurhash:/WgF}G?az0fs.x[jat7xFRjNHt6s.4;oe-:RkVtkCi^Nbo|xZRjWB
|
|
30
|
+
// Which means that the `pathComponents[0]` is `/` and we need to skip it to get the hash.
|
|
31
|
+
let blurhash = url.pathComponents[1]
|
|
32
|
+
let size = CGSize(width: source.width, height: source.height)
|
|
33
|
+
|
|
34
|
+
DispatchQueue.global(qos: .userInitiated).async {
|
|
35
|
+
if let image = image(fromBlurhash: blurhash, size: size) {
|
|
36
|
+
DispatchQueue.main.async {
|
|
37
|
+
completedBlock?(UIImage(cgImage: image), nil, nil, true)
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
let error = makeNSError(description: "Unable to generate an image from the given blurhash")
|
|
41
|
+
completedBlock?(nil, nil, error, false)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return nil
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func shouldBlockFailedURL(with url: URL, error: Error) -> Bool {
|
|
48
|
+
// If the algorithm failed to generate an image from the url,
|
|
49
|
+
// it's not possible that next time it will work :)
|
|
50
|
+
return true
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import ExpoModulesCore
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Describes how the image should be resized to fit its container.
|
|
5
|
+
- Note: It mirrors the CSS [`object-fit`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) property.
|
|
6
|
+
*/
|
|
7
|
+
enum ContentFit: String, Enumerable {
|
|
8
|
+
/**
|
|
9
|
+
The image is scaled to maintain its aspect ratio while fitting within the container's box.
|
|
10
|
+
The entire image is made to fill the box, while preserving its aspect ratio,
|
|
11
|
+
so the image will be "letterboxed" if its aspect ratio does not match the aspect ratio of the box.
|
|
12
|
+
*/
|
|
13
|
+
case contain
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
The image is sized to maintain its aspect ratio while filling the element's entire content box.
|
|
17
|
+
If the image's aspect ratio does not match the aspect ratio of its box, then the object will be clipped to fit.
|
|
18
|
+
*/
|
|
19
|
+
case cover
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
The image is sized to fill the element's content box. The entire object will completely fill the box.
|
|
23
|
+
If the image's aspect ratio does not match the aspect ratio of its box, then the image will be stretched to fit.
|
|
24
|
+
*/
|
|
25
|
+
case fill
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
The image is not resized and is centered by default.
|
|
29
|
+
When specified, the exact position can be controlled with `ContentPosition`.
|
|
30
|
+
*/
|
|
31
|
+
case none
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
The image is sized as if `none` or `contain` were specified,
|
|
35
|
+
whichever would result in a smaller concrete image size.
|
|
36
|
+
*/
|
|
37
|
+
case scaleDown = "scale-down"
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
`ContentFit` cases can be directly translated to the native `UIView.ContentMode`
|
|
41
|
+
except `scaleDown` that needs to be handled differently at the later step of rendering.
|
|
42
|
+
*/
|
|
43
|
+
func toContentMode() -> UIView.ContentMode {
|
|
44
|
+
switch self {
|
|
45
|
+
case .contain:
|
|
46
|
+
return .scaleAspectFit
|
|
47
|
+
case .cover:
|
|
48
|
+
return .scaleAspectFill
|
|
49
|
+
case .fill:
|
|
50
|
+
return .scaleToFill
|
|
51
|
+
case .none, .scaleDown:
|
|
52
|
+
return .center
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import ExpoModulesCore
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
Represents a position value that might be either `Double` or `String`.
|
|
5
|
+
*/
|
|
6
|
+
typealias ContentPositionValue = Either<Double, String>
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
Specifies the alignment of the image within the container's box.
|
|
10
|
+
- Note: Its intention is to behave like the CSS [`object-position`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) property.
|
|
11
|
+
*/
|
|
12
|
+
struct ContentPosition: Record {
|
|
13
|
+
static let center = Self()
|
|
14
|
+
|
|
15
|
+
@Field
|
|
16
|
+
var top: ContentPositionValue?
|
|
17
|
+
|
|
18
|
+
@Field
|
|
19
|
+
var bottom: ContentPositionValue?
|
|
20
|
+
|
|
21
|
+
@Field
|
|
22
|
+
var right: ContentPositionValue?
|
|
23
|
+
|
|
24
|
+
@Field
|
|
25
|
+
var left: ContentPositionValue?
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
Returns a horizontal content offset based on the `left` or `right` field.
|
|
29
|
+
*/
|
|
30
|
+
func offsetX(contentWidth: Double, containerWidth: Double) -> Double {
|
|
31
|
+
let diff = containerWidth - contentWidth
|
|
32
|
+
|
|
33
|
+
if let leftDistance = distance(from: left) {
|
|
34
|
+
return -diff / 2 + leftDistance
|
|
35
|
+
}
|
|
36
|
+
if let rightDistance = distance(from: right) {
|
|
37
|
+
return diff / 2 - rightDistance
|
|
38
|
+
}
|
|
39
|
+
if let factor = factor(from: left) {
|
|
40
|
+
return -diff / 2 + diff * factor
|
|
41
|
+
}
|
|
42
|
+
if let factor = factor(from: right) {
|
|
43
|
+
return diff / 2 - diff * factor
|
|
44
|
+
}
|
|
45
|
+
return 0
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
Returns a vertical content offset based on the `top` or `bottom` field.
|
|
50
|
+
*/
|
|
51
|
+
func offsetY(contentHeight: Double, containerHeight: Double) -> Double {
|
|
52
|
+
let diff = containerHeight - contentHeight
|
|
53
|
+
|
|
54
|
+
if let topDistance = distance(from: top) {
|
|
55
|
+
return -diff / 2 + topDistance
|
|
56
|
+
}
|
|
57
|
+
if let bottomDistance = distance(from: bottom) {
|
|
58
|
+
return diff / 2 - bottomDistance
|
|
59
|
+
}
|
|
60
|
+
if let factor = factor(from: top) {
|
|
61
|
+
return -diff / 2 + diff * factor
|
|
62
|
+
}
|
|
63
|
+
if let factor = factor(from: bottom) {
|
|
64
|
+
return diff / 2 - diff * factor
|
|
65
|
+
}
|
|
66
|
+
return 0
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
A `CGPoint` with horizontal and vertical content offsets.
|
|
71
|
+
*/
|
|
72
|
+
func offset(contentSize: CGSize, containerSize: CGSize) -> CGPoint {
|
|
73
|
+
return CGPoint(
|
|
74
|
+
x: offsetX(contentWidth: contentSize.width, containerWidth: containerSize.width),
|
|
75
|
+
y: offsetY(contentHeight: contentSize.height, containerHeight: containerSize.height)
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
Returns a static offset from the given position value or `nil` when it cannot be cast to a `Double`.
|
|
82
|
+
*/
|
|
83
|
+
private func distance(from value: ContentPositionValue?) -> Double? {
|
|
84
|
+
if let value: Double = value?.get() {
|
|
85
|
+
return value
|
|
86
|
+
}
|
|
87
|
+
if let value: String = value?.get() {
|
|
88
|
+
return Double(value)
|
|
89
|
+
}
|
|
90
|
+
return nil
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
Returns a factor from the percentage value from the given position.
|
|
95
|
+
The value must be a string containing a number and `%` character, or equal to `"center"` which is an equivalent to `50%`.
|
|
96
|
+
*/
|
|
97
|
+
private func factor(from value: ContentPositionValue?) -> Double? {
|
|
98
|
+
guard let value: String = value?.get() else {
|
|
99
|
+
return nil
|
|
100
|
+
}
|
|
101
|
+
if value == "center" {
|
|
102
|
+
return 0.5
|
|
103
|
+
}
|
|
104
|
+
guard value.contains("%"), let percentage = Double(value.replacingOccurrences(of: "%", with: "")) else {
|
|
105
|
+
return nil
|
|
106
|
+
}
|
|
107
|
+
return percentage / 100
|
|
108
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'ExpoImage'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.description = package['description']
|
|
10
|
+
s.license = package['license']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.homepage = package['homepage']
|
|
13
|
+
s.platform = :ios, '13.0'
|
|
14
|
+
s.swift_version = '5.4'
|
|
15
|
+
s.source = { git: 'https://github.com/expo/expo.git' }
|
|
16
|
+
s.static_framework = true
|
|
17
|
+
|
|
18
|
+
s.dependency 'ExpoModulesCore'
|
|
19
|
+
s.dependency 'SDWebImage', '~> 5.17.0'
|
|
20
|
+
s.dependency 'SDWebImageWebPCoder', '~> 0.13.0'
|
|
21
|
+
s.dependency 'SDWebImageAVIFCoder', '~> 0.10.1'
|
|
22
|
+
s.dependency 'SDWebImageSVGCoder', '~> 1.7.0'
|
|
23
|
+
|
|
24
|
+
# Swift/Objective-C compatibility
|
|
25
|
+
s.pod_target_xcconfig = {
|
|
26
|
+
'DEFINES_MODULE' => 'YES',
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
s.source_files = "**/*.{h,m,swift}"
|
|
30
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import SDWebImage
|
|
4
|
+
import ExpoModulesCore
|
|
5
|
+
|
|
6
|
+
enum ImageCachePolicy: String, Enumerable {
|
|
7
|
+
case none = "none"
|
|
8
|
+
case disk = "disk"
|
|
9
|
+
case memory = "memory"
|
|
10
|
+
case memoryAndDisk = "memory-disk"
|
|
11
|
+
|
|
12
|
+
func toSdCacheType() -> SDImageCacheType {
|
|
13
|
+
switch self {
|
|
14
|
+
case .none:
|
|
15
|
+
return .none
|
|
16
|
+
case .disk:
|
|
17
|
+
return .disk
|
|
18
|
+
case .memory:
|
|
19
|
+
return .memory
|
|
20
|
+
case .memoryAndDisk:
|
|
21
|
+
return .all
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import SDWebImage
|
|
4
|
+
import ExpoModulesCore
|
|
5
|
+
|
|
6
|
+
enum ImageCacheType: String, Enumerable {
|
|
7
|
+
case none
|
|
8
|
+
case disk
|
|
9
|
+
case memory
|
|
10
|
+
|
|
11
|
+
static func fromSdCacheType(_ sdImageCacheType: SDImageCacheType) -> ImageCacheType {
|
|
12
|
+
switch sdImageCacheType {
|
|
13
|
+
case .none:
|
|
14
|
+
return .none
|
|
15
|
+
case .disk, .all:
|
|
16
|
+
return .disk
|
|
17
|
+
case .memory:
|
|
18
|
+
return .memory
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|