2012-05-29 32 views
6

我正在将两个UIImage合并到一个上下文中。它工作,但它执行得非常慢,我需要一个更快的解决方案。由于我的解决方案是在iPad 1G上拨打mergeImage: withImage:大约需要400毫秒。合并两个UIImages比CGContextDrawImage更快

这是我做的:

-(CGContextRef)mergeImage:(UIImage*)img1 withImage:(UIImage*)img2 
{ 
    CGSize size = [ImageToolbox getScreenSize]; 
    CGContextRef context = [ImageToolbox createARGBBitmapContextFromImageSize:CGSizeMake(size.width, size.height)]; 

    CGContextSetRenderingIntent(context, kCGRenderingIntentSaturation); 

    CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), img1.CGImage); 
    CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), img2.CGImage); 


    return context; 
} 

下面是从ImageToolbox类的静态方法:

static CGRect screenRect; 

+ (CGContextRef)createARGBBitmapContextFromImageSize:(CGSize)imageSize 
{ 
    CGContextRef context = NULL; 
    CGColorSpaceRef colorSpace; 
    void *   bitmapData; 
    int    bitmapByteCount; 
    int    bitmapBytesPerRow; 

    size_t pixelsWide = imageSize.width; 
    size_t pixelsHigh = imageSize.height; 

    bitmapBytesPerRow = (pixelsWide * 4); 
    bitmapByteCount  = (bitmapBytesPerRow * pixelsHigh); 

    colorSpace = CGColorSpaceCreateDeviceRGB(); 
    if (colorSpace == NULL) 
    { 
     fprintf(stderr, "Error allocating color space\n"); 
     return NULL; 
    } 

    bitmapData = malloc(bitmapByteCount); 
    if (bitmapData == NULL) 
    { 
     fprintf (stderr, "Memory not allocated!"); 
     CGColorSpaceRelease(colorSpace); 
     return NULL; 
    } 

    context = CGBitmapContextCreate (bitmapData, 
            pixelsWide, 
            pixelsHigh, 
            8,  // bits per component 
            bitmapBytesPerRow, 
            colorSpace, 
            kCGImageAlphaPremultipliedFirst); 
    if (context == NULL) 
    { 
     free (bitmapData); 
     fprintf (stderr, "Context not created!"); 
    } 

    CGColorSpaceRelease(colorSpace); 

    return context; 
} 

+(CGSize)getScreenSize 
{ 
    if (screenRect.size.width == 0 && screenRect.size.height == 0) 
    { 
     screenRect = [[UIScreen mainScreen] bounds];  

    } 
    return CGSizeMake(screenRect.size.height, screenRect.size.width-20); 
} 

任何建议,以提高性能?

+0

你能测量每种方法需要多长时间吗? – EmilioPelaez

+0

drawImage调用大约需要400 ms,其余的方法每个都在10ms以下。 –

+0

这些图像可以事先与您的应用程序结合使用吗?性能下降很可能是由于您的色彩空间的一些组合以及alpha的预乘。与那些玩一下。 –

回答

0

我没有设法找到合并图像的更快的方式。我缩小了图像尺寸以使操作更快。

0

我肯定会推荐使用Instruments来分析哪些消息需要花费最多的时间,以便能够真正分解它。另外,我写了一些方法,我认为应该用更少的代码来做同样的事情,但是您必须将所有内容都写出来,才能真正保持可定制性。在这里,他们是反正:

-(CGContextRef)mergeImage:(UIImage *)img1 withImage:(UIImage *)img2 
{ 
    CGSize size = [ImageToolbox getScreenSize]; 
    CGRect rect = CGRectMake(0, 0, size.width, size.height); 

    UIGraphicsBeginImageContextWithOptions(size, YES, 1.0); 

    CGContextRef context = UIGraphicsGetCurrentContext(); 

    CGContextSetRenderingIntent(context, kCGRenderingIntentSaturation); 

    [img1 drawInRect:rect]; 
    [img2 drawInRect:rect]; 

    UIGraphicsEndImageContext(); 

    return context; 
} 

或者,如果你想马上合成图像:

- (UIImage *)mergeImage:(UIImage *)img1 withImage:(UIImage *)img2 
{ 
    CGSize size = [ImageToolbox getScreenSize]; 
    CGRect rect = CGRectMake(0, 0, size.width, size.height); 

    UIGraphicsBeginImageContextWithOptions(size, YES, 1.0); 

    CGContextRef context = UIGraphicsGetCurrentContext(); 

    CGContextSetRenderingIntent(context, kCGRenderingIntentSaturation); 

    [img1 drawInRect:rect]; 
    [img2 drawInRect:rect]; 

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 

    UIGraphicsEndImageContext(); 

    return image; 
} 

我不知道他们是否会更快或没有,但我真的不知道该怎么除非仪器配置文件发生故障,否则很容易加快您的操作。

无论如何,我希望这有助于。

+0

我刚刚意识到可能存在各种各样的与我的方法愚蠢的记忆问题,但他们是简单的修复。如果您需要或不需要,您可以轻松保留上下文。但你明白了。 – Ben

+0

没有CGContextDrawImage调用,您的解决方案不起作用。您必须在drawInRect调用后创建一个CGContextDrawImage。但是我能够获得方法的执行时间:dr​​awInRect本身需要400ms,它在img_decode_stage上以200ms结束,在img_interpolate_read上以200ms结束。 –

+0

啊,是的,你可以很容易地使用,而不是drawInRect。只是表明少用代码并不总是更好。很明显,在任何解决方案中,花费最长时间的消息都是实际的绘图消息。对于你而言,如果你真的想挤出表现,你将不得不挑剔挑剔。例如:而不是使用CGRectMake两次在var中使用它一次并重用它,因为男性分配略微征税,尽管使用一个像这样的小结构可能无关紧要。分配上下文时,请使用var大小,而不是分配新的CGSize。 – Ben