UIImage rotation without bursts of memory

I am currently rotating images using CGContextDrawImage, but when it is called, a gigantic burst of memory appears. Newer devices can handle this, but devices with a lower port, such as the iPhone 4, cannot. Image is a large file made by the user inAVCaptureSessionPresetHigh

I am currently rotating the image using this extension on UIImage

func rotate(orientation: UIImageOrientation) -> UIImage{
    if(orientation == UIImageOrientation.Up){return self}

    var transform: CGAffineTransform = CGAffineTransformIdentity

    if(orientation == UIImageOrientation.Down || orientation == UIImageOrientation.DownMirrored){
        transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height)
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
    }
    else if(orientation == UIImageOrientation.Left || orientation == UIImageOrientation.LeftMirrored){
        transform = CGAffineTransformTranslate(transform, self.size.width, 0)
        transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))
    }
    else if(orientation == UIImageOrientation.Right || orientation == UIImageOrientation.RightMirrored){
        transform = CGAffineTransformTranslate(transform, 0, self.size.height)
        transform = CGAffineTransformRotate(transform,  CGFloat(-M_PI_2))
    }


    if(orientation == UIImageOrientation.UpMirrored || orientation == UIImageOrientation.DownMirrored){
        transform = CGAffineTransformTranslate(transform, self.size.width, 0)
        transform = CGAffineTransformScale(transform, -1, 1)
    }
    else if(orientation == UIImageOrientation.LeftMirrored || orientation == UIImageOrientation.RightMirrored){
        transform = CGAffineTransformTranslate(transform, self.size.height, 0)
        transform = CGAffineTransformScale(transform, -1, 1);
    }

    let ref: CGContextRef = CGBitmapContextCreate(nil, Int(self.size.width), Int(self.size.height), CGImageGetBitsPerComponent(self.CGImage), 0, CGImageGetColorSpace(self.CGImage), CGImageGetBitmapInfo(self.CGImage))
    CGContextConcatCTM(ref, transform)

    if(orientation == UIImageOrientation.Left || orientation == UIImageOrientation.LeftMirrored || orientation == UIImageOrientation.Right || orientation == UIImageOrientation.RightMirrored){
        CGContextDrawImage(ref, CGRectMake(0, 0, self.size.height, self.size.width), self.CGImage)
    }
    else{
        CGContextDrawImage(ref, CGRectMake(0, 0, self.size.width, self.size.height), self.CGImage)
    }


    let cgImg: CGImageRef = CGBitmapContextCreateImage(ref)
    let rotated: UIImage = UIImage(CGImage: cgImg)!

    return rotated
}

This code works great on devices like the iPhone 5 and 6, but almost always crashes the iPhone 4s due to low memory.

I know that I can just load the image with EXIF ​​data that determines the orientation, but I feel like I just rotate the image before loading it to prevent further problems along the line.

iOS EXIF? ,

UIImage(image.CGImage, scale: 1.0, orientation: UIImageOrientation.Right)

EXIF, - , . - , , GPU, ?

.

, , ?

+4
1

( ) , UIGraphicsEndImageContext() , ( , , ).

, , , rotateExif(orientation),

extension UIImage{
    func rotateExif(orientation: UIImageOrientation) -> UIImage{

        if(orientation == UIImageOrientation.Up){return self}

        let current = self.imageOrientation
        let currentDegrees: Int = (
            current == UIImageOrientation.Down || current == UIImageOrientation.DownMirrored ? 180 : (
                current == UIImageOrientation.Left || current == UIImageOrientation.LeftMirrored ? 270 : (
                    current == UIImageOrientation.Right || current == UIImageOrientation.RightMirrored ? 90 : 0
                )
            )
        )
        let changeDegrees: Int = (
            orientation == UIImageOrientation.Down || orientation == UIImageOrientation.DownMirrored ? 180 : (
                orientation == UIImageOrientation.Left || orientation == UIImageOrientation.LeftMirrored ? 270 : (
                    orientation == UIImageOrientation.Right || orientation == UIImageOrientation.RightMirrored ? 90 : 0
                )
            )
        )


        let mirrored: Bool = (
            current == UIImageOrientation.DownMirrored || current == UIImageOrientation.UpMirrored ||
            current == UIImageOrientation.LeftMirrored || current == UIImageOrientation.RightMirrored ||
            orientation == UIImageOrientation.DownMirrored || orientation == UIImageOrientation.UpMirrored ||
            orientation == UIImageOrientation.LeftMirrored || orientation == UIImageOrientation.RightMirrored
        )

        let degrees: Int = currentDegrees + changeDegrees

        let newOrientation: UIImageOrientation = (
            degrees == 270 || degrees == 630 ? (mirrored ? UIImageOrientation.LeftMirrored : UIImageOrientation.Left) : (
                degrees == 180 || degrees == 540 ? (mirrored ? UIImageOrientation.DownMirrored : UIImageOrientation.Down) : (
                    degrees == 90 || degrees == 450 ? (mirrored ? UIImageOrientation.RightMirrored : UIImageOrientation.Right) : (
                        mirrored ? UIImageOrientation.UpMirrored : UIImageOrientation.Up
                    )
                )
            )
        )

        return UIImage(CGImage: self.CGImage!, scale: 1.0, orientation: newOrientation)
    }
}

EXIF ​​ , orientation. , , Right, Right, Down. RightMirrored, Left, UpMirrored.

, UIImage, image.rotate(image.imageOrientation).

+2

Source: https://habr.com/ru/post/1607222/