react-native-fast-image 8.27.3 → 8.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -276,7 +276,7 @@ Changing it restarts the animation.
276
276
  How the image is filtered when it's drawn smaller or larger than its size (like CSS's `image-rendering`):
277
277
 
278
278
  - `'auto'` **(Default)** - The platform's usual filtering.
279
- - `'smooth'` - iOS only. Keeps a large image drawn much smaller than its size (e.g. a big photo as a thumbnail, or fine lines and text) from looking jagged or noisy. **It uses more memory:** the image is also kept at smaller sizes for drawing, about a third more than the decoded image. On Android it's the same as `'auto'` (images are already decoded at about the view's size there).
279
+ - `'smooth'` - iOS only. Keeps a large image drawn much smaller than its size (e.g. a big photo as a thumbnail, or fine lines and text) from looking jagged or noisy. Such an image is already decoded at about the view's size by default (see `downsample`), so this is for images shown at less than half their size with `downsample={false}`, or a little smaller than their size. **It uses more memory:** the image is also kept at smaller sizes for drawing, about a third more than the decoded image. On Android it's the same as `'auto'` (images are always decoded at about the view's size there).
280
280
  - `'pixelated'` - Sharp pixels, without smoothing, e.g. for pixel art drawn larger than its size. On Android, animated images are still smoothed.
281
281
 
282
282
  ---
@@ -312,9 +312,12 @@ Downloads, local files (`file://`, `content://`) and bundled images (`require()`
312
312
 
313
313
  iOS only. Decodes a large image at about the size it's shown at, instead of at full size, so it takes much less memory.
314
314
 
315
- Use it when you show images much larger than their views and can't get them at the right size, e.g. user uploads or other people's URLs in a list. If you control the images, serve them at the size they're shown instead (resized on your server or by an image CDN), which also saves bandwidth.
315
+ - `true` **(Default)** - An image at least twice the size its view needs is decoded at about the view's size. If the view grows, the image is decoded again for its new size (from the disk cache).
316
+ - `false` - Images are decoded at full size, e.g. for an image that's zoomed in on with a transform (a pinch-to-zoom viewer), which would otherwise show the smaller copy enlarged.
316
317
 
317
- Decoding a smaller copy can take a little longer, so use it where the memory matters. Needs SDWebImage 5.19.7 or later. Photo library images are always decoded this way. On Android images are already decoded at about the view's size.
318
+ It doesn't change `onLoad`'s width and height (the image's own size) or the cached file. Needs SDWebImage 5.19.7 or later: before 5.19 images are decoded at full size, and 5.19.0 to 5.19.6 show photos stored sideways with an EXIF orientation (most phone photos) sideways. Photo library images are always decoded this way, and on Android images are always decoded at about the view's size.
319
+
320
+ If you control the images, serve them at the size they're shown (resized on your server or by an image CDN), which also saves bandwidth.
318
321
 
319
322
  ---
320
323
 
package/dist/index.d.ts CHANGED
@@ -161,9 +161,9 @@ export interface FastImageProps extends AccessibilityProps, ViewProps {
161
161
  transition?: boolean | number | Transition | null;
162
162
  /**
163
163
  * iOS only. Decodes a large image at about the size it's shown at, so it
164
- * takes much less memory. For images much larger than their views that
165
- * you can't get at the right size (if you can, resize them on your server
166
- * or with an image CDN instead). See the README.
164
+ * takes much less memory. `true` (default). `false` decodes images at
165
+ * full size, e.g. for an image that's zoomed in on with a transform. See
166
+ * the README.
167
167
  */
168
168
  downsample?: boolean;
169
169
  /**
@@ -10,12 +10,16 @@
10
10
  // the image's header before it decodes, as React Native's Image does.
11
11
  @interface FFFDownsampledImage : SDAnimatedImage
12
12
 
13
- // The url to load a source's url with, when it's downsampled.
14
- + (NSURL*) loadURLForURL: (NSURL*)url;
15
-
16
13
  // Sets a load's context to decode the image for a box (in pixels) to cover
17
- // or fit in. `key` is the source's cache key (its url, or its cacheKey).
18
- + (void) addToContext: (SDWebImageMutableContext*)context forKey: (NSString*)key box: (CGSize)box cover: (BOOL)cover;
14
+ // or fit in.
15
+ + (void) addToContext: (SDWebImageMutableContext*)context box: (CGSize)box cover: (BOOL)cover;
16
+
17
+ // Sets a load's context to decode the image at full size, through this class
18
+ // when it's supported. Every FastImage load uses it, so loads of the same url
19
+ // can share a download: SDWebImage's downloader decodes each load of a
20
+ // download with the first load's image class (and each with its own size),
21
+ // and SDWebImage's own thumbnail decoding can't cover a box.
22
+ + (void) addFullSizeToContext: (SDWebImageMutableContext*)context;
19
23
 
20
24
  // The size of the full image (in points, like UIImage's size) that an image
21
25
  // loaded this way was decoded from, for onLoad, or zero for other images.
@@ -2,13 +2,12 @@
2
2
  #import <ImageIO/ImageIO.h>
3
3
  #import <SDWebImage/SDImageCoder.h>
4
4
  #import <SDWebImage/SDImageCacheDefine.h>
5
- #import <SDWebImage/SDWebImageCacheKeyFilter.h>
6
5
  #import <SDWebImage/UIImage+Metadata.h>
6
+ #import <SDWebImage/NSData+ImageContentType.h>
7
+ #import <SDWebImage/SDImageCodersManager.h>
7
8
 
8
9
  // The decode option that carries the full image's size to the view.
9
10
  static SDImageCoderOption const FFFDecodeSourceSize = @"FFFDecodeSourceSize";
10
- // Added to the url's fragment, which isn't sent to the server.
11
- static NSString* const FFFDownsampledFragment = @"fastimage-downsampled";
12
11
 
13
12
  // The image's size in pixels as it's shown (EXIF orientations 5 to 8 turn it
14
13
  // sideways), from its header, or zero if ImageIO can't read it.
@@ -83,38 +82,20 @@ static CGSize FFFPixelSize(NSData* data) {
83
82
  return supported;
84
83
  }
85
84
 
86
- + (NSURL*) loadURLForURL: (NSURL*)url {
87
- // SDWebImage's downloader shares a download between loads of the same
88
- // url, and decodes each load's image with the first load's image class.
89
- // After a load that isn't downsampled (e.g. a preload), this class
90
- // wouldn't be used, and the box would be decoded as SDWebImage does (to
91
- // fill it, stretched). With its own url, a downsampled load only shares
92
- // downloads with other downsampled ones. Not a photo library url, which
93
- // isn't downloaded, and whose loader reads everything after ph:// as the
94
- // photo's identifier.
95
- if ([url.scheme isEqualToString: @"ph"]) {
96
- return url;
85
+ + (void) addFullSizeToContext: (SDWebImageMutableContext*)context {
86
+ if (![self isSupported]) {
87
+ context[SDWebImageContextAnimatedImageClass] = [SDAnimatedImage class];
88
+ return;
97
89
  }
98
- NSURLComponents* components = [NSURLComponents componentsWithURL: url resolvingAgainstBaseURL: NO];
99
- if (!components) {
100
- return url;
101
- }
102
- components.fragment = components.fragment.length > 0
103
- ? [components.fragment stringByAppendingFormat: @"-%@", FFFDownsampledFragment]
104
- : FFFDownsampledFragment;
105
- return components.URL ?: url;
90
+ context[SDWebImageContextAnimatedImageClass] = [FFFDownsampledImage class];
91
+ context[SDWebImageContextImageDecodeOptions] = @{FFFDecodeSourceSize: [FFFSourceSize new]};
106
92
  }
107
93
 
108
- + (void) addToContext: (SDWebImageMutableContext*)context forKey: (NSString*)key box: (CGSize)box cover: (BOOL)cover {
94
+ + (void) addToContext: (SDWebImageMutableContext*)context box: (CGSize)box cover: (BOOL)cover {
109
95
  context[SDWebImageContextAnimatedImageClass] = [FFFDownsampledImage class];
110
- // Cached under the source's own key (not the url from loadURLForURL:),
111
- // so the disk cache keeps one download for every size and for loads
112
- // that aren't downsampled.
113
- context[SDWebImageContextCacheKeyFilter] = [SDWebImageCacheKeyFilter cacheKeyFilterWithBlock: ^NSString* (NSURL* _Nonnull loadURL) {
114
- return key;
115
- }];
116
- // The memory cache key is the url with these (SDWebImage's thumbnail
117
- // key), so views of other sizes don't get this image.
96
+ // The memory cache key is the source's key with these (SDWebImage's
97
+ // thumbnail key), so views of other sizes don't get this image. The disk
98
+ // cache keeps the downloaded file under the source's key, for every size.
118
99
  context[SDWebImageContextImageThumbnailPixelSize] = [NSValue valueWithCGSize: box];
119
100
  context[SDWebImageContextImagePreserveAspectRatio] = @(!cover);
120
101
  context[SDWebImageContextImageDecodeOptions] = @{FFFDecodeSourceSize: [FFFSourceSize new]};
@@ -129,6 +110,22 @@ static CGSize FFFPixelSize(NSData* data) {
129
110
  }
130
111
 
131
112
  - (instancetype) initWithData: (NSData*)data scale: (CGFloat)scale options: (SDImageCoderOptions*)options {
113
+ // An SVG isn't decoded smaller: it's a vector image, drawn at any size.
114
+ // This class can't decode it, and SDWebImage would then give it to the
115
+ // SVG coder with the box, which draws it into a bitmap that size. Decoded
116
+ // as without downsample instead (this init can return another image).
117
+ if ([NSData sd_imageFormatForImageData: data] == SDImageFormatSVG) {
118
+ NSMutableDictionary* vectorOptions = options ? [options mutableCopy] : [NSMutableDictionary dictionary];
119
+ [vectorOptions removeObjectForKey: SDImageCoderDecodeThumbnailPixelSize];
120
+ UIImage* image = [[SDImageCodersManager sharedManager] decodedImageWithData: data options: vectorOptions];
121
+ FFFSourceSize* sourceSize = options[FFFDecodeSourceSize];
122
+ if (image && [sourceSize isKindOfClass: [FFFSourceSize class]]) {
123
+ sourceSize.size = image.size;
124
+ }
125
+ self = (id) image;
126
+ return self;
127
+ }
128
+
132
129
  NSValue* boxValue = options[SDImageCoderDecodeThumbnailPixelSize];
133
130
  CGSize box = boxValue ? boxValue.CGSizeValue : CGSizeZero;
134
131
  NSNumber* preserveAspectRatio = options[SDImageCoderDecodePreserveAspectRatio];
@@ -88,6 +88,9 @@ static UIImage* FFFBlurredImage(UIImage* image, CGFloat scale, CGFloat radius, B
88
88
  // rather than dimming like the system's controls.
89
89
  self.tintAdjustmentMode = UIViewTintAdjustmentModeNormal;
90
90
  _loopCount = -1;
91
+ // Images are decoded at about the size they're shown at unless
92
+ // downsample is false, as on Android.
93
+ _downsample = YES;
91
94
  return self;
92
95
  }
93
96
 
@@ -991,8 +994,7 @@ NSString *FFFErrorMessage(NSError *error)
991
994
  }
992
995
  CGSize box = [self decodeBox];
993
996
  SDWebImageContext* context = [self contextForSource: source box: box cover: [self decodeCovers]];
994
- NSURL* url = CGSizeEqualToSize(box, CGSizeZero) ? source.url : [FFFDownsampledImage loadURLForURL: source.url];
995
- NSString* key = [manager cacheKeyForURL: url context: context];
997
+ NSString* key = [manager cacheKeyForURL: source.url context: context];
996
998
  return [(SDImageCache*) manager.imageCache imageFromMemoryCacheForKey: key] != nil;
997
999
  }
998
1000
 
@@ -1002,15 +1004,14 @@ NSString *FFFErrorMessage(NSError *error)
1002
1004
  context[SDWebImageContextImageLoader] = source.imageLoader;
1003
1005
  context[SDWebImageContextCacheKeyFilter] = source.cacheKeyFilter;
1004
1006
  if (CGSizeEqualToSize(box, CGSizeZero)) {
1005
- context[SDWebImageContextAnimatedImageClass] = [SDAnimatedImage class];
1007
+ [FFFDownsampledImage addFullSizeToContext: context];
1006
1008
  if (!source.memoryCache) {
1007
1009
  // Only on disk, also when it comes from there.
1008
1010
  context[SDWebImageContextStoreCacheType] = @(SDImageCacheTypeDisk);
1009
1011
  }
1010
1012
  return context;
1011
1013
  }
1012
- NSString* key = source.cacheKeyFilter ? source.cacheKey : source.url.absoluteString;
1013
- [FFFDownsampledImage addToContext: context forKey: key box: box cover: cover];
1014
+ [FFFDownsampledImage addToContext: context box: box cover: cover];
1014
1015
  if ([source isPhotoLibrary]) {
1015
1016
  // Photos makes the photo at the size asked for, with no file
1016
1017
  // downloaded: SDWebImage would keep this smaller copy on disk as the
@@ -1058,7 +1059,7 @@ NSString *FFFErrorMessage(NSError *error)
1058
1059
  };
1059
1060
  }
1060
1061
  CFTimeInterval startedAt = CACurrentMediaTime();
1061
- NSURL* url = context[SDWebImageContextImageThumbnailPixelSize] ? [FFFDownsampledImage loadURLForURL: source.url] : source.url;
1062
+ NSURL* url = source.url;
1062
1063
  if (!events) {
1063
1064
  // Only this load's image: SDWebImage would clear the view (to the
1064
1065
  // placeholder) if it fails, and a cancelled load can still complete.
@@ -1,5 +1,6 @@
1
1
  #import "FFFastImageViewManager.h"
2
2
  #import "FFFastImageView.h"
3
+ #import "FFFDownsampledImage.h"
3
4
 
4
5
  #import <SDWebImage/SDImageCache.h>
5
6
  #import <SDWebImage/SDWebImageManager.h>
@@ -128,13 +129,16 @@ RCT_REMAP_VIEW_PROPERTY(tintColor, imageColor, UIColor)
128
129
  static NSMutableArray<dispatch_block_t> *FFFPendingPreloads;
129
130
  static NSUInteger FFFPreloadsInFlight;
130
131
 
131
- // A preload's context: the source's headers and cache key.
132
+ // A preload's context: the source's headers and cache key, and the image
133
+ // class views use, so a view of the same url can share its download (see
134
+ // FFFDownsampledImage).
132
135
  static SDWebImageMutableContext *FFFPreloadContext(FFFastImageSource *source)
133
136
  {
134
137
  SDWebImageMutableContext *context = [NSMutableDictionary dictionary];
135
138
  context[SDWebImageContextDownloadRequestModifier] = source.requestModifier;
136
139
  context[SDWebImageContextImageLoader] = source.imageLoader;
137
140
  context[SDWebImageContextCacheKeyFilter] = source.cacheKeyFilter;
141
+ [FFFDownsampledImage addFullSizeToContext:context];
138
142
  return context;
139
143
  }
140
144
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-fast-image",
3
- "version": "8.27.3",
3
+ "version": "8.28.0",
4
4
  "description": "FastImage, performant React Native image component.",
5
5
  "keywords": [
6
6
  "cache",