How to scale down an image in iOS, anti-aliased but not soft?
Asked Answered
S

4

6

I have tried the UIImage+Resize category that's popular, and with varying interpolation settings. I have tried scaling via CG methods, and CIFilters. However, I can never get an image downsized that does not either look slightly soft in focus, nor full of jagged artifacts. Is there another solution, or a third party library, which would let me get a very crisp image?

It must be possible on the iPhone, because for instance the Photos app will show a crisp image even when pinching to scale it down.

Sew answered 2/2, 2012 at 17:45 Comment(0)
L
6

You said CG, but did not specify your approach.

Using drawing or bitmap context:

CGContextSetInterpolationQuality(gtx, kCGInterpolationHigh);
CGContextSetShouldAntialias(gtx, true); << default varies by context type
CGContextDrawImage(gtx, rect, image);

and make sure your views and their layers are not resizing the image again. I've had good results with this. It's possible other views are affecting your view or the context. If it does not look good, try it in isolation to sanity check whether or not something is distorting your view/image.

If you are drawing to a bitmap, then you create the bitmap with the target dimensions, then draw to that.

Ideally, you will maintain the aspect ratio.

Also note that this can be quite CPU intensive -- repeatedly drawing/scaling in HQ will cost a lot of time, so you may want to create a resized copy instead (using CGBitmapContext).

Lelahleland answered 16/2, 2012 at 6:55 Comment(2)
I'd been using a UI Graphics Context and drawing via drawInRect or drawAtPoint, as well as this. However, you made me look again at my code, and I realized it was in fact due to another aspect of my code.Sew
yes - it's a good idea to be explicit about graphics contexts' settings, because they and other aspects of the graphics system can vary so much.Lelahleland
C
4

Here is the Routine that I wrote to do this. There is a bit of soft focus, though depending on how far you are scaling the original image its not too bad. I'm scaling programatic Screen Shot Images.

- (UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize {

    UIGraphicsBeginImageContext(newSize);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}
Curler answered 16/2, 2012 at 21:32 Comment(0)
A
0

CGContextSetInterpolationQuality is what you are looking for.

You should try this category additions http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/

Amphibolous answered 16/2, 2012 at 8:32 Comment(0)
C
0

When an image is scaled down, it is often a good idea to apply some sharpening.

The problem is, Core Image on iOS does not (yet) implement the sharpening filters (CISharpenLuminance, CIUnsharpMask), so you would have to roll your own. Or nag Apple till they implement these filters on iOS, too.

However, Sharpen luminance and Unsharp mask are fairly advanced filters, and in previous projects I have found that even a simple 3x3 kernel would produce clearly visible and satisfactory results.

Hence, if you feel like working at the pixel level, you could get the image data out of a graphics context, bit mask your way to R, G and B values and code graphics like it is 1999. It will be a bit like re-inventing the wheel, though.

Maybe there are some standard graphics libraries around that can do this, too (ImageMagick?)

Cairo answered 16/2, 2012 at 19:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.