4

I am building a custom image keyboard and am having trouble properly resizing an image. I have tried a bunch of different methods with no success. The issue is the image is either bigger than I would like it to be or, if I resize it to half of my intended size, then it is more blurry than the original is. In the following example I am attempting to resize the image to the same size (see bottom of post for a screenshot) as it is being displayed on screen. Here is my code for calling the resizing:

println("Starting Size is \(image!.size)")
println("New Size is: \(sender.frame.size))")
println("Initial Scale: \(image!.scale)")

image = imageResize(image!, size: CGSize(width: sender.frame.width, height: sender.frame.height))

println("Final Size is \(image!.size)")
println("Final Scale: \(image!.scale)")

Here is the console output for the above print statements:

Starting Size is (750.0, 750.0)
New Size is: (78.0, 78.0))
Initial Scale: 1.0
Final Size is (78.0, 78.0)
Final Scale: 2.0

Here is the imageResize function

func imageResize(image:UIImage, size:CGSize)-> UIImage {
    UIGraphicsBeginImageContextWithOptions(size, false, 0)
    var context = UIGraphicsGetCurrentContext()

    CGContextSetInterpolationQuality(context, kCGInterpolationHigh)
    image.drawInRect(CGRect(origin: CGPointZero, size: size))

    let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return scaledImage
}

Finally, here is screenshot:

Example Image Resizing

Update:

To clarify, the image on the bottom of the screenshot is from the keyboard. It is a UIButton with the full size (750x750) image placed in it. When I am copying the image to the pasteboard, I begin with the full size image and downsize it to match the frame of the UIButton in the keyboard. So I am trying to get the image in the text message to be the same size and have the same clarity of the image in the keyboard.

Update #2

I updated my image resizing function to adjust the image size depending on the screen scale:

func imageResize(image:UIImage, size:CGSize)-> UIImage {

    let scale  = UIScreen.mainScreen().scale
    let newSize = CGSize(width: size.width / scale, height: size.height / scale)

    UIGraphicsBeginImageContextWithOptions(newSize, false, scale)
    var context = UIGraphicsGetCurrentContext()

    CGContextSetInterpolationQuality(context, kCGInterpolationHigh)
    image.drawInRect(CGRect(origin: CGPointZero, size: newSize))

    let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return scaledImage
}

Here is the console output will some details about the image:

Starting Size is (750.0, 750.0)
New Size is: (78.0, 78.0))
Initial Scale: 1.0
Final Size is (39.0, 39.0)
Final Scale: 2.0

Lastly, here is what the image looks like on the device (iPhone 6):

Second Screenshot

As you can see, although the image has the proper frame, it appears blurry in comparison to the UIButton in the keyboard. I should be able to achieve the same resolution as the UIButton since I am starting with the full size image in both cases. Any thoughts as to why I am losing resolution?

Update #3

I updated my code to multiply the image by the scale as opposed to dividing by it.

let newSize = CGSize(width: size.width * scale, height: size.height * scale)

Here is the result:

Starting Size is (750.0, 750.0)
New Size is: (78.0, 78.0))
Initial Scale: 1.0
Final Size is (156.0, 156.0)
Final Scale: 2.0

Update 3

I really appreciate your help, but I am not still not understanding how to pull this all together to get a properly sized photo. To completely clarify my goal, I am trying to make the image copied into the message appear exactly like the image in the UIButton within the keyboard. Here is the code I am using to add the image to the pasteboard to copy it into the message text. The pasteboard code is run after the image is resized:

pb.setData(UIImagePNGRepresentation(image), forPasteboardType: type)
mgeno
  • 191
  • 3
  • 13
  • What's the blurry part? The smaller image in your screen shot is actually _sharper_! – matt Sep 01 '15 at 03:11
  • If you scale an image down here will be fewer pixels so it can not be as sharp. A 100x100 pixels image downsized to 50x50 pixels will have 1/4 the number of pixels. It is clear what you are asking. – zaph Sep 01 '15 at 03:32
  • Stated: "'if I resize it to half of my intended size, then it is more blurry" Why resizing to 1/2 of the intended size. – zaph Sep 01 '15 at 12:39
  • How are you displaying th image? – zaph Sep 01 '15 at 18:18
  • To display the image in the UIButton I am just using the `setImage(image, forState: .Normal)` function. For the message field, after adding the image to the paste board with `pb.setData(UIImagePNGRepresentation(image), forPasteboardType: type)`, I paste the image into the message by holding down on the text box and pressing paste when the prompt appears – mgeno Sep 01 '15 at 18:55
  • I am getting same issue. Image showing proper in iPhone 6+ nut it's lossing quality in iPhone 6! – kb920 Jan 19 '16 at 11:09

2 Answers2

1

Note: points are not pixels. High resolution screens may have points comprised of more than one pixel. Sized are generally specified in points but images are in pixels. Thus for Retina displays a scale factor must be used if one needs to know the actual fixed size.

If the image is scaled to the needed point size and the display has a greater resolution than the point size, scale > 1 the image will appear more blurry.

If you are scaling at runtime you need to multiple the needed point size by the display scale value to get the pixel size to scale to. To get the screen scale:

let scale = UIScreen.mainScreen().scale
zaph
  • 111,848
  • 21
  • 189
  • 228
  • I added a second update to my question, I really appreciate your help so far – mgeno Sep 01 '15 at 17:20
  • Multiply, not divide. You want to create an image (scale * display_size in points). `let newSize = CGSize(width: size.width * scale, height: size.height * scale)`. If the size of the display area in points is 78 x 78 the display area on an iPhone 6 inpixels is 156 x 156. You want the scaled image in pixels to be the size of the display area in pixels. – zaph Sep 01 '15 at 17:30
  • Thanks for your help zaph, I updated my post to show what is happening now. Any more insight you can offer? – mgeno Sep 01 '15 at 18:02
0

I am answering this because after further work, I discovered that the issue wasn't related to the image resizing. The problem has something to do with the pasteboard. Zaph, was correct in his suggestions to correct the image resizing issues. I posted a follow up question regarding the pasteboard here:

Pasteboard UIImage not using scale

Community
  • 1
  • 1
mgeno
  • 191
  • 3
  • 13