情景
项目当中需要截取当前屏幕图片,然后处理分享到微信朋友或朋友圈。微信分享图片需要设置一张不超过32K大小的缩略图,超过32K将导致分享失败。功能是已经上线,过程中有些细节和注意的地方,在这里分享下(不妥之处,望指正!)。
上代码前先拓展下:
1、关于UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale)参数;
1)size :
参数size为新创建的位图上下文的大小。它同时是由UIGraphicsGetImageFromCurrentImageContext函数返回的图形大小2)opaque:
如果图形完全不用透明,设置为YES以优化位图的存储3)scale:
缩放因子 iPhone 4是2.0,其他是1.0。虽然这里可以用[UIScreen mainScreen].scale来获取,但实际上设为0后,系统就会自动设置正确的比例了.
拓展
以前的iphone 设备屏幕分辨率都是320*480,后来apple 在iPhone 4中采用了名为Retina的显示技术,iPhone 4采用了960x640像素分辨率的显示屏幕。由于屏幕大小没有变,还是3.5英寸,分辨率的提升将iPhone 4的显示分辨率提升至iPhone 3GS的四倍,每英寸的面积里有326个像素。
scale属性的值有两个:
scale = 1; 的时候是代表当前设备是320*480的分辨率(就是iphone4之前的设备)
scale = 2; 的时候是代表分辨率为640*960的分辨率
2、关于UIImageJPEGRepresentation和UIImagePNGRepresentation
关于二者区别,可以看他们处理同一张图的效果,如图:
![]()
![]()
时间上相差不大,但当任务量大之后,UIImageJPEGRepresentation处理图片高效率就会更加体现出来;另外UIImageJPEGRepresentation处理图片后的大小上优势也是相当明显。
我们将选用UIImageJPEGRepresentation方法来处理截屏图片。
正文
1、上代码。这段代码也是在网上查阅其他同胞后整理的!
UIGraphicsBeginImageContextWithOptions([UIScreen mainScreen].bounds.size, NO, 1.0); [self.view.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage * img = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); float scaleNum =1.0; NSData * dataJPEG =UIImageJPEGRepresentation(img, 1.0); NSLog(@"UIImageJPEGRepresentation处理图片--%.2fK", dataJPEG.length/1024.0); float imageDataLength = dataJPEG.length/1024.0; while (imageDataLength>32.0) { scaleNum = scaleNum - 0.01; dataJPEG =UIImageJPEGRepresentation(img, scaleNum); imageDataLength = dataJPEG.length/1024.0; NSLog(@"压缩后图片大小%.2fk",imageDataLength); } UIImage * finalImg = [UIImage imageWithData:dataJPEG];
问题来了-主界面卡死。原因如图
很明显上面那段while,导致了死循环。另外我们发现上面那段代码将图片压缩到55.58K后就不能再小了!(这导致iPhone能正常分享,iPad就卡住)
2、解决办法改变UIImageJPEGRepresentation第二个缩放参数不奏效情况下,改变UIGraphicsBeginImageContextWithOptions第三个参数的值!(过程涉及耗时运算,这里将计算任务放进异步线程)
#define asy(task) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{task})
#define getMainQueue(task) dispatch_async(dispatch_get_main_queue(), ^{task})
- (IBAction)screenShot:(UIButton *)sender {
asy(
UIImage * finalImage = [self compressScreenShotToSize:32.0 withContextScale:[UIScreen mainScreen].scale];
getMainQueue(//回主线程
self.finalImage.image = finalImage;
);
);
}
-(void)compressScreenShotToSize:(CGFloat)finalSize withContextScale:(CGFloat)contextScale{
float JPEGScale = 1.0;
//位图
UIGraphicsBeginImageContextWithOptions([UIScreen mainScreen].bounds.size, NO, contextScale);
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//data
NSData * dataJPEG =UIImageJPEGRepresentation(img, JPEGScale);
float imageDataLength = dataJPEG.length/1024.0;
while (imageDataLength>finalSize) {
JPEGScale = JPEGScale - 0.2;
if (JPEGScale<0.0) {
break;//跳出
}
dataJPEG =UIImageJPEGRepresentation(img, JPEGScale);
imageDataLength = dataJPEG.length/1024.0;
}
if (imageDataLength <finalSize) {
return [UIImage imageWithData:dataJPEG];//符合要求
}
if (imageDataLength >finalSize) {
[self compressScreenShotToSize:finalSize withContextScale:contextScale-0.1];//递归
}
return nil;
}
总结
整个过程并没有涉及复杂的内容,皆为基础,如果大家有更好更高效方式,希望分享下。不足之处请指正!