热门标签 | HotTags
当前位置:  开发笔记 > IOS > 正文

iOS中大尺寸图片的旋转与缩放实例详解

图片缩小旋转是我们在开发中经常会遇到的一个功能,下面这篇文章主要给大家介绍了关于iOS中大尺寸图片的旋转与缩放的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧

前言

由于iPhone的硬件性能限制,直到iPhone 6s开始,才将最大内存拓展到2G。

可即使是如此,也不代表一个应用可使用的空间是2G。

一张10000 x 10000的图片,如果通过UIImageJPEGRepresentation方法将图片转成内存数据,会有一个峰值波动。

这里的峰值其实是图片在解压时产生的位图数据所占空间,然后才转换成我们可以操作的NSData。

其计算公式是 W x H x 4 / 1024 / 1024 也就是 10000 x 10000 x4 /1024 / 1024 = 381.4(M)。

这里会产生381M的消耗,及时会被回收,但是想一下,如果图片尺寸很大,数量很多的时候,很容易就会发生异常了。

本文将给大家详细介绍关于iOS大尺寸图片旋转与缩放的相关内容,分享出来供大家参考学习,话不多说了,接下来说下具体的操作

旋转

我们知道如果对一个UIImage对象进行旋转操作,相信做项目时肯定会有用到 UIImage 这个类,可以有如下的方式

通过 CGContextDrawImage 进行图片绘制

+ (UIImage *)image:(UIImage *)image rotation:(UIImageOrientation)orientation {

 long double rotate = 0.0;
 CGRect rect;
 float translateX = 0;
 float translateY = 0;
 float scaleX = 1.0;
 float scaleY = 1.0;

 switch (orientation) {
 case UIImageOrientationLeft:
 rotate = M_PI_2;
 rect = CGRectMake(0, 0, image.size.height, image.size.width);
 translateX = 0;
 translateY = -rect.size.width;
 scaleY = rect.size.width/rect.size.height;
 scaleX = rect.size.height/rect.size.width;
 break;
 default:
 rotate = 0.0;
 rect = CGRectMake(0, 0, image.size.width, image.size.height);
 translateX = 0;
 translateY = 0;
 break;
 }

 UIGraphicsBeginImageContext(rect.size);
 CGContextRef cOntext= UIGraphicsGetCurrentContext();
 //做CTM变换
 CGContextTranslateCTM(context, 0.0, rect.size.height);
 CGContextScaleCTM(context, 1.0, -1.0);
 CGContextRotateCTM(context, rotate);
 CGContextTranslateCTM(context, translateX, translateY);

 CGContextScaleCTM(context, scaleX, scaleY);
 //绘制图片
 CGContextDrawImage(context, CGRectMake(0, 0, rect.size.width, rect.size.height), image.CGImage);
 UIImage *newPic = UIGraphicsGetImageFromCurrentImageContext();
 return newPic;
} 

这里有一个问题是,这里会创建一个新的图片大小空间的,然后进行重新绘制。可能会存在一个隐患,就是当图片尺寸过大的时候,就会出现内存占用过高的情况

接下来介绍一种另辟蹊径的解决方法--通过给图片添加滤镜的方式。

既然操作的对象是图片,那么它就会各种滤镜展示。系统给我们提供了多大一百多种滤镜,这里的滤镜不单只颜色等状态发生变化。

这其中就有我们需要的滤镜Key inputTransform。

+ (UIImage *)getRotationImage:(UIImage *)image rotation:(CGFloat)rotation {

 CIImage *ciImage = [[CIImage alloc] initWithImage:image];
 CIFilter *filter = [CIFilter filterWithName:@"CIAffineTransform" keysAndValues:kCIInputImageKey, ciImage, nil];

 [filter setDefaults];
 CGAffineTransform transform = CATransform3DGetAffineTransform([self rotateTransform:CATransform3DIdentity clockwise:NO angle:rotation]);
 [filter setValue:[NSValue valueWithBytes:&transform objCType:@encode(CGAffineTransform)] forKey:@"inputTransform"];

 //根据滤镜设置图片
 CIContext *cOntext= [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer : @(NO)}];
 CIImage *outputImage = [filter outputImage];
 CGImageRef cgImage = [context createCGImage:outputImage fromRect:[outputImage extent]];

 UIImage *result = [UIImage imageWithCGImage:cgImage];

 CGImageRelease(cgImage);

 return result;
}
+ (CATransform3D)rotateTransform:(CATransform3D)initialTransform clockwise:(BOOL)clockwise angle:(CGFloat)angle {

 CGFloat arg = angle*M_PI / 180.0f;
 if(!clockwise){
 arg *= -1;
 }
 //进行形变
 CATransform3D transform = initialTransform;
 transform = CATransform3DRotate(transform, arg, 0, 0, 1);
 CGFloat _flipState1 = 0;
 CGFloat _flipState2 = 0;
 transform = CATransform3DRotate(transform, _flipState1*M_PI, 0, 1, 0);
 transform = CATransform3DRotate(transform, _flipState2*M_PI, 1, 0, 0);

 return transform;
} 

通过这种操作,可以利用GPU来进行图片操作,可以一定程度的降低消耗,节约资源。

缩放

既然图片很大,那么我们可以通过缩放的方式,来减小图片的尺寸,减少内存消耗,进而降低异常风险。

我们通常采用UIImage提供的系统方法drawInRect 及其一系列的方法,来进行图片缩放。

可是这种操作的缺陷和最开始介绍的旋转一样,其实质都是进行图片的重新绘制。

通过绘制图片的方式进行图片缩放

+ (UIImage *)image:(UIImage *)image transformtoSize:(CGSize)Newsize {
 // 创建一个bitmap的context
 UIGraphicsBeginImageContext(Newsize);
 // 绘制改变大小的图片
 [image drawInRect:CGRectMake(0, 0, Newsize.width, Newsize.height)];
 // 从当前context中创建一个改变大小后的图片
 UIImage *TransformedImg=UIGraphicsGetImageFromCurrentImageContext();
 // 使当前的context出堆栈
 UIGraphicsEndImageContext();
 // 返回新的改变大小后的图片
 return TransformedImg;
}

这里是内存消耗。通过看图可以发现,针对大图,在进行缩放的时候,内存消耗的峰值能达到426M,耗时在1.5s左右
由于我们使用的手机是iPhone X,在更低端的设备上,这是多么大的损耗,很容易发生异常

既然上面的方法损耗很大,我们来看下另外的一种方式。

先看下内存消耗

通过图上可以看出,在进行图片缩放的时候,内存有小幅增加,产生的消耗在18M,耗时也在1.5s左右。

这样的效果是非常显著的。下面来看代码

+(UIImage *)resizeImage:(UIImage *)image toSize:(CGSize)size {

 CIImage *ciImage = [[CIImage alloc] initWithImage:image];
 //创建一个input image类型的滤镜
 CIFilter *filter = [CIFilter filterWithName:@"CIAffineTransform" keysAndValues:kCIInputImageKey, ciImage, nil];
 //设置默认的滤镜效果
 [filter setDefaults];

 //设置缩放比例
 CGFloat scale = 1;
 if (size.width != CGFLOAT_MAX) {
 scale = (CGFloat) size.width / image.size.width;
 } else if (size.height != CGFLOAT_MAX) {
 scale = (CGFloat) size.height / image.size.height;
 }

 //进行赋值
 CGAffineTransform transform = CGAffineTransformMakeScale(scale, scale);
 [filter setValue:[NSValue valueWithBytes:&transform objCType:@encode(CGAffineTransform)] forKey:@"inputTransform"];

 //通过GPU的方式来进行处理
 CIContext *cOntext= [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer : @(NO)}];
 //根据滤镜输出图片
 CIImage *outputImage = [filter outputImage];
 CGImageRef cgImage = [context createCGImage:outputImage fromRect:[outputImage extent]];
 //创建UIImage 对象,并释放资源
 UIImage *result = [UIImage imageWithCGImage:cgImage];

 CGImageRelease(cgImage);

 return result;
}

可以发现我们这里使用的和旋转是同样的方式。通过给图片添加滤镜能够很安全的实现我们的需求。

总结

1.针对巨幅图片操作,可以采用这种思路:先生成一个尺寸小的缩略图,然后在进行各种操作,可以降低资源消耗;

2.通过CoreImage.framework来进行图片处理。

3.之前一直对CoreImage.framework的理解,只是其能够对图片和视频添加那种可见的滤镜,未曾想过这种滤镜也支持缩放和旋转。

? 为什么CoreImage.framework的方式能够很安全呢?

该框架从iOS 5开始投入使用,通过对CoreGraphics.framework、CoreVideo.framework、Image I/O.framework进行数据处理,

可以自由在CPU和GPU之间切换运算方式,

可以最大限度的利用GPU来进行计算,降低内存消耗,

甚至可以对视频进行实时滤镜处理。

针对不能通过原生对UIView进行transform操作的时候,CoreImage.framework会是你的朋友。

最直接的来自文档

Core Image is an image processing and analysis technology designed to provide near real-time processing for still and video images. It operates on image data types from the Core Graphics, Core Video, and Image I/O frameworks, using either a GPU or CPU rendering path. Core Image hides the details of low-level graphics processing by providing an easy-to-use application programming interface (API). You don't need to know the details of OpenGL, OpenGL ES, or Metal to leverage the power of the GPU, nor do you need to know anything about Grand Central Dispatch (GCD) to get the benefit of multicore processing. Core Image handles the details for you.

它已经帮你把所有东西都处理好了,大胆的用吧

代码地址 (本地下载)

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。


推荐阅读
  • macOS Big Sur全新设计大版本更新,10+个值得关注的新功能
    本文介绍了Apple发布的新一代操作系统macOS Big Sur,该系统采用全新的界面设计,包括图标、应用界面、程序坞和菜单栏等方面的变化。新系统还增加了通知中心、桌面小组件、强化的Safari浏览器以及隐私保护等多项功能。文章指出,macOS Big Sur的设计与iPadOS越来越接近,结合了去年iPadOS对鼠标的完善等功能。 ... [详细]
  • 本文介绍了互联网思维中的三个段子,涵盖了餐饮行业、淘品牌和创业企业的案例。通过这些案例,探讨了互联网思维的九大分类和十九条法则。其中包括雕爷牛腩餐厅的成功经验,三只松鼠淘品牌的包装策略以及一家创业企业的销售额增长情况。这些案例展示了互联网思维在不同领域的应用和成功之道。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • win10电脑蓝屏代码0x000000a5无法进入系统解决方法详解
    许多用户在使用电脑的时候遇到蓝屏问题,重启无法进入系统。本文提供了解决方法:调整BIOS设置、禁用安全启动、重装系统等。如果以上方法都无法解决问题,需要重新安装一个系统。详细步骤请参考正文内容。 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
  • 如何提高PHP编程技能及推荐高级教程
    本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
  • 爱奇艺如何使用扫码登录二维码
    本文介绍了在使用爱奇艺时如何通过扫码登录二维码的具体操作方法,包括打开爱奇艺app、点击“我的”按钮、点击扫码按钮等步骤。同时提供了操作环境的相关信息,包括手机品牌型号、系统版本和软件版本。 ... [详细]
  • 本文介绍了iOS开发中检测和解决内存泄漏的方法,包括静态分析、使用instruments检查内存泄漏以及代码测试等。同时还介绍了最能挣钱的行业,包括互联网行业、娱乐行业、教育行业、智能行业和老年服务行业,并提供了选行业的技巧。 ... [详细]
  • 苹果手机home键设置1.我们点击打开iPhone手机桌面上的设置图标。2.点击打开页面中的通用选项。 ... [详细]
  • 苹果8p电池多少毫安的_iphonexs电池多少毫安,iphonexs换电池多少钱
    使用iPhoneXS手机用户都反映XS的电池不耐用,同一系列的XR相比之下电池续航能力要强很多。iphonexs电池多少毫安,电池不耐用的原因有哪些&# ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 生成对抗式网络GAN及其衍生CGAN、DCGAN、WGAN、LSGAN、BEGAN介绍
    一、GAN原理介绍学习GAN的第一篇论文当然由是IanGoodfellow于2014年发表的GenerativeAdversarialNetworks(论文下载链接arxiv:[h ... [详细]
  • 信息安全等级保护是指对国家秘密信息、法人和其他组织及公民的专有信息以及公开信息和存储、传输、处理这些信息的信息系统分等级实行安全保护,对信息系统中使用的信息安全产品实 ... [详细]
  • 无线认证设置故障排除方法及注意事项
    本文介绍了解决无线认证设置故障的方法和注意事项,包括检查无线路由器工作状态、关闭手机休眠状态下的网络设置、重启路由器、更改认证类型、恢复出厂设置和手机网络设置等。通过这些方法,可以解决无线认证设置可能出现的问题,确保无线网络正常连接和上网。同时,还提供了一些注意事项,以便用户在进行无线认证设置时能够正确操作。 ... [详细]
  • 斯诺登质疑FBI要求苹果解锁iPhone的真实意图
    爱德华·斯诺登对FBI要求苹果解锁iPhone一事表示质疑,称其完全是扯谈。斯诺登在一次峰会上发表了自己的看法,并分享了一篇揭穿FBI真实企图的文章。他认为这场战役将是未来十年内最重大的科技案件。斯诺登对于监控隐私问题非常敢于发表意见。 ... [详细]
author-avatar
碎蜂CYM夜一
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有