Slicing up a UIImage on iPhone

executor21 picture executor21 · Oct 29, 2008 · Viewed 22.3k times · Source

Objective: take a UIImage, crop out a square in the middle, change size of square to 320x320 pixels, slice up the image into 16 80x80 images, save the 16 images in an array.

Here's my code:

CGImageRef originalImage, resizedImage, finalImage, tmp;
float imgWidth, imgHeight, diff;
UIImage *squareImage, *playImage;
NSMutableArray *tileImgArray;
int r, c;

originalImage = [image CGImage];

imgWidth = image.size.width;
imgHeight = image.size.height;
diff = fabs(imgWidth - imgHeight);

if(imgWidth > imgHeight){
    resizedImage = CGImageCreateWithImageInRect(originalImage, CGRectMake(floor(diff/2), 0, imgHeight, imgHeight));
}else{
    resizedImage = CGImageCreateWithImageInRect(originalImage, CGRectMake(0, floor(diff/2), imgWidth, imgWidth));
}
CGImageRelease(originalImage);

squareImage = [UIImage imageWithCGImage:resizedImage];      
if(squareImage.size.width != squareImage.size.height){
    NSLog(@"image cutout error!");
    //*code to return to main menu of app, irrelevant here
}else{
    float newDim = squareImage.size.width;
    if(newDim != 320.0){
        CGSize finalSize = CGSizeMake(320.0, 320.0);
        UIGraphicsBeginImageContext(finalSize);
        [squareImage drawInRect:CGRectMake(0, 0, finalSize.width, finalSize.height)];
        playImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }else{
        playImage = squareImage;
    }
}

finalImage = [playImage CGImage];
tileImgArray = [NSMutableArray arrayWithCapacity:0];
for(int i = 0; i < 16; i++){
    r = i/4;
    c = i%4;
    //*
    tmp = CGImageCreateWithImageInRect(finalImage, CGRectMake(c*tileSize, r*tileSize, tileSize, tileSize));
    [tileImgArray addObject:[UIImage imageWithCGImage:tmp]];
}

The code works correctly when the original (the variable image) has its smaller dimension either bigger or smaller than 320 pixels. When it's exactly 320, the resulting 80x80 images are almost entirely black, some with a few pixels at the edges that may (I can't really tell) be from the original image.

I tested by displaying the full image both directly:

[UIImage imageWithCGImage:finalImage];

And indirectly:

[UIImage imageWithCGImage:CGImageCreateWithImageInRect(finalImage, CGRectMake(0, 0, 320, 320))];

In both cases, the display worked. The problems only arise when I attempt to slice out some part of the image.

Answer

executor21 picture executor21 · Oct 30, 2008

After some more experimentation, I found the following solution (I still don't know why it didn't work as originally written, though.) But anyway, the slicing works after the resize code is put in place even when resizing is unnecessary:

if(newDim != 320.0){
            CGSize finalSize = CGSizeMake(320.0, 320.0);
            UIGraphicsBeginImageContext(finalSize);
            [squareImage drawInRect:CGRectMake(0, 0, finalSize.width, finalSize.height)];
            playImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
}else{
            CGSize finalSize = CGSizeMake(320.0, 320.0);
            UIGraphicsBeginImageContext(finalSize);
            [squareImage drawInRect:CGRectMake(0, 0, finalSize.width, finalSize.height)];
            playImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
}

Anyone has any clue WHY this is going on?

P.S. Yes, if/else is no longer required here. Removing it before I knew it was going to work would be stupid, though.