From fe0e42afc25d66efeb0ceaefbec089b99f93cf90 Mon Sep 17 00:00:00 2001 From: zxiou Date: Thu, 21 Nov 2019 19:17:44 +0800 Subject: [PATCH 1/3] fix the core render of SDAnimatedImagePlayer and fix assignment animationRepeatCount does not work Signed-off-by: zxiou --- .DS_Store | Bin 0 -> 6148 bytes Examples/.DS_Store | Bin 0 -> 6148 bytes .../SDWebImage Demo/DetailViewController.m | 2 + .../SDWebImage Demo/MasterViewController.m | 1 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 ++ SDWebImage/.DS_Store | Bin 0 -> 6148 bytes SDWebImage/Core/SDAnimatedImagePlayer.m | 118 ++++++++++-------- SDWebImage/Core/SDAnimatedImageView.m | 13 ++ 8 files changed, 90 insertions(+), 52 deletions(-) create mode 100644 .DS_Store create mode 100644 Examples/.DS_Store create mode 100644 SDWebImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 SDWebImage/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..2d16dfcc10fe0dc9f4cb84573ae26c03191498de GIT binary patch literal 6148 zcmeHKL2uJA6n^dsq(g`vCfLyzPODI>!nz$Mg%S?CAu?^!0By+{(reAtH(crbu)ZnhaP3K#`$ngXa`9OXs3{gc(! z>bGv+u^RZhXT5cYqI3(d80UR2dreO-y<+HV|3HZNx9|CfQCOZdH=c{6@S-HlBsmH~ zobu)##W)FaxsIy>l&5jh+?-6dySpv^w7WBH@ky`OZt*AG?dh~(J$%&J+dmzB z`aJnE{d%s{W%x3Zc3TX~D&fIj>MpU~4BkVIwR@;TI8!_H zj+f=nkydMF*xYA53Rv`i8<}c3hv!>A-A-rZ);01!fgk zQ;$tL|6lz1{y$4HPeuWwz<;Fxt2?gK$CC8fI#(Q>wH(_iHZq!5DU=lK^l>a5I*K>3 bNy8W?2hrA8DZ~*p^C2K*Fr86gr3(B460Dw@ literal 0 HcmV?d00001 diff --git a/Examples/.DS_Store b/Examples/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..fa4d26ea88797260ea849d0f24dece6255454310 GIT binary patch literal 6148 zcmeHKyG{c^3>-s>NED=`++W}iR?$&VUqK6qC=DbM5~;7^yZAK54R+`PKil})$n0;v()XH#$nA@s@^(#Iq$WNeoyzB54s!I oL1Bn?OpJESjkn{gD9XC#Yd-IVQ)1AW4?0ml1Fnlq3jDPKpS%Yac>n+a literal 0 HcmV?d00001 diff --git a/Examples/SDWebImage Demo/DetailViewController.m b/Examples/SDWebImage Demo/DetailViewController.m index 4327c9dd..ee9be9df 100644 --- a/Examples/SDWebImage Demo/DetailViewController.m +++ b/Examples/SDWebImage Demo/DetailViewController.m @@ -24,6 +24,8 @@ [self.imageView sd_setImageWithURL:self.imageURL placeholderImage:nil options:SDWebImageProgressiveLoad]; + self.imageView.shouldCustomLoopCount = YES; + self.imageView.animationRepeatCount = NSIntegerMax; } - (void)viewDidLoad { diff --git a/Examples/SDWebImage Demo/MasterViewController.m b/Examples/SDWebImage Demo/MasterViewController.m index 14aea5ca..bb86ba17 100644 --- a/Examples/SDWebImage Demo/MasterViewController.m +++ b/Examples/SDWebImage Demo/MasterViewController.m @@ -63,6 +63,7 @@ [SDWebImageDownloader sharedDownloader].config.executionOrder = SDWebImageDownloaderLIFOExecutionOrder; self.objects = [NSMutableArray arrayWithObjects: + @"https://s2.ax1x.com/2019/11/01/KHYIgJ.gif", @"http://www.httpwatch.com/httpgallery/authentication/authenticatedimage/default.aspx?0.35786508303135633", // requires HTTP auth, used to demo the NTLM auth @"http://assets.sbnation.com/assets/2512203/dogflops.gif", @"https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif", diff --git a/SDWebImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SDWebImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/SDWebImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/SDWebImage/.DS_Store b/SDWebImage/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..516153fe4952f37097299528382f83d7f653aab6 GIT binary patch literal 6148 zcmeHK!AiqG5Z!H~CWzRBV2`!GD;y$GSL2X8_|4=Qa!f(^uMNm7f}N`6EC$S?4B zoY~zLOBFnc*qJcsotMhS+WLlR!Lw!FxC1eEb1xrdZ7;pT z-kFyVd~Kf#5zlSUzlg$dud>q-N$y2Sn9AfR2qEP9GD-q5Zi`V8WO5!?4d6OfuTq^% zng`9Ay?<1n*6c~ERR_CyIGtMN?q1{gw14;TIC+{rzbIBYe1KB6HO}A_jCq0gZkog* zxdq=Weilba3=jjvzzQ*-w?K1qg=(f!i2-8ZXAI!}V1pt$8ViMT>wpG-A9373L;)M` z5{R}&M`NK7MnJeq1yreAUop5!2fwZ39F2uSmCm?a8RpR|bA3bMa&_?AGMsToA+^K+ zF|f!$S#>LT{-1n*|6fd^9x*@+{3`~y(RI6RC`q5KOU2oxg eM{yNY3ixd_03D5mLhyjlkAS3s8e-sA8TbIFeo$oq literal 0 HcmV?d00001 diff --git a/SDWebImage/Core/SDAnimatedImagePlayer.m b/SDWebImage/Core/SDAnimatedImagePlayer.m index 2efd8805..39658b43 100644 --- a/SDWebImage/Core/SDAnimatedImagePlayer.m +++ b/SDWebImage/Core/SDAnimatedImagePlayer.m @@ -23,6 +23,7 @@ @property (nonatomic, strong) NSMutableDictionary *frameBuffer; @property (nonatomic, assign) NSTimeInterval currentTime; @property (nonatomic, assign) BOOL bufferMiss; +@property (nonatomic, assign) BOOL needsDisplayWhenImageBecomesAvailable; @property (nonatomic, assign) NSUInteger maxBufferCount; @property (nonatomic, strong) NSOperationQueue *fetchQueue; @property (nonatomic, strong) dispatch_semaphore_t lock; @@ -165,6 +166,7 @@ self.currentLoopCount = 0; self.currentTime = 0; self.bufferMiss = NO; + self.needsDisplayWhenImageBecomesAvailable = NO; [self handleFrameChange]; } @@ -217,8 +219,6 @@ if (!self.isPlaying) { return; } - // Calculate refresh duration - NSTimeInterval duration = self.displayLink.duration; NSUInteger totalFrameCount = self.totalFrameCount; if (totalFrameCount <= 1) { @@ -226,8 +226,6 @@ [self stopPlaying]; return; } - NSUInteger currentFrameIndex = self.currentFrameIndex; - NSUInteger nextFrameIndex = (currentFrameIndex + 1) % totalFrameCount; NSTimeInterval playbackRate = self.playbackRate; if (playbackRate <= 0) { @@ -236,7 +234,46 @@ return; } - // Check if we have the frame buffer firstly to improve performance + // Calculate refresh duration + NSTimeInterval duration = self.displayLink.duration; + + NSUInteger currentFrameIndex = self.currentFrameIndex; + NSUInteger nextFrameIndex = (currentFrameIndex + 1) % totalFrameCount; + + // Check if we need to display new frame firstly + BOOL bufferFull = NO; + if (self.needsDisplayWhenImageBecomesAvailable) { + UIImage *currentFrame; + SD_LOCK(self.lock); + currentFrame = self.frameBuffer[@(currentFrameIndex)]; + SD_UNLOCK(self.lock); + + // Update the current frame + if (currentFrame) { + SD_LOCK(self.lock); + // Remove the frame buffer if need + if (self.frameBuffer.count > self.maxBufferCount) { + self.frameBuffer[@(currentFrameIndex)] = nil; + } + // Check whether we can stop fetch + if (self.frameBuffer.count == totalFrameCount) { + bufferFull = YES; + } + SD_UNLOCK(self.lock); + + // Update the current frame immediately + self.currentFrame = currentFrame; + [self handleFrameChange]; + + self.bufferMiss = NO; + self.needsDisplayWhenImageBecomesAvailable = NO; + } + else { + self.bufferMiss = YES; + } + } + + // Check if we have the frame buffer if (!self.bufferMiss) { // Then check if timestamp is reached self.currentTime += duration; @@ -246,6 +283,10 @@ // Current frame timestamp not reached, return return; } + + // Otherwise, we shoudle be ready to display next frame + self.needsDisplayWhenImageBecomesAvailable = YES; + self.currentFrameIndex = nextFrameIndex; self.currentTime -= currentDuration; NSTimeInterval nextDuration = [self.animatedProvider animatedImageDurationAtIndex:nextFrameIndex]; nextDuration = nextDuration / playbackRate; @@ -253,45 +294,19 @@ // Do not skip frame self.currentTime = nextDuration; } - } - - // Update the current frame - UIImage *currentFrame; - UIImage *fetchFrame; - SD_LOCK(self.lock); - currentFrame = self.frameBuffer[@(currentFrameIndex)]; - fetchFrame = currentFrame ? self.frameBuffer[@(nextFrameIndex)] : nil; - SD_UNLOCK(self.lock); - BOOL bufferFull = NO; - if (currentFrame) { - SD_LOCK(self.lock); - // Remove the frame buffer if need - if (self.frameBuffer.count > self.maxBufferCount) { - self.frameBuffer[@(currentFrameIndex)] = nil; - } - // Check whether we can stop fetch - if (self.frameBuffer.count == totalFrameCount) { - bufferFull = YES; - } - SD_UNLOCK(self.lock); - self.currentFrame = currentFrame; - [self handleFrameChange]; - self.currentFrameIndex = nextFrameIndex; - self.bufferMiss = NO; - } else { - self.bufferMiss = YES; - } - - // Update the loop count when last frame rendered - if (nextFrameIndex == 0 && !self.bufferMiss) { - // Update the loop count - self.currentLoopCount++; - [self handleLoopChnage]; - // if reached the max loop count, stop animating, 0 means loop indefinitely - NSUInteger maxLoopCount = self.totalLoopCount; - if (maxLoopCount != 0 && (self.currentLoopCount >= maxLoopCount)) { - [self stopPlaying]; - return; + + // Update the loop count when last frame rendered + if (nextFrameIndex == 0) { + // Update the loop count + self.currentLoopCount++; + [self handleLoopChnage]; + + // if reached the max loop count, stop animating, 0 means loop indefinitely + NSUInteger maxLoopCount = self.totalLoopCount; + if (maxLoopCount != 0 && (self.currentLoopCount >= maxLoopCount)) { + [self stopPlaying]; + return; + } } } @@ -301,14 +316,13 @@ } // Check if we should prefetch next frame or current frame - NSUInteger fetchFrameIndex; - if (self.bufferMiss) { - // When buffer miss, means the decode speed is slower than render speed, we fetch current miss frame - fetchFrameIndex = currentFrameIndex; - } else { - // Or, most cases, the decode speed is faster than render speed, we fetch next frame - fetchFrameIndex = nextFrameIndex; - } + // When buffer miss, means the decode speed is slower than render speed, we fetch current miss frame + // Or, most cases, the decode speed is faster than render speed, we fetch next frame + NSUInteger fetchFrameIndex = self.bufferMiss? currentFrameIndex : nextFrameIndex; + UIImage *fetchFrame; + SD_LOCK(self.lock); + fetchFrame = self.bufferMiss? nil : self.frameBuffer[@(nextFrameIndex)]; + SD_UNLOCK(self.lock); if (!fetchFrame && !bufferFull && self.fetchQueue.operationCount == 0) { // Prefetch next frame in background queue diff --git a/SDWebImage/Core/SDAnimatedImageView.m b/SDWebImage/Core/SDAnimatedImageView.m index 181f2db9..78f1cb8b 100644 --- a/SDWebImage/Core/SDAnimatedImageView.m +++ b/SDWebImage/Core/SDAnimatedImageView.m @@ -306,6 +306,19 @@ #pragma mark - UIImageView Method Overrides #pragma mark Image Data +- (void)setAnimationRepeatCount:(NSInteger)animationRepeatCount +{ +#if SD_UIKIT + [super setAnimationRepeatCount:animationRepeatCount]; +#else + _animationRepeatCount = animationRepeatCount; +#endif + + if (self.shouldCustomLoopCount) { + self.player.totalLoopCount = animationRepeatCount; + } +} + - (void)startAnimating { if (self.player) { From d5da5dbef7362a683c2bb1d0dc7eac7f5459ab2b Mon Sep 17 00:00:00 2001 From: zxiou Date: Thu, 21 Nov 2019 19:32:11 +0800 Subject: [PATCH 2/3] delete useless files --- .DS_Store | Bin 6148 -> 0 bytes Examples/.DS_Store | Bin 6148 -> 0 bytes SDWebImage/.DS_Store | Bin 6148 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store delete mode 100644 Examples/.DS_Store delete mode 100644 SDWebImage/.DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 2d16dfcc10fe0dc9f4cb84573ae26c03191498de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKL2uJA6n^dsq(g`vCfLyzPODI>!nz$Mg%S?CAu?^!0By+{(reAtH(crbu)ZnhaP3K#`$ngXa`9OXs3{gc(! z>bGv+u^RZhXT5cYqI3(d80UR2dreO-y<+HV|3HZNx9|CfQCOZdH=c{6@S-HlBsmH~ zobu)##W)FaxsIy>l&5jh+?-6dySpv^w7WBH@ky`OZt*AG?dh~(J$%&J+dmzB z`aJnE{d%s{W%x3Zc3TX~D&fIj>MpU~4BkVIwR@;TI8!_H zj+f=nkydMF*xYA53Rv`i8<}c3hv!>A-A-rZ);01!fgk zQ;$tL|6lz1{y$4HPeuWwz<;Fxt2?gK$CC8fI#(Q>wH(_iHZq!5DU=lK^l>a5I*K>3 bNy8W?2hrA8DZ~*p^C2K*Fr86gr3(B460Dw@ diff --git a/Examples/.DS_Store b/Examples/.DS_Store deleted file mode 100644 index fa4d26ea88797260ea849d0f24dece6255454310..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKyG{c^3>-s>NED=`++W}iR?$&VUqK6qC=DbM5~;7^yZAK54R+`PKil})$n0;v()XH#$nA@s@^(#Iq$WNeoyzB54s!I oL1Bn?OpJESjkn{gD9XC#Yd-IVQ)1AW4?0ml1Fnlq3jDPKpS%Yac>n+a diff --git a/SDWebImage/.DS_Store b/SDWebImage/.DS_Store deleted file mode 100644 index 516153fe4952f37097299528382f83d7f653aab6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK!AiqG5Z!H~CWzRBV2`!GD;y$GSL2X8_|4=Qa!f(^uMNm7f}N`6EC$S?4B zoY~zLOBFnc*qJcsotMhS+WLlR!Lw!FxC1eEb1xrdZ7;pT z-kFyVd~Kf#5zlSUzlg$dud>q-N$y2Sn9AfR2qEP9GD-q5Zi`V8WO5!?4d6OfuTq^% zng`9Ay?<1n*6c~ERR_CyIGtMN?q1{gw14;TIC+{rzbIBYe1KB6HO}A_jCq0gZkog* zxdq=Weilba3=jjvzzQ*-w?K1qg=(f!i2-8ZXAI!}V1pt$8ViMT>wpG-A9373L;)M` z5{R}&M`NK7MnJeq1yreAUop5!2fwZ39F2uSmCm?a8RpR|bA3bMa&_?AGMsToA+^K+ zF|f!$S#>LT{-1n*|6fd^9x*@+{3`~y(RI6RC`q5KOU2oxg eM{yNY3ixd_03D5mLhyjlkAS3s8e-sA8TbIFeo$oq From dd8ea8f7fbca9c9ba29d55bb945cddc0812cd736 Mon Sep 17 00:00:00 2001 From: zxiou Date: Fri, 22 Nov 2019 11:49:57 +0800 Subject: [PATCH 3/3] delete IDEWorkspaceChecks --- .DS_Store | Bin 0 -> 8196 bytes .../xcshareddata/IDEWorkspaceChecks.plist | 8 -------- SDWebImage/.DS_Store | Bin 0 -> 8196 bytes 3 files changed, 8 deletions(-) create mode 100644 .DS_Store delete mode 100644 SDWebImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 SDWebImage/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..eeded2ff3a566d60f92b5dce46dd51e480df6b18 GIT binary patch literal 8196 zcmeI1O^?z*7{{Ms(Jh*d95%|a7f)_XSq*S8LADp1=0EN8OVjcc0AQV=Uk9iGfPqzL^&&P4ikKI5 zu9Wo17AiwOKnOj^ydq1yXl^wP5CI}U1c(3;AOh<^0H4{S7-u~9)hx9{fC&7T1jPNp z#45C{b)r<>IXUgTk+DfS<0z_b*fXLl9VGlUO@O(Od=N`@+dr1^#xn+H2rH%5r z^P5HmKU>B#r_T!~ck^M^anmQ_+dVh$d%FLC^XR1SdXK`OIIM2(@i=$GI7p>A^aEV- z^dO9VUUc{{_A|MUqb9_0Du>nDXtdjE?3g#L=6J^(HJcXpZ#2f^igD#?{nmbW@aFC4 z-T3_n6&cfa2e>p7>BspnUpZ+U@wkUG!gT>0u;Bm#@L(SX;Nq){K)uRX8x$>T7sGF~ zRz|Tf*cl+(i-5p&cnwE*wfG1sffRc$qF&uO;)6sYFR^Q=f9xG_+x8*}*m(S-~X?96m)t-fC#KYfR$~>?%)nTe?8A` zCUR{PYZt31V%hL@AD7p%(!X12sh8pAz^1W)Krj literal 0 HcmV?d00001 diff --git a/SDWebImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/SDWebImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d98100..00000000 --- a/SDWebImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/SDWebImage/.DS_Store b/SDWebImage/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..3ed219f226727dcd24292f55e3fccd9848d5849f GIT binary patch literal 8196 zcmeHMT}&KR6u#dA?Tj7DfLN%y*+pz2NG((ZTD0A=w6=w&*rh!57b+J4=8TeQ8XS&fUyC z_nvd^xpThx?%dp2#u(bOS|ekXj4_EWF4a|3U8Qh4zpf}DUsFgDG@hl#ow1Z@r>KAN z3hzJ>AP^uBAP^uBAP^vMJs?1PHZRgL`@XOSb$~#CzzvB2e?LU&;xgvT86mw_2UXq? zfFwTxc!k<3Z;*`oGUm$}A<04oVkk*56#fwdVmRrezF*9jGeU~t4F2H*{><=CDDY;d z_)*WDAtq!{2M7cRT!{c*K7}mKY?fjA!t;A-%rqRgq2X(U3JQx>tdwN>6-y5#M(pu~ zn{=~IdonY~d)-NQB;~hzY}=e~CsVzKK0c(D$8F0^8kU~%1{<1AE{FOIOS8w@?X0Ca zUYvw5@Ok7RwQ_2zwP90zw5hpux;{G9($YZfdzz=GWvOCa2dJ)K>9m3{q2+O`tLaeYWFaVW>#)a}mb zIm)LmZJXIq%NbHj(@8U(HIuHs-88u~=}Me*#x~7v+c8|jwhs2Y`h=Sgw8+#y;Mf^A z?gblC)vTlM*D02f(>o|4g(~B-?Hl7^oL)WSkgSe1i1g$$t1BXR)^6C;a$ju6Y>8T0 zrj#pd`f`S2q)h$5xS_ct2a`@(w=}~V9w1~b*EnM68Mzeoa*vf9)o05p*WP;D?cwlJ z?|hX0Y|1#6HQY(HT9U*ZRpDw`JtrN~=nnVV8jq-XmT*Zp8ZIaq4_vJ*|LRqeCljQ!iJvvIs zI6~JR?vT_A(!+e>uB7Ac8`CYCo2Rz3DjYt@_1iT~*Ca`*j`huW=vBvR1&Y-|Fy;Xw zt9%m*v-PZ%w!0p7gcikP>=ZlA&a(6DL-rZ_id|;kv7gzW>@POQ{sx1L60AiP>QIjj zxEn2K#TK+-7aqiZBrt>#7&r)vv!oO!*ub&{bq#phET;_xZXRClbrv< eklIn-7W3tdkYu6qzkdj@g8e_(|2^v6(A7UOUMBVc literal 0 HcmV?d00001