0

現在、iOS4.1以降を対象とした画像処理アプリを開発しています。

iOS5でアプリを実行しているときにCVOpenGLESTextureCacheを使用したい。

以下のコードでテクスチャキャッシュを作成します

NSDictionary *empty = [NSDictionary dictionary];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                        [NSNumber numberWithBool:NO], kCVPixelBufferCGImageCompatibilityKey,
                        [NSNumber numberWithBool:NO], kCVPixelBufferCGBitmapContextCompatibilityKey,
                        empty, kCVPixelBufferIOSurfacePropertiesKey,
                        nil];
CVPixelBufferCreate(kCFAllocatorDefault, texSize_.width, texSize_.height, kCVPixelFormatType_32BGRA, (CFDictionaryRef)options, &renderTarget);
CVOpenGLESTextureCacheCreateTextureFromImage (kCFAllocatorDefault,
                                   filterTextureCache, renderTarget,
                                   NULL, // texture attributes
                                   GL_TEXTURE_2D,
                                   GL_RGBA, // opengl format
                                   (int)texSize_.width, 
                                   (int)texSize_.height,
                                   GL_BGRA, // native iOS format
                                   GL_UNSIGNED_BYTE,
                                   0,
                                   &renderTexture);
texID_ = CVOpenGLESTextureGetName(renderTexture);

いくつかの要素を標準メソッド(glFrameBufferTexture2DおよびglDrawArray)によって作成されたテクスチャにレンダリングします。

その後、CVPixelBufferを読み取って画像を作成してみました。

- (UIImage *)imageFromTextureCache {
    if (renderTarget) {
        if (kCVReturnSuccess == CVPixelBufferLockBaseAddress(renderTarget,
                                                             kCVPixelBufferLock_ReadOnly)) {
            uint8_t* pixels=(uint8_t*)CVPixelBufferGetBaseAddress(renderTarget);

            CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, pixels, CVPixelBufferGetDataSize(renderTarget), bufferFree);
            CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
            CGImageRef imageRef = CGImageCreate(texSize_.width, texSize_.height, 8, 32, 4 * texSize_.width, colorSpaceRef, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst, provider, NULL, NO, kCGRenderingIntentDefault);
            CGImageRef cloppedImageRef = imageRef;
            if (!CGSizeEqualToSize(CGSizeMake(1.0, 1.0), contentRatio_)) {
                cloppedImageRef = CGImageCreateWithImageInRect(imageRef, CGRectMake(0, 0, texSize_.width * contentRatio_.width, texSize_.height * contentRatio_.height));
            }

            UIImage *image = [UIImage imageWithCGImage:cloppedImageRef];

            if (!CGSizeEqualToSize(CGSizeMake(1.0, 1.0), contentRatio_)) {
                CGImageRelease(cloppedImageRef);
            }
            CGColorSpaceRelease(colorSpaceRef);
            CGDataProviderRelease(provider);
            CVPixelBufferUnlockBaseAddress(renderTarget, kCVPixelBufferLock_ReadOnly);
            return image;
        }
        return nil;
    }
    return nil;
}

UIImage *image = [outputTexture_ imageFromTextureCache];

次に、以前にレンダリングされた画像を取得しました。現在ではありません。

しかし、現在レンダリングされている画像を取得するために、以下のようにコードを変更しました。

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texID, 0);
GLubyte *buffer = (GLubyte *)calloc(sizeof(GLubyte), 1);
glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

UIImage *image = [outputTexture_ imageFromTextureCache];

何が起こるのか理解できません。そして、私はそれについての文書を見つけることができませんでした。

誰か助けてくれますか?

安い英語でごめんなさい...ありがとう。

4

2 に答える 2

0

テクスチャキャッシュに関連付けられているテクスチャから直接読み取る場合、そのテクスチャに対して行うOpenGL ESレンダリングが、それらのバイトを読み取るまでに完了するとは限りません。使用時に正しい現在のフレームが表示される理由は、glReadPixels()レンダリングが完了するまでブロックされるためです。

テクスチャから読み取る前にすべてのレンダリングが終了したことを保証するためにglFinish()、テクスチャデータを読み取る前に呼び出しを行うことができます。これは、すべてのレンダリングが完了するまでブロックされます。glFlush()ビデオの場合、よろめきで実行できるいくつかのトリックがありglFinish()、わずかに優れたパフォーマンスが求められますが、あなたの場合は単純なものglFinish()でうまくいくはずです。

于 2012-06-25T20:04:44.460 に答える
0

はい、バッファにアクセスする前にglFlushを使用し、アクセスした後にglFinishを使用します。私は同じ問題を抱えていました

http://www.khronos.org/opengles/sdk/1.1/docs/man/glFlush.xml

于 2012-06-27T06:03:11.433 に答える