Draw on image using UIGraphicsImageRenderer rotates my image and produces a memory peak

I take the image from the phone's camera and then send it to my MainViewController to show it on an UIImageView. Then I do some image processing on my image and when I want to draw the result on my image I encounter 2 problems.

  • The first one is that when my UIGraphicsImageRenderer wants to render the image by using UIGraphicsImageRenderer.image. I get a peak of memory usage and my application gets shut down.

  • The second one is that my image (this one is smaller to be able to see the result) gets rotated and I don't know why. I mean, when I show it first in the preview, the image is fine and then when I show it post draw on it, it gets rotated. And if I force an inverse rotation, it works if the image comes from the assets instead of the camera but not with the camera.

The image's size from the camera is 3024x4032 And the one I use from the assets to see the result of the draw is 2448x3264 Here's the code of my draw function :

public static func Draw(image : UIImage, boxes : [CGRect] , imageToDraw : CGImage) -> UIImage
 {
        var bmp = image
            autoreleasepool
            {
             let rendererFormat = UIGraphicsImageRendererFormat()
             rendererFormat.scale = 1
             let renderer = UIGraphicsImageRenderer(size : image.size, format: rendererFormat)

             bmp = renderer.image { (ctx) in

                         ctx.cgContext.draw(bmp.cgImage!, in: CGRect(x: 1, y: 1, width: bmp.size.width-1, height: bmp.size.height-1))
                         ctx.cgContext.setShouldAntialias(true)

                         for bb in boxes
                            {
                                 var w : Float = Float(bb.width - bb.minX + 1)
                                 var h : Float = Float(bb.height - bb.minY + 1)
                                 let cx : Float = Float(bb.minX + ( bb.width - bb.minX)/2.0)
                                 let cy : Float = Float(bb.minY + ( bb.height - bb.minY)/2.0)

                                 w *= 1.5
                                 h *= 1.5
                                 let x : Float = cx - w/2
                                 let y : Float = cy - h/2

                                 if(w<h) { w=h }
                                 else { h=w }

                                 let rect = CGRect(x: CGFloat(x), y: CGFloat(y), width: CGFloat(w), height: CGFloat(h))

                                 ctx.cgContext.draw(imageToDraw, in: rect)

                            }

                 }

         }

         return bmp

     }
Accepted Answer

The memory spike is unavoidable – when drawing an image there must be memory on the order of the image's pixelWidth * pixelHeight (usually *4, but other constants are possible) available. If this is causing your application to terminate, you may want to verify that you are not trying to draw a very oversized image, or trying to enlarge the image accidentally (by creating a context significantly bigger than the original image).

As for the rotation, this is because images can be internally rotated (the pixels need not be written left to right, top to bottom) and this is common for camera sourced images. UIImage has an imageOrientation property that allows UIKit to draw these kinds of images correctly, which CGImage lacks. If you use UIImage's draw() methods instead, you should get the correct drawing.

Draw on image using UIGraphicsImageRenderer rotates my image and produces a memory peak
 
 
Q