iPhone:当从应用程序文档中的文件加载图像时,创建Texture2D的速度要慢得多,为什么?

发布于 2024-08-13 17:50:23 字数 4439 浏览 7 评论 0原文

比什么慢?比从应用程序包加载的图像创建相同的纹理慢。 慢了多少? iPhone 上慢 80 倍,Mac 上的比率相似(但总体更快)。

我下面的示例显示使用 imageNamed: 加载图像:从第一张图像创建纹理;将图像保存到应用程序文档目录中的文件中;从该文件加载图像;从第二张图像创建纹理。

图像为 640x640 png,每种情况下创建 100 个 64x64 纹理。 创建时间为 0.51 秒 vs. 41.3 秒。

谁能解释一下这种巨大的差异,并指出我加快第二种情况的方法和方法,使其与第一种情况一样快(如果可能的话)?

鲁迪夫

#import "Texture2D.h"

#define START_TIMER NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
#define END_TIMER NSTimeInterval stop = [NSDate timeIntervalSinceReferenceDate]; NSLog(@"Time = %f", stop-start); 


@interface UIImage (CS_Extensions)
-(UIImage *) imageAtRect:(CGRect)rect;
+(NSString *) documentsDirectory;
+(void) saveImage:(UIImage *)image toDocumentsFile:(NSString *)filename;
+(UIImage *) imageFromDocumentsFile:(NSString *)filename;
+(BOOL) documentsFileExists:(NSString *)filename;
+(void) createTexturesFromImage:(UIImage *)image640x640 texture:(Texture2D **)texture;

@end;

@implementation UIImage (MiscExt)

-(UIImage *)imageAtRect:(CGRect)rect {
    CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], rect);
    UIImage* subImage = [UIImage imageWithCGImage: imageRef];
    CGImageRelease(imageRef);
    return subImage;
}

+(NSString *) documentsDirectory {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    return documentsDirectory;
}

+(UIImage *) imageFromDocumentsFile:(NSString *)filename {
    //  NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
    NSString *documentsDirectory = [self documentsDirectory];
    NSString *path = [NSString stringWithFormat:@"%@/%@", documentsDirectory, filename];
    NSLog(@"%s : path %@", __FUNCTION__, path);
    NSData *data = [[NSData alloc] initWithContentsOfFile:path];
    UIImage *image = [[UIImage alloc] initWithData:data];
    return image;
}

+(void) saveImage:(UIImage *)image toDocumentsFile:(NSString *)filename {
    if (image != nil) {     // save to local file
        //      NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
        NSString *documentsDirectory = [self documentsDirectory];
        NSString *path = [NSString stringWithFormat:@"%@/%@", documentsDirectory, filename];
        NSLog(@"%s : path %@", __FUNCTION__, path);
        //You can write an NSData to the fs w/ a method on NSData.
        //If you have a UIImage, you can do UIImageJPEGRepresentation() or UIImagePNGRepresentation to get data.
        NSData *data = UIImagePNGRepresentation(image);
        [data writeToFile:path atomically:YES];
        // Check if file exists
        NSFileManager *fileManager = [NSFileManager defaultManager];
        BOOL ok = [fileManager fileExistsAtPath:path];
        if (ok) {
            NSLog(@"%s : written file %@", __FUNCTION__, path);
        }
        else {
            NSLog(@"%s : failed to write file %@", __FUNCTION__, path);
        }
    }
}

+(BOOL) documentsFileExists:(NSString *)filename {
    NSString *documentsDirectory = [self documentsDirectory];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:filename];
    NSLog(@"%s : path %@", __FUNCTION__, path);
    BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path];
    return exists;
}

+(void) createTexturesFromImage:(UIImage *)image640x640 texture:(Texture2D **)texture {
    NSLog(@"%s -> ", __FUNCTION__);
    START_TIMER;
    for (int x = 0; x < 9; ++x) {
        for (int y = 0; y < 9; ++y) {
            UIImage *ulCorner = [image640x640 imageAtRect:CGRectMake(x*64,y*64,64,64)];
            texture[y*10+x] = [[Texture2D alloc] initWithImage:ulCorner];
        }
    }
    END_TIMER;
    NSLog(@"%s <- ", __FUNCTION__);
}

@end


-(void) test {

    Texture2D *texture1[100];
    Texture2D *texture2[100];

    // compare texture creation from a bundled file vs Documents file
    {
        UIImage *imageBundled = [UIImage imageNamed:@"bivio-640x640.png"];
        [UIImage createTexturesFromImage:imageBundled texture:texture1];

        [UIImage saveImage:imageBundled toDocumentsFile:@"docfile.png"];
        BOOL ok = [UIImage documentsFileExists:@"docfile.png"];

        UIImage *imageFromFile = [UIImage imageFromDocumentsFile:@"docfile.png"];
        [UIImage createTexturesFromImage:imageFromFile texture:texture2];
    }
}

