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

Animated WebP Image not showing correctly using UIImageView or FLAnimatedImageView #1951

Closed
dreampiggy opened this Issue Jun 29, 2017 · 7 comments

Comments

Projects
None yet
2 participants
@dreampiggy
Contributor

dreampiggy commented Jun 29, 2017

New Issue Checklist

Issue Info

Info Value
Platform Name ios
Platform Version 7.0-10.0
SDWebImage Version 4.0
Integration Method cocoapods
Xcode Version Xcode 8.3.2
Repro rate all the time (100%)
Repro with our demo prj YES, the demo Image-5 renders wrong.
Demo project link https://github.com/dreampiggy/AnimatedWebPDemo

Issue Description and Steps

Description:

SDWebImage 4.0 add support to animated WebP. But when downloading and showing some of animated WebP using SDWebImage API(eg. sd_setImageWithURL:) to UIImageView or FLAnimatedImageView instance, the imageview can't render correctly.

Comparing to another animated WebP library (YYImage), it seems that the decoder for WebP to get per frame images works wrong.

Also, current implementation does not support WebP disposal method, which cause many animated WebP images look strange. And due to UIImage's API, the duration parameter just use the average duration for each frame, which is different from the animated WebP standard which allows set different duration per frame and also cause some images look strange.

For more detail and intuitive effect, you can go to the demo project to build and run.

Step:

  1. find some animated WebP images' URLs.
  2. create an FLAnimatedImageView or UIImageView instance and use sd_setImageWithURL: API to set image.
  3. when showing animated WebP images, the images not showing correctly(looks strange).

@dreampiggy dreampiggy changed the title from Animated WebP Image not showing correctly using neither UIImageView nor FLAnimatedImageView to Animated WebP Image not showing correctly using UIImageView or FLAnimatedImageView Jun 29, 2017

@dreampiggy

This comment has been minimized.

Contributor

dreampiggy commented Jun 29, 2017

By reading the decoder from YYImage and SDWebImage , I found that for single frame animated WebP, the libwebp's WebPBitstreamFeatures.height and width is the images' actual size. But for multiple frame images, this will return the current frame canvas size(but not image size, which can be smaller than total image size). This will make the final UIImage array contains different size, cause UIImageView render bug(The UIKit doc specify "All images included in the animated image should share the same size and scale."). We should useWebPDemuxGetI to get the actual image size.

Looks at this animated webp image (actual size is 100x100), but the rendered animated images array (via none blend mode) used for +[UIImage animatedImageWithImages:duration:] show the wrong size.

Xcode debug

@dreampiggy

This comment has been minimized.

Contributor

dreampiggy commented Jun 29, 2017

The YYImageCoder code reference :YYImage

This image size is correct:
Xcode debug

@dreampiggy

This comment has been minimized.

Contributor

dreampiggy commented Jun 29, 2017

There is an simple fix(which first create UIImage through CGImageCreate from WebPData. Then draw this UIImage to an new CGBitmapContext with actual size(not just the canvas size).

fix screenshot

The simple fix fork is here: SDWebImage

Consider a higher performance(because create CGBitmapContext waste extra time), maybe we can modify the RGBA vector transform to do these. I found that YYImage use the vImage_Buffer and add an vImage_CGAffineTransform to do this vector transform(refer here). I will try this solution for performance later.

@dreampiggy

This comment has been minimized.

Contributor

dreampiggy commented Jun 30, 2017

Also, I found that the animated WebP dipose method(see here) is not support, currently is assume that all frames use the background disposal.

By sharing a blend canvas while decoding multiple frame animated webp image, we could do disposal and blend correctly(not relay on that last image).

@dreampiggy

This comment has been minimized.

Contributor

dreampiggy commented Jun 30, 2017

PR is here: #1952

@dreampiggy

This comment has been minimized.

Contributor

dreampiggy commented Jul 3, 2017

Because +[UIImage animatedImageWithImages:duration:] just use the average duration for each frame, which is not the animated WebP standard. Animated WebP can has different duration per frame. Therefore, we should divide the total duration and add image item multiple times to solve this issue. The code like this:

NSArray<UIImage *> *)images;
NSUInteger count = images.count;
int durations[count];
int const gcd = gcdArray(count, durations);
NSMutableArray<UIImage *> *animatedImages = [NSMutableArray arrayWithCapacity:count];
[images enumerateObjectsUsingBlock:^(UIImage * _Nonnull image, NSUInteger idx, BOOL * _Nonnull stop) {
    int duration = durations[idx];
    int repeatCount = duration / gcd;
    for (int i = 0; i < repeatCount; ++i) {
        [animatedImages addObject:image];
    }
}];

@bpoplauschi bpoplauschi added this to the 4.1.0 milestone Jul 24, 2017

bpoplauschi added a commit that referenced this issue Jul 31, 2017

Merge pull request #1952 from dreampiggy/master
#1951: Fix animated WebP decoding issue, including canvas size, the support for dispose method and the duration per frame
@bpoplauschi

This comment has been minimized.

Member

bpoplauschi commented Jul 31, 2017

Fixed by #1952

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment