SDWebImage源码解析(二)

Posted by 黄成都 on 2017-05-02
Words 3.1k and Reading Time 15 Minutes
Viewed Times

1 概述

SDWebImage使用了很多工具类来对图片的处理。比如获取图片类型、图片放大缩小、GIF图片处理、图片解压缩处理等。接下来我就要分析下面这几个工具类的实现。

2 NSData+ImageContentType分析

这个类提供了一个类方法sd_imageFormatForImageData。通过这个方法传入图片的NSData数据,然后返回图片类型。图片类型通过SDImageFormat来定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/**
不同图片类型的枚举

- SDImageFormatUndefined: 未知
- SDImageFormatJPEG: JPG
- SDImageFormatPNG: PNG
- SDImageFormatGIF: GIF
- SDImageFormatTIFF: TIFF
- SDImageFormatWebP: WEBP
*/
typedef NS_ENUM(NSInteger, SDImageFormat) {
SDImageFormatUndefined = -1,
SDImageFormatJPEG = 0,
SDImageFormatPNG,
SDImageFormatGIF,
SDImageFormatTIFF,
SDImageFormatWebP
};
/**
根据图片NSData获取图片的类型

@param data NSData数据
@return 图片数据类型
*/
+ (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data {
if (!data) {
return SDImageFormatUndefined;
}

uint8_t c;
//获取图片数据的第一个字节数据
[data getBytes:&c length:1];
//根据字母的ASC码比较
switch (c) {
case 0xFF:
return SDImageFormatJPEG;
case 0x89:
return SDImageFormatPNG;
case 0x47:
return SDImageFormatGIF;
case 0x49:
case 0x4D:
return SDImageFormatTIFF;
case 0x52:
// R as RIFF for WEBP
if (data.length < 12) {
return SDImageFormatUndefined;
}

NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
return SDImageFormatWebP;
}
}
return SDImageFormatUndefined;
}

3 SDWebImageCompat分析

SDWebImageCompat就提供一个全局方法SDScaledImageForKey。这个方法根据原始图片绘制一张放大或者缩小的图片。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
给定一张图片,通过scale属性返回一个放大的图片。

@param key 图片名称
@param image 资源图片
@return 处理以后的图片
*/
inline UIImage *SDScaledImageForKey(NSString * _Nullable key, UIImage * _Nullable image) {
//异常处理
if (!image) {
return nil;
}
#if SD_MAC
return image;
#elif SD_UIKIT || SD_WATCH
//如果是动态图片,比如GIF图片,则迭代处理
if ((image.images).count > 0) {
NSMutableArray<UIImage *> *scaledImages = [NSMutableArray array];
//迭代处理每一张图片
for (UIImage *tempImage in image.images) {
[scaledImages addObject:SDScaledImageForKey(key, tempImage)];
}
//把处理结束的图片再合成一张动态图片
return [UIImage animatedImageWithImages:scaledImages duration:image.duration];
}
else {//非动态图片
#if SD_WATCH
if ([[WKInterfaceDevice currentDevice] respondsToSelector:@selector(screenScale)]) {
#elif SD_UIKIT
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
#endif
CGFloat scale = 1;
// “@2x.png”的长度为7,所以此处添加了这个判断,很巧妙
if (key.length >= 8) {
NSRange range = [key rangeOfString:@"@2x."];
if (range.location != NSNotFound) {
scale = 2.0;
}

range = [key rangeOfString:@"@3x."];
if (range.location != NSNotFound) {
scale = 3.0;
}
}
//返回对应分辨率下面的图片
UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
image = scaledImage;
}
return image;
}
#endif
}

4 UIImage+MultiFormat分类分析

UIImage+MultiFormat分类实现了NSData与UIImage对象之间的相互转换。并且是根据图片类型做转换。比如GIF的UIImage转换为GIF格式的NSData。
并且还有UIImage的Orientation和alpha的处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/**
根据image的data数据。生成对应的image对象

@param data 图片的数据
@return image对象
*/
+ (nullable UIImage *)sd_imageWithData:(nullable NSData *)data {
if (!data) {
return nil;
}
UIImage *image;
//获取data的图片类型,png,gif,jpg
SDImageFormat imageFormat = [NSData sd_imageFormatForImageData:data];
if (imageFormat == SDImageFormatGIF) {
//gif处理:返回一张只包含数据第一张image 的gif图片
image = [UIImage sd_animatedGIFWithData:data];
}
#ifdef SD_WEBP
else if (imageFormat == SDImageFormatWebP)
{
image = [UIImage sd_imageWithWebPData:data];
}
#endif
else {
image = [[UIImage alloc] initWithData:data];
#if SD_UIKIT || SD_WATCH
//获取方向
UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data];
//如果不是向上的,还需要再次生成图片
if (orientation != UIImageOrientationUp) {
image = [UIImage imageWithCGImage:image.CGImage
scale:image.scale
orientation:orientation];
}
#endif
}


return image;
}

#if SD_UIKIT || SD_WATCH

/**
根据图片数据获取图片的方向

@param imageData 图片数据
@return 方向
*/
+(UIImageOrientation)sd_imageOrientationFromImageData:(nonnull NSData *)imageData {
//默认是向上的
UIImageOrientation result = UIImageOrientationUp;
CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
if (imageSource) {
//获取图片的属性列表
CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL);
if (properties) {
CFTypeRef val;
int exifOrientation;
//获取图片方向
val = CFDictionaryGetValue(properties, kCGImagePropertyOrientation);
if (val) {
CFNumberGetValue(val, kCFNumberIntType, &exifOrientation);
result = [self sd_exifOrientationToiOSOrientation:exifOrientation];
} // else - if it's not set it remains at up
CFRelease((CFTypeRef) properties);
} else {
//NSLog(@"NO PROPERTIES, FAIL");
}
CFRelease(imageSource);
}
return result;
}
/**
根据不同的值返回不同的图片方向

@param exifOrientation 输入值
@return 图片的方向
*/
+ (UIImageOrientation) sd_exifOrientationToiOSOrientation:(int)exifOrientation {
UIImageOrientation orientation = UIImageOrientationUp;
switch (exifOrientation) {
case 1:
orientation = UIImageOrientationUp;
break;

case 3:
orientation = UIImageOrientationDown;
break;

case 8:
orientation = UIImageOrientationLeft;
break;

case 6:
orientation = UIImageOrientationRight;
break;

case 2:
orientation = UIImageOrientationUpMirrored;
break;

case 4:
orientation = UIImageOrientationDownMirrored;
break;

case 5:
orientation = UIImageOrientationLeftMirrored;
break;

case 7:
orientation = UIImageOrientationRightMirrored;
break;
default:
break;
}
return orientation;
}
#endif

