CGContextDrawImage是否可以动态解压缩PNG?

时间:2010-10-18 22:43:00

标签: iphone objective-c core-graphics

我正在尝试编写一个采用PNG图块集的iPhone应用程序,并在屏幕上显示它们的片段,我正试图让它以20fps刷新整个屏幕。目前我在模拟器上管理大约3或4fps,在设备上管理0.5到2fps(iPhone 3G),具体取决于屏幕上的内容。

我目前正在使用Core Graphics,目前正试图找到避免咬弹和重构OpenGL的方法。我已经对代码进行了Shark时间配置文件分析,大约70-80%正在进行的所有事情都归结为一个名为copyImageBlockSetPNG的函数,该函数是从CGContextDrawImage中调用的,CGContextDrawImage本身正在调用各种其他函数。 PNG的名称。 Inflate也在那里,占其中的37%。

问题是,我已经将图像从UIImage加载到内存中了,为什么代码仍然关心它是一个PNG?是否在加载时不解压缩为本机未压缩格式?我可以自己转换吗?分析意味着每当我从中绘制一个部分时,它就会对图像进行解压缩,最终会出现一帧的30次或更多次。

解决方案

-(CGImageRef)inflate:(CGImageRef)compressedImage
{
    size_t width = CGImageGetWidth(compressedImage);
    size_t height = CGImageGetHeight(compressedImage);

    CGContextRef    context = NULL;
    CGColorSpaceRef colorSpace;
    int             bitmapByteCount;
    int             bitmapBytesPerRow;

    bitmapBytesPerRow   = (width * 4);
    bitmapByteCount     = (bitmapBytesPerRow * height);

    colorSpace = CGColorSpaceCreateDeviceRGB();
    context = CGBitmapContextCreate (NULL,
                                 width,
                                 height,
                                 8,
                                 bitmapBytesPerRow,
                                 colorSpace,
                                 kCGImageAlphaPremultipliedLast);
    CGColorSpaceRelease( colorSpace );

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), compressedImage);
    CGImageRef result = CGBitmapContextCreateImage(context);
    CFRelease(context);
    return result;
}

它基于zneak的代码(因此他获得了大奖)但我已经将一些参数更改为CGBitmapContextCreate,以便在我将PNG图像提供给它时​​停止崩溃。

2 个答案:

答案 0 :(得分:4)

为了回答你的上一个问题,你的经验案例似乎证明一旦加载就不会解压缩。

要将它们转换为未压缩的数据,您可以在CGBitmapContext中绘制它们(一次)并从中获取CGImage。它应该是未压缩的。

我不应该这样做:

CGImageRef Inflate(CGImageRef compressedImage)
{
    size_t width = CGImageGetWidth(compressedImage);
    size_t height = CGImageGetHeight(compressedImage);

    CGContextRef context = CGBitmapContextCreate(
        NULL,
        width,
        height,
        CGImageGetBitsPerComponent(compressedImage),
        CGImageGetBytesPerRow(compressedImage),
        CGImageGetColorSpace(compressedImage),
        CGImageGetBitmapInfo(compressedImage)
    );

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), compressedImage);
    CGImageRef result = CGBitmapContextCreateImage(context);
    CFRelease(context);
    return result;
}

不要忘记释放完成后获得的CGImage。

答案 1 :(得分:0)

这个问题完全救了我的一天!谢谢!!虽然我不确定问题出在哪里,但我遇到了这个问题。 Speed up UIImage creation from SpriteSheet

我想补充一点,还有另一种方法可以直接加载图像解压缩,qithout必须写入上下文。

NSDictionary *dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
                                                 forKey:(id)kCGImageSourceShouldCache];
NSData *imageData = [NSData dataWithContentsOfFile:@"path/to/image.png"]];
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)(imageData), NULL);
CGImageRef atlasCGI = CGImageSourceCreateImageAtIndex(source, 0, (__bridge CFDictionaryRef)dict);
CFRelease(source);

我相信这种方式有点快。希望它有所帮助!