0

c++ アプリケーションで目的の C を使用して、OSX にイメージをロードしています。OpenGL アプリケーションです。これは、opengl に画像を読み込むために使用するコードです。

bool OSXSpecifics::loadPNGOSX(const char *fileName, int &outWidth, int &outHeight, GLuint *outTexture) {
NSImage *image = [[NSImage alloc] initWithContentsOfFile:[NSString stringWithUTF8String: fileName]];
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithData:[image TIFFRepresentation]];

NSArray* imageReps = [image representations];

bool hasAlpha;

for (NSImageRep *imageRep in imageReps) {
    if ([imageRep pixelsHigh] > outHeight) {
        outHeight = [imageRep pixelsHigh];
    }
    if ([imageRep pixelsWide] > outWidth) {
        outWidth = [imageRep pixelsWide];
    }
}
if ([bitmap hasAlpha] == YES) {
    hasAlpha = true;
} else {
    hasAlpha = false;
}


glGenTextures(1, outTexture);
glBindTexture(GL_TEXTURE_2D, *outTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glTexImage2D(GL_TEXTURE_2D, 0, hasAlpha ? 4 : 3, outWidth, outHeight, 0,
             hasAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, [bitmap bitmapData]);
[bitmap release];
[image release];
return true;
}

Instruments のおかげで、この関数が呼び出されるたびにメモリ リークが検出されました。Instrumentsは、膨大な量のメモリを使用している[NSImage TIFFRepresentation]と述べています。[NSBitmapImageRep bitmapData]

制御不能になることはありませんが、この関数が呼び出されるたびにメモリ使用量が数百キロバイト上昇します。

Objective-C に関する私の経験は限られているため、うまくいくと思っていたので、これを修正する方法がわかりませんrelease

OpenGL テクスチャは後で解放されますが、それがメモリ リークの原因ではないことを確認しました。

編集: さらにテストを行った結果、これは理論的にはメモリ リークではないことを発見しました。しかし、この関数が呼び出されるたびに、アプリケーションのメモリ使用量が増加し、減少することはありません。この関数は、ゲーム内のシーンがロードされるときに呼び出されるため、シーンがロードされるたびにメモリ使用量が数メガバイト増加します。どうしてこれが起こっているのでしょうか。すべてのメモリを使い果たしているのはこの関数だと確信しています。

4

1 に答える 1

1

まず最初に:コードがリークしているようには見えません。私の推測では、NSImageは内部で無害なキャッシュを実行しており、この画像ファイルを2回ロードした場合に、同じNSImageを再利用できるようになっています。または、ファイルシステムのキャッシュかもしれません。メモリが不足すると、これらのキャッシュがフラッシュされ、解放されたメモリがアプリケーションで使用できるようになります。

そうは言っても、コードは非常に複雑に見えます。NSImage(NSImageRepsで構成され、そのうちの1つはNSBitmapImageRepである可能性が非常に高い)を作成し、そのTIFFRepresentationを取得し(つまり、すべてのデータをTIFFに再エンコードし、場合によっては再度圧縮します)、そこからNSBitmapImageRepを作成します(解凍とデコード再びTIFF)、そしてそのbitmapDataを取得します。

少なくとも、ファイルからNSDataを作成し、そこからNSBitmapImageRepを作成する必要があります。これにより、NSImageの作成とTIFFの手順全体がスキップされます。

おそらく、低レベルのImageIOライブラリを使用しただけの場合はさらに良いでしょう。ファイルからCGImageRefを作成し、画像の生の解凍されたデータをOpenGLに渡します。CIImageまたはCoreVideoを使用すると、OpenGLテクスチャを作成するためのより良い方法があるかもしれないことを漠然と覚えていますが、それを逆(テクスチャからCIImage)と混同している可能性があります。

于 2012-10-17T17:20:20.900 に答える