- (nullable NSData *)sd_imageData {
return [self sd_imageDataAsFormat:SDImageFormatUndefined];
}
/**
根据指定的图片类型,把image对象转换为对应格式的data

@param imageFormat 指定的image格式
@return 返回data对象
*/
- (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat {
NSData *imageData = nil;
if (self) {
#if SD_UIKIT || SD_WATCH
int alphaInfo = CGImageGetAlphaInfo(self.CGImage);
//是否有透明度
BOOL hasAlpha = !(alphaInfo == kCGImageAlphaNone ||
alphaInfo == kCGImageAlphaNoneSkipFirst ||
alphaInfo == kCGImageAlphaNoneSkipLast);
//只有png图片有alpha属性
BOOL usePNG = hasAlpha;

// the imageFormat param has priority here. But if the format is undefined, we relly on the alpha channel
//是否是PNG类型的图片
if (imageFormat != SDImageFormatUndefined) {
usePNG = (imageFormat == SDImageFormatPNG);
}
//根据不同的图片类型获取到对应的图片data
if (usePNG) {
imageData = UIImagePNGRepresentation(self);
} else {
imageData = UIImageJPEGRepresentation(self, (CGFloat)1.0);
}
#else
NSBitmapImageFileType imageFileType = NSJPEGFileType;
if (imageFormat == SDImageFormatGIF) {
imageFileType = NSGIFFileType;
} else if (imageFormat == SDImageFormatPNG) {
imageFileType = NSPNGFileType;
}

imageData = [NSBitmapImageRep representationOfImageRepsInArray:self.representations
usingType:imageFileType
properties:@{}];
#endif
}
return imageData;
}

5 UIImage+GIF分类分析

UIImage+GIF实现了对GIF图片的NSData的处理。并且处理方法就是取出GIF图片的第一张UIImage来显示。如果真的要显示动态图片的话,我们需要使用FLAnimatedImageView来显示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
根据gif图片的data生成对应的gif的UIImage对象。而且只会取GIF图片的第一张UIImage。

@param data gif图片的data对象
@return 生成的image对象。这里只获取gif图片的第一张图像,如果要实现gif完整图像,使用FLAnimatedImageView
*/
+ (UIImage *)sd_animatedGIFWithData:(NSData *)data {
if (!data) {
return nil;
}
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
//获取GIF图片包含的UIImage数量
size_t count = CGImageSourceGetCount(source);
UIImage *staticImage;
//如果只有一张UIImage
if (count <= 1) {
staticImage = [[UIImage alloc] initWithData:data];
} else {
#if SD_WATCH
CGFloat scale = 1;
scale = [WKInterfaceDevice currentDevice].screenScale;
#elif SD_UIKIT
CGFloat scale = 1;
scale = [UIScreen mainScreen].scale;
#endif
//获取第一张UIImage对象
CGImageRef CGImage = CGImageSourceCreateImageAtIndex(source, 0, NULL);
#if SD_UIKIT || SD_WATCH
//获取gif图片的第一张图片
UIImage *frameImage = [UIImage imageWithCGImage:CGImage scale:scale orientation:UIImageOrientationUp];
//用第一张图片生成一个新的gif图片
staticImage = [UIImage animatedImageWithImages:@[frameImage] duration:0.0f];
#elif SD_MAC
staticImage = [[UIImage alloc] initWithCGImage:CGImage size:NSZeroSize];
#endif
CGImageRelease(CGImage);
}

CFRelease(source);

return staticImage;
}
/**
判断一张图片是不是GIF图片

@return bool值
*/
- (BOOL)isGIF {
return (self.images != nil);
}

6 SDWebImageDecoder分析

通过这个类实现图片的解压缩操作。对于太大的图片,先按照一定比例缩小图片然后再解压缩。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
#if SD_UIKIT || SD_WATCH
//每个像素占用的字节数
static const size_t kBytesPerPixel = 4;
//色彩空间占用的字节数
static const size_t kBitsPerComponent = 8;

/**
解压缩图片

@param image UIImage对象
@return 返回解压缩以后的图片
*/
+ (nullable UIImage *)decodedImageWithImage:(nullable UIImage *)image {
//图片是否能够加压缩
if (![UIImage shouldDecodeImage:image]) {
return image;
}

// autorelease the bitmap context and all vars to help system to free memory when there are memory warning.
// on iOS7, do not forget to call [[SDImageCache sharedImageCache] clearMemory];
/*
*解压缩操作放入一个自动释放池里面。一遍自动释放所有的变量。
*/
@autoreleasepool{

CGImageRef imageRef = image.CGImage;
//获取图片的色彩空间
CGColorSpaceRef colorspaceRef = [UIImage colorSpaceForImageRef:imageRef];
//宽度和高度
size_t width = CGImageGetWidth(imageRef);
size_t height = CGImageGetHeight(imageRef);
//图片占用的字节数
size_t bytesPerRow = kBytesPerPixel * width;

// kCGImageAlphaNone is not supported in CGBitmapContextCreate.
// Since the original image here has no alpha info, use kCGImageAlphaNoneSkipLast
// to create bitmap graphics contexts without alpha info.
//创建一个绘制图片的上下文
CGContextRef context = CGBitmapContextCreate(NULL,
width,
height,
kBitsPerComponent,
bytesPerRow,
colorspaceRef,
kCGBitmapByteOrderDefault|kCGImageAlphaNoneSkipLast);
if (context == NULL) {
return image;
}

// Draw the image into the context and retrieve the new bitmap image without alpha
//绘制一个和图片大小一样的图片
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
//创建一个么有alpha通道的图片
CGImageRef imageRefWithoutAlpha = CGBitmapContextCreateImage(context);
//得到解压缩以后的图片
UIImage *imageWithoutAlpha = [UIImage imageWithCGImage:imageRefWithoutAlpha
scale:image.scale
orientation:image.imageOrientation];

CGContextRelease(context);
CGImageRelease(imageRefWithoutAlpha);

return imageWithoutAlpha;
}
}

/*
*定义一张图片可以占用的最大空间
*/
static const CGFloat kDestImageSizeMB = 60.0f;

static const CGFloat kSourceImageTileSizeMB = 20.0f;

static const CGFloat kBytesPerMB = 1024.0f * 1024.0f;
//1MB可以存储多少像素
static const CGFloat kPixelsPerMB = kBytesPerMB / kBytesPerPixel;
//如果像素小于这个值,则不解压缩
static const CGFloat kDestTotalPixels = kDestImageSizeMB * kPixelsPerMB;
static const CGFloat kTileTotalPixels = kSourceImageTileSizeMB * kPixelsPerMB;

static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to overlap the seems where tiles meet.



/**
如果原始图片占用的空间太大。则按照一定的比例解压缩。从而不让解压缩以后的图片占用的空间太大。

@param image UIImage对象
@return 返回处理结束的UIImage对象
*/
+ (nullable UIImage *)decodedAndScaledDownImageWithImage:(nullable UIImage *)image {
//图片是否支持解压缩
if (![UIImage shouldDecodeImage:image]) {
return image;
}
//图片不需要处理。直接解压缩
if (![UIImage shouldScaleDownImage:image]) {
return [UIImage decodedImageWithImage:image];
}

CGContextRef destContext;

// autorelease the bitmap context and all vars to help system to free memory when there are memory warning.
// on iOS7, do not forget to call [[SDImageCache sharedImageCache] clearMemory];
@autoreleasepool {
CGImageRef sourceImageRef = image.CGImage;

CGSize sourceResolution = CGSizeZero;
//获取原始图片的宽度和高度
sourceResolution.width = CGImageGetWidth(sourceImageRef);
sourceResolution.height = CGImageGetHeight(sourceImageRef);
//获取原始图片的总像素
float sourceTotalPixels = sourceResolution.width * sourceResolution.height;
// Determine the scale ratio to apply to the input image
// that results in an output image of the defined size.
// see kDestImageSizeMB, and how it relates to destTotalPixels.
//根据一定的比例设置目标图片的宽度和高度
float imageScale = kDestTotalPixels / sourceTotalPixels;
CGSize destResolution = CGSizeZero;
destResolution.width = (int)(sourceResolution.width*imageScale);
destResolution.height = (int)(sourceResolution.height*imageScale);

// current color space
//获取原始图片的像素空间。默认是RGB
CGColorSpaceRef colorspaceRef = [UIImage colorSpaceForImageRef:sourceImageRef];
//每一行像素占用的内存空间大小
size_t bytesPerRow = kBytesPerPixel * destResolution.width;

// Allocate enough pixel data to hold the output image.
//目标图片占用的总内存空间大小。一行占用内存空间大小*高度
void* destBitmapData = malloc( bytesPerRow * destResolution.height );
if (destBitmapData == NULL) {
return image;
}
//根据各种设置创建一个上下文环境
destContext = CGBitmapContextCreate(destBitmapData,
destResolution.width,
destResolution.height,
kBitsPerComponent,
bytesPerRow,
colorspaceRef,
kCGBitmapByteOrderDefault|kCGImageAlphaNoneSkipLast);

if (destContext == NULL) {
free(destBitmapData);
return image;
}
//设置目标图片的质量
CGContextSetInterpolationQuality(destContext, kCGInterpolationHigh);
CGRect sourceTile = CGRectZero;
sourceTile.size.width = sourceResolution.width;
sourceTile.size.height = (int)(kTileTotalPixels / sourceTile.size.width );
sourceTile.origin.x = 0.0f;
CGRect destTile;
destTile.size.width = destResolution.width;
destTile.size.height = sourceTile.size.height * imageScale;
destTile.origin.x = 0.0f;
float sourceSeemOverlap = (int)((kDestSeemOverlap/destResolution.height)*sourceResolution.height);
CGImageRef sourceTileImageRef;
int iterations = (int)( sourceResolution.height / sourceTile.size.height );
int remainder = (int)sourceResolution.height % (int)sourceTile.size.height;
if(remainder) {
iterations++;
}
// Add seem overlaps to the tiles, but save the original tile height for y coordinate calculations.
float sourceTileHeightMinusOverlap = sourceTile.size.height;
sourceTile.size.height += sourceSeemOverlap;
destTile.size.height += kDestSeemOverlap;
for( int y = 0; y < iterations; ++y ) {
@autoreleasepool {
sourceTile.origin.y = y * sourceTileHeightMinusOverlap + sourceSeemOverlap;
destTile.origin.y = destResolution.height - (( y + 1 ) * sourceTileHeightMinusOverlap * imageScale + kDestSeemOverlap);
sourceTileImageRef = CGImageCreateWithImageInRect( sourceImageRef, sourceTile );
if( y == iterations - 1 && remainder ) {
float dify = destTile.size.height;
destTile.size.height = CGImageGetHeight( sourceTileImageRef ) * imageScale;
dify -= destTile.size.height;
destTile.origin.y += dify;
}
CGContextDrawImage( destContext, destTile, sourceTileImageRef );
CGImageRelease( sourceTileImageRef );
}
}

CGImageRef destImageRef = CGBitmapContextCreateImage(destContext);
CGContextRelease(destContext);
if (destImageRef == NULL) {
return image;
}
//生成处理结束以后的图片
UIImage *destImage = [UIImage imageWithCGImage:destImageRef scale:image.scale orientation:image.imageOrientation];
CGImageRelease(destImageRef);
if (destImage == nil) {
return image;
}
return destImage;
}
}

/**
imge是否能够加压缩

@param image 图片
@return 能否解压缩
*/
+ (BOOL)shouldDecodeImage:(nullable UIImage *)image {
// Prevent "CGBitmapContextCreateImage: invalid context 0x0" error
if (image == nil) {
return NO;
}

// do not decode animated images
//如果是动态图片不处理
if (image.images != nil) {
return NO;
}

CGImageRef imageRef = image.CGImage;
//获取image的alpha通道。通过通道获取图片数据
CGImageAlphaInfo alpha = CGImageGetAlphaInfo(imageRef);
BOOL anyAlpha = (alpha == kCGImageAlphaFirst ||
alpha == kCGImageAlphaLast ||
alpha == kCGImageAlphaPremultipliedFirst ||
alpha == kCGImageAlphaPremultipliedLast);
// do not decode images with alpha
//如果有alpha通道值,则不处理
if (anyAlpha) {
return NO;
}

return YES;
}

/**
是否需要减少原始图片的大小

@param image UIImage对象
@return 是否支持scale
*/
+ (BOOL)shouldScaleDownImage:(nonnull UIImage *)image {
BOOL shouldScaleDown = YES;

CGImageRef sourceImageRef = image.CGImage;
CGSize sourceResolution = CGSizeZero;
sourceResolution.width = CGImageGetWidth(sourceImageRef);
sourceResolution.height = CGImageGetHeight(sourceImageRef);
//图片总共像素
float sourceTotalPixels = sourceResolution.width * sourceResolution.height;
//如果图片的总像素大于一定比例,则需要做简化处理
float imageScale = kDestTotalPixels / sourceTotalPixels;
if (imageScale < 1) {
shouldScaleDown = YES;
} else {
shouldScaleDown = NO;
}

return shouldScaleDown;
}

/**
获取图片的色彩空间

@param imageRef 图片
@return 色彩空间
*/
+ (CGColorSpaceRef)colorSpaceForImageRef:(CGImageRef)imageRef {
// current
CGColorSpaceModel imageColorSpaceModel = CGColorSpaceGetModel(CGImageGetColorSpace(imageRef));
CGColorSpaceRef colorspaceRef = CGImageGetColorSpace(imageRef);

BOOL unsupportedColorSpace = (imageColorSpaceModel == kCGColorSpaceModelUnknown ||
imageColorSpaceModel == kCGColorSpaceModelMonochrome ||
imageColorSpaceModel == kCGColorSpaceModelCMYK ||
imageColorSpaceModel == kCGColorSpaceModelIndexed);
if (unsupportedColorSpace) {
colorspaceRef = CGColorSpaceCreateDeviceRGB();
CFAutorelease(colorspaceRef);
}
return colorspaceRef;
}
#elif SD_MAC
+ (nullable UIImage *)decodedImageWithImage:(nullable UIImage *)image {
return image;
}

+ (nullable UIImage *)decodedAndScaledDownImageWithImage:(nullable UIImage *)image {
return image;
}

7 总结

下面是几个分类工具的使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
根据图片数据获取图片类型

*/
- (IBAction)getImageType:(id)sender {
NSData *imageData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"rock.gif" ofType:nil]];
SDImageFormat formate = [NSData sd_imageFormatForImageData:imageData];
NSString *message = [NSString stringWithFormat:@"%d",formate];
showMessage(message,self);
}


