Apple Developer Connection
高度な検索
Member Login ログイン | ご入会 ADC連絡先

Technical Note TN2143
Quartz Composerコンポジションの画像の受け渡しと取得

Quartz Composerコンポジションには入力と出力があり、コンポジションに値を渡したり、コンポジションから値を取得したりすることができます。これらの入力は型付きであり、数値、テキスト文字列、または画像を受け入れます(コンポジションの入力と出力およびそれらの作成方法に関する詳細は、『Quartz Composer Programming Guide』を参照)。このテクニカルノートでは、コンポジションとの画像の受け渡しと、コンポジションからの画像の取得を効率的に行う方法を重点的に取り上げます。





画像をコンポジションに渡す

コンポジションに画像入力がある場合は、QCViewまたはQCRendererクラスの- (BOOL) setValue:(id)value forInputKey:(NSString*)keyメソッドを使用して、コンポジションに画像を渡すことができます。Quartz Composerと互換性のある画像を渡す必要があります。このメソッドは、入力に画像をうまく設定できるとYESを返します。Quartz Composerは渡された画像を保持するので、渡した後は画像を安全に解放できます。

互換性のある画像の種類は次のとおりです。

重要:必ずこのような元のソースから最も近いタイプを使って画像を渡すようにすると、パフォーマンスが向上します。たとえば、CGImageRefをQuartz Composerに渡す場合は、CIImageやNSImageに変換せず、元のCGImageRefを直接渡します。

Quartz ComposerにNSImagesまたはCGImageRefsとして渡される画像は、ビデオカードの最大テクスチャサイズ(通常は2048×2048以上)に適合するようにリサイズされます。他方で、最大テクスチャサイズより大きなCIImagesおよびCVImageBuffersはリサイズされず、適切に表示されない可能性があります。

Quartz Composerに渡す画像のソースがどこかに応じて、以下のタイプを使用してください。

NSImage

AppKitから取得した画像を渡すには、NSImageを使用します。NSImageを渡す-setValue:(id)value forInputKey:(NSString*)keyを呼び出した後で、画像入力で-valueForInputKey:(NSString*)keyを呼び出すと、別のNSImageインスタンスが返されます。これは、Quartz Composerが必要に応じて、元のNSImageにいくつかの操作(色補正やダウンサンプリングなど)を実行するためです。

警告:Quartz Composerには、NSImageを渡すときにカラープロファイル情報が消失し、画像ピクセルの色相が若干シフトする問題があります。これが特に明らかになるのは、画像をNSImageとしてQuartz Composerと何回かやり取りするときです。結果として、色の忠実性が問題になるときには、Quartz Composerに画像を渡す際にNSImagesを使用しないでください(代わりに、CGImageRefを使用します)。

先頭に戻る

CGImageRef

ImageIO(/System/Library/Frameworks/ApplicationServices.framework/Frameworks/ImageIO.frameworkを参照)によってディスクから画像ファイルをロードしたり、Quartz 2D APIから画像を直接取得したり、あるいはカラーマッチングを必要とする未加工ピクセルデータを渡すときにはCGImageRefを使用します。

リスト1:ImageIOを使用してバイナリデータまたはファイルからCGImageRefを作成

CGImageRef CreateCGImageFromData(NSData* data)
{
    CGImageRef        imageRef = NULL;
    CGImageSourceRef  sourceRef;

    sourceRef = CGImageSourceCreateWithData((CFDataRef)data, NULL);
    if(sourceRef) {
        imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL);
        CFRelease(sourceRef);
    }

    return imageRef;
}

CGImageRef CreateCGImageFromFile(NSString* path)
{
    NSURL*            url = [NSURL fileURLWithPath:path];
    CGImageRef        imageRef = NULL;
    CGImageSourceRef  sourceRef;

    sourceRef = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
    if(sourceRef) {
        imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL);
        CFRelease(sourceRef);
    }

    return imageRef;
}

先頭に戻る

CIImage

Core Imageフィルタから得られる画像にはCIImageを使用します。

重要:CGImageRefs、CVImageBuffers、未加工ピクセルデータ、またはOpenGLテクスチャをQuartz Composerに渡す場合は、これらをCIImagesにラップしないでください。パフォーマンスに影響します。

先頭に戻る

CVImageBuffer

