CGBitmapContextСоздать на iPhone / iPad - PullRequest
6 голосов
/ 12 апреля 2010

У меня есть метод, который должен анализировать кучу больших изображений PNG пиксель за пикселем (PNG имеют размер 600x600 пикселей каждый). Кажется, он отлично работает на симуляторе, но на устройстве (iPad) я получаю EXC_BAD_ACCESS в некоторых функциях копирования внутренней памяти. Кажется, размер - виновник, потому что, если я попробую это на маленьких изображениях, все, кажется, работает. Ниже приведено описание метода, описанного ниже.

+ (CGRect) getAlphaBoundsForUImage: (UIImage*) image 
{    
    CGImageRef imageRef = [image CGImage];

NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

unsigned char *rawData = malloc(height * width * 4);
memset(rawData,0,height * width * 4);

NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

CGColorSpaceRelease(colorSpace);

CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);

/* non-memory related stuff */

free(rawData);

Когда я запускаю это на куче изображений, он запускается 12 раз, а затем вылетает, а на симуляторе он запускается без проблем. Ребята, у вас есть идеи?

Ответы [ 8 ]

3 голосов
/ 11 июня 2012

Перейти к продукту -> Редактировать схемы -> Включить объекты Zombie. Поставьте галочку перед включением объектов Zombie. Теперь соберите и запустите его. Это может дать вам лучшее и точное описание ошибки EXC_BAD_ACCES.

3 голосов
/ 26 февраля 2012

Запуск 12 раз, а затем сбой звучит как проблема нехватки памяти.Возможно, что внутри CGContext создает несколько больших автоматически выпускаемых структур.Поскольку вы делаете это в цикле, они не освобождаются, поэтому у вас заканчивается память и вымираете.

Я не уверен, как Core Foundation работает с временными объектами.Я не думаю, что объекты CF имеют эквивалент автоматического выпуска, и контекст Core Graphics почти наверняка имеет дело с объектами CF, а не с NSObjects.

Чтобы уменьшить отток памяти в вашем коде, я бы предложил рефакторинг его таксоздайте закадровый CGContext один раз, прежде чем начинать обработку, и используйте его повторно для обработки каждого изображения.Затем отпустите его, когда вы закончите.В любом случае это будет быстрее (поскольку вы не выделяете огромные структуры данных при каждом проходе цикла.)

Держу пари, что это устранит проблему сбоев, и я уверен, что это такжеВаш код намного, намного быстрее.Распределение памяти очень медленное по сравнению с другими операциями, и вы обходитесь довольно большими структурами данных для обработки изображений RGBA 600x600 пикселей.

0 голосов
/ 31 декабря 2012

Я решил проблему, создав квадратный контекст (ширина = высота). У меня была текстура 512x256, и она вылетала каждый раз, когда я отправлял данные в OpenGL. Теперь я выделяю буфер 512x512, НО ЕЩЕ 512x256 рендеринга. Надеюсь, это поможет.

0 голосов
/ 12 июня 2012

Может заменить

CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);

с

CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGColorSpaceRelease(colorSpace);

как может понадобиться ссылка на цветовое пространство? Просто случайное предположение ... А может быть даже поставить это за релиз контекста?

// cleanup
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
0 голосов
/ 19 марта 2012

Попробуйте запустить распределение инструментов, пока вы запускаете приложение на устройстве, это может быть связано с проблемой памяти. Если вы находитесь в цикле, создайте внутри этого цикла пул автоматического выпуска.

0 голосов
/ 14 апреля 2010

Я использовал степень выровненного размера строки в приложении, которое определяло размер строки напрямую, так как я создавал изображения программно. Но я бы также порекомендовал toastie попробовать CGImageGetBytesPerRow перед тем, как попробовать мое предложение.

0 голосов
/ 14 апреля 2010

Возможно CGImageGetBytesPerRow (мощность двух звуков чрезмерна).

0 голосов
/ 13 апреля 2010

Я получал похожий сбой на своем iPad (конечно, iPhoneOS 3.2), используя CGImageCreate (). Видя твои трудности, намекнул. Я решил проблему, выровняв свой bytesPerRow со следующей по величине степенью 2.

size_t bytesPerRowPower2 = (size_t) round( pow( 2.0, trunc( log((double) bytesPerRow) / log(2.0) ) + 1.0 ) );

Дайте нам знать, если решение проблемы выравнивания по двум рядам также решит вашу проблему. Вам нужно было бы выделить * rawData с измененным размером и передать bytesPerRowPower2 в CGBitmapContextCreate () ... Высота, похоже, не требует выравнивания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...