修复使用前置摄像头拍摄的图像的方向 ios
Fix orientation of images taken with front camera ios
我使用 Swift 在我的应用中使用自定义相机实现。
当图像被捕获时,被称为func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?)
。我使用 photo.fileDataRepresentation()
获取图像数据,之后我使用 UIImage
.
上的以下扩展来修复照片的方向
func fixedOrientation() -> UIImage? {
guard imageOrientation != UIImage.Orientation.up else {
// This is default orientation, don't need to do anything
return self.copy() as? UIImage
}
guard let cgImage = self.cgImage else {
// CGImage is not available
return nil
}
guard let colorSpace = cgImage.colorSpace, let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else {
return nil // Not able to create CGContext
}
var transform = CGAffineTransform.identity
switch imageOrientation {
case .down, .downMirrored:
transform = transform.translatedBy(x: size.width, y: size.height)
transform = transform.rotated(by: CGFloat.pi)
case .left, .leftMirrored:
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.rotated(by: CGFloat.pi / 2.0)
case .right, .rightMirrored:
transform = transform.translatedBy(x: 0, y: size.height)
transform = transform.rotated(by: CGFloat.pi / -2.0)
case .up, .upMirrored:
break
@unknown default:
break
}
// Flip image one more time if needed to, this is to prevent flipped image
switch imageOrientation {
case .upMirrored, .downMirrored:
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
case .leftMirrored, .rightMirrored:
transform = transform.translatedBy(x: size.height, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
case .up, .down, .left, .right:
break
@unknown default:
break
}
ctx.concatenate(transform)
switch imageOrientation {
case .left, .leftMirrored, .right, .rightMirrored:
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.height, height: size.width))
default:
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
}
guard let newCGImage = ctx.makeImage() else { return nil }
return UIImage(cgImage: newCGImage, scale: 1, orientation: .up)
}
显然这对于使用后置摄像头拍摄的图像效果很好,但使用正面摄像头时我遇到了问题。
- 如果自拍照片是人像,方法returns照片镜像。(这没什么大不了的)
- 如果自拍照片是横向拍摄的 right/left,输出代码是照片也被镜像但错误地旋转了。这是我需要你帮助的地方,以正确旋转照片。
注意:我也在旋转设备时将 videoOrientation
从 AVCaptureConnection
更改。
事实证明,我在更改 videoOrientation
时旋转确实发生了变化,这是错误的。在拍摄照片之前,我必须移动该逻辑。现在它工作正常。如果使用前置摄像头,我还通过将 isVideoMirrored
设置为 true 来解决镜像问题。
我使用 Swift 在我的应用中使用自定义相机实现。
当图像被捕获时,被称为func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?)
。我使用 photo.fileDataRepresentation()
获取图像数据,之后我使用 UIImage
.
func fixedOrientation() -> UIImage? {
guard imageOrientation != UIImage.Orientation.up else {
// This is default orientation, don't need to do anything
return self.copy() as? UIImage
}
guard let cgImage = self.cgImage else {
// CGImage is not available
return nil
}
guard let colorSpace = cgImage.colorSpace, let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: cgImage.bitsPerComponent, bytesPerRow: 0, space: colorSpace, bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else {
return nil // Not able to create CGContext
}
var transform = CGAffineTransform.identity
switch imageOrientation {
case .down, .downMirrored:
transform = transform.translatedBy(x: size.width, y: size.height)
transform = transform.rotated(by: CGFloat.pi)
case .left, .leftMirrored:
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.rotated(by: CGFloat.pi / 2.0)
case .right, .rightMirrored:
transform = transform.translatedBy(x: 0, y: size.height)
transform = transform.rotated(by: CGFloat.pi / -2.0)
case .up, .upMirrored:
break
@unknown default:
break
}
// Flip image one more time if needed to, this is to prevent flipped image
switch imageOrientation {
case .upMirrored, .downMirrored:
transform = transform.translatedBy(x: size.width, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
case .leftMirrored, .rightMirrored:
transform = transform.translatedBy(x: size.height, y: 0)
transform = transform.scaledBy(x: -1, y: 1)
case .up, .down, .left, .right:
break
@unknown default:
break
}
ctx.concatenate(transform)
switch imageOrientation {
case .left, .leftMirrored, .right, .rightMirrored:
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.height, height: size.width))
default:
ctx.draw(cgImage, in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
}
guard let newCGImage = ctx.makeImage() else { return nil }
return UIImage(cgImage: newCGImage, scale: 1, orientation: .up)
}
显然这对于使用后置摄像头拍摄的图像效果很好,但使用正面摄像头时我遇到了问题。
- 如果自拍照片是人像,方法returns照片镜像。(这没什么大不了的)
- 如果自拍照片是横向拍摄的 right/left,输出代码是照片也被镜像但错误地旋转了。这是我需要你帮助的地方,以正确旋转照片。
注意:我也在旋转设备时将 videoOrientation
从 AVCaptureConnection
更改。
事实证明,我在更改 videoOrientation
时旋转确实发生了变化,这是错误的。在拍摄照片之前,我必须移动该逻辑。现在它工作正常。如果使用前置摄像头,我还通过将 isVideoMirrored
设置为 true 来解决镜像问题。