网页客服,欢迎咨询

iPhone相机拍照真实图片区域与预览视图的关系以及处理

2025-01-06 14:05:03 239
  • 收藏
  • 管理
    总篇第144篇 2022年第19篇场景我们在开发VIN码识别控件的时候,遇到了预览框预览到的图片和真实截取出来的图片在不同iPhone上获得的图片不一致。不同尺寸屏幕的手机上发生了不同类型的位置偏移。从下图可见,左侧的图片为实际相机预览看到的,右侧为拍照后得到的,2张图的内容有区别。原因探查经过调研发现,iOS相机拍照时的预览内容与实际得到的真实图片不是100%一致的。当我们在相机拍摄时,自定义了输出照片的长宽像素值(比如1280×720),iPhone的取景框默认会撑满不留黑边的展示出照片,会进行"等比放大"处理,这样就会有部分图像是超出屏幕可视区的。这就好比单反相机的一个参数:查看区域和拍摄区域的视野率。我们这里的VIN相机默认设置了1280×720的分辨率进行拍摄,经过测试,iPhone拍摄后获取到的真实图片与图像预览区视图存在一定的换算关系,如下图:手机纵向拍摄举例,这里分为2种情况:1.情况A:当实际照片的宽高比大于屏幕拍摄预览的宽高比时,系统会将实际照片和拍摄预览区以高度对齐,然后在水平方向上居中展示,左右部分超出。a.手机屏幕看到的图像部分为半透明蓝色区域;b.图片左右侧半透明绿色区域示意为,实际照片超出屏幕的部分;c.淡粉色透明区域为实际VIN码取景框与屏幕边界的间距;2.情况B:当实际图片的宽高比小于拍摄区的宽高比时,系统会将实际图片和拍摄区以宽度对齐,然后在垂直方向上居中展示,上下部分超出。a.手机屏幕看到的为半透明粉色区域;b.图片上下半透明绿色区域为实际照片超出屏幕的部分;c.VIN码取景框左右淡粉色透明区域为取景框屏幕边界的间距;由此可以看出,当我们需要在拍照获取到的照片上,准确计算出取景框看到的图像部分进行裁切时,根据情况A或B,在计算了屏幕边界距离的基础上,需要再加上屏幕上的非可见区域部分的距离,才可以得到一个完美的所见即所得的VIN照片。代码处理如上图所示,由于不同手机屏幕宽高比的不同,我们的预览区的宽高比也是动态的。所以针对出现的图片宽高比和预览区宽高比不同的情况,我们要做出相应的位置补偿。计算裁切区域在屏幕大小照片上的位置补偿根据图片和预览区的宽高比,分别计算在A、B两种情况下水平和垂直方向上的补偿,然后重新计算裁切区在屏幕大小照片上的大小和位置信息。- (CGRect)fixCropRect:(CGRect)cropRect realImageSize:(CGSize)realImageSize previewRect:(CGRect)previewRect { CGRect fixedCropRect = cropRect; // 图片宽高比 CGFloat imageRatio = realImageSize.width / realImageSize.height; // 预览框的宽高比 CGFloat previewRatio = previewRect.size.width / previewRect.size.height; if (imageRatio > previewRatio) { // 图片的宽高比 > 拍摄区的宽高比 /* 当出现情况A的时候: 图片宽高比: 720/1280 = 0.5625 拍摄预览区宽高比: 390/753 = 0.517928287 图片的宽高比 > 拍摄区的宽高比时, 系统自动以【高】对齐, 实际图片比可视区宽, 横向居中【左右】超出屏幕 */ // 计算实际图片换算到屏幕的宽度: 423.5625 CGFloat imageScreenWidth = imageRatio * previewRect.size.height; // 计算出 x 需要补偿的距离, 并且补偿 x fixedCropRect.origin.x = (imageScreenWidth - cropRect.size.width)/2; } else if (imageRatio previewRatio) { // 图片的宽高比 > 拍摄区的宽高比 /* 当出现情况A的时候: 图片宽高比: 720/1280 = 0.5625 拍摄预览区宽高比: 390/753 = 0.517928287 图片的宽高比 > 拍摄区的宽高比时, 系统自动以【高】对齐, 实际图片比可视区宽, 横向居中【左右】超出屏幕 */ // 以高为基准, 计算图片放大比例 CGFloat scale = PREVIEW_HEIGHT / imageSize.height; CGFloat x = cropRect.origin.x / scale; CGFloat y = cropRect.origin.y / scale; CGFloat w = cropRect.size.width / scale; CGFloat h = cropRect.size.height / scale; rectOnImage = CGRectMake(x, y, w, h); } else { // 图片的宽高比 previewRatio) { // 图片的宽高比 > 拍摄区的宽高比 /* 当出现情况A的时候: 图片宽高比: 720/1280 = 0.5625 拍摄预览区宽高比: 390/753 = 0.517928287 图片的宽高比 > 拍摄区的宽高比时, 系统自动以【高】对齐, 实际图片比可视区宽, 横向居中【左右】超出屏幕 */ // ↓↓↓ 补偿计算 ↓↓↓ // 求实际图片换算到屏幕的宽度: 423.5625 CGFloat imageScreenWidth = imageRatio * previewRect.size.height; // 计算出 x 需要补偿的距离, 并且补偿 x cropRect.origin.x = (imageScreenWidth - cropRect.size.width)/2; // ↓↓↓ 比例放大计算 ↓↓↓ // 以高为基准, 计算图片放大比例 CGFloat scale = PREVIEW_HEIGHT / imageSize.height; CGFloat x = cropRect.origin.x / scale; CGFloat y = cropRect.origin.y / scale; CGFloat w = cropRect.size.width / scale; CGFloat h = cropRect.size.height / scale; rectOnImage = CGRectMake(x, y, w, h); } else { // 图片的宽高比 iPhone相机拍照真实图片区域与预览视图的关系以及处理
    上一页:openLooKeng跨源异构在之家的升级与实践 下一页:iPhone兼容性修复:吸顶效果的Tabs标签页组件的完美自定义
    全部评论(0)