2015-03-23 22:07:33 +00:00
|
|
|
/**
|
|
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*/
|
2015-03-11 02:11:28 +00:00
|
|
|
|
2015-07-14 11:06:17 +00:00
|
|
|
#import <UIKit/UIKit.h>
|
2015-03-11 02:11:28 +00:00
|
|
|
|
2015-07-27 15:48:31 +00:00
|
|
|
#import "RCTBridge.h"
|
2015-09-02 15:25:10 +00:00
|
|
|
#import "RCTURLRequestHandler.h"
|
2016-01-20 19:03:22 +00:00
|
|
|
#import "RCTResizeMode.h"
|
2015-07-27 15:48:31 +00:00
|
|
|
|
2015-03-11 02:11:28 +00:00
|
|
|
@class ALAssetsLibrary;
|
|
|
|
|
2015-07-27 20:46:59 +00:00
|
|
|
typedef void (^RCTImageLoaderProgressBlock)(int64_t progress, int64_t total);
|
2015-09-04 11:35:44 +00:00
|
|
|
typedef void (^RCTImageLoaderCompletionBlock)(NSError *error, UIImage *image);
|
2015-07-15 20:17:13 +00:00
|
|
|
typedef void (^RCTImageLoaderCancellationBlock)(void);
|
|
|
|
|
2015-09-04 11:35:44 +00:00
|
|
|
@interface UIImage (React)
|
|
|
|
|
|
|
|
@property (nonatomic, copy) CAKeyframeAnimation *reactKeyframeAnimation;
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
2015-09-02 15:25:10 +00:00
|
|
|
@interface RCTImageLoader : NSObject <RCTBridgeModule, RCTURLRequestHandler>
|
2015-05-11 20:08:39 +00:00
|
|
|
|
2016-02-16 20:41:20 +00:00
|
|
|
/**
|
|
|
|
* The maximum number of concurrent image loading tasks. Loading and decoding
|
|
|
|
* images can consume a lot of memory, so setting this to a higher value may
|
|
|
|
* cause memory to spike. If you are seeing out-of-memory crashes, try reducing
|
|
|
|
* this value.
|
|
|
|
*/
|
|
|
|
@property (nonatomic, assign) NSUInteger maxConcurrentLoadingTasks;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The maximum number of concurrent image decoding tasks. Decoding large
|
|
|
|
* images can be especially CPU and memory intensive, so if your are decoding a
|
|
|
|
* lot of large images in your app, you may wish to adjust this value.
|
|
|
|
*/
|
|
|
|
@property (nonatomic, assign) NSUInteger maxConcurrentDecodingTasks;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Decoding large images can use a lot of memory, and potentially cause the app
|
|
|
|
* to crash. This value allows you to throttle the amount of memory used by the
|
|
|
|
* decoder independently of the number of concurrent threads. This means you can
|
|
|
|
* still decode a lot of small images in parallel, without allowing the decoder
|
|
|
|
* to try to decompress multiple huge images at once. Note that this value is
|
|
|
|
* only a hint, and not an indicator of the total memory used by the app.
|
|
|
|
*/
|
|
|
|
@property (nonatomic, assign) NSUInteger maxConcurrentDecodingBytes;
|
|
|
|
|
2015-05-11 20:08:39 +00:00
|
|
|
/**
|
2015-07-27 15:48:31 +00:00
|
|
|
* Loads the specified image at the highest available resolution.
|
2015-10-20 12:00:50 +00:00
|
|
|
* Can be called from any thread, will call back on an unspecified thread.
|
2015-05-11 20:08:39 +00:00
|
|
|
*/
|
2015-07-27 15:48:31 +00:00
|
|
|
- (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag
|
2015-07-15 20:17:13 +00:00
|
|
|
callback:(RCTImageLoaderCompletionBlock)callback;
|
2015-03-11 02:11:28 +00:00
|
|
|
|
2015-07-14 11:06:17 +00:00
|
|
|
/**
|
|
|
|
* As above, but includes target size, scale and resizeMode, which are used to
|
|
|
|
* select the optimal dimensions for the loaded image.
|
|
|
|
*/
|
2015-07-27 15:48:31 +00:00
|
|
|
- (RCTImageLoaderCancellationBlock)loadImageWithTag:(NSString *)imageTag
|
2015-07-15 20:17:13 +00:00
|
|
|
size:(CGSize)size
|
|
|
|
scale:(CGFloat)scale
|
2016-01-20 19:03:22 +00:00
|
|
|
resizeMode:(RCTResizeMode)resizeMode
|
2015-07-27 20:46:59 +00:00
|
|
|
progressBlock:(RCTImageLoaderProgressBlock)progressBlock
|
|
|
|
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock;
|
2015-07-14 11:06:17 +00:00
|
|
|
|
2016-01-20 19:03:22 +00:00
|
|
|
/**
|
|
|
|
* Loads an image without clipping the result to fit - used by RCTImageView.
|
|
|
|
*/
|
|
|
|
- (RCTImageLoaderCancellationBlock)loadImageWithoutClipping:(NSString *)imageTag
|
|
|
|
size:(CGSize)size
|
|
|
|
scale:(CGFloat)scale
|
|
|
|
resizeMode:(RCTResizeMode)resizeMode
|
|
|
|
progressBlock:(RCTImageLoaderProgressBlock)progressBlock
|
|
|
|
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock;
|
|
|
|
|
2015-07-14 11:06:17 +00:00
|
|
|
/**
|
2015-09-02 15:25:10 +00:00
|
|
|
* Finds an appropriate image decoder and passes the target size, scale and
|
2015-10-19 16:04:54 +00:00
|
|
|
* resizeMode for optimal image decoding. Can be called from any thread,
|
|
|
|
* will call callback on an unspecified thread.
|
2015-07-14 11:06:17 +00:00
|
|
|
*/
|
2015-09-02 15:25:10 +00:00
|
|
|
- (RCTImageLoaderCancellationBlock)decodeImageData:(NSData *)imageData
|
|
|
|
size:(CGSize)size
|
|
|
|
scale:(CGFloat)scale
|
2016-01-20 19:03:22 +00:00
|
|
|
resizeMode:(RCTResizeMode)resizeMode
|
2015-09-02 15:25:10 +00:00
|
|
|
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock;
|
2015-07-15 20:17:13 +00:00
|
|
|
|
2016-03-03 10:20:20 +00:00
|
|
|
/**
|
|
|
|
* Decodes an image without clipping the result to fit.
|
|
|
|
*/
|
|
|
|
- (RCTImageLoaderCancellationBlock)decodeImageDataWithoutClipping:(NSData *)data
|
|
|
|
size:(CGSize)size
|
|
|
|
scale:(CGFloat)scale
|
|
|
|
resizeMode:(RCTResizeMode)resizeMode
|
|
|
|
completionBlock:(RCTImageLoaderCompletionBlock)completionBlock;
|
|
|
|
|
Added getImageSize method
Summary:
public
This diff adds a `getSize()` method to `Image` to retrieve the width and height of an image prior to displaying it. This is useful when working with images from uncontrolled sources, and has been a much-requested feature.
In order to retrieve the image dimensions, the image may first need to be loaded or downloaded, after which it will be cached. This means that in principle you could use this method to preload images, however it is not optimized for that purpose, and may in future be implemented in a way that does not fully load/download the image data.
A fully supported way to preload images will be provided in a future diff.
The API (separate success and failure callbacks) is far from ideal, but until we agree on a unified standard, this was the most conventional way I could think of to implement it. If it returned a promise or something similar, it would be unique among all such APIS in the framework.
Please note that this has been a long time coming, in part due to much bikeshedding about what the API should look like, so while it's not unlikely that the API may change in future, I think having *some* way to do this is better than waiting until we can define the "perfect" way.
Reviewed By: vjeux
Differential Revision: D2797365
fb-gh-sync-id: 11eb1b8547773b1f8be0bc55ddf6dfedebf7fc0a
2016-01-01 02:50:26 +00:00
|
|
|
/**
|
|
|
|
* Get image size, in pixels. This method will do the least work possible to get
|
|
|
|
* the information, and won't decode the image if it doesn't have to.
|
|
|
|
*/
|
|
|
|
- (RCTImageLoaderCancellationBlock)getImageSize:(NSString *)imageTag
|
|
|
|
block:(void(^)(NSError *error, CGSize size))completionBlock;
|
|
|
|
|
2015-03-11 02:11:28 +00:00
|
|
|
@end
|
2015-07-27 15:48:31 +00:00
|
|
|
|
|
|
|
@interface RCTBridge (RCTImageLoader)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The shared image loader instance
|
|
|
|
*/
|
|
|
|
@property (nonatomic, readonly) RCTImageLoader *imageLoader;
|
|
|
|
|
2015-09-02 15:25:10 +00:00
|
|
|
@end
|
|
|
|
|
|
|
|
/**
|
2015-10-19 16:04:54 +00:00
|
|
|
* Provides the interface needed to register an image loader. Image data
|
2015-09-02 15:25:10 +00:00
|
|
|
* loaders are also bridge modules, so should be registered using
|
|
|
|
* RCT_EXPORT_MODULE().
|
|
|
|
*/
|
|
|
|
@protocol RCTImageURLLoader <RCTBridgeModule>
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Indicates whether this data loader is capable of processing the specified
|
|
|
|
* request URL. Typically the handler would examine the scheme/protocol of the
|
|
|
|
* URL to determine this.
|
|
|
|
*/
|
|
|
|
- (BOOL)canLoadImageURL:(NSURL *)requestURL;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Send a network request to load the request URL. The method should call the
|
|
|
|
* progressHandler (if applicable) and the completionHandler when the request
|
|
|
|
* has finished. The method should also return a cancellation block, if
|
|
|
|
* applicable.
|
|
|
|
*/
|
2015-10-19 16:04:54 +00:00
|
|
|
- (RCTImageLoaderCancellationBlock)loadImageForURL:(NSURL *)imageURL
|
|
|
|
size:(CGSize)size
|
|
|
|
scale:(CGFloat)scale
|
2016-01-20 19:03:22 +00:00
|
|
|
resizeMode:(RCTResizeMode)resizeMode
|
2015-10-19 16:04:54 +00:00
|
|
|
progressHandler:(RCTImageLoaderProgressBlock)progressHandler
|
|
|
|
completionHandler:(RCTImageLoaderCompletionBlock)completionHandler;
|
2015-09-02 15:25:10 +00:00
|
|
|
|
|
|
|
@optional
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If more than one RCTImageURLLoader responds YES to `-canLoadImageURL:`
|
2015-10-19 16:04:54 +00:00
|
|
|
* then `loaderPriority` is used to determine which one to use. The loader
|
2015-09-02 15:25:10 +00:00
|
|
|
* with the highest priority will be selected. Default priority is zero. If
|
2015-10-19 16:04:54 +00:00
|
|
|
* two or more valid loaders have the same priority, the selection order is
|
2015-09-02 15:25:10 +00:00
|
|
|
* undefined.
|
|
|
|
*/
|
2015-10-19 16:04:54 +00:00
|
|
|
- (float)loaderPriority;
|
2015-09-02 15:25:10 +00:00
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Provides the interface needed to register an image decoder. Image decoders
|
|
|
|
* are also bridge modules, so should be registered using RCT_EXPORT_MODULE().
|
|
|
|
*/
|
2015-10-19 16:04:54 +00:00
|
|
|
@protocol RCTImageDataDecoder <RCTBridgeModule>
|
2015-09-02 15:25:10 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Indicates whether this handler is capable of decoding the specified data.
|
|
|
|
* Typically the handler would examine some sort of header data to determine
|
|
|
|
* this.
|
|
|
|
*/
|
|
|
|
- (BOOL)canDecodeImageData:(NSData *)imageData;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Decode an image from the data object. The method should call the
|
|
|
|
* completionHandler when the decoding operation has finished. The method
|
|
|
|
* should also return a cancellation block, if applicable.
|
|
|
|
*/
|
2015-10-19 16:04:54 +00:00
|
|
|
- (RCTImageLoaderCancellationBlock)decodeImageData:(NSData *)imageData
|
|
|
|
size:(CGSize)size
|
|
|
|
scale:(CGFloat)scale
|
2016-01-20 19:03:22 +00:00
|
|
|
resizeMode:(RCTResizeMode)resizeMode
|
2015-10-19 16:04:54 +00:00
|
|
|
completionHandler:(RCTImageLoaderCompletionBlock)completionHandler;
|
2015-09-02 15:25:10 +00:00
|
|
|
|
|
|
|
@optional
|
|
|
|
|
2015-07-27 15:48:31 +00:00
|
|
|
/**
|
2015-10-19 16:04:54 +00:00
|
|
|
* If more than one RCTImageDataDecoder responds YES to `-canDecodeImageData:`
|
|
|
|
* then `decoderPriority` is used to determine which one to use. The decoder
|
|
|
|
* with the highest priority will be selected. Default priority is zero.
|
|
|
|
* If two or more valid decoders have the same priority, the selection order is
|
2015-09-02 15:25:10 +00:00
|
|
|
* undefined.
|
2015-07-27 15:48:31 +00:00
|
|
|
*/
|
2015-10-19 16:04:54 +00:00
|
|
|
- (float)decoderPriority;
|
2015-07-27 15:48:31 +00:00
|
|
|
|
|
|
|
@end
|