YYWebImage icon indicating copy to clipboard operation
YYWebImage copied to clipboard

处理Webp图片有问题

Open AbooJan opened this issue 9 years ago • 6 comments

原图片地址:http://78re52.com1.z0.glb.clouddn.com/resource/Ship.jpg Webp图片地址:http://78re52.com1.z0.glb.clouddn.com/resource/Ship.jpg?imageView2/2/format/webp

我直接用 YYWebImageManager 类里面的 requestImageWithURL 方法把图片下载下来,发现下载到的Webp图片竟然比原图片大了7倍多!!!!!! 我用 yy_setImageWithURL 方法显示图片,缓存到的图片也是大了7倍多!!!

而我同样用 SDWebImageManager 里面的 downloadImageWithURL 方法下载图片,发现webp图片的大小才正常。

希望可以尽快修复

AbooJan avatar Dec 02 '16 10:12 AbooJan

@ibireme 我看源码里面下载图片用的还是之前的 NSURLConnection, SDWebImage 已经改用NSURLSession.

        // request image from web
        [_lock lock];
        if (![self isCancelled]) {
            _connection = [[NSURLConnection alloc] initWithRequest:_request delegate:[_YYWebImageWeakProxy proxyWithTarget:self]];
            if (![_request.URL isFileURL] && (_options & YYWebImageOptionShowNetworkActivity)) {
                [YYWebImageManager incrementNetworkActivityCount];
            }
        }
        [_lock unlock];

AbooJan avatar Dec 04 '16 10:12 AbooJan

@ibireme 可以参考一下SDWebImage里面对Webp图片的处理,我看它里面只引用了一个头文件 webp/decode.h,方法也挺简洁:

+ (UIImage *)sd_imageWithWebPData:(NSData *)data {
    WebPDecoderConfig config;
    if (!WebPInitDecoderConfig(&config)) {
        return nil;
    }

    if (WebPGetFeatures(data.bytes, data.length, &config.input) != VP8_STATUS_OK) {
        return nil;
    }

    config.output.colorspace = config.input.has_alpha ? MODE_rgbA : MODE_RGB;
    config.options.use_threads = 1;

    // Decode the WebP image data into a RGBA value array.
    if (WebPDecode(data.bytes, data.length, &config) != VP8_STATUS_OK) {
        return nil;
    }

    int width = config.input.width;
    int height = config.input.height;
    if (config.options.use_scaling) {
        width = config.options.scaled_width;
        height = config.options.scaled_height;
    }

    // Construct a UIImage from the decoded RGBA value array.
    CGDataProviderRef provider =
    CGDataProviderCreateWithData(NULL, config.output.u.RGBA.rgba, config.output.u.RGBA.size, FreeImageData);
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = config.input.has_alpha ? kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast : 0;
    size_t components = config.input.has_alpha ? 4 : 3;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
    CGImageRef imageRef = CGImageCreate(width, height, 8, components * 8, components * width, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

    CGColorSpaceRelease(colorSpaceRef);
    CGDataProviderRelease(provider);

    UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
    CGImageRelease(imageRef);

    return image;
}

AbooJan avatar Dec 04 '16 10:12 AbooJan

@ibireme 在类 YYImageCoder 的方法 _updateSourceWebP 里面,本来 _datalength 只有 574090, 转化后的 webPDatasize 也是这个大小,最后到沙盒里面去看缓存到图片竟然有 15.6M ,我觉得问题出在这里

AbooJan avatar Dec 04 '16 10:12 AbooJan

要看缓存的是解压缩前的还是后的,sd目前目前缓存的源文件,每次使用前解压

CodeLife2012 avatar Dec 15 '16 06:12 CodeLife2012

不一定是bug,只是策略不同

CodeLife2012 avatar Dec 15 '16 06:12 CodeLife2012

@AbooJan 大神 怎么实现webp文件只播放一次

Mr-lins avatar May 11 '17 11:05 Mr-lins