0

我正在尝试对图像应用多种效果。我创建了一个单独的文件来处理我可以发送UIImageView和接收修改后的副本的效果处理。为了节省处理时间,我首先将图像加载到单独的处理文件中并存储在内存中,而不是每次要修改时都加载图像。流程是 getImageData -> modifyRGB -> displayImage。一切正常,直到最后一步。返回的修改后的图像会在屏幕上显示片刻,然后 Xcode 崩溃并出现EXEC_BAD_ACCESS:code 1 错误。我反复检查代码,找不到问题。任何帮助是极大的赞赏。谢谢!

更新更多信息

我正在使用带有自动引用计数的 Xcode 4.3.1

使用换行符,我可以验证当self.imageView.image = [self.imageManipulation displayImage]; 行时发生崩溃 被执行。图像已更新,但随后程序立即崩溃。使用 NSZombie,我收到一个错误-[Not A Type retain]: message sent to deallocated instance 0x2cceaf80

从我的 viewController 我使用:

[self.imageManipulation getImageData:self.imageView.image];
[self.imageManipulation modifyRGB];
self.imageView.image = [self.imageManipulation displayImage];

我的 ImageManipulation 文件包括:

@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
4

3 回答 3

1

我更改了我的dispayImage()方法以接收UIImageView属性并返回VOID。这样,所有工作都对传递的UIImageView完成,而不是本地化实例,并且没有返回任何内容。

我的猜测是,我之前使用的返回UIImage方法崩溃了,因为返回的引用在方法完成的第二秒被释放。这也让我可以使用CGImageRelease而不会产生任何不良影响。

这是新方法:

- (void)displayImage:(UIImageView *)image
{
   CGContextRef context;
   CGImageRef imageRef = [image.image CGImage];

   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
   context = CGBitmapContextCreate(rgbaDataNew, width, height, 8, 4 * width, colorSpace,  kCGImageAlphaPremultipliedLast ); 
   imageRef = CGBitmapContextCreateImage (context);
   image.image = [UIImage imageWithCGImage:imageRef];
   CGColorSpaceRelease(colorSpace);    
   CGContextRelease(context);  
   CGImageRelease(imageRef);
   image = nil;
}

感谢所有提供帮助的人!仅从您的建议中,我就学到了很多东西。这是我第一次使用 bt 和 NSZombie,现在我正在虔诚地使用它们!再次感谢!

于 2012-05-24T12:27:12.300 回答
0

您正在释放 imageRef,这会导致 UIImage 被自动释放。

确保保留 UIImage 以防止此类事件发生:

- (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] retain]; 

    CGColorSpaceRelease(colorSpace);    
    CGContextRelease(context);  
    CGImageRelease(imageRef); //this line would cause outputImage to be released
    return outputImage;
}
于 2012-05-19T12:21:02.517 回答
0

displayImage告诉编译器你想保留图像__strong

UIImage __strong *outputImage = [UIImage imageWithCGImage:imageRef];

或者,如果您愿意:

__strong UIImage *outputImage = [UIImage imageWithCGImage:imageRef];
于 2012-05-20T11:47:47.857 回答