Search code examples
iosswiftimagescreenshotscale

Partial screenshot & loss of image quality


I'm printing a partial screenshot for camera roll, email, sms, FB, Twitter, etc... Partial screen selected - 100 pixels from top, 100 from bottom.

I used following code:

let top: CGFloat = 100
let bottom: CGFloat = 100

let size = CGSize(width: view.frame.size.width, height: view.frame.size.height - top - bottom)

UIGraphicsBeginImageContext(size)

let context = UIGraphicsGetCurrentContext()!

CGContextTranslateCTM(context, 0, -top)

view.layer.renderInContext(context)

let snapshot = UIGraphicsGetImageFromCurrentImageContext()

UIGraphicsEndImageContext()

UIImageWriteToSavedPhotosAlbum(snapshot, nil, nil, nil)

The resultant screenshot was of a poor quality.

I have researched for hours and found several people have a similar problem. I can't quite get my head around modifying solutions given to them to my issue.

I did manage to find a semi-fix. I changed:

UIGraphicsBeginImageContext(size)

to

UIGraphicsBeginImageContextWithOptions(imageView.bounds.size,true,2.0)

which essentially scales up my screenshot by factor of 2.0

This seems to give me a sharper/better quality partial screenshot, although the image is larger than I intended.

Is there another solution I can apply that might be more appropriate?

Thanks!


Solution

  • The problem is that UIGraphicsBeginImageContext() creates an image context with a scale of 1.0, however your layer (as it's being displayed on-screen) has a scale equivalent to the device's screen's scale – which is most likely higher than 1.0.

    You therefore want to be using UIGraphicsBeginImageContextWithOptions() as you correctly said, but instead of passing 2.0 for the scale (which will work on 2x displays, but not on others), pass 0.0.

    As the documentation says for the scale argument:

    The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.

    The context will therefore automatically detect the scale factor of the screen when you do this, and the image will come out nice and clear on any device you run it on.