Browse Source

swift api compatibility

ibireme 9 years ago
parent
commit
d82174cc79

+ 8 - 4
Demo/YYTextDemo/YYImage/YYAnimatedImageView.h

@@ -11,6 +11,8 @@
 
 
 #import <UIKit/UIKit.h>
 #import <UIKit/UIKit.h>
 
 
+NS_ASSUME_NONNULL_BEGIN
+
 /**
 /**
  An image view for displaying animated image.
  An image view for displaying animated image.
  
  
@@ -38,7 +40,7 @@
  
  
  The default value is `YES`.
  The default value is `YES`.
  */
  */
-@property (nonatomic, assign) BOOL autoPlayAnimatedImage;
+@property (nonatomic) BOOL autoPlayAnimatedImage;
 
 
 /**
 /**
  Index of the currently displayed frame (index from 0).
  Index of the currently displayed frame (index from 0).
@@ -48,7 +50,7 @@
  
  
  You can add an observer to this property to observe the playing status.
  You can add an observer to this property to observe the playing status.
  */
  */
-@property (nonatomic, assign) NSUInteger currentAnimatedImageIndex;
+@property (nonatomic) NSUInteger currentAnimatedImageIndex;
 
 
 /**
 /**
  Whether the image view is playing animation currently.
  Whether the image view is playing animation currently.
@@ -76,7 +78,7 @@
  When receive memory warning or app enter background, the buffer will be released 
  When receive memory warning or app enter background, the buffer will be released 
  immediately, and may grow back at the right time.
  immediately, and may grow back at the right time.
  */
  */
-@property (nonatomic, assign) NSUInteger maxBufferSize;
+@property (nonatomic) NSUInteger maxBufferSize;
 
 
 @end
 @end
 
 
@@ -107,7 +109,7 @@
 /// Returns the frame image from a specified index.
 /// Returns the frame image from a specified index.
 /// This method may be called on background thread.
 /// This method may be called on background thread.
 /// @param index  Frame index (zero based).
 /// @param index  Frame index (zero based).
-- (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index;
+- (nullable UIImage *)animatedImageFrameAtIndex:(NSUInteger)index;
 
 
 /// Returns the frames's duration from a specified index.
 /// Returns the frames's duration from a specified index.
 /// @param index  Frame index (zero based).
 /// @param index  Frame index (zero based).
@@ -119,3 +121,5 @@
 /// It may used to display sprite animation with a single image (sprite sheet).
 /// It may used to display sprite animation with a single image (sprite sheet).
 - (CGRect)animatedImageContentsRectAtIndex:(NSUInteger)index;
 - (CGRect)animatedImageContentsRectAtIndex:(NSUInteger)index;
 @end
 @end
+
+NS_ASSUME_NONNULL_END

+ 16 - 7
Demo/YYTextDemo/YYImage/YYAnimatedImageView.m

@@ -135,7 +135,7 @@ typedef NS_ENUM(NSUInteger, YYAnimatedImageType) {
     NSUInteger _curIndex; ///< current frame index (from 0)
     NSUInteger _curIndex; ///< current frame index (from 0)
     NSUInteger _totalFrameCount; ///< total frame count
     NSUInteger _totalFrameCount; ///< total frame count
     
     
-    BOOL _loopEnd; ///< weather the loop is end.
+    BOOL _loopEnd; ///< whether the loop is end.
     NSUInteger _curLoop; ///< current loop count (from 0)
     NSUInteger _curLoop; ///< current loop count (from 0)
     NSUInteger _totalLoop; ///< total loop count, 0 means infinity
     NSUInteger _totalLoop; ///< total loop count, 0 means infinity
     
     
@@ -165,22 +165,28 @@ typedef NS_ENUM(NSUInteger, YYAnimatedImageType) {
     if ([self isCancelled]) return;
     if ([self isCancelled]) return;
     view->_incrBufferCount++;
     view->_incrBufferCount++;
     if (view->_incrBufferCount == 0) [view calcMaxBufferCount];
     if (view->_incrBufferCount == 0) [view calcMaxBufferCount];
-    if ((int)view->_incrBufferCount > (int)view->_maxBufferCount) {
+    if (view->_incrBufferCount > (NSInteger)view->_maxBufferCount) {
         view->_incrBufferCount = view->_maxBufferCount;
         view->_incrBufferCount = view->_maxBufferCount;
     }
     }
     NSUInteger idx = _nextIndex;
     NSUInteger idx = _nextIndex;
     NSUInteger max = view->_incrBufferCount < 1 ? 1 : view->_incrBufferCount;
     NSUInteger max = view->_incrBufferCount < 1 ? 1 : view->_incrBufferCount;
     NSUInteger total = view->_totalFrameCount;
     NSUInteger total = view->_totalFrameCount;
+    view = nil;
+    
     for (int i = 0; i < max; i++, idx++) {
     for (int i = 0; i < max; i++, idx++) {
         @autoreleasepool {
         @autoreleasepool {
             if (idx >= total) idx = 0;
             if (idx >= total) idx = 0;
             if ([self isCancelled]) break;
             if ([self isCancelled]) break;
+            __strong YYAnimatedImageView *view = _view;
+            if (!view) break;
             LOCK_VIEW(BOOL miss = (view->_buffer[@(idx)] == nil));
             LOCK_VIEW(BOOL miss = (view->_buffer[@(idx)] == nil));
+            
             if (miss) {
             if (miss) {
                 UIImage *img = [_curImage animatedImageFrameAtIndex:idx];
                 UIImage *img = [_curImage animatedImageFrameAtIndex:idx];
-                img = [img yy_imageByDecoded];
+                img = img.yy_imageByDecoded;
                 if ([self isCancelled]) break;
                 if ([self isCancelled]) break;
                 LOCK_VIEW(view->_buffer[@(idx)] = img ? img : [NSNull null]);
                 LOCK_VIEW(view->_buffer[@(idx)] = img ? img : [NSNull null]);
+                view = nil;
             }
             }
         }
         }
     }
     }
@@ -373,16 +379,18 @@ typedef NS_ENUM(NSUInteger, YYAnimatedImageType) {
 
 
 // dynamically adjust buffer size for current memory.
 // dynamically adjust buffer size for current memory.
 - (void)calcMaxBufferCount {
 - (void)calcMaxBufferCount {
-    NSUInteger bytes = _curAnimatedImage.animatedImageBytesPerFrame;
-    if (bytes == 0) bytes = 1;
+    int64_t bytes = (int64_t)_curAnimatedImage.animatedImageBytesPerFrame;
+    if (bytes == 0) bytes = 1024;
     
     
     int64_t total = _YYDeviceMemoryTotal();
     int64_t total = _YYDeviceMemoryTotal();
     int64_t free = _YYDeviceMemoryFree();
     int64_t free = _YYDeviceMemoryFree();
     int64_t max = MIN(total * 0.2, free * 0.6);
     int64_t max = MIN(total * 0.2, free * 0.6);
     max = MAX(max, BUFFER_SIZE);
     max = MAX(max, BUFFER_SIZE);
     if (_maxBufferSize) max = max > _maxBufferSize ? _maxBufferSize : max;
     if (_maxBufferSize) max = max > _maxBufferSize ? _maxBufferSize : max;
-    _maxBufferCount = (float)max / (float)bytes;
-    if (_maxBufferCount == 0) _maxBufferCount = 1;
+    double maxBufferCount = (double)max / (double)bytes;
+    if (maxBufferCount < 1) maxBufferCount = 1;
+    else if (maxBufferCount > 512) maxBufferCount = 512;
+    _maxBufferCount = maxBufferCount;
 }
 }
 
 
 - (void)dealloc {
 - (void)dealloc {
@@ -398,6 +406,7 @@ typedef NS_ENUM(NSUInteger, YYAnimatedImageType) {
 
 
 - (void)stopAnimating {
 - (void)stopAnimating {
     [super stopAnimating];
     [super stopAnimating];
+    [_requestQueue cancelAllOperations];
     _link.paused = YES;
     _link.paused = YES;
     self.currentIsPlayingAnimation = NO;
     self.currentIsPlayingAnimation = NO;
 }
 }

+ 16 - 4
Demo/YYTextDemo/YYImage/YYFrameImage.h

@@ -19,6 +19,8 @@
 #import "YYAnimatedImageView.h"
 #import "YYAnimatedImageView.h"
 #endif
 #endif
 
 
+NS_ASSUME_NONNULL_BEGIN
+
 /**
 /**
  An image to display frame-based animation.
  An image to display frame-based animation.
  
  
@@ -49,7 +51,9 @@
  
  
  @return An initialized YYFrameImage object, or nil when an error occurs.
  @return An initialized YYFrameImage object, or nil when an error occurs.
  */
  */
-- (instancetype)initWithImagePaths:(NSArray *)paths oneFrameDuration:(NSTimeInterval)oneFrameDuration loopCount:(NSUInteger)loopCount;
+- (nullable instancetype)initWithImagePaths:(NSArray<NSString *> *)paths
+                           oneFrameDuration:(NSTimeInterval)oneFrameDuration
+                                  loopCount:(NSUInteger)loopCount;
 
 
 /**
 /**
  Create a frame animated image from files.
  Create a frame animated image from files.
@@ -65,7 +69,9 @@
  
  
  @return An initialized YYFrameImage object, or nil when an error occurs.
  @return An initialized YYFrameImage object, or nil when an error occurs.
  */
  */
-- (instancetype)initWithImagePaths:(NSArray *)paths frameDurations:(NSArray *)frameDurations loopCount:(NSUInteger)loopCount;
+- (nullable instancetype)initWithImagePaths:(NSArray<NSString *> *)paths
+                             frameDurations:(NSArray<NSNumber *> *)frameDurations
+                                  loopCount:(NSUInteger)loopCount;
 
 
 /**
 /**
  Create a frame animated image from an array of data.
  Create a frame animated image from an array of data.
@@ -78,7 +84,9 @@
  
  
  @return An initialized YYFrameImage object, or nil when an error occurs.
  @return An initialized YYFrameImage object, or nil when an error occurs.
  */
  */
-- (instancetype)initWithImageDataArray:(NSArray *)dataArray oneFrameDuration:(NSTimeInterval)oneFrameDuration loopCount:(NSUInteger)loopCount;
+- (nullable instancetype)initWithImageDataArray:(NSArray<NSData *> *)dataArray
+                               oneFrameDuration:(NSTimeInterval)oneFrameDuration
+                                      loopCount:(NSUInteger)loopCount;
 
 
 /**
 /**
  Create a frame animated image from an array of data.
  Create a frame animated image from an array of data.
@@ -92,6 +100,10 @@
  
  
  @return An initialized YYFrameImage object, or nil when an error occurs.
  @return An initialized YYFrameImage object, or nil when an error occurs.
  */
  */
-- (instancetype)initWithImageDataArray:(NSArray *)dataArray frameDurations:(NSArray *)frameDurations loopCount:(NSUInteger)loopCount;
+- (nullable instancetype)initWithImageDataArray:(NSArray<NSData *> *)dataArray
+                                 frameDurations:(NSArray *)frameDurations
+                                      loopCount:(NSUInteger)loopCount;
 
 
 @end
 @end
+
+NS_ASSUME_NONNULL_END

+ 9 - 7
Demo/YYTextDemo/YYImage/YYImage.h

@@ -30,7 +30,7 @@ FOUNDATION_EXPORT const unsigned char YYImageVersionString[];
 #import "YYAnimatedImageView.h"
 #import "YYAnimatedImageView.h"
 #endif
 #endif
 
 
-
+NS_ASSUME_NONNULL_BEGIN
 
 
 
 
 /**
 /**
@@ -53,10 +53,10 @@ FOUNDATION_EXPORT const unsigned char YYImageVersionString[];
  */
  */
 @interface YYImage : UIImage <YYAnimatedImage>
 @interface YYImage : UIImage <YYAnimatedImage>
 
 
-+ (YYImage *)imageNamed:(NSString *)name; // no cache!
-+ (YYImage *)imageWithContentsOfFile:(NSString *)path;
-+ (YYImage *)imageWithData:(NSData *)data;
-+ (YYImage *)imageWithData:(NSData *)data scale:(CGFloat)scale;
++ (nullable YYImage *)imageNamed:(NSString *)name; // no cache!
++ (nullable YYImage *)imageWithContentsOfFile:(NSString *)path;
++ (nullable YYImage *)imageWithData:(NSData *)data;
++ (nullable YYImage *)imageWithData:(NSData *)data scale:(CGFloat)scale;
 
 
 /**
 /**
  If the image is created from data or file, then the value indicates the data type.
  If the image is created from data or file, then the value indicates the data type.
@@ -67,7 +67,7 @@ FOUNDATION_EXPORT const unsigned char YYImageVersionString[];
  If the image is created from animated image data (multi-frame GIF/APNG/WebP),
  If the image is created from animated image data (multi-frame GIF/APNG/WebP),
  this property stores the original image data.
  this property stores the original image data.
  */
  */
-@property (nonatomic, readonly) NSData *animatedImageData;
+@property (nullable, nonatomic, readonly) NSData *animatedImageData;
 
 
 /**
 /**
  The total memory usage (in bytes) if all frame images was loaded into memory.
  The total memory usage (in bytes) if all frame images was loaded into memory.
@@ -85,6 +85,8 @@ FOUNDATION_EXPORT const unsigned char YYImageVersionString[];
  
  
  See `animatedImageMemorySize` for memory cost.
  See `animatedImageMemorySize` for memory cost.
  */
  */
-@property (nonatomic, assign) BOOL preloadAllAnimatedImageFrames;
+@property (nonatomic) BOOL preloadAllAnimatedImageFrames;
 
 
 @end
 @end
+
+NS_ASSUME_NONNULL_END

+ 53 - 50
Demo/YYTextDemo/YYImage/YYImageCoder.h

@@ -11,6 +11,8 @@
 
 
 #import <UIKit/UIKit.h>
 #import <UIKit/UIKit.h>
 
 
+NS_ASSUME_NONNULL_BEGIN
+
 /**
 /**
  Image file type.
  Image file type.
  */
  */
@@ -76,15 +78,15 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
  An image frame object.
  An image frame object.
  */
  */
 @interface YYImageFrame : NSObject <NSCopying>
 @interface YYImageFrame : NSObject <NSCopying>
-@property (nonatomic, assign) NSUInteger index;    ///< Frame index (zero based)
-@property (nonatomic, assign) NSUInteger width;    ///< Frame width
-@property (nonatomic, assign) NSUInteger height;   ///< Frame height
-@property (nonatomic, assign) NSUInteger offsetX;  ///< Frame origin.x in canvas (left-bottom based)
-@property (nonatomic, assign) NSUInteger offsetY;  ///< Frame origin.y in canvas (left-bottom based)
-@property (nonatomic, assign) NSTimeInterval duration;      ///< Frame duration in seconds
-@property (nonatomic, assign) YYImageDisposeMethod dispose; ///< Frame dispose method.
-@property (nonatomic, assign) YYImageBlendOperation blend;  ///< Frame blend operation.
-@property (nonatomic, strong) UIImage *image; ///< The image.
+@property (nonatomic) NSUInteger index;    ///< Frame index (zero based)
+@property (nonatomic) NSUInteger width;    ///< Frame width
+@property (nonatomic) NSUInteger height;   ///< Frame height
+@property (nonatomic) NSUInteger offsetX;  ///< Frame origin.x in canvas (left-bottom based)
+@property (nonatomic) NSUInteger offsetY;  ///< Frame origin.y in canvas (left-bottom based)
+@property (nonatomic) NSTimeInterval duration;          ///< Frame duration in seconds
+@property (nonatomic) YYImageDisposeMethod dispose;     ///< Frame dispose method.
+@property (nonatomic) YYImageBlendOperation blend;      ///< Frame blend operation.
+@property (nullable, nonatomic, strong) UIImage *image; ///< The image.
 + (instancetype)frameWithImage:(UIImage *)image;
 + (instancetype)frameWithImage:(UIImage *)image;
 @end
 @end
 
 
@@ -124,9 +126,9 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
  */
  */
 @interface YYImageDecoder : NSObject
 @interface YYImageDecoder : NSObject
 
 
-@property (nonatomic, readonly) NSData *data;       ///< Image data.
-@property (nonatomic, readonly) YYImageType type;   ///< Image data type.
-@property (nonatomic, readonly) CGFloat scale;      ///< Image scale.
+@property (nullable, nonatomic, readonly) NSData *data;    ///< Image data.
+@property (nonatomic, readonly) YYImageType type;          ///< Image data type.
+@property (nonatomic, readonly) CGFloat scale;             ///< Image scale.
 @property (nonatomic, readonly) NSUInteger frameCount;     ///< Image frame count.
 @property (nonatomic, readonly) NSUInteger frameCount;     ///< Image frame count.
 @property (nonatomic, readonly) NSUInteger loopCount;      ///< Image loop count, 0 means infinite.
 @property (nonatomic, readonly) NSUInteger loopCount;      ///< Image loop count, 0 means infinite.
 @property (nonatomic, readonly) NSUInteger width;          ///< Image canvas width.
 @property (nonatomic, readonly) NSUInteger width;          ///< Image canvas width.
@@ -158,7 +160,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
  
  
  @return Whether succeed.
  @return Whether succeed.
  */
  */
-- (BOOL)updateData:(NSData *)data final:(BOOL)final;
+- (BOOL)updateData:(nullable NSData *)data final:(BOOL)final;
 
 
 /**
 /**
  Convenience method to create a decoder with specified data.
  Convenience method to create a decoder with specified data.
@@ -166,7 +168,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
  @param scale Image's scale.
  @param scale Image's scale.
  @return A new decoder, or nil if an error occurs.
  @return A new decoder, or nil if an error occurs.
  */
  */
-+ (instancetype)decoderWithData:(NSData *)data scale:(CGFloat)scale;
++ (nullable instancetype)decoderWithData:(NSData *)data scale:(CGFloat)scale;
 
 
 /**
 /**
  Decodes and returns a frame from a specified index.
  Decodes and returns a frame from a specified index.
@@ -175,7 +177,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
     If NO, it will try to returns the original frame data without blend.
     If NO, it will try to returns the original frame data without blend.
  @return A new frame with image, or nil if an error occurs.
  @return A new frame with image, or nil if an error occurs.
  */
  */
-- (YYImageFrame *)frameAtIndex:(NSUInteger)index decodeForDisplay:(BOOL)decodeForDisplay;
+- (nullable YYImageFrame *)frameAtIndex:(NSUInteger)index decodeForDisplay:(BOOL)decodeForDisplay;
 
 
 /**
 /**
  Returns the frame duration from a specified index.
  Returns the frame duration from a specified index.
@@ -191,13 +193,13 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
  @param index  Frame image index (zero-based).
  @param index  Frame image index (zero-based).
  @return The ImageIO frame property.
  @return The ImageIO frame property.
  */
  */
-- (NSDictionary *)framePropertiesAtIndex:(NSUInteger)index;
+- (nullable NSDictionary *)framePropertiesAtIndex:(NSUInteger)index;
 
 
 /**
 /**
  Returns the image's properties. See "CGImageProperties.h" in ImageIO.framework
  Returns the image's properties. See "CGImageProperties.h" in ImageIO.framework
  for more information.
  for more information.
  */
  */
-- (NSDictionary *)imageProperties;
+- (nullable NSDictionary *)imageProperties;
 
 
 @end
 @end
 
 
@@ -231,10 +233,10 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
  */
  */
 @interface YYImageEncoder : NSObject
 @interface YYImageEncoder : NSObject
 
 
-@property (nonatomic, readonly) YYImageType type;   ///< Image type.
-@property (nonatomic, assign) NSUInteger loopCount; ///< Loop count, 0 means infinit, only available for GIF/APNG/WebP.
-@property (nonatomic, assign) BOOL lossless;        ///< Lossless, only available for WebP.
-@property (nonatomic, assign) CGFloat quality;      ///< Compress quality, 0.0~1.0, only available for JPG/JP2/WebP.
+@property (nonatomic, readonly) YYImageType type; ///< Image type.
+@property (nonatomic) NSUInteger loopCount;       ///< Loop count, 0 means infinit, only available for GIF/APNG/WebP.
+@property (nonatomic) BOOL lossless;              ///< Lossless, only available for WebP.
+@property (nonatomic) CGFloat quality;            ///< Compress quality, 0.0~1.0, only available for JPG/JP2/WebP.
 
 
 - (instancetype)init UNAVAILABLE_ATTRIBUTE;
 - (instancetype)init UNAVAILABLE_ATTRIBUTE;
 + (instancetype)new UNAVAILABLE_ATTRIBUTE;
 + (instancetype)new UNAVAILABLE_ATTRIBUTE;
@@ -244,7 +246,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
  @param type Image type.
  @param type Image type.
  @return A new encoder, or nil if an error occurs.
  @return A new encoder, or nil if an error occurs.
  */
  */
-- (instancetype)initWithType:(YYImageType)type NS_DESIGNATED_INITIALIZER;
+- (nullable instancetype)initWithType:(YYImageType)type NS_DESIGNATED_INITIALIZER;
 
 
 /**
 /**
  Add an image to encoder.
  Add an image to encoder.
@@ -271,7 +273,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
  Encodes the image and returns the image data.
  Encodes the image and returns the image data.
  @return The image data, or nil if an error occurs.
  @return The image data, or nil if an error occurs.
  */
  */
-- (NSData *)encode;
+- (nullable NSData *)encode;
 
 
 /**
 /**
  Encodes the image to a file.
  Encodes the image to a file.
@@ -287,7 +289,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
  @param quality Image quality, 0.0~1.0.
  @param quality Image quality, 0.0~1.0.
  @return The image data, or nil if an error occurs.
  @return The image data, or nil if an error occurs.
  */
  */
-+ (NSData *)encodeImage:(UIImage *)image type:(YYImageType)type quality:(CGFloat)quality;
++ (nullable NSData *)encodeImage:(UIImage *)image type:(YYImageType)type quality:(CGFloat)quality;
 
 
 /**
 /**
  Convenience method to encode image from a decoder.
  Convenience method to encode image from a decoder.
@@ -296,7 +298,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
  @param quality Image quality, 0.0~1.0.
  @param quality Image quality, 0.0~1.0.
  @return The image data, or nil if an error occurs.
  @return The image data, or nil if an error occurs.
  */
  */
-+ (NSData *)encodeImageWithDecoder:(YYImageDecoder *)decoder type:(YYImageType)type quality:(CGFloat)quality;
++ (nullable NSData *)encodeImageWithDecoder:(YYImageDecoder *)decoder type:(YYImageType)type quality:(CGFloat)quality;
 
 
 @end
 @end
 
 
@@ -319,7 +321,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
  Wherher the image can be display on screen without additional decoding.
  Wherher the image can be display on screen without additional decoding.
  @warning It just a hint for your code, change it has no other effect.
  @warning It just a hint for your code, change it has no other effect.
  */
  */
-@property (nonatomic, assign) BOOL yy_isDecodedForDisplay;
+@property (nonatomic) BOOL yy_isDecodedForDisplay;
 
 
 /**
 /**
  Saves this image to iOS Photos Album. 
  Saves this image to iOS Photos Album. 
@@ -332,7 +334,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
     assetURL: An URL that identifies the saved image file. If the image is not saved, assetURL is nil.
     assetURL: An URL that identifies the saved image file. If the image is not saved, assetURL is nil.
     error: If the image is not saved, an error object that describes the reason for failure, otherwise nil.
     error: If the image is not saved, an error object that describes the reason for failure, otherwise nil.
  */
  */
-- (void)yy_saveToAlbumWithCompletionBlock:(void(^)(NSURL *assetURL, NSError *error))completionBlock;
+- (void)yy_saveToAlbumWithCompletionBlock:(nullable void(^)(NSURL * _Nullable assetURL, NSError * _Nullable error))completionBlock;
 
 
 /**
 /**
  Return a 'best' data representation for this image.
  Return a 'best' data representation for this image.
@@ -343,7 +345,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
  
  
  @return Image data, or nil if an error occurs.
  @return Image data, or nil if an error occurs.
  */
  */
-- (NSData *)yy_imageDataRepresentation;
+- (nullable NSData *)yy_imageDataRepresentation;
 
 
 @end
 @end
 
 
@@ -355,13 +357,13 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) {
 CG_EXTERN YYImageType YYImageDetectType(CFDataRef data);
 CG_EXTERN YYImageType YYImageDetectType(CFDataRef data);
 
 
 /// Convert YYImageType to UTI (such as kUTTypeJPEG).
 /// Convert YYImageType to UTI (such as kUTTypeJPEG).
-CG_EXTERN CFStringRef YYImageTypeToUTType(YYImageType type);
+CG_EXTERN CFStringRef _Nullable YYImageTypeToUTType(YYImageType type);
 
 
 /// Convert UTI (such as kUTTypeJPEG) to YYImageType.
 /// Convert UTI (such as kUTTypeJPEG) to YYImageType.
 CG_EXTERN YYImageType YYImageTypeFromUTType(CFStringRef uti);
 CG_EXTERN YYImageType YYImageTypeFromUTType(CFStringRef uti);
 
 
 /// Get image type's file extension (such as @"jpg").
 /// Get image type's file extension (such as @"jpg").
-CG_EXTERN NSString *YYImageTypeGetExtension(YYImageType type);
+CG_EXTERN NSString *_Nullable YYImageTypeGetExtension(YYImageType type);
 
 
 
 
 
 
@@ -402,7 +404,7 @@ CG_EXTERN NSInteger YYUIImageOrientationToEXIFValue(UIImageOrientation orientati
  
  
  @return A decoded image, or NULL if an error occurs.
  @return A decoded image, or NULL if an error occurs.
  */
  */
-CG_EXTERN CGImageRef YYCGImageCreateDecodedCopy(CGImageRef imageRef, BOOL decodeForDisplay);
+CG_EXTERN CGImageRef _Nullable YYCGImageCreateDecodedCopy(CGImageRef imageRef, BOOL decodeForDisplay);
 
 
 /**
 /**
  Create an image copy with an orientation.
  Create an image copy with an orientation.
@@ -412,9 +414,9 @@ CG_EXTERN CGImageRef YYCGImageCreateDecodedCopy(CGImageRef imageRef, BOOL decode
  @param destBitmapInfo Destimation image bitmap, only support 32bit format (such as ARGB8888).
  @param destBitmapInfo Destimation image bitmap, only support 32bit format (such as ARGB8888).
  @return A new image, or NULL if an error occurs.
  @return A new image, or NULL if an error occurs.
  */
  */
-CG_EXTERN CGImageRef YYCGImageCreateCopyWithOrientation(CGImageRef imageRef,
-                                              UIImageOrientation orientation,
-                                              CGBitmapInfo destBitmapInfo);
+CG_EXTERN CGImageRef _Nullable YYCGImageCreateCopyWithOrientation(CGImageRef imageRef,
+                                                                  UIImageOrientation orientation,
+                                                                  CGBitmapInfo destBitmapInfo);
 
 
 /**
 /**
  Create an image copy with CGAffineTransform.
  Create an image copy with CGAffineTransform.
@@ -425,10 +427,10 @@ CG_EXTERN CGImageRef YYCGImageCreateCopyWithOrientation(CGImageRef imageRef,
  @param destBitmapInfo Destimation image bitmap, only support 32bit format (such as ARGB8888).
  @param destBitmapInfo Destimation image bitmap, only support 32bit format (such as ARGB8888).
  @return A new image, or NULL if an error occurs.
  @return A new image, or NULL if an error occurs.
  */
  */
-CG_EXTERN CGImageRef YYCGImageCreateAffineTransformCopy(CGImageRef imageRef,
-                                              CGAffineTransform transform,
-                                              CGSize destSize,
-                                              CGBitmapInfo destBitmapInfo);
+CG_EXTERN CGImageRef _Nullable YYCGImageCreateAffineTransformCopy(CGImageRef imageRef,
+                                                                  CGAffineTransform transform,
+                                                                  CGSize destSize,
+                                                                  CGBitmapInfo destBitmapInfo);
 
 
 /**
 /**
  Encode an image to data with CGImageDestination.
  Encode an image to data with CGImageDestination.
@@ -438,7 +440,7 @@ CG_EXTERN CGImageRef YYCGImageCreateAffineTransformCopy(CGImageRef imageRef,
  @param quality   The quality (0.0~1.0)
  @param quality   The quality (0.0~1.0)
  @return A new image data, or nil if an error occurs.
  @return A new image data, or nil if an error occurs.
  */
  */
-CG_EXTERN CFDataRef YYCGImageCreateEncodedData(CGImageRef imageRef, YYImageType type, CGFloat quality);
+CG_EXTERN CFDataRef _Nullable YYCGImageCreateEncodedData(CGImageRef imageRef, YYImageType type, CGFloat quality);
 
 
 
 
 /**
 /**
@@ -468,12 +470,11 @@ CG_EXTERN NSUInteger YYImageGetWebPFrameCount(CFDataRef webpData);
                             (speed down, and may lose some details).
                             (speed down, and may lose some details).
  @return The decoded image, or NULL if an error occurs.
  @return The decoded image, or NULL if an error occurs.
  */
  */
-CG_EXTERN CGImageRef YYCGImageCreateWithWebPData(CFDataRef webpData,
-                                       BOOL decodeForDisplay,
-                                       BOOL useThreads,
-                                       BOOL bypassFiltering,
-                                       BOOL noFancyUpsampling);
-
+CG_EXTERN CGImageRef _Nullable YYCGImageCreateWithWebPData(CFDataRef webpData,
+                                                           BOOL decodeForDisplay,
+                                                           BOOL useThreads,
+                                                           BOOL bypassFiltering,
+                                                           BOOL noFancyUpsampling);
 
 
 typedef NS_ENUM(NSUInteger, YYImagePreset) {
 typedef NS_ENUM(NSUInteger, YYImagePreset) {
     YYImagePresetDefault = 0,  ///< default preset.
     YYImagePresetDefault = 0,  ///< default preset.
@@ -495,8 +496,10 @@ typedef NS_ENUM(NSUInteger, YYImagePreset) {
  @param preset        Preset for different image type, default is YYImagePresetDefault.
  @param preset        Preset for different image type, default is YYImagePresetDefault.
  @return WebP data, or nil if an error occurs.
  @return WebP data, or nil if an error occurs.
  */
  */
-CG_EXTERN CFDataRef YYCGImageCreateEncodedWebPData(CGImageRef imageRef,
-                                         BOOL lossless,
-                                         CGFloat quality,
-                                         int compressLevel,
-                                         YYImagePreset preset);
+CG_EXTERN CFDataRef _Nullable YYCGImageCreateEncodedWebPData(CGImageRef imageRef,
+                                                             BOOL lossless,
+                                                             CGFloat quality,
+                                                             int compressLevel,
+                                                             YYImagePreset preset);
+
+NS_ASSUME_NONNULL_END

+ 36 - 23
Demo/YYTextDemo/YYImage/YYImageCoder.m

@@ -1399,7 +1399,8 @@ CGImageRef YYCGImageCreateWithWebPData(CFDataRef webpData,
     config.output.u.RGBA.stride = (int)bytesPerRow;
     config.output.u.RGBA.stride = (int)bytesPerRow;
     config.output.u.RGBA.size = destLength;
     config.output.u.RGBA.size = destLength;
     
     
-    if (WebPDecode(payload, payloadSize, &config) != VP8_STATUS_OK) goto fail;
+    VP8StatusCode result = WebPDecode(payload, payloadSize, &config);
+    if ((result != VP8_STATUS_OK) && (result != VP8_STATUS_NOT_ENOUGH_DATA)) goto fail;
     
     
     if (iter.x_offset != 0 || iter.y_offset != 0) {
     if (iter.x_offset != 0 || iter.y_offset != 0) {
         void *tmp = calloc(1, destLength);
         void *tmp = calloc(1, destLength);
@@ -2150,7 +2151,8 @@ CGImageRef YYCGImageCreateWithWebPData(CFDataRef webpData,
         config.output.u.RGBA.rgba = pixels;
         config.output.u.RGBA.rgba = pixels;
         config.output.u.RGBA.stride = (int)bytesPerRow;
         config.output.u.RGBA.stride = (int)bytesPerRow;
         config.output.u.RGBA.size = length;
         config.output.u.RGBA.size = length;
-        if (WebPDecode(payload, payloadSize, &config) != VP8_STATUS_OK) { // decode
+        VP8StatusCode result = WebPDecode(payload, payloadSize, &config); // decode
+        if ((result != VP8_STATUS_OK) && (result != VP8_STATUS_NOT_ENOUGH_DATA)) {
             WebPDemuxReleaseIterator(&iter);
             WebPDemuxReleaseIterator(&iter);
             free(pixels);
             free(pixels);
             return NULL;
             return NULL;
@@ -2415,27 +2417,38 @@ CGImageRef YYCGImageCreateWithWebPData(CFDataRef webpData,
     }
     }
     
     
     for (int i = 0; i < count; i++) {
     for (int i = 0; i < count; i++) {
-        id imageSrc = _images[i];
-        NSDictionary *frameProperty = NULL;
-        if (_type == YYImageTypeGIF && count > 1) {
-            frameProperty = @{(NSString *)kCGImagePropertyGIFDictionary : @{(NSString *) kCGImagePropertyGIFDelayTime:_durations[i]}};
-        } else {
-            frameProperty = @{(id)kCGImageDestinationLossyCompressionQuality : @(_quality)};
-        }
-        
-        if ([imageSrc isKindOfClass:[UIImage class]]) {
-            CGImageDestinationAddImage(destination, ((UIImage *)imageSrc).CGImage, (CFDictionaryRef)frameProperty);
-        } else if ([imageSrc isKindOfClass:[NSURL class]]) {
-            CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)imageSrc, NULL);
-            if (source) {
-                CGImageDestinationAddImageFromSource(destination, source, i, (CFDictionaryRef)frameProperty);
-                CFRelease(source);
+        @autoreleasepool {
+            id imageSrc = _images[i];
+            NSDictionary *frameProperty = NULL;
+            if (_type == YYImageTypeGIF && count > 1) {
+                frameProperty = @{(NSString *)kCGImagePropertyGIFDictionary : @{(NSString *) kCGImagePropertyGIFDelayTime:_durations[i]}};
+            } else {
+                frameProperty = @{(id)kCGImageDestinationLossyCompressionQuality : @(_quality)};
             }
             }
-        } else if ([imageSrc isKindOfClass:[NSData class]]) {
-            CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)imageSrc, NULL);
-            if (source) {
-                CGImageDestinationAddImageFromSource(destination, source, i, (CFDictionaryRef)frameProperty);
-                CFRelease(source);
+            
+            if ([imageSrc isKindOfClass:[UIImage class]]) {
+                UIImage *image = imageSrc;
+                if (image.imageOrientation != UIImageOrientationUp && image.CGImage) {
+                    CGBitmapInfo info = CGImageGetBitmapInfo(image.CGImage) | CGImageGetAlphaInfo(image.CGImage);
+                    CGImageRef rotated = YYCGImageCreateCopyWithOrientation(image.CGImage, image.imageOrientation, info);
+                    if (rotated) {
+                        image = [UIImage imageWithCGImage:rotated];
+                        CFRelease(rotated);
+                    }
+                }
+                if (image.CGImage) CGImageDestinationAddImage(destination, ((UIImage *)imageSrc).CGImage, (CFDictionaryRef)frameProperty);
+            } else if ([imageSrc isKindOfClass:[NSURL class]]) {
+                CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)imageSrc, NULL);
+                if (source) {
+                    CGImageDestinationAddImageFromSource(destination, source, i, (CFDictionaryRef)frameProperty);
+                    CFRelease(source);
+                }
+            } else if ([imageSrc isKindOfClass:[NSData class]]) {
+                CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)imageSrc, NULL);
+                if (source) {
+                    CGImageDestinationAddImageFromSource(destination, source, i, (CFDictionaryRef)frameProperty);
+                    CFRelease(source);
+                }
             }
             }
         }
         }
     }
     }
@@ -2724,7 +2737,7 @@ CGImageRef YYCGImageCreateWithWebPData(CFDataRef webpData,
 }
 }
 
 
 + (NSData *)encodeImageWithDecoder:(YYImageDecoder *)decoder type:(YYImageType)type quality:(CGFloat)quality {
 + (NSData *)encodeImageWithDecoder:(YYImageDecoder *)decoder type:(YYImageType)type quality:(CGFloat)quality {
-    if (!decoder || !decoder.frameCount == 0) return nil;
+    if (!decoder || decoder.frameCount == 0) return nil;
     YYImageEncoder *encoder = [[YYImageEncoder alloc] initWithType:type];
     YYImageEncoder *encoder = [[YYImageEncoder alloc] initWithType:type];
     encoder.quality = quality;
     encoder.quality = quality;
     for (int i = 0; i < decoder.frameCount; i++) {
     for (int i = 0; i < decoder.frameCount; i++) {

+ 10 - 6
Demo/YYTextDemo/YYImage/YYSpriteSheetImage.h

@@ -19,6 +19,8 @@
 #import "YYAnimatedImageView.h"
 #import "YYAnimatedImageView.h"
 #endif
 #endif
 
 
+NS_ASSUME_NONNULL_BEGIN
+
 /**
 /**
  An image to display sprite sheet animation.
  An image to display sprite sheet animation.
  
  
@@ -79,13 +81,13 @@
  
  
  @return An image object, or nil if an error occurs.
  @return An image object, or nil if an error occurs.
  */
  */
-- (instancetype)initWithSpriteSheetImage:(UIImage *)image
-                            contentRects:(NSArray *)contentRects
-                          frameDurations:(NSArray *)frameDurations
-                               loopCount:(NSUInteger)loopCount;
+- (nullable instancetype)initWithSpriteSheetImage:(UIImage *)image
+                                     contentRects:(NSArray<NSValue *> *)contentRects
+                                   frameDurations:(NSArray<NSNumber *> *)frameDurations
+                                        loopCount:(NSUInteger)loopCount;
 
 
-@property (nonatomic, readonly) NSArray *contentRects;
-@property (nonatomic, readonly) NSArray *frameDurations;
+@property (nonatomic, readonly) NSArray<NSValue *> *contentRects;
+@property (nonatomic, readonly) NSArray<NSValue *> *frameDurations;
 @property (nonatomic, readonly) NSUInteger loopCount;
 @property (nonatomic, readonly) NSUInteger loopCount;
 
 
 /**
 /**
@@ -98,3 +100,5 @@
 - (CGRect)contentsRectForCALayerAtIndex:(NSUInteger)index;
 - (CGRect)contentsRectForCALayerAtIndex:(NSUInteger)index;
 
 
 @end
 @end
+
+NS_ASSUME_NONNULL_END