Slower than what? slower than creating the same textures from an image loaded from the app bundle.
How much slower ? 80 times slower on iPhone, similar ratio (but faster overall) on Mac.

My example below shows loading an image with imageNamed: ; creating textures from the first image ; saving image to a file in the app's Documents directory ; loading an image from that file ; creating textures from the second image.

Images are 640x640 png, 100 textures 64x64 are created in each case.
Creation times are 0.51 s vs. 41.3 s.

Can anyone explain this huge difference, and point me to ways and means of speeding up the second case, to make it as fast as the first, if possible ?

Rudif

#import "Texture2D.h"

#define START_TIMER NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
#define END_TIMER NSTimeInterval stop = [NSDate timeIntervalSinceReferenceDate]; NSLog(@"Time = %f", stop-start); 


@interface UIImage (CS_Extensions)
-(UIImage *) imageAtRect:(CGRect)rect;
+(NSString *) documentsDirectory;
+(void) saveImage:(UIImage *)image toDocumentsFile:(NSString *)filename;
+(UIImage *) imageFromDocumentsFile:(NSString *)filename;
+(BOOL) documentsFileExists:(NSString *)filename;
+(void) createTexturesFromImage:(UIImage *)image640x640 texture:(Texture2D **)texture;

@end;

@implementation UIImage (MiscExt)

-(UIImage *)imageAtRect:(CGRect)rect {
    CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], rect);
    UIImage* subImage = [UIImage imageWithCGImage: imageRef];
    CGImageRelease(imageRef);
    return subImage;
}

+(NSString *) documentsDirectory {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    return documentsDirectory;
}

+(UIImage *) imageFromDocumentsFile:(NSString *)filename {
    //  NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
    NSString *documentsDirectory = [self documentsDirectory];
    NSString *path = [NSString stringWithFormat:@"%@/%@", documentsDirectory, filename];
    NSLog(@"%s : path %@", __FUNCTION__, path);
    NSData *data = [[NSData alloc] initWithContentsOfFile:path];
    UIImage *image = [[UIImage alloc] initWithData:data];
    return image;
}

+(void) saveImage:(UIImage *)image toDocumentsFile:(NSString *)filename {
    if (image != nil) {     // save to local file
        //      NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
        NSString *documentsDirectory = [self documentsDirectory];
        NSString *path = [NSString stringWithFormat:@"%@/%@", documentsDirectory, filename];
        NSLog(@"%s : path %@", __FUNCTION__, path);
        //You can write an NSData to the fs w/ a method on NSData.
        //If you have a UIImage, you can do UIImageJPEGRepresentation() or UIImagePNGRepresentation to get data.
        NSData *data = UIImagePNGRepresentation(image);
        [data writeToFile:path atomically:YES];
        // Check if file exists
        NSFileManager *fileManager = [NSFileManager defaultManager];
        BOOL ok = [fileManager fileExistsAtPath:path];
        if (ok) {
            NSLog(@"%s : written file %@", __FUNCTION__, path);
        }
        else {
            NSLog(@"%s : failed to write file %@", __FUNCTION__, path);
        }
    }
}

+(BOOL) documentsFileExists:(NSString *)filename {
    NSString *documentsDirectory = [self documentsDirectory];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:filename];
    NSLog(@"%s : path %@", __FUNCTION__, path);
    BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:path];
    return exists;
}

+(void) createTexturesFromImage:(UIImage *)image640x640 texture:(Texture2D **)texture {
    NSLog(@"%s -> ", __FUNCTION__);
    START_TIMER;
    for (int x = 0; x < 9; ++x) {
        for (int y = 0; y < 9; ++y) {
            UIImage *ulCorner = [image640x640 imageAtRect:CGRectMake(x*64,y*64,64,64)];
            texture[y*10+x] = [[Texture2D alloc] initWithImage:ulCorner];
        }
    }
    END_TIMER;
    NSLog(@"%s <- ", __FUNCTION__);
}

@end


-(void) test {

    Texture2D *texture1[100];
    Texture2D *texture2[100];

    // compare texture creation from a bundled file vs Documents file
    {
        UIImage *imageBundled = [UIImage imageNamed:@"bivio-640x640.png"];
        [UIImage createTexturesFromImage:imageBundled texture:texture1];

        [UIImage saveImage:imageBundled toDocumentsFile:@"docfile.png"];
        BOOL ok = [UIImage documentsFileExists:@"docfile.png"];

        UIImage *imageFromFile = [UIImage imageFromDocumentsFile:@"docfile.png"];
        [UIImage createTexturesFromImage:imageFromFile texture:texture2];
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

残龙傲雪 2024-08-20 17:50:23

当您构建项目时,XCode 会优化您放入资源中的 PNG。

本文详细解释了它: http://iphonedevelopment.blogspot.com /2008/10/iphone-optimized-pngs.html

When you built your project, XCode optimises PNGs that you put in resources.

This article explains it in details: http://iphonedevelopment.blogspot.com/2008/10/iphone-optimized-pngs.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文