Создание повторно используемого изображения из контекста Core Graphics мне ничего не дает

Я пытаюсь ускорить свой код рисования. Вместо того, чтобы создавать графический контекст, рисовать в нем текущее изображение и рисовать поверх него, я пытаюсь создать контекст, используя некоторые пиксельные данные, и просто изменить их напрямую. Проблема в том, что я новичок в базовой графике и не могу создать начальное изображение. Я хочу просто сплошное красное изображение, но ничего не получаю. Вот что я использую для исходного изображения. Я предполагаю, что проблема будет такой же с остальной частью кода.

pixels = malloc(320*460*4);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pixels, 320, 460, 8, 4*320, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);

CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextAddRect(context, CGRectMake(0, 0, 320, 460));
CGContextFillPath(context);
trace = [[UIImageView alloc] initWithImage:UIGraphicsGetImageFromCurrentImageContext()];
CGContextRelease(context);

Изменить: проблема оказалась в UIGraphicsGetImageFromCurrentImageContext(). Далее следует рабочее решение, но обратите внимание, что оно не быстрее, чем гораздо более простое UIGraphicsBeginImageContext()

pixels = malloc(320*460*4);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pixels, 320, 460, 8, 4*320, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);

CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextAddRect(context, CGRectMake(0, 0, 320, 460));
CGContextFillPath(context);
CGDataProviderRef dp = CGDataProviderCreateWithData(NULL, pixels, 320*460*4, NULL);
CGImageRef img = CGImageCreate(320, 460, 8, 32, 4*320, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big, dp, NULL, NO, kCGRenderingIntentDefault);
trace = [[UIImageView alloc] initWithImage:[UIImage imageWithCGImage:img]];
CGImageRelease(img);
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);

person David Kanarek    schedule 19.01.2010    source источник
comment
Вы на самом деле должны получить прямоугольник пространства окна вашего приложения (т. е. экрана за вычетом строки состояния) во время выполнения, а не жестко кодировать нулевое начало и размеры 320 × 460. Во-первых, ваш код не обрабатывает альбомный (например, 480 × 300) экран. Во-вторых, было бы хорошо, если бы ваше приложение автоматически обрабатывало больший размер экрана (например, на планшете). Вам, вероятно, потребуется использовать -[UIScreen applicationFrame:]: developer.apple.com/iphone/library/documentation/UIKit/   -  person Peter Hosey    schedule 20.01.2010


Ответы (1)


Во-первых, кажется, что контекст, в который вы рисуете, не связан с «текущим контекстом изображения» UIGraphics. Вы куда-нибудь звонили UIGraphicsBeginImageContext(CGSize size)?

Не уверен, что это даст вам то, что вам нужно, но это, безусловно, означает, что у вас меньше шансов вернуть nil в качестве текущего контекста изображения.

person Ben Zotto    schedule 19.01.2010
comment
Проблема в том, что если я использую это, то для рисования мне нужно использовать UIGraphicsGetCurrentContext(), что не позволяет мне использовать данные пикселей, которые у меня есть, но спасибо, что указали мне правильное направление. попробую заменить UIGraphicsGetImageFromCurrentImageContext() - person David Kanarek; 19.01.2010
comment
Я думаю, что немного не уверен, чего вы в основном пытаетесь достичь здесь. Почему вы не можете иметь подкласс UIView, как обычно, и заполнить свой фон внутри вызова drawRect:? Откуда берутся требования к изображению/растровому изображению? - person Ben Zotto; 19.01.2010
comment
Думаю, надо будет попробовать этот маршрут. Поскольку эти обновления происходят очень быстро, перерисовка всего изображения занимает слишком много времени. Я надеялся использовать те же исходные данные и просто немного изменить их. К сожалению, ваш ответ заставил меня двигаться в правильном направлении, но этот путь оказался слишком медленным. Я отдаю вам должное, потому что вы нашли проблему и привели меня к решению. Спасибо за вашу помощь. - person David Kanarek; 19.01.2010
comment
Обновил вопрос с решением. - person David Kanarek; 19.01.2010
comment
Опять же, не уверен, что именно вы здесь делаете, но обратите внимание, что в обычном пути перерисовки представления drawRect: получает недопустимый прямоугольник в качестве аргумента. Вам нужно только перерисовать запрошенную часть. Если вы перемещаете объекты и у вас возникают проблемы с частотой кадров, потому что вы перестраиваете все окно в каждом кадре, вы можете повысить производительность, если ограничите перерисовку недопустимым прямоугольником. И наоборот, вы можете явно аннулировать часть окна с помощью setNeedsDisplayInRect: Надеюсь, это полезно. - person Ben Zotto; 19.01.2010
comment
Это действительно так. Пройдет некоторое время, прежде чем я смогу его протестировать, но я надеюсь, что частичные обновления улучшат производительность. Еще раз спасибо. - person David Kanarek; 19.01.2010