Skip to content

Commit

Permalink
webP with display link
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Mork committed Jul 26, 2016
1 parent 1fd3b4d commit d5ce662
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 60 deletions.
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

0 comments on commit d5ce662

Please sign in to comment.