3

タイトルが正確に正しいかどうかはわかりませんが、問題がどこにあるのかはわかりません。

スプライトシートからUIImageの配列をロードする必要があります。これを、UIImageViewのアニメーションとして使用します。

スプライトシートは、巨大なアトラス(2048x2048)とスプライトの説明を含むjsonを生成するTexturePackerを使用して生成されます。

今まで問題なく動作していて、たった0.5〜0.8秒で100フレームをロードしても、本当に満足していました。

問題は、ドキュメントフォルダからスプライトシートをロードする必要があることです(ダウンロードされているため、アプリに統合できません)。そのため、の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);
}

読み込みに時間がかかる場所を示すアップロードシステムプロファイラーセッションを試すこともできます

ここに画像の説明を入力してください

4

1 に答える 1

2

さて、私はついに問題がどこにあるのかを理解しました。Instruments Timeプロファイラーを注意深く調べた後、copyImageBlockSetPNGに多くの時間が費やされていることに気付きました。これが、フレームごとにディスクから画像をロードしていることを最初に信じさせた理由です。結局、誰かがすでにこの問題を抱えていましたCGContextDrawImageはその場でPNGを解凍しますか?、そして、ディスクからではなく、フレームごとにメモリをロードしていたことは事実でした。代わりに、フレームごとに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);

それが役に立てば幸い!

于 2013-03-10T19:22:32.390 に答える