这是我第一个篇文章,后面希望自己能陆续记录自己遇到的小问题。
工作很多年了,我一直认为效率至上,所以一直都觉得记录是一件很浪费时间的事情。最近被一些事情触动,觉得记录是一个很好的习惯。现在开始养成也不晚。加油!!
下面进入正题!!!!!
###背景:
项目里图片库用的就是SD,最近想在图片缓存的过程中做些转码相关的工作。
于是写了下面的代码。
```
SDWebImageCacheSerializer *cs =
[SDWebImageCacheSerializer cacheSerializerWithBlock:
^NSData * _Nullable(
UIImage * _Nonnull image,
NSData * _Nullable data,
NSURL * _Nullable imageURL)
{
//中间不重要
return data;
}];
```
在整体方案中,我们做了开关,如果出现线上问题,以上代码会变成下面的样子。
```
SDWebImageCacheSerializer *cs =
[SDWebImageCacheSerializer cacheSerializerWithBlock:nil];
```
###问题描述:
把block设置成nil之后,下载到本地的gif图用电脑打开不能播放。
###问题定位:
SDImageCache.m 类中下面的方法
```
- (void)storeImage:(nullableUIImage*)image
imageData:(nullableNSData*)imageData
forKey:(nullableNSString*)key
toMemory:(BOOL)toMemory
toDisk:(BOOL)toDisk
completion:(nullableSDWebImageNoParamsBlock)completionBlock
```
有如下代码:
```
SDImageFormat format;
if ([SDImageCoderHelper CGImageContainsAlpha:image.CGImage]) {
format =SDImageFormatPNG;
}else{
format =SDImageFormatJPEG;
}
data = [[SDImageCodersManager sharedManager] encodedDataWithImage:image format:format options:nil];
```
###问题解答:
image.CGImage已经是解码之后的图片,通过判断图片是否有透明度,不管是啥图片都只存了两种类型,png、jpeg。
所以gif图片存成了png 就不能自动播放了。
###那图片gif图又是如何能正常播放的呢?
gif一定是有Alpha通道的(虽然不知道为什么)所以图片在存储的时候,存成了png图片。
下次启动图片解码的时候使用SDImageAPNGCoder这类解码,解码过程如下:
```
- (UIImage*)decodedImageWithData:(NSData*)data options:(nullableSDImageCoderOptions*)options {
。。。
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
if(!source) {
returnnil;
}
size_t count = CGImageSourceGetCount(source);
UIImage*animatedImage;
BOOLdecodeFirstFrame = [options[SDImageCoderDecodeFirstFrameOnly]boolValue];
if(decodeFirstFrame || count <=1) {
animatedImage = [[UIImagealloc]initWithData:datascale:scale];
}else{
NSMutableArray<SDImageFrame *> *frames = [NSMutableArray array];
for(size_ti =0; i < count; i++) {
CGImageRef imageRef = CGImageSourceCreateImageAtIndex(source, i, NULL);
if(!imageRef) {
continue;
}
floatduration = [selfsd_frameDurationAtIndex:isource:source];
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef scale:scale orientation:UIImageOrientationUp];
CGImageRelease(imageRef);
SDImageFrame *frame = [SDImageFrame frameWithImage:image duration:duration];
[framesaddObject:frame];
}
NSUIntegerloopCount = [selfsd_imageLoopCountWithSource:source];
animatedImage = [SDImageCoderHelper animatedImageWithFrames:frames];
animatedImage.sd_imageLoopCount= loopCount;
}
animatedImage.sd_imageFormat = SDImageFormatPNG;
CFRelease(source);
return animatedImage;
}
```
综上,gif图又解码成了序列帧。
###那如果是webp图片会怎么样?
图片存储的时候,调用CacheSerializer的block,block直接返回nil。那硬盘缓存只能存储已经解码过的image。然后在进行判断当前图片是否有透明度,选择存储png或者jpg。下次从缓存读取图片的时候,读取的就是png或者jpg。所以webp图片也不会有问题。
ps:sd这考虑的还是非常全面的,不会到是方案设计带来的意外惊喜,还是有意为之,总之厉害的很。
网友评论