Search code examples
iphoneimage-resizingmaskingretina

Retina image blows up 4 times in Xcode


At the moment I'm working on a streaming radio app for a friend for iPhone and iPad.

While implementing my designs into code I struck a funny bug(?). I wish to display album art on the background and masking that, using this example tutorial.

It works fine on low resolution iPhones, but as soon as I test it on an iPhone 4 & 5 (test devices and emulator) the picture is shown 4x as large as it should be.

enter image description here

It should display like this: enter image description here

I've added both normal pictures, as well as @2x's, which come in at 320x320 & 640x640 (@2x) The last thing I should add, it works fine if I don't mask the images. But I believe the mask works (if it wouldn't be blown up 4x). So probably, the code is magnifying the picture twice, instead of just once.

To add a bit of my code:

albumArt = [[UIImageView alloc] init];
[albumArt setFrame:CGRectMake(0, 0, 320, 320)];
UIImage *image = [UIImage imageNamed:@"testPopArt.png"];
UIImage *mask = [UIImage imageNamed:@"popArtMask.png"];
finalAlmbumArt = [self maskImage:image withMask:mask];
[albumArt setBackgroundColor:[UIColor colorWithPatternImage:finalAlmbumArt]];
[appBackground addSubview:albumArt];

Solution

  • You neet to tell the UIImage the scale of the :

    - (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage {
    
        CGImageRef maskRef = maskImage.CGImage;
    
        CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                            CGImageGetHeight(maskRef),
                                            CGImageGetBitsPerComponent(maskRef),
                                            CGImageGetBitsPerPixel(maskRef),
                                            CGImageGetBytesPerRow(maskRef),
                                            CGImageGetDataProvider(maskRef), NULL, false);
    
        CGImageRef masked = CGImageCreateWithMask([image CGImage], mask);
        CGFloat scale = [UIScreen mainScreen].scale;
        return [UIImage imageWithCGImage:masked scale:scale orientation:UIImageOrientationDown];
    
    }
    

    You could probably also get the effect with a CAGradientLayer so that you do not have to make a new image. It will be a bit less CPU intensive.