3

I'm replacing UIGraphicsBeginImageContext with UIGraphicsImageRendererFormat to optimize performance and modernize my code. For some reason, UIGraphicsImageRendererFormat is returning a blank image in my function. I must be doing something wrong!

Old function: (works fine)

func drawImageInRect(inputImage: UIImage, inRect imageRect: CGRect) -> UIImage {

    UIGraphicsBeginImageContext(self.size)
    self.draw(in:(CGRect(x:0.0, y:0.0, width:self.size.width, height:self.size.height)))
    inputImage.draw(in:(imageRect))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage!
}

New function: (draws nothing)

func drawImageInRect(inputImage: UIImage, inRect imageRect: CGRect) -> UIImage {


    let renderFormat = UIGraphicsImageRendererFormat.default()
    renderFormat.opaque = true
    let renderer = UIGraphicsImageRenderer(size: self.size, format: renderFormat)

    let scaledImage = renderer.image {
        (context) in
        inputImage.draw(in: imageRect)
    }
    return scaledImage
}
Chewie The Chorkie
  • 4,896
  • 9
  • 46
  • 90
  • 2
    BTW - It would be helpful to others if you mention that these functions are in a `UIImage` extension. – rmaddy Jun 13 '18 at 21:49
  • `extension UIImage { func drawing(_ image: UIImage, in rect: CGRect) -> UIImage { let renderFormat = UIGraphicsImageRendererFormat.default() renderFormat.opaque = true return UIGraphicsImageRenderer(size: size, format: renderFormat).image { _ in draw(in: CGRect(origin: .zero, size: size)) image.draw(in: rect) } } }` – Leo Dabus Jun 13 '18 at 22:14

1 Answers1

1

The problem is that in your updated function you forgot to draw self so you get a black background where the original image should be.

func drawImageInRect(inputImage: UIImage, inRect imageRect: CGRect) -> UIImage {
    let renderFormat = UIGraphicsImageRendererFormat.default()
    renderFormat.opaque = true
    let renderer = UIGraphicsImageRenderer(size: self.size, format: renderFormat)

    let scaledImage = renderer.image {
        (context) in
        // Add the following missing line
        self.draw(in:(CGRect(x:0.0, y:0.0, width:self.size.width, height:self.size.height)))
        inputImage.draw(in: imageRect)
    }
    return scaledImage
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • That certainly helps it actually display something, but for some reason my performance goes way down. (CPU is now at 80%!) Also it doesn't draw what it does with the older function. Any idea why? – Chewie The Chorkie Jun 14 '18 at 17:07
  • The code in my answer produces the identical image as the working code in your question. I tested both in an Xcode 9.4 Swift playground. But again, please confirm whether this code is part of a `UIImage` extension or not. – rmaddy Jun 14 '18 at 17:08
  • It is part of a UIImage extension, yes. Slower performance and not the same result because it's performing two draws? – Chewie The Chorkie Jun 14 '18 at 17:10
  • Your working code and my answer both perform two draws - the original image (`self`) and the `inputImage`. – rmaddy Jun 14 '18 at 17:11
  • For some reason, both functions don't have equivalent results. – Chewie The Chorkie Jun 14 '18 at 17:14
  • Update your question with the two images being used and then add both results. – rmaddy Jun 14 '18 at 17:15
  • I'm not using two images as far as I'm aware, I'm just using one. I updated my question with the full UIImage extension. Thank you! – Chewie The Chorkie Jun 14 '18 at 17:17
  • I added images of the before and after results – Chewie The Chorkie Jun 14 '18 at 17:28
  • Sorry the images were incorrect then in the wrong order! Fixed my image edit in the question – Chewie The Chorkie Jun 14 '18 at 17:30
  • It works the same for me. I load a PNG into a `UIImage`. I then call `let newImage = myImage.applyRotateHueInRect(rect: CGRect(x: 800, y: 500, width: 600, height: 600), rotatedByHue: 1.2)`. I used the exact extension code you just posted. I ran it twice, once for each implementation of `drawImageInRect` and I get the same result for both. – rmaddy Jun 14 '18 at 17:33
  • I decided to use only CIFilters to scale (CILanczosScaleTransform) and place (CISourceAtopCompositing) smaller images on others, and wow, performance went WAY up. I'll mark this answer correct even though I couldn't get the same results. I hope it helps someone, but I suggest not using draw or UIGraphicsImageRendererFormat if you constantly updating an image. – Chewie The Chorkie Jun 15 '18 at 19:05