QuickTimeムービー、OpenGLレンダリング、または未加工ピクセルデータから得られる画像にはCVImageBufferを使用します。これは次のソースから画像を渡す最適な方法です。

  • QuickTimeムービー:QuickTime 7 APIを使用して、ムービーをレンダリングするビジュアルコンテキストを作成します(『QuickTime Reference Update』を参照)。次に、QTVisualContextCopyImageForTime()が取得したCVImageBuffersを適切なコンポジションの画像入力に渡して、それらを解放します。最高のパフォーマンスを得るには、コンポジションのレンダリングに使用するのと同じOpenGLコンテキストとピクセルフォーマットを使用するQuickTime OpenGLテクスチャコンテキストの使用を強く推奨します(QCViewはこの情報を提供しないのでQCRendererを使用すると仮定します)。

  • OpenGLレンダリング:CVOpenGLBufferCreate()を使ってCVOpenGLBufferRefを作成し、これをCVOpenGLBufferAttach()でOpenGLコンテキストにアタッチして、そのコンテキストでOpenGLレンダリングを実行します。次に、glFlush()を呼び出してレンダリングを終了し、最終的にCVOpenGLBufferRefを適切なコンポジションの画像入力に渡して解放します(CVOpenGLBufferRefの詳細については、『Core Video Reference』を参照)。

  • 未加工ピクセルデータ:k32ARGBPixelFormatまたはk8IndexedGrayPixelFormatといったピクセルフォーマットを使用して、CVPixelBufferCreate()でCVPixelBufferRefを作成します(Quartz Composerでは、プレーナーピクセルバッファをサポートしていません)。次に、CVPixelBufferLockBaseAddress()、CVPixelBufferGetBaseAddress()、およびCVPixelBufferGetBytesPerRow()を使用して、ピクセルに直接書き込み(完了したら、忘れずにCVPixelBufferUnlockBaseAddress()を呼び出してください)、最終的にCVPixelBufferRefを適切なコンポジションの画像入力に渡して解放します(CVPixelBufferRef APIの詳細については、『Core Video Reference』を参照)。

CVOpenGLBufferRefsまたはCVPixelBufferRefを作成・破壊するのは、かなり高価な処理になる可能性があります。これらのバッファが一定のサイズを持っている場合は、それらをリサイクルして、CVOpenGLBufferPoolRefやCVPixelBufferPoolRefなどの適切なバッファを使用するほうが効率的です(CVOpenGLBufferPoolRefとCVPixelBufferPoolRef APIの詳細については、『Core Video Reference』を参照)。

注:Quartz ComposerはCVImageBuffersの内容を不変であると見なすため、Quartz Composerにそれらを渡した後で変更しないでください。

Quartz ComposerでCVImageBuffersを使用する方法に関するサンプルコードは、/Developer/Examples/Quartz Composer/Performerにあります。

先頭に戻る

コンポジションから画像を取得する

コンポジションに画像出力がある場合は、QCViewまたはQCRendererクラスの- (id) valueForOutputKey:(NSString*)keyメソッドを使用して、それらの画像を取得することができます。このメソッドは画像をNSImageとして返すか、画像がない場合(または内部エラーの場合)はnilを返します。出力の画像が変わるたびに、-valueForOutputKey:は新しいNSImageインスタンスを返すので、それらの画像の旧バージョンを置いておく必要がある場合は、それらをコピーしなくても安全に保持できます。

注:Quartz Composerが生み出すNSImages(グレー画像から得られるものでも)はRGBフォーマットで、表示色空間を使用します。

このNSImageをNSImageViewに渡すと、ユーザインターフェイスに表示することができます。NSImageは、次のコードを使用すると、LZW圧縮TIFFファイルとして保存することもできます。

リスト2:NSImageをLZW圧縮TIFFファイルとして保存

NSImage*          image;
BOOL            success;

image = [myRenderer valueForOutputKey:@"foo"];
if(image) {
    success = [[image TIFFRepresentationUsingCompression:NSTIFFCompressionLZW factor:1.0]
        writeToFile:@"/Users/foo/bar.tiff" atomically:YES];
    if(success == NO) {
        /*
            ハンドルエラー
        */
    }
}

NSImageの未加工ピクセル内容にアクセスする必要がある場合は、このコードにあるような手法を使用してNSBitmapImageRepに変換する必要があります。

リスト3:NSImageの未加工ピクセルにアクセス

NSImage*          image;
NSSize            imageSize;
NSBitmapImageRep*  bitmapImage;
NSRect            imageRect;

image = [myRenderer valueForOutputKey:@"foo"];
if(image) {
    imageSize = [image size];
    imageRect = NSMakeRect(0, 0, imageSize.width, imageSize.height);
    [image lockFocus];
    bitmapImage = [[NSBitmapImageRep alloc] initWithFocusedViewRect:imageRect];
    [image unlockFocus];

    if(bitmapImage) {
        /*
            [bitmapImage bitmapData]および[bitmapImage bytesPerRow]を使用して
            未加工ピクセル内容を処理する
        */
        [bitmapImage release];
    }
}

先頭に戻る

ドキュメント改訂履歴

日付メモ
2005-10-04NSImageからNSBitmapImageRepへの変換コードのタイプミスを修正。
2005-06-24Quartz Composerと画像を効率的にやり取りする方法を説明

掲載日: 2005-10-04




Did this document help you?
Yes: Tell us what works for you.

It’s good, but: Report typos, inaccuracies, and so forth.

It wasn’t helpful: Tell us what would have helped.