【问题标题】:Does CGContextDrawImage decompress PNG on the fly?CGContextDrawImage 是否即时解压缩 PNG?
【发布时间】:2010-10-18 22:43:00
【问题描述】:

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

我目前正在使用 Core Graphics,目前正在尝试寻找避免硬着头皮在 OpenGL 中进行重构的方法。我已经对代码进行了 Shark 时间曲线分析,大约 70-80% 发生的所有事情都归结为一个名为 copyImageBlockSetPNG 的函数,该函数是从 CGContextDrawImage 内部调用的,它本身正在调用各种其他函数名称中的PNG。通货膨胀也在那里,占其中的 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 图像时崩溃。

【问题讨论】:

    标签: iphone objective-c core-graphics


    【解决方案1】:

    为了回答您的最后一个问题,您的经验案例似乎证明它们在加载后并未解压缩。

    要将它们转换为未压缩的数据,您可以(一次)在 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。

    【讨论】:

    • 我的应用程序现在因运行时错误而崩溃 - : CGBitmapContextCreate: 不支持的参数组合:8 个整数位/组件; 32 位/像素;三分量色彩空间; kCGImageAlphaLast; 5376 字节/行。有什么想法吗?
    • @p.g.l.hall Internet 说 CGBitmapContexts 仅支持预乘 alpha。尝试使用kCGImageAlphaPremultipliedLast 而不是CGImageGetBitmapInfo(...)
    • 好的,谢谢你所做的一切 :) 我已经尝试过了,我还必须将颜色空间更改为 CGColorSpaceCreateDeviceRGB() 以阻止它告诉我它不受支持 - 现在我得到另一个错误::CGBitmapContextCreate:无效数据字节/行:对于 8 个整数位/组件、3 个组件、kCGImageAlphaPremultipliedLast,应至少为 768。
    • p.g.l.hall:该错误消息准确地告诉您您做错了什么。阅读它,然后修复它。 (注意:硬编码 768 是错误的解决方案。)
    • @Peter Hosey 你在哪里看到他硬编码的?您是否阅读了问题的“解决方案”部分? (如果您希望人们收到您的 cmets 通知,请不要忘记前导 @。)
    【解决方案2】:

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

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

    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);
    

    我相信这样会快一点。希望对您有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-27
      • 2011-04-08
      相关资源
      最近更新 更多