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 纹理稍后会被释放,并且我已经确认它不是内存泄漏的来源。

编辑:经过进一步测试,我发现这在理论上不是内存泄漏,因为 Instruments 没有报告“内存泄漏”。但是,每当调用此函数时,应用程序的内存使用量就会上升并且永远不会下降。当加载游戏中的场景时调用此函数,因此每当加载场景时,内存使用量就会增加几兆字节。这怎么可能发生。我确信正是这个功能耗尽了所有内存。

4

1 回答 1

1

首先:代码看起来没有泄漏。我的猜测是 NSImage 在内部进行了一些无害的缓存,以确保如果您再次加载此图像文件,它可以重新使用相同的 NSImage,这可能就是您所看到的。或者可能是文件系统缓存。如果内存变得紧张,这些缓存可能会被刷新,并且释放的内存可供您的应用程序使用。

也就是说,您的代码似乎过于复杂。您创建一个 NSImage(由 NSImageReps 组成,其中一个很可能是 NSBitmapImageRep)然后获取它的 TIFFRepresentation(即将所有数据重新编码为 TIFF,可能再次压缩它),然后从中创建一个 NSBitmapImageRep(解压缩和解码TIFF 再次),然后获取它的 bitmapData。

At the least, you should probably create an NSData from the file and create your NSBitmapImageRep from that. That will skip the entire NSImage creation and TIFF steps.

Even better would probably be if you just went and used the lower-level ImageIO library. Create a CGImageRef from your file, then hand the image's raw, decompressed data off to OpenGL. I vaguely remember there might even be a better way to create an OpenGL texture if you go through CIImage or CoreVideo, but I may be mixing that up with the reverse (texture to CIImage).

于 2012-10-17T17:20:20.900 回答