/**
获取一张图片对应的两倍或者三倍屏幕对应的图片

*/
- (IBAction)getScaleImage:(id)sender {
UIImage *sourceImage = [UIImage imageNamed:@"2.png"];
UIImage *dis2ScaleImage = SDScaledImageForKey(@"dist@2x.png", sourceImage);
UIImage *dis3ScaleImage = SDScaledImageForKey(@"dist@3x.png", sourceImage);
NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
//NSLog(@"document:%@",documentPath);
NSString *path1 = [documentPath stringByAppendingPathComponent:@"dist.png"];
[UIImagePNGRepresentation(sourceImage) writeToFile:path1 atomically:YES];
NSString *path2 = [documentPath stringByAppendingPathComponent:@"dist@2x.png"];
[UIImagePNGRepresentation(dis2ScaleImage) writeToFile:path2 atomically:YES];
NSString *path3 = [documentPath stringByAppendingPathComponent:@"dist@3x.png"];
[UIImagePNGRepresentation(dis3ScaleImage) writeToFile:path3 atomically:YES];
}

/**
解压缩图片

@param sender 解压缩图片
*/
- (IBAction)unZipImage:(id)sender {
UIImage *sourceImage = [UIImage imageNamed:@"2.png"];
UIImage *distImage = [UIImage decodedAndScaledDownImageWithImage:sourceImage];
NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *path1 = [documentPath stringByAppendingPathComponent:@"distImage.png"];
[UIImagePNGRepresentation(distImage) writeToFile:path1 atomically:YES];
NSString *path2 = [documentPath stringByAppendingPathComponent:@"sourceImage.png"];
[UIImagePNGRepresentation(sourceImage) writeToFile:path2 atomically:YES];

}

最后原文地址.html),demo地址


...

...

00:00
00:00