2012-05-19 1 views
0

Я пытаюсь применить несколько эффектов к изображениям. Я создал отдельный файл для обработки обработки эффектов, который я могу отправить UIImageView и получить измененную копию. Чтобы сохранить время обработки, я сначала загружаю изображение в отдельный файл обработки и сохраняю его в памяти, а не загружаю изображение каждый раз, когда я его модифицирую. Поток - getImageData -> modifyRGB -> displayImage. Все работает до последнего шага. Возвращенное измененное изображение отображается на экране в течение секунды, а затем Xcode выдает ошибку EXEC_BAD_ACCESS: код 1. Я неоднократно повторял код и не могу найти проблему. Любая помощь приветствуется. Спасибо!Приложение Сбой при попытке обновления UIImageView после изменения значений RGB для проекта iOS

ОБНОВЛЕНИЕ С ПОДРОБНЕЕ

Я использую Xcode 4.3.1 с автоматическим подсчетом ссылок

Использование разрывов строк, я могу подтвердить, что авария происходит, когда линия self.imageView.image = [self.imageManipulation displayImage]; Выполняется. Изображение обновляется, но затем программа сразу же падает. Использование NSZombie, я получаю сообщение об ошибке - [Not A Тип сохранения]: сообщение, отправленное на освобождаться например 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 
+1

Обычно Excess_Bad_Access приходит, если вы обращаетесь к данным, которые были выпущены или объект не имеет ссылки на него. Проверьте свой код для выделения и отпускания на объекте, на котором возникает исключение. –

+0

К сожалению, ваш вопрос слишком широк. Установили ли некоторые точки останова для сужения при ошибке? Вы скользнули слайдер сжатия списка потоков вправо в Навигаторе отладки, чтобы увидеть большую часть стека в момент выброса исключения или введите «bt» (для «backtrace») в lldb (или gdb)? Как сказал roronoa, вероятно, из-за попытки получить доступ к тем, что уже выпущено, но некоторые базовые отладки, чтобы сузить его, либо ответят на него за вас, либо, по крайней мере, дадут нам достаточно подсказок, чтобы помочь. –

+0

Я попытаюсь сузить его дальше. Сбой происходит при выполнении строки ** self.imageView.image = [self.imageManipulation displayImage]; **. И, несмотря на то, что он выходит из строя на этой линии, затемненное измененное изображение все еще отображается, но только на долю секунды перед сбоем. Метод ** [self.imageManipulation displayImage] ** выполняется полностью - проверяется с помощью контрольных точек. Я буду продолжать проверять. –

ответ

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, и теперь я использую их религиозно! Еще раз спасибо!

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; 
} 
+0

Я попытался удалить эту строку, и я все равно получаю ту же ** [Не сохраняю тип **] **. Я даже попытался удалить все 3 из этих строк CG..Release, и я все равно получаю ту же ошибку. –

+0

Вам не нужно удалять эти разделительные линии. Вышеприведенный код должен работать нормально. –

+0

Извините, я не добавил ** ** **, который вы добавили. Я использую ARC и, к сожалению, не могу использовать команду сохранения. Есть ли другой вариант? Я прошу прощения за то, что не заметил версию Xcode, которую я использую ранее. Спасибо за помощь. –

0

В displayImage сказать компилятору вы хотите сохранить изображение с __strong:

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

или если вы предпочитаете:

__strong UIImage *outputImage = [UIImage imageWithCGImage:imageRef]; 
Смежные вопросы