从SpriteSheet加速UIImage的创建

时间:2013-03-08 20:50:02

标签: ios objective-c performance core-image

我不确定我的标题是否完全正确,但我不确定我的问题究竟在哪里。

我需要从spritesheet加载一个UIImages数组,然后我将它用作UIImageView中的动画。

使用TexturePacker生成spritesheet,它生成巨大的图集(2048x2048)和带有精灵描述的json。

直到现在,我已经让它无故障地工作,甚至在0.5-0.8秒内加载100帧,我真的很满意。

问题是现在我需要从Documents文件夹加载spritesheets(它们已下载,因此无法集成到应用程序中),因此我必须使用UIImage imageWithContentsOfFile而不是UIImage imagenamed 。 这使得我的加载时间增加了5-15秒,具体取决于动画中的帧数。 我猜这个问题是因为图像没有被缓存,是为每一帧加载它,但我不明白为什么

这是代码:

// With this line, perfect
//UIImage *atlas = [UIImage imageNamed:@"media/spritesheets/default-pro7@2x.png"];
// But with this one, incredibly looooong loading times
UIImage *atlas = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"media/spritesheets/default-pro7@2x" ofType:@"png"]];

CGImageRef atlasCGI = [atlas CGImage];

for( NSDictionary* dict in frames) {

    NSDictionary *frame = [dict objectForKey:@"frame"];
    int x = [[frame objectForKey:@"x"] intValue];
    int y = [[frame objectForKey:@"y"] intValue];
    int width = [[frame objectForKey:@"w"] intValue];
    int height = [[frame objectForKey:@"h"] intValue];

    NSDictionary *spriteSize = [dict objectForKey:@"spriteSourceSize"];
    int realx = [[spriteSize objectForKey:@"x"] intValue];

    NSDictionary *size = [dict objectForKey:@"sourceSize"];
    int realWidth = [[size objectForKey:@"w"] intValue];
    int realHeight = [[size objectForKey:@"h"] intValue];

    //Initialize the canvas size!
    canvasSize = CGSizeMake(realWidth, realHeight);

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

    bitmapData = malloc( bitmapByteCount );

    //Create the context
    context = CGBitmapContextCreate(bitmapData, canvasSize.width, canvasSize.height, 8, bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);

    // Clear background
    CGContextClearRect(context,CGRectMake(0.0f,0.0f,canvasSize.width,canvasSize.height));

    // Get spriteRect
    CGRect cropRect = CGRectMake(x, y, width, height);
    CGImageRef imageRef = CGImageCreateWithImageInRect(atlasCGI, cropRect);

    //Draw the image into the bitmap context
    CGContextDrawImage(context, CGRectMake(realx, 0, width, height), imageRef);

    //Get the result image
    resultImage = CGBitmapContextCreateImage(context);

    UIImage *result = result = [UIImage imageWithCGImage:resultImage];

    [images addObject:result];

    //Cleanup
    free(bitmapData);
    CGImageRelease(resultImage);
    CGImageRelease(imageRef);
}

我甚至可以尝试上传系统分析器会话,这些会话显示加载

的时间

enter image description here

1 个答案:

答案 0 :(得分:2)

好吧,我终于找到了问题所在。在使用Instruments Time Profiler更仔细地观察之后,我注意到在copyImageBlockSetPNG中花了很多时间,这让我首先相信我是从每个帧的磁盘加载图像。事实上,有人已经遇到了这个问题Does CGContextDrawImage decompress PNG on the fly?,结果是我每帧都加载内存,但不是来自磁盘,而是每帧都以png格式从内存中解压缩。

在该帖子中有一个解决方案,其中包括将图像写入上下文并从中获取图像的未压缩副本。

这有效,但我找到了其他方式,我相信它更有效率

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

希望它有所帮助!