情景
项目当中需要截取当前屏幕图片,然后处理分享到微信朋友或朋友圈。微信分享图片需要设置一张不超过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();//dataNSData * 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;}
总结
整个过程并没有涉及复杂的内容,皆为基础,如果大家有更好更高效方式,希望分享下。不足之处请指正!
如果觉得《微信截屏分享 图片压缩处理!》对你有帮助,请点赞、收藏,并留下你的观点哦!