当前位置: 首页 > 科技观察

关于“发送原图”功能的iOS开发记录

时间:2023-03-13 05:08:23 科技观察

本文主要记录一个bug从发现、定位到延迟解决的过程。文末补上踩过的坑。最近在做“发送原图”功能的时候,遇到一个bug:Android、Windows、Mac客户端发送原图,iOS客户端收到。保存原图后,原图的物理大小保持不变,存储空间变小,相应的位置等Exif信息丢失。同时,iOS客户端之间发送原图没有问题。针对这个问题,做了如下测试研究,现记录下来:微信风格发送原图1.首先介绍一下发送原图的过程:比如在微信发送原图时Android端,先上传到IM服务器,上传成功后发送消息体;(上传成功后,服务器会分配缩略图、大图、原图分别对应的三个url)接收方收到消息体,下载缩略图;点击缩略图下载大图;然后点击“查看原图”按钮下载原图;下载成功后,长按图片保存原图。2、问题定位在最后一步,保存图片的部分:下载的图片大小和服务器存储大小完全一致,保存后大小发生变化(目前是“jpg”格式变小,而“png”格式的图片变大);下载方式尝试了AFNetwoking下载、SDWebImage普通下载和高级下载方式(因为产品需求需要显示原图下载进度)结论是下载的图片大小和服务器存储大小完全一样,因为在SDWebImage中有是已经在高级下载方法的completionBlock中下载的位值。我尝试了各种我能找到的保存图片的方法,但都没有用。验证测试:将Android端生成的图片(包括图片“jpg”和截图“png”)从浏览器中下载相同大小的图片文件到电脑上,将图片文件拖入项目中,执行保存图像的方法,大小也会改变。补充测试:Android端拍一张图片(5M大小),发送到iOS客户端(下载大小5M),保存(3M大小),然后将保存的图片发送到Android客户端(3M大小)保存后的大小)。),Android客户端发送给iOS客户端(保存后大小为3M)。结论:只会进行一次压缩,保存图片后会丢失图片的Exif信息,但Exif信息的大小远小于文件丢失的大小。图片的物理尺寸没有改变。3、竞品该功能现状:Android、Windows、Mac发送原图,iOS客户端接收来自腾讯(QQ、微信)的原图。所有终端收发原图都没有问题。钉钉图片变小,Exif信息丢失,BearyChat发送原图变小,Exif信息丢失,Slack只支持发送图片,没有发送原图功能。,可以优化一张图片在位图上的存储大小。计算方法:水平像素、垂直像素、1色黑白或3基色*色深位数=MB数,可能因不同系统的基数不同。如果你想解决这个问题,你必须首先研究图像编码和解码等非常底层的东西。目前性价比很低。什么是“.heic”格式的图像?它以前被称为“实时”图像。打开下图红框内的按钮,即可开启该模式。拍照后,会在照片前后两秒左右截取“Gif”图片的片段,区别于“Gif”图片,这种格式还包含声音(目前只有)什么样的手机可以以“.heic”格式拍照?仅限iOS11系统且CPU为A10及以上(***还必须是iPhone7),其他情况下拍摄的图片为普通“活”图片,即会自动转为“.jpg”/.jpeg”格式需要转换格式时。如何判断一张图片是否为“.heic”格式?SDWebImage-NSData+ImageContentType.m已更新。第一次遇到这个问题的时候,提了一个issue,让我提供对应的url。.+(SDImageFormat)sd_imageFormatForImageData:(nullableNSData*)data{if(!data){returnSDImageFormatUndefined;}//Filesignaturestable:http://www.garykessler.net/library/file_sigs.htmluint8_tc;[datagetBytes:&clength:1];开关(c){case0xFF:returnSDImageFormatJPEG;case0x89:returnSDImageFormatPNG;case0x47:returnSDImageFormatGIF;case0x49:case0x4D:returnSDImageFormatTIFF;case0x52:{if(data.length>=12){//RIFF....WEBPNSString*testString=[[NSStringalloc]initWithData:[datasubdataWithRange:NSMakeRange(0,12)]encoding:NSASCIIStringEncoding];if([testStringhasPrefix:@"RIFF"]&&[testStringhasSuffix:@"WEBP"]){returnSDImageFormatWebP;}}break;}case0x00:{if(data.length>=12){//....ftypheic....ftypheix....ftyphevc....ftyphevxNSString*testString=[[NSStringalloc]initWithData:[datasubdataWithRange:NSMakeRange(4,8)]编码:NSASCIIStringEncoding];if([testStringisEqualToString:@"ftypheic"]||[testStringisEqualToString:@"ftypheix"]||[testStringisEqualToString:@"ftyphevc"]||[testStringisEqualToString:@"ftyphevx"]){returnSDImageFormatHEIC;}}break;}}returnSDImageFormatUndefined;}+(nonnullCFStringRef)sd_UTTypeFromSDImageFormat:(SDImageFormat)format{CFStringRefUTType;开关(格式){caseSDImageFormatJPEG:UTType=kUTTypeJPEG;break;caseSDImageFormatPNG:UTType=kUTTypePNG;break;caseSDImageFormatGIF:UTType=kUTTypeGIF;break;caseSDImageFormatTIFF:UTType=kUTTypeTIFF;break;caseSDImageFormatWebP:UTType=kSDUTTypeWebP;break;break;default://defaultiskUTTypePNGUTType=kUTTypePNG;break;}returnUTType;}我们应该如何处理“.heic”格式的图像?首先,肯定不是支持这种类型的服务器,因为Windows和Android是不支持正常显示这种类型的图片的,尤其是Windows已经明确表示以后不支持微信了。目前的处理方式是转为jpg格式,所以直接使用UIImageJPEGRepresentation(originalImage,0.82);转为jpg,但经过多次测试发现必须设置压缩比为0.82,转换后的尺寸尽量接近原图尺寸