I’m trying to apply multiple effects to images. I’ve created a separate file to handle the effects processing that I can send a UIImageView to and receive a modified copy. To save processing time, I first load the image into the separate processing file and store it in memory, rather than load the image every time I want to modify it. The flow is getImageData -> modifyRGB -> displayImage. Everything works till the last step. The returned modified image is displayed on screen for a split second, then Xcode crashes with a EXEC_BAD_ACCESS:code 1 error. I’ve been over the code repeatedly, and can’t find the problem. Any help is greatly appreciated. Thank you!
UPDATE WITH MORE INFO
I’m using Xcode 4.3.1 with Automatic Reference Counting
Using Line Breaks, I can verify that the crash happens when the line self.imageView.image = [self.imageManipulation displayImage]; is executed. The image IS updated, but then the program immediately crashes.
Using NSZombie, i get an error -[Not A Type retain]: message sent to deallocated instance 0x2cceaf80
From my viewController I use:
[self.imageManipulation getImageData:self.imageView.image];
[self.imageManipulation modifyRGB];
self.imageView.image = [self.imageManipulation displayImage];
My ImageManipulation file consists of:
@implementation ImageManipulation
static unsigned char *rgbaDataOld;
static unsigned char *rgbaDataNew;
static int width;
static int height;
- (void)getImageData:(UIImage *)image
{
CGImageRef imageRef = [image CGImage];
width = CGImageGetWidth(imageRef);
height = CGImageGetHeight(imageRef);
rgbaDataOld = malloc(height * width * 4);
rgbaDataNew = malloc(height * width * 4);
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(rgbaDataOld, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
CGImageRelease(imageRef);
}
//modify rgb values
- (void)modifyRGB
{
for (int byteIndex = 0 ; byteIndex < width * height * 4; byteIndex += 4)
{
rgbaDataNew[byteIndex] = (char) (int) (rgbaDataOld[byteIndex] / 3) + 1;
rgbaDataNew[byteIndex+1] = (char) (int) (rgbaDataOld[byteIndex+1] / 3 + 1);
rgbaDataNew[byteIndex+2] = (char) (int) (rgbaDataOld[byteIndex+2] / 3) + 1;
rgbaDataNew[byteIndex+3] = (char) (int) 255;
}
}
//set image
- (UIImage *)displayImage
{
CGContextRef context;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
context = CGBitmapContextCreate(rgbaDataNew, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast );
CGImageRef imageRef = CGBitmapContextCreateImage (context);
UIImage *outputImage = [UIImage imageWithCGImage:imageRef];
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
CGImageRelease(imageRef);
return outputImage;
}
@end
I changed my dispayImage() method to receive a UIImageView property and return VOID. This way, all work is done to the passed UIImageView instead of a localized instance and nothing is returned.
My guess is that the returned UIImage approach I was using before was crashing because the returned reference was deallocated the second the method completed. This also allows me to use CGImageRelease without any ill effects.
Here’s the new approach:
Thank you to everyone that offered help! I learned a tremendous amount just from your suggestions. This was my first time using bt and NSZombie and now I’m using them religiously! Thanks again!