Let's say you start with a UIImage and you wish to crop it. The most common method is to use CGImageCreateWithImageInRect to get a CGImageRef and create a new image from it like so:
CGRect cropRect = CGRectMake(x*width, y*height, width, height);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
Now let's say you later need to convert this UIImage into an NSData object. For example, this will happen if you wish to store the image on disk using NSKeyedArchiver. Or you can get an NSData object out by doing the following explicitly:
NSData *imageData = UIImagePNGRepresentation(croppedImage);
I did this and later on I tried to reconstruct a new UIImage object by doing:
UIImage *image = [UIImage imageWithData:imageData];
I did this for a series of 48 images. Most of them were fine, but after every 4 images the next 2 were corrupted with the top and bottom of each image swapped. If I take out the conversion to NSData and back again, it works fine. I also get the exact same problem if I use NSKeyedArchiver to write an array of the images out to disk (which I'm guessing calls something like UIImagePNGRepresentation in its encoding routine). My theory is this must have something to do with how I build the images from CGImageRefs.
What is the workaround for this? I can't seem to figure out how to put CGImageRefs into NSData object and I'd prefer a solution that builds the UIImage correctly so that it may be serialized.
Edit:
Some people asked for the actual code being run, so I'm adding it here
UIImage *image = self.animationObject.image;
for (int y=0; y<[self.animationInfoObject.numInY intValue]; y++) {
for (int x=0; x<[self.animationInfoObject.numInX intValue]; x++) {
CGRect cropRect = CGRectMake(x*width, y*height, width, height);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
NSData *imageData = UIImageJPEGRepresentation(croppedImage, 1.0);
[self addImageToArray:imageData];
CFRelease(imageRef);
}
}
The image from self.animationObject.image is a grid of images with numInX and and numInY images in each direction. I crop each individual image out of the 2D grid and save them.
Later on, I put the images in a image view to animate them. Here is the code:
NSMutableArray *animationArray = [[NSMutableArray alloc] init];
for (int frame=0; frame<[[photoObject frameArray] count]; frame++) {
NSData *imageData =[[photoObject imageArray] objectAtIndex:[[[photoObject frameArray] objectAtIndex:frame] integerValue]-1];
UIImage *image = [UIImage imageWithData:imageData];
[animationArray addObject:image];
}
This all works fine on an iPhone 6 but does not work on an iPhone 5. It also seems to only be a problem when the grid of images is long. For example, for the example I'm using self.animationObject.image has numInY as 3 and numInX 2 and the total size of the image is 1536x3072 (each mini-image is 768x1024). It is the bottom two images that have their tops and bottoms flipped.