iOS开发关于“发送原图”功能问题的记录
来源:互联网 发布:身份证照片识别软件 编辑:程序博客网 时间:2024/06/05 11:14
近期在做“发送原图”功能的时候,遇到一个bug:在Android、Windows、Mac 客户端发送原图,iOS客户端接收,保存原图后,原图物理尺寸不变,存储空间变小,对应的location等Exif信息丢失。与此同时,iOS客户端之间互发原图没有问题。针对这个问题,做了以下测试调研,现记录下来:
一. 首先介绍一下发送一张原图的流程:
比如 Android 端发送一张原图,先上传到 IM 的服务器,上传成功后再发送消息体;(上传成功后,服务器会分配三个url分别对应缩略图、大图、原图)
接收方接收到消息体,下载缩略图;
点击缩略图,下载大图;
再点击“查看原图”按钮,下载原图;
下载成功后,长按图片,保存原图。
二. 问题定位是在最后一步,保存图片的部分:
下载的图片大小与服务器存储大小是完全一致的,保存之后大小就发生了变化(目前是“jpg”格式变小,“png”格式图片变大);
下载的方式分别尝试了 AFNetwoking 下载、SDWebImage 的普通下载和高级下载方式(因为产品需求要求显示下载原图进度)
结论下载的图片大小与服务器存储大小是完全一致的是因为在 SDWebImage 高级下载方法的 completionBlock 中有已下载的 bit 值
尝试了能找到的各种保存图片的方式,均不行
验证测试:将安卓端产生的图片(包括拍照“jpg”和屏幕截图“png”)从浏览器下载到电脑,大小不变,将该图片文件拖到项目中,执行保存图片的方法,大小也发生了变化。
补充测试:安卓端拍摄一张图片(大小为5M),发送给 iOS 客户端(下载大小为5M),保存(大小为3M),再将该保存的图片发给安卓客户端(保存后为3M),安卓客户端再发送给iOS 客户端(保存后大小为3M)。结论:该压缩只会进行一次
保存图片后,图片的Exif信息丢失,但是Exif信息的大小远小于文件损失的大小。图片物理尺寸没有发生变化
三. 竞品的该功能现状:
Android、Windows、Mac发送原图,iOS客户端接收
腾讯系(QQ、WeChat)各端发送接收原图都没有问题
钉钉 的图片变小,Exif 信息丢失
BearyChat 发送原图的图片变小,Exif 信息丢失
Slack 只支持发送图片,没有发送原图功能
四. 基于现有情况的分析
iOS 系统在保存图片的时候,会对图片进行编解码操作,可能在位图上进行优化
一张图片的存储大小的计算方式:水平像素垂直像素1色黑白或3基色*颜色深度bit数 = MB数,可能是不同系统的基数不同导致
如果要解决这个问题,要先研究一下图片编解码这些很底层的东西,目前来看,性价比很低
如果您之前踩过类似的坑并找到有效的解决方法,方便的话,劳烦请私信告知
五. 补充点干货
1. 关于iOS11新增的“.heic”格式图片
什么是“.heic”格式图片?
之前叫“live”图片,打开下图红框中的按钮即可打开该模式,拍照后会截取拍照前后大概两秒的一个片段,与“Gif”图不同的是,该格式还包含了声音(目前只有)
image.png
什么样的手机才能拍出“.heic”格式图片?
只有在 iOS11系统下且CPU为A10及其以上(最低也得是iPhone 7),其他情况下拍出来的都是普通“live”图,即在需要转换格式的时候会自动转换为“.jpg/.jpeg”格式
如何判断一张图片是否是“.heic”格式?
SDWebImage-NSData+ImageContentType.m 已更新,刚开始遇到这个问题的时候提了个issue,还让我提供对应url。。
+ (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data {
if
(!data) {
return
SDImageFormatUndefined;
}
// File signatures table: http://www.garykessler.net/library/file_sigs.html
uint8_t c;
[data getBytes:&c length:
1
];
switch
(c) {
case
0xFF
:
return
SDImageFormatJPEG;
case
0x89
:
return
SDImageFormatPNG;
case
0x47
:
return
SDImageFormatGIF;
case
0x49
:
case
0x4D
:
return
SDImageFormatTIFF;
case
0x52
: {
if
(data.length >=
12
) {
//RIFF....WEBP
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(
0
,
12
)] encoding:NSASCIIStringEncoding];
if
([testString hasPrefix:@
"RIFF"
] && [testString hasSuffix:@
"WEBP"
]) {
return
SDImageFormatWebP;
}
}
break
;
}
case
0x00
: {
if
(data.length >=
12
) {
//....ftypheic ....ftypheix ....ftyphevc ....ftyphevx
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(
4
,
8
)] encoding:NSASCIIStringEncoding];
if
([testString isEqualToString:@
"ftypheic"
]
|| [testString isEqualToString:@
"ftypheix"
]
|| [testString isEqualToString:@
"ftyphevc"
]
|| [testString isEqualToString:@
"ftyphevx"
]) {
return
SDImageFormatHEIC;
}
}
break
;
}
}
return
SDImageFormatUndefined;
}
+ (nonnull CFStringRef)sd_UTTypeFromSDImageFormat:(SDImageFormat)format {
CFStringRef UTType;
switch
(format) {
case
SDImageFormatJPEG:
UTType = kUTTypeJPEG;
break
;
case
SDImageFormatPNG:
UTType = kUTTypePNG;
break
;
case
SDImageFormatGIF:
UTType = kUTTypeGIF;
break
;
case
SDImageFormatTIFF:
UTType = kUTTypeTIFF;
break
;
case
SDImageFormatWebP:
UTType = kSDUTTypeWebP;
break
;
case
SDImageFormatHEIC:
UTType = kSDUTTypeHEIC;
break
;
default
:
// default is kUTTypePNG
UTType = kUTTypePNG;
break
;
}
return
UTType;
}
对于“.heic”格式图片我们应该怎么处理?
首先肯定不是服务器去支持这个类型,因为 Windows、Android 是不支持该类型的图片正常显示的,尤其是 Windows 明确表示以后也不会支持。
微信目前的处理方式是转换成了 jpg 格式,因此直接使用 UIImageJPEGRepresentation(originalImage, 0.82); 转换为jpg即可
但是经多次测试后发现,必须设置压缩比为0.82,转换后的大小才尽可能的接近原图大小
- iOS开发关于“发送原图”功能问题的记录
- IM的发送原图功能
- 【matlab】:matlab关于原图修改及画图的相关问题
- 关于iOS开发的一些记录
- iOS开发 关于iBeacon的一些记录
- 记录ios开发的一些问题
- 带查看原图功能的图像浏览器
- iOS开发关于微信摇一摇功能的简单的介绍
- ios开发中关于绘图的问题
- 关于iOS开发CPU架构的问题
- iOS 开发中关于支付功能的学习心得 ----支付宝
- 记录IOS开发中遇到的问题以及解决方法
- dede5.7 调用原图 缩略图 的问题
- 关于发送短信的问题
- 关于开发安卓sqlite的小问题记录
- 开发记录——关于play传值的问题
- 关于oc 开发上传图片 功能遇到的问题分享
- iOS发送邮件功能
- 如何创建主键自增表
- SpringMVC常用注解
- spring aop注解使用的例子
- 指针
- calcPi
- iOS开发关于“发送原图”功能问题的记录
- OSG学习:C#调用非托管C++方法——C++/CLI
- 手写堆heap(STL的heap算法)
- QT程序打开网页
- java中读取配置文件的方法fileSystemXmlapplicationContext与classPathXmlApplicationContext
- 用C语言实现三子棋
- Python/Anaconda-python2.x代码转为python3.x代码
- CF 879 C. Short Program 思维+二进制
- Trafodion安装执行initialize trafodion失败