19

I use the following code to getting images from the sprite. And it works fine everywhere except the iPhone 4 (HD version).

- (UIImage *)croppedImage:(CGRect)rect {
    CGImageRef image = CGImageCreateWithImageInRect([self CGImage], rect);
    UIImage *result = [UIImage imageWithCGImage:image];
    CGImageRelease(image);
    return result;
}

The iPhone 4 automatically load HD version of the image (sprite@2x.png) instead sprite.png. The original image has a scale 2, but the resulting image has a scale 1 and wrong size.

How to handle this behavior taking into account the different scales for iPhone 3G[s] and the iPhone 4?

I have read this document, but about the use CGImageCreateWithImageInRect here says nothing.

Victor
  • 3,497
  • 3
  • 39
  • 51
  • I would be very interested if you could look at my answer. I'm sure there is a better way to achieve what we want. But the correct answer here seems to me not to the point. Could you use the code above + the rect translation with scale and see if it works? – Daniel Jul 28 '13 at 19:13

2 Answers2

32

From what I can tell the CGImageCreateWithImageInRect will do the right thing. What you need to change is the UIImage initilization

http://developer.apple.com/iphone/library/documentation/uikit/reference/UIImage_Class/Reference/Reference.html#//apple_ref/occ/clm/UIImage/imageWithCGImage:scale:orientation:

Change it to [UIImage imageWithCGImage:image scale:self.scale orientation:self. imageOrientation] and it should work just fine. (this is assuming this is a category on UIImage which it looks like it is)

Joshua Weinberg
  • 28,598
  • 2
  • 97
  • 90
  • 3
    Thank you. I missed this function. Also, I need to multiply source image rect by self.scale. – Victor Jul 04 '10 at 08:49
  • 2
    Thanks. This saved me hours :-) Also: I needed to multiply the scale factor to my crop rect dimentions to make the result look properly. – esbenr Aug 21 '12 at 11:58
  • 1
    Yes multiplying the rect seems to be an odd workaround for something that should just "do the right thing". The key is the scale, not this method mentioned in the answer. – Daniel Jul 28 '13 at 18:46
  • 1
    I think you need to 2x the rect before you call CGImageCreateWithImageInRect too. – fluke Sep 29 '13 at 06:26
14

You should multiply the crop rect by the image scale. From my experience, it's unnecessary to use any different image initilization.

- (UIImage *)_cropImage:(UIImage *)image withRect:(CGRect)cropRect
{
    cropRect = CGRectMake(cropRect.origin.x * image.scale,
                          cropRect.origin.y * image.scale,
                          cropRect.size.width * image.scale,
                          cropRect.size.height * image.scale);

    CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect);

    UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];

    CGImageRelease(imageRef);

    return croppedImage;
}
Daniel
  • 23,129
  • 12
  • 109
  • 154