iOS UIImage 转 NSData 方案
前言:需要把image 转为二进制data 进行存储 压缩 上传 时预判原始图大小时候使用了UIImagePNGRepresentation发现比原图大引发以下内容总结
常用方案1
1 2 3 4 | / / 加载图片 UIImage * image = [UIImage imageNamed:@ "test1.jpg" ]; / / 将图片转换为NSData对象 NSData * imageData = UIImageJPEGRepresentation(image, 1 ); |
参数解释:
-
image:要转换的UIImage对象。
- 这是需要转换为JPEG数据的原始图像对象。
-
compressionQuality:表示JPEG压缩质量的参数,范围为0.0到1.0。
- compressionQuality值为0.0表示最高压缩,图像质量最低。
- compressionQuality值为1.0表示无压缩,图像质量最高。 (⚠️ 1.0 不代表当前获取的data 和 原始data 一样大,甚至远远大于原始data)
- compressionQuality值在0.0和1.0之间表示不同程度的压缩和图像质量权衡。
关键点:
- 当压缩参数越接近1 图像质量越高,那么转换后的JPEG数据将保留较高的图像质量,但会占用更多的空间。
- 图像内容复杂度:如果原始图像包含复杂的纹理、细节和颜色变化等特征,JPEG压缩算法会产生较大的数据文件。这是因为JPEG是一种有损压缩格式,会在压缩过程中舍弃部分图像细节,但仍然需要更多的数据来表示复杂的图像内容。
- 原始图像已经是JPEG格式:如果原始图像已经是JPEG格式,再次进行JPEG转换可能会导致数据的进一步损失,并且文件大小可能会变大。这是因为每次重新压缩JPEG图像时,会引入额外的压缩失真和冗余数据。
- 原始图像的压缩方式不同:UIImageJPEGRepresentation使用的是系统的JPEG压缩算法,而原始图像可能是使用其他方式进行压缩或存储的(如其他图像编辑软件或网络服务)。不同的压缩方式可能会导致文件大小的差异。
总而言之,JPEG图像的文件大小取决于多个因素,包括压缩质量、图像内容复杂度和压缩算法等。因此,如果发现使用UIImageJPEGRepresentation转换后的JPEG数据比原始图像大很多,可以适当调整压缩质量参数,或尝试其他的图像压缩方法来优化文件大小。
常用方案2
1 2 3 4 5 | / / 加载图片 UIImage * image = [UIImage imageNamed:@ "test1.png" ]; / / 将图片转换为NSData对象 NSData * imageData = UIImagePNGRepresentation(image); |
关键点:
- 透明性:PNG格式支持图像的透明性,而JPEG格式不支持。因此,如果原始图像包含透明通道或需要保留透明性,则应选择使用UIImagePNGRepresentation来保持图像的完整性。
- 压缩质量:与JPEG不同,PNG是一种无损压缩格式,不会对图像数据进行压缩或丢失。因此,UIImagePNGRepresentation函数不接受关于压缩质量的参数,转换后的PNG数据的大小与原始图像保持一致,可能会比JPEG数据更大。
- 色彩空间:将UIImage对象转换为PNG数据时,保留了原始图像的色彩空间和位深度信息。即使原始图像采用了较高的位深度(例如16位),转换后的PNG数据也能够保持相同的位深度,以保留更多的颜色信息。这在需要更精确色彩表示的应用场景中是重要的。
- 内存消耗:由于PNG数据是无损压缩的,转换大尺寸或高分辨率的UIImage对象时可能会占用相对较大的内存空间。因此,在处理大型图像时,要确保内存使用情况合理控制,避免出现内存警告或崩溃。
- 其他格式转换考虑:除了PNG格式,如果需要在应用程序中处理图像的其他用途,如网络传输、显示在UIImageView中,或者在支持的图像编辑库中进行处理,可能需要将UIImage对象转换为其他合适的格式,如JPEG或HEIC等。
总之,通过理解UIImagePNGRepresentation的一些特性和限制,可以根据具体需求合理选择使用和处理PNG格式的图像数据。
方案3:CGImageDestinationCreateWithData
1 2 3 4 5 6 7 8 9 10 11 12 | + (NSData * )kfz_rawData:(UIImage * )image { NSDictionary * options = @{(__bridge NSString * )kCGImageSourceShouldCache : @NO, (__bridge NSString * )kCGImageSourceShouldCacheImmediately : @NO }; / / 目的是不期望图片有缓存和解码行为 NSMutableData * data = [NSMutableData data]; CGImageDestinationRef destRef = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)data, kUTTypeJPEG, 1 , (__bridge CFDictionaryRef)options); CGImageDestinationAddImage(destRef, image.CGImage, (__bridge CFDictionaryRef)options); CGImageDestinationFinalize(destRef); CFRelease(destRef); return data; } |
参数解释:
CGImageDestinationCreateWithData函数是Core Graphics框架中用于创建一个基于数据的目标对象的函数。他接受4个参数:
- data:一个CFMutableData对象,用于存储图像数据。调用CGImageDestinationFinalize时,最终的图像数据将被写入这个data对象。
- type:一个CFStringRef,指定要创建的图像数据的文件类型。你可以使用常量如kUTTypeJPEG、kUTTypePNG、kUTTypeGIF等来表示不同的文件类型。
- count:一个size_t值,指定要创建的图像数据中图像的数量。通常只需要使用1,表示只有一个图像。
- options:一个CFDictionaryRef类型的字典,包含一些可选的参数和选项。你可以在这个字典中指定图像的相关设置,如压缩质量、色彩空间、背景颜色等。如果你不需要特定的选项,可以将其设置为nil,使用默认选项参考如下:
-
对于JPEG文件(
kUTTypeJPEG
),默认选项通常包括:- 压缩质量为0.75,即75%的图像质量。
- 使用RGB颜色空间。
-
对于PNG文件(
kUTTypePNG
),默认选项通常包括:- 不进行压缩,即无损压缩。
- 使用RGBA颜色空间。
-
对于GIF文件(
kUTTypeGIF
),默认选项通常包括:- 使用LZW压缩算法。
- 使用RGBA颜色空间。
最终,该函数会返回一个CGImageDestinationRef对象,该对象可以用于将图像数据添加到目标中,并完成最终的图像输出。
关键特点:
-
目标类型灵活性:CGImageDestinationCreateWithData允许你选择将图像数据写入的目标类型。你可以使用不同的图像容器类型,如JPEG、PNG、GIF等,根据需要选择适合的目标。
-
减少内存占用:使用CGImageDestinationCreateWithData,你可以逐步将图像数据写入目标,而不需要一次性将整个图像数据加载到内存中。这对于处理大型图像或内存受限的环境非常有用。
-
动画支持:CGImageDestinationCreateWithData还支持创建一个包含多个帧的图像目标,从而创建一个具有动画效果的图像文件。你可以按顺序添加多个图像帧到目标中,并设置每个帧的压缩参数和属性。
-
自定义选项:你可以通过提供自定义的属性键值对来自定义图像写入过程。可以控制图像的压缩质量、元数据、缩放、字节对齐等参数和属性。
-
错误处理:如果在图像写入过程中出现错误,CGImageDestinationCreateWithData可以提供错误处理功能。你可以检查状态来获取有关错误的信息或状态码,并根据需要进行适当的错误处理。
综上所述,CGImageDestinationCreateWithData提供了一种灵活且可定制的方式,用于将图像数据写入指定目标。它的特点包括目标类型的选择、内存占用的减少、动画支持、自定义选项和错误处理。这使得它成为处理图像写入操作时的有效工具。
和方案2的比较:
CGImageDestinationCreateWithData
和UIImageJPEGRepresentation
这两种方法都可以将UIImage对象转换为JPEG格式的NSData数据,但它们有一些不同之处。
- 灵活性和控制性:
-
CGImageDestinationCreateWithData
方法允许你指定更多的选项和参数来控制输出图像的质量、缓存行为以及其他属性。你可以使用选项字典来自定义编码过程,并根据需求进行优化。UIImageJPEGRepresentation
方法相对简单,只需传入一个UIImage对象和一个质量参数(0.0到1.0之间的值)即可。它提供了一个简便的方式来进行图像转换,但没有提供对更多选项的直接访问。
- 性能和效率:
-
CGImageDestinationCreateWithData
方法在处理大尺寸图像时可能会更加高效,因为它可以逐步写入数据,而不需要完全加载整个图像到内存中。这对于处理内存受限的情况或处理大型图像时可能是一个优势。UIImageJPEGRepresentation
方法会将整个UIImage对象加载到内存中,并一次性转换为NSData数据。对于小型图像和常规用途,这可能没有明显影响,但处理大图像时可能会占用更多的内存。
因此,选择哪种方法取决于你的具体需求。如果你需要更多的控制权和灵活性,以及能够处理大型图像,那么CGImageDestinationCreateWithData
可能更适合。如果你需要一个简单且易于使用的方法来转换图像,并且对性能和内存使用没有过多要求,那么UIImageJPEGRepresentation
可以是一个很好的选择。
参考链接:
1、https://www.jianshu.com/p/dac08fa1704a (UIImage 转 NSData调研)
2、https://www.jianshu.com/p/ea475f608526 (iOS UIImage图片文件大小)
posted on 2023-07-28 15:42 ACM_Someone like you 阅读(2162) 评论(0) 编辑 收藏 举报
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)