Как я могу создать фильм Quicktime из серии сгенерированных изображений?

Мне нужно создать фильм из серии сгенерированных изображений. (Я создаю изображения на основе результатов программы физического моделирования.)

Я нашел образец Apple в QtKitCreateMovie и использовал его в качестве отправной точки. Вместо того, чтобы загружать jpg из пакета приложения, я рисую в NSImage, а затем добавляю этот NSImage в объект фильма. Вот основной код, который я использовал для тестирования. mMovie является экземпляром QTMovie:

NSImage *anImage = [[NSImage alloc] initWithSize:NSMakeSize(frameSize, frameSize)];
[anImage lockFocus];

float blendValue;
for (blendValue = 0.0; blendValue <= 1.0; blendValue += 0.05) {
    [[[NSColor blueColor] blendedColorWithFraction:blendValue ofColor:[NSColor redColor]] setFill];
    [NSBezierPath fillRect:NSMakeRect(0, 0, frameSize, frameSize)];
    [mMovie addImage:anImage forDuration:duration withAttributes:myDict];
}
[anImage unlockFocus];
[anImage release];

Это работает в OS X 10.5, но в OS X 10.6 я получаю исключение индекс массива за пределами границ при вызове addImage:forDuration:withAttributes: (http://openradar.appspot.com/radar?id=1146401)

Как правильно создать фильм под 10.6?

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


person SSteve    schedule 13.05.2011    source источник
comment
Вы можете сделать заливку цветом немного быстрее, используя функцию NSRectFill, которая использует NSCompositeCopy, а не +[NSBezierPath fillRect:], которая по умолчанию равна NSCompositeSourceOver. Результат не будет отличаться (поскольку все цвета, которыми вы заливаете, имеют альфа-канал 1,0), но копирование, которое я проверял в последний раз, было значительно быстрее.   -  person Peter Hosey    schedule 14.05.2011
comment
Кроме того, нет особых причин устанавливать, должен ли контекст сглаживаться, когда вы не заполняете кривую траекторию.   -  person Peter Hosey    schedule 14.05.2011
comment
Спасибо, Питер. Я изменил свои звонки с +[NSBezierPath fillRect:] на NSRectFill. В моем реальном коде я рисую изогнутые пути.   -  person SSteve    schedule 14.05.2011


Ответы (1)


Ты делаешь это правильно, но ты делаешь это неправильно.

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

Исключение «за пределами» связано с тем, что изображение не имеет представлений. QTMovie, кажется, пытается перебрать массив, возвращаемый изображением в ответ на сообщение representations, но этот массив пуст, потому что изображение не закончено.

Каким-то образом вам это сошло с рук в Leopard (вероятно, из-за деталей реализации, которые изменились в Snow Leopard), но я бы сказал, что тогда это была не меньшая ваша ошибка.

Решение состоит в том, чтобы просто блокировать фокус и разблокировать фокус на изображении каждый раз в цикле:

float blendValue;
for (blendValue = 0.0; blendValue <= 1.0; blendValue += 0.05) {
    [anImage lockFocus];
    [[NSGraphicsContext currentContext] setShouldAntialias:NO];
    [[[NSColor blueColor] blendedColorWithFraction:blendValue ofColor:[NSColor redColor]] setFill];
    [NSBezierPath fillRect:NSMakeRect(0, 0, frameSize, frameSize)];
    [anImage unlockFocus];

    [mMovie addImage:anImage forDuration:duration withAttributes:myDict];
}
person Peter Hosey    schedule 14.05.2011