Commit e4557336 authored by yuzheng's avatar yuzheng

新增gifImagePlayBlock允许使用FLAnimatedImage等替换内部的GIF播放方案

parent beabdfff
......@@ -29,6 +29,8 @@
900EF00F1C2C0B1100EA709B /* TZAssetModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EF00E1C2C0B1100EA709B /* TZAssetModel.m */; };
900EF0121C2C107400EA709B /* TZPhotoPreviewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EF0111C2C107400EA709B /* TZPhotoPreviewController.m */; };
900EF0161C2C134900EA709B /* TZPhotoPreviewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 900EF0141C2C134900EA709B /* TZPhotoPreviewCell.m */; };
901F2295215CABD600F604ED /* FLAnimatedImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 901F2291215CABD600F604ED /* FLAnimatedImage.m */; };
901F2296215CABD600F604ED /* FLAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 901F2293215CABD600F604ED /* FLAnimatedImageView.m */; };
902938D81EE2D02C000F2F8F /* TZLocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 902938D71EE2D02C000F2F8F /* TZLocationManager.m */; };
9038D5911C3974F0007DE549 /* TZTestCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 9038D5901C3974F0007DE549 /* TZTestCell.m */; };
903996931F447604005E77C2 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 903996921F447604005E77C2 /* Photos.framework */; };
......@@ -150,6 +152,10 @@
900EF0111C2C107400EA709B /* TZPhotoPreviewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZPhotoPreviewController.m; sourceTree = "<group>"; };
900EF0131C2C134800EA709B /* TZPhotoPreviewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZPhotoPreviewCell.h; sourceTree = "<group>"; };
900EF0141C2C134900EA709B /* TZPhotoPreviewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZPhotoPreviewCell.m; sourceTree = "<group>"; };
901F2290215CABD600F604ED /* FLAnimatedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLAnimatedImage.h; sourceTree = "<group>"; };
901F2291215CABD600F604ED /* FLAnimatedImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLAnimatedImage.m; sourceTree = "<group>"; };
901F2292215CABD600F604ED /* FLAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLAnimatedImageView.h; sourceTree = "<group>"; };
901F2293215CABD600F604ED /* FLAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLAnimatedImageView.m; sourceTree = "<group>"; };
902938D61EE2D02C000F2F8F /* TZLocationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZLocationManager.h; sourceTree = "<group>"; };
902938D71EE2D02C000F2F8F /* TZLocationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZLocationManager.m; sourceTree = "<group>"; };
9038D58F1C3974F0007DE549 /* TZTestCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZTestCell.h; sourceTree = "<group>"; };
......@@ -234,6 +240,7 @@
900E657E1C2BB8D5003D9A9E /* TZImagePickerController */ = {
isa = PBXGroup;
children = (
901F228F215CABD600F604ED /* FLAnimatedImage */,
900EEFF51C2BBF7600EA709B /* TZImagePickerController */,
900E65821C2BB8D5003D9A9E /* AppDelegate.h */,
900E65831C2BB8D5003D9A9E /* AppDelegate.m */,
......@@ -317,6 +324,17 @@
path = TZImagePickerController;
sourceTree = "<group>";
};
901F228F215CABD600F604ED /* FLAnimatedImage */ = {
isa = PBXGroup;
children = (
901F2290215CABD600F604ED /* FLAnimatedImage.h */,
901F2291215CABD600F604ED /* FLAnimatedImage.m */,
901F2292215CABD600F604ED /* FLAnimatedImageView.h */,
901F2293215CABD600F604ED /* FLAnimatedImageView.m */,
);
path = FLAnimatedImage;
sourceTree = "<group>";
};
903996911F447603005E77C2 /* Frameworks */ = {
isa = PBXGroup;
children = (
......@@ -550,7 +568,9 @@
900EF0161C2C134900EA709B /* TZPhotoPreviewCell.m in Sources */,
900E65871C2BB8D5003D9A9E /* ViewController.m in Sources */,
90CE84AE1C3A89EF003D0779 /* TZImageManager.m in Sources */,
901F2295215CABD600F604ED /* FLAnimatedImage.m in Sources */,
900E65841C2BB8D5003D9A9E /* AppDelegate.m in Sources */,
901F2296215CABD600F604ED /* FLAnimatedImageView.m in Sources */,
900E65811C2BB8D5003D9A9E /* main.m in Sources */,
900EF0121C2C107400EA709B /* TZPhotoPreviewController.m in Sources */,
6D5358CD1D64600F00928CC6 /* NSBundle+TZImagePicker.m in Sources */,
......
//
// FLAnimatedImage.h
// Flipboard
//
// Created by Raphael Schaad on 7/8/13.
// Copyright (c) 2013-2015 Flipboard. All rights reserved.
//
#import <UIKit/UIKit.h>
// Allow user classes conveniently just importing one header.
#import "FLAnimatedImageView.h"
#ifndef NS_DESIGNATED_INITIALIZER
#if __has_attribute(objc_designated_initializer)
#define NS_DESIGNATED_INITIALIZER __attribute((objc_designated_initializer))
#else
#define NS_DESIGNATED_INITIALIZER
#endif
#endif
extern const NSTimeInterval kFLAnimatedImageDelayTimeIntervalMinimum;
//
// An `FLAnimatedImage`'s job is to deliver frames in a highly performant way and works in conjunction with `FLAnimatedImageView`.
// It subclasses `NSObject` and not `UIImage` because it's only an "image" in the sense that a sea lion is a lion.
// It tries to intelligently choose the frame cache size depending on the image and memory situation with the goal to lower CPU usage for smaller ones, lower memory usage for larger ones and always deliver frames for high performant play-back.
// Note: `posterImage`, `size`, `loopCount`, `delayTimes` and `frameCount` don't change after successful initialization.
//
@interface FLAnimatedImage : NSObject
@property (nonatomic, strong, readonly) UIImage *posterImage; // Guaranteed to be loaded; usually equivalent to `-imageLazilyCachedAtIndex:0`
@property (nonatomic, assign, readonly) CGSize size; // The `.posterImage`'s `.size`
@property (nonatomic, assign, readonly) NSUInteger loopCount; // 0 means repeating the animation indefinitely
@property (nonatomic, strong, readonly) NSDictionary *delayTimesForIndexes; // Of type `NSTimeInterval` boxed in `NSNumber`s
@property (nonatomic, assign, readonly) NSUInteger frameCount; // Number of valid frames; equal to `[.delayTimes count]`
@property (nonatomic, assign, readonly) NSUInteger frameCacheSizeCurrent; // Current size of intelligently chosen buffer window; can range in the interval [1..frameCount]
@property (nonatomic, assign) NSUInteger frameCacheSizeMax; // Allow to cap the cache size; 0 means no specific limit (default)
// Intended to be called from main thread synchronously; will return immediately.
// If the result isn't cached, will return `nil`; the caller should then pause playback, not increment frame counter and keep polling.
// After an initial loading time, depending on `frameCacheSize`, frames should be available immediately from the cache.
- (UIImage *)imageLazilyCachedAtIndex:(NSUInteger)index;
// Pass either a `UIImage` or an `FLAnimatedImage` and get back its size
+ (CGSize)sizeForImage:(id)image;
// On success, the initializers return an `FLAnimatedImage` with all fields initialized, on failure they return `nil` and an error will be logged.
- (instancetype)initWithAnimatedGIFData:(NSData *)data;
// Pass 0 for optimalFrameCacheSize to get the default, predrawing is enabled by default.
- (instancetype)initWithAnimatedGIFData:(NSData *)data optimalFrameCacheSize:(NSUInteger)optimalFrameCacheSize predrawingEnabled:(BOOL)isPredrawingEnabled NS_DESIGNATED_INITIALIZER;
+ (instancetype)animatedImageWithGIFData:(NSData *)data;
@property (nonatomic, strong, readonly) NSData *data; // The data the receiver was initialized with; read-only
@end
typedef NS_ENUM(NSUInteger, FLLogLevel) {
FLLogLevelNone = 0,
FLLogLevelError,
FLLogLevelWarn,
FLLogLevelInfo,
FLLogLevelDebug,
FLLogLevelVerbose
};
@interface FLAnimatedImage (Logging)
+ (void)setLogBlock:(void (^)(NSString *logString, FLLogLevel logLevel))logBlock logLevel:(FLLogLevel)logLevel;
+ (void)logStringFromBlock:(NSString *(^)(void))stringBlock withLevel:(FLLogLevel)level;
@end
#define FLLog(logLevel, format, ...) [FLAnimatedImage logStringFromBlock:^NSString *{ return [NSString stringWithFormat:(format), ## __VA_ARGS__]; } withLevel:(logLevel)]
@interface FLWeakProxy : NSProxy
+ (instancetype)weakProxyForObject:(id)targetObject;
@end
This diff is collapsed.
//
// FLAnimatedImageView.h
// Flipboard
//
// Created by Raphael Schaad on 7/8/13.
// Copyright (c) 2013-2015 Flipboard. All rights reserved.
//
#import <UIKit/UIKit.h>
@class FLAnimatedImage;
@protocol FLAnimatedImageViewDebugDelegate;
//
// An `FLAnimatedImageView` can take an `FLAnimatedImage` and plays it automatically when in view hierarchy and stops when removed.
// The animation can also be controlled with the `UIImageView` methods `-start/stop/isAnimating`.
// It is a fully compatible `UIImageView` subclass and can be used as a drop-in component to work with existing code paths expecting to display a `UIImage`.
// Under the hood it uses a `CADisplayLink` for playback, which can be inspected with `currentFrame` & `currentFrameIndex`.
//
@interface FLAnimatedImageView : UIImageView
// Setting `[UIImageView.image]` to a non-`nil` value clears out existing `animatedImage`.
// And vice versa, setting `animatedImage` will initially populate the `[UIImageView.image]` to its `posterImage` and then start animating and hold `currentFrame`.
@property (nonatomic, strong) FLAnimatedImage *animatedImage;
@property (nonatomic, copy) void(^loopCompletionBlock)(NSUInteger loopCountRemaining);
@property (nonatomic, strong, readonly) UIImage *currentFrame;
@property (nonatomic, assign, readonly) NSUInteger currentFrameIndex;
// The animation runloop mode. Enables playback during scrolling by allowing timer events (i.e. animation) with NSRunLoopCommonModes.
// To keep scrolling smooth on single-core devices such as iPhone 3GS/4 and iPod Touch 4th gen, the default run loop mode is NSDefaultRunLoopMode. Otherwise, the default is NSDefaultRunLoopMode.
@property (nonatomic, copy) NSString *runLoopMode;
@end
This diff is collapsed.
......@@ -133,7 +133,7 @@
}
else {
// images数组过大时内存会飙升,在这里限制下最大count
NSInteger maxCount = [TZImagePickerConfig sharedInstance].gifPreviewMaxImagesCount ?: 200;
NSInteger maxCount = [TZImagePickerConfig sharedInstance].gifPreviewMaxImagesCount ?: 50;
NSInteger interval = MAX((count + maxCount / 2) / maxCount, 1);
NSMutableArray *images = [NSMutableArray array];
......
......@@ -24,6 +24,7 @@
#import "TZGifPhotoPreviewController.h"
#import "TZLocationManager.h"
#import "TZPhotoPreviewController.h"
#import "TZPhotoPreviewCell.h"
@class TZAlbumCell, TZAssetCell;
@protocol TZImagePickerControllerDelegate;
......@@ -317,10 +318,13 @@
@property(nonatomic, assign) BOOL allowPickingImage;
@property (nonatomic, assign) BOOL allowPickingVideo;
@property (strong, nonatomic) NSBundle *languageBundle;
/// 默认是200,如果一个GIF过大,里面图片个数可能超过1000,会导致内存飙升而崩溃
@property (assign, nonatomic) NSInteger gifPreviewMaxImagesCount;
@property (assign, nonatomic) BOOL showSelectedIndex;
@property (assign, nonatomic) BOOL showPhotoCannotSelectLayer;
@property (assign, nonatomic) BOOL notScaleImage;
@property (assign, nonatomic) BOOL needFixComposition;
/// 默认是50,如果一个GIF过大,里面图片个数可能超过1000,会导致内存飙升而崩溃
@property (assign, nonatomic) NSInteger gifPreviewMaxImagesCount;
/// 【自定义GIF播放方案】为了避免内存过大,内部默认限制只播放50帧(平均取),可通过gifPreviewMaxImagesCount属性调整,若对GIF预览有更好的效果要求,可实现这个block采用FLAnimatedImage等三方库来播放,但注意FLAnimatedImage有播放速度较慢问题,自行取舍下。
@property (nonatomic, copy) void (^gifImagePlayBlock)(TZPhotoPreviewView *view, UIImageView *imageView, NSData *gifData, NSDictionary *info);
@end
......@@ -874,7 +874,7 @@
if (config == nil) {
config = [[TZImagePickerConfig alloc] init];
config.preferredLanguage = nil;
config.gifPreviewMaxImagesCount = 200;
config.gifPreviewMaxImagesCount = 50;
}
});
return config;
......
......@@ -178,7 +178,11 @@
if (!isDegraded) {
self.isRequestingGIF = NO;
self.progressView.hidden = YES;
if ([TZImagePickerConfig sharedInstance].gifImagePlayBlock) {
[TZImagePickerConfig sharedInstance].gifImagePlayBlock(self, self.imageView, data, info);
} else {
self.imageView.image = [UIImage sd_tz_animatedGIFWithData:data];
}
[self resizeSubviews];
}
}];
......
......@@ -19,6 +19,7 @@
#import "TZLocationManager.h"
#import "TZAssetCell.h"
#import <MobileCoreServices/MobileCoreServices.h>
#import "FLAnimatedImage.h"
@interface ViewController ()<TZImagePickerControllerDelegate,UICollectionViewDataSource,UICollectionViewDelegate,UIImagePickerControllerDelegate,UIAlertViewDelegate,UINavigationControllerDelegate> {
NSMutableArray *_selectedPhotos;
......@@ -342,6 +343,25 @@
// 设置是否显示图片序号
imagePickerVc.showSelectedIndex = self.showSelectedIndexSwitch.isOn;
// 自定义gif播放方案
[[TZImagePickerConfig sharedInstance] setGifImagePlayBlock:^(TZPhotoPreviewView *view, UIImageView *imageView, NSData *gifData, NSDictionary *info) {
FLAnimatedImage *animatedImage = [FLAnimatedImage animatedImageWithGIFData:gifData];
FLAnimatedImageView *animatedImageView;
for (UIView *subview in imageView.subviews) {
if ([subview isKindOfClass:[FLAnimatedImageView class]]) {
animatedImageView = (FLAnimatedImageView *)subview;
animatedImageView.frame = imageView.bounds;
animatedImageView.animatedImage = nil;
}
}
if (!animatedImageView) {
animatedImageView = [[FLAnimatedImageView alloc] initWithFrame:imageView.bounds];
animatedImageView.runLoopMode = NSDefaultRunLoopMode;
[imageView addSubview:animatedImageView];
}
animatedImageView.animatedImage = animatedImage;
}];
// 设置首选语言 / Set preferred language
// imagePickerVc.preferredLanguage = @"zh-Hans";
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment