2012-05-29 1 views
6

Я объединяю два UIImages в один контекст. Он работает, но он работает довольно медленно, и я нуждаюсь в более быстром решении. В качестве моего решения требуется около 400 мс, чтобы сделать звонок mergeImage: withImage: на iPad 1G.Слияние двух 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 мс, остальные методы составляют менее 10 мс каждый. –

+0

Эти изображения, которые вы можете комбинировать заранее и отправить с вашим приложением? Лучшее попадание в производительность, скорее всего, связано с некоторой комбинацией вашего цветового пространства и преувеличением альфы. Поиграйте с ними немного. –

ответ

0

Мне не удалось найти более быстрый способ слияния изображений. Я уменьшил размеры изображений, чтобы ускорить работу.

0

Я бы порекомендовал использовать инструменты для профилирования того, какое сообщение занимает больше всего времени, поэтому вы можете действительно сломать его. Кроме того, я написал несколько методов, которые, как я думаю, должны делать то же самое с гораздо меньшим количеством кода, но вы должны все записать так, как вы делаете, чтобы действительно сохранить настройки. Вот они в любом случае:

-(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. Но мне удалось получить время выполнения методов: drawInRect занимает 400 мс, который заканчивается на 200 мс на img_decode_stage и 200 мс на img_interpolate_read. –

+0

Ahh да, вы можете легко использовать это вместо drawInRect. Просто идет, чтобы показать, что меньше кода не всегда лучше. Очевидно, что в любом решении сообщения, которые занимают больше времени, являются фактическими сообщениями чертежа. Для вас вам нужно будет придираться, если вы действительно хотите выжать производительность. Например: вместо использования CGRectMake дважды используйте его один раз в var и повторно используйте его, так как распределение мужчин немного обкладывается налогом, хотя с небольшой структурой вроде это, вероятно, не имеет значения. Когда вы назначаете контекст, используйте размер var вместо выделения нового CGSize. – Ben

Смежные вопросы