解决UIImage显示方向和内存方向不一致的问题

来源:互联网 发布:碧然德 倍世 知乎 编辑:程序博客网 时间:2024/05/18 01:24

iOS中的UIImage中有imageOrientation属性,该属性决定了UIImage在手机上显示时的方向。如果imageOrientation的值为left或right,那么显示出来的图像和实际图像在内存中的存储就存在90度的旋转问题。比如显示出来的图片是720*1280的,实际上该图在内存中是按1280*720存储的。
在stackoverflow上折腾了一番,找到了下面靠谱的解决办法。

extension UIImage {    func fixImageOrientation() -> UIImage? {        guard let cgImage = self.cgImage else {            return nil        }        if self.imageOrientation == UIImageOrientation.up {            return self        }        let width  = self.size.width        let height = self.size.height        var transform = CGAffineTransform.identity        switch self.imageOrientation {        case .down, .downMirrored:            transform = transform.translatedBy(x: width, y: height)            transform = transform.rotated(by: CGFloat.pi)        case .left, .leftMirrored:            transform = transform.translatedBy(x: width, y: 0)            transform = transform.rotated(by: 0.5*CGFloat.pi)        case .right, .rightMirrored:            transform = transform.translatedBy(x: 0, y: height)            transform = transform.rotated(by: -0.5*CGFloat.pi)        case .up, .upMirrored:            break        }        switch self.imageOrientation {        case .upMirrored, .downMirrored:            transform = transform.translatedBy(x: width, y: 0)            transform = transform.scaledBy(x: -1, y: 1)        case .leftMirrored, .rightMirrored:            transform = transform.translatedBy(x: height, y: 0)            transform = transform.scaledBy(x: -1, y: 1)        default:            break;        }        // Now we draw the underlying CGImage into a new context, applying the transform        // calculated above.        guard let colorSpace = cgImage.colorSpace else {            return nil        }        guard let context = CGContext(            data: nil,            width: Int(width),            height: Int(height),            bitsPerComponent: cgImage.bitsPerComponent,            bytesPerRow: 0,            space: colorSpace,            bitmapInfo: UInt32(cgImage.bitmapInfo.rawValue)            ) else {                return nil        }        context.concatenate(transform);        switch self.imageOrientation {        case .left, .leftMirrored, .right, .rightMirrored:            // Grr...            context.draw(cgImage, in: CGRect(x: 0, y: 0, width: height, height: width))        default:            context.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))        }        // And now we just create a new UIImage from the drawing context        guard let newCGImg = context.makeImage() else {            return nil        }        let img = UIImage(cgImage: newCGImg)        return img;    } }

上面的代码能根据UIImage中的imageOrientation去翻转图像的实际存储布局。

如果想任意角度旋转图像,比如来个30度?下面的函数可以实现。

func imageRotatedByDegrees(oldImage: UIImage, deg degrees: CGFloat) -> UIImage {    //Calculate the size of the rotated view's containing box for our drawing space    var rotatedViewBox: UIView = UIView(frame: CGRect(x: 0, y: 0, width: oldImage.size.width, height: oldImage.size.height))    print(oldImage.size.height)    if (oldImage.imageOrientation == .right)    {        rotatedViewBox = UIView(frame: CGRect(x: 0, y: 0, width: oldImage.size.height, height: oldImage.size.width))    }    let t: CGAffineTransform = CGAffineTransform(rotationAngle: degrees * CGFloat.pi / 180)    rotatedViewBox.transform = t    let rotatedSize: CGSize = rotatedViewBox.frame.size    //Create the bitmap context    UIGraphicsBeginImageContext(rotatedSize)    let bitmap: CGContext = UIGraphicsGetCurrentContext()!    //Move the origin to the middle of the image so we will rotate and scale around the center.    bitmap.translateBy(x: rotatedSize.width / 2, y: rotatedSize.height / 2)    //Rotate the image context    bitmap.rotate(by: (degrees * CGFloat.pi / 180))    //Now, draw the rotated/scaled image into the context    bitmap.scaleBy(x: 1.0, y: -1.0)    bitmap.draw(oldImage.cgImage!, in: CGRect(x: -oldImage.size.height / 2, y: -oldImage.size.width / 2, width: oldImage.size.height, height: oldImage.size.width))    let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!    UIGraphicsEndImageContext()    return newImage}
原创粉丝点击