Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webP with display link #7

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion WebPImageView.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ typedef void (^WebPAnimationFinished)(NSInteger);
@property(nonatomic)WebPImage *image;

/**
fetch the image from disk or remotely.
fetch the image from disk or remotely.
*/
@property(nonatomic)NSURL *url;

Expand Down
140 changes: 81 additions & 59 deletions WebPImageView.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,62 @@ @interface WebPImageView ()
@property(nonatomic)NSInteger iterationCount; //how times has the animation looped
@property(nonatomic)BOOL moveIndex;
@property(nonatomic, copy)NSString *context;

@property(nonatomic)CADisplayLink *displayLink;
@end

@implementation WebPImageView

- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
self.image = [[WebPImage alloc] init];
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayDidRefresh:)];
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
self.backgroundColor = [UIColor clearColor];
self.aspectScale = 1;
self.loopCount = 0;
self.displayLink.paused = YES;
self.layer.contentsScale = [UIScreen mainScreen].scale;

}
return self;
}

- (void)displayDidRefresh:(CADisplayLink *)link {

if (!self.animated || self.pause) {
return; //stop any running animated
}

if (self.iterationCount >= self.loopCount && self.loopCount > 0) {
return;
}

if (self.index > 0 && self.image.hasAlpha) {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:NO];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.prevImg = img;
}

if (self.index >= self.image.frames.count) {
self.index = 0;
self.prevImg = nil;
self.iterationCount++;
if (self.didFinishAnimation) {
self.didFinishAnimation(self.iterationCount);
}

if (self.iterationCount >= self.loopCount && self.loopCount > 0) {
self.index = self.image.frames.count-1;
return;
}
}
[self.layer setNeedsDisplay];

self.moveIndex = YES;
}

- (void)setBackgroundColor:(UIColor *)backgroundColor {
[super setBackgroundColor:backgroundColor];
CGFloat white = 0;
Expand Down Expand Up @@ -88,7 +130,7 @@ - (void)setUrl:(NSURL*)url progress:(WebPImageProgress)progress finished:(WebPIm
[manager cancelImageForSession:self.urlSessionId url:_url];
}
_url = url;

self.loadingView.hidden = NO;
[self.loadingView setProgress:0];
__weak typeof(self) weakSelf = self;
Expand All @@ -103,25 +145,34 @@ - (void)setUrl:(NSURL*)url progress:(WebPImageProgress)progress finished:(WebPIm
}];
}

- (NSInteger)frameInterval:(NSInteger)displayDuration {
return displayDuration*60/1000*2;
}

- (void)startDisplay {

self.loadingView.hidden = YES;
self.animated = NO;
self.prevImg = nil;
self.index = 0;
self.iterationCount = 0;
[self newContext];
[self invalidateIntrinsicContentSize];
[self setNeedsLayout];

if (self.image.frames.count > 1) {

WebPFrame *frame = self.image.frames[self.index];
self.displayLink.frameInterval = [self frameInterval:frame.displayDuration];
self.animated = YES;
[self doAnimation:self.image.frames[self.index]];
self.pause = NO;
}
[self setNeedsDisplay];
[self.layer setNeedsDisplay];

}

- (CGSize)intrinsicContentSize {
if (self) {
return self.image.size;
return self.image.size;
}
return CGSizeZero;
}
Expand All @@ -135,47 +186,6 @@ - (void)newContext {
self.context = [NSString stringWithFormat:@"%@",str];
}

-(void)doAnimation:(WebPFrame*)frame {
if (!self.animated || self.pause) {
return; //stop any running animated
}
if (self.iterationCount >= self.loopCount && self.loopCount > 0) {
return;
}
NSString *ctx = [self.context copy];
__weak typeof(self) weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, frame.displayDuration * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
if (weakSelf.index > 0 && weakSelf.image.hasAlpha) {
UIGraphicsBeginImageContextWithOptions(weakSelf.bounds.size, NO, 0.0);
[weakSelf drawViewHierarchyInRect:weakSelf.bounds afterScreenUpdates:NO];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
weakSelf.prevImg = img;
}

if (weakSelf.index >= weakSelf.image.frames.count) {
weakSelf.index = 0;
weakSelf.prevImg = nil;
weakSelf.iterationCount++;
if (weakSelf.didFinishAnimation) {
weakSelf.didFinishAnimation(weakSelf.iterationCount);
}
if (weakSelf.iterationCount >= weakSelf.loopCount && weakSelf.loopCount > 0) {
weakSelf.index = weakSelf.image.frames.count-1;
return;
}
}
if (weakSelf.pause) {
return;
}
[weakSelf setNeedsDisplay];
weakSelf.moveIndex = YES;
if([ctx isEqualToString:weakSelf.context]) {
[weakSelf doAnimation:weakSelf.image.frames[weakSelf.index]];
}
});
}

-(void)layoutSubviews {
[super layoutSubviews];
UIEdgeInsets inset = self.loadingInset;
Expand Down Expand Up @@ -209,13 +219,14 @@ -(void)layoutSubviews {
if (y < 0) {
y = 0;
}

self.offsetOrigin = CGPointMake(x, y);
}
}

- (void)setAspectScale:(CGFloat)aspectScale {
if (_aspectScale != aspectScale && !self.animated) {
[self setNeedsDisplay];
[self.layer setNeedsDisplay];
}
_aspectScale = aspectScale;
}
Expand All @@ -226,22 +237,28 @@ - (void)setPause:(BOOL)pause {
if (self.index >= self.image.frames.count) {
self.index = self.image.frames.count-1;
}
if(self.image.frames.count > 0) {
[self newContext];
[self doAnimation:self.image.frames[self.index]];
}
}
self.displayLink.paused = pause;
}

- (CGFloat)aspect {
return self.aspectScale;
}

- (void)drawRect:(CGRect)rect {
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {

if (self.image.frames.count == 0) {
return; //nothing to draw so don't even try
return;
}
CGContextRef ctx = UIGraphicsGetCurrentContext();
[self.backgroundColor setFill];

CGContextSetFillColorWithColor(ctx, self.backgroundColor.CGColor);

if (self.prevImg) {
UIGraphicsPushContext(ctx);
[self.prevImg drawInRect:self.bounds];
UIGraphicsPopContext();
}

if (self.index > 0 && self.index < self.image.frames.count) {
WebPFrame *prevFrame = self.image.frames[self.index-1];
if (prevFrame.dispose) {
Expand All @@ -255,7 +272,8 @@ - (void)drawRect:(CGRect)rect {
}
}
}
if(self.index > -1 && self.index < self.image.frames.count) {

if(self.index > -1 && self.index < _image.frames.count) {
WebPFrame *frame = self.image.frames[self.index];
CGRect imgFrame = CGRectMake(self.offsetOrigin.x + (frame.frame.origin.x/self.aspectScale),
self.offsetOrigin.y + (frame.frame.origin.y/self.aspectScale),
Expand All @@ -267,16 +285,20 @@ - (void)drawRect:(CGRect)rect {
CGContextFillRect(ctx, imgFrame);
}
}

UIGraphicsPushContext(ctx);
[frame.image drawInRect:imgFrame];
UIGraphicsPopContext();

if (self.moveIndex) {
self.index++;
self.moveIndex = NO;
}
}
}

- (CGFloat)aspect {
return self.aspectScale;
- (void)dealloc {
[self.displayLink removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}

@end