2012-05-29 3 views
6

Ich füge zwei UIImagages in einen Kontext zusammen. Es funktioniert, aber es funktioniert ziemlich langsam und ich brauche eine schnellere Lösung. Als meine Lösung dauert es etwa 400ms, um den mergeImage: withImage: Anruf auf einem iPad 1G zu tätigen.Zwei UIImagages schneller zusammenführen als CGContextDrawImage

Hier ist, was ich tue:

-(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; 
} 

Und hier ist die statischen Methoden aus der ImageToolbox Klasse:

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

Irgendwelche Vorschläge, die Leistung zu steigern?

+0

Können Sie messen, wie lange jede Methode dauert? – EmilioPelaez

+0

Die Aufrufe von drawImage dauern etwa 400 ms, der Rest der Methoden liegt jeweils unter 10 ms. –

+0

Sind diese Bilder, die Sie vorher kombinieren können, mit Ihrer App zu versenden? Der Performance-Hit ist wahrscheinlich auf eine Kombination aus Farbraum und Alpha-Multiplikation zurückzuführen. Spielen Sie ein bisschen mit denen herum. –

Antwort

0

Ich habe es nicht geschafft, einen schnelleren Weg der Zusammenführung der Bilder zu finden. Ich habe die Bildgröße reduziert, um die Operation schneller zu machen.

0

Ich würde auf jeden Fall empfehlen, Instrumente zu verwenden, um zu profilieren, welche Nachricht die meiste Zeit in Anspruch nimmt, damit Sie sie wirklich unterbrechen können. Außerdem habe ich ein paar Methoden geschrieben, von denen ich denke, dass sie dasselbe mit viel weniger Code machen sollten, aber Sie müssen alles so geschrieben haben, wie Sie es tun, um die Dinge wirklich anpassbar zu halten. Hier sind sie sowieso:

-(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; 
} 

Oder wenn Sie das kombinierte Bild sofort gesucht:

- (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; 
} 

Ich habe keine Ahnung, ob sie schneller sein würde oder nicht, aber ich würde wirklich nicht wissen, wie man beschleunigen Sie das, was Sie sehr leicht haben, es sei denn, Sie hatten das Instrumentenprofil kaputt.

In jedem Fall hoffe ich, dass dies hilft.

+0

Ich habe gerade festgestellt, dass es bei meinen Methoden allerlei dumme Speicherprobleme geben kann, aber es sind einfache Fehlerbehebungen. Sie können den Kontext leicht behalten, wenn Sie brauchen oder nicht. Aber du hast die Idee. – Ben

+0

Ihre Lösungen funktionieren nicht ohne einen CGContextDrawImage-Aufruf. Sie müssen nach den drawInRect-Aufrufen ein CGContextDrawImage-Objekt erstellen. Aber ich konnte die Ausführungszeiten der Methoden ermitteln: drawInRect benötigt 400ms, was in 200ms auf img_decode_stage und 200ms auf img_interpolate_read endet. –

+0

Ahh ja das könnte man einfach anstelle von drawInRect verwenden. Zeigt nur, dass weniger ist nicht immer besser mit Code. Offensichtlich sind in jeder Lösung die Nachrichten, die am längsten dauern, die eigentlichen Zeichnungsnachrichten. Für Ihre müssen Sie pingelig werden, wenn Sie wirklich Leistung ausdrücken wollen. Zum Beispiel: anstatt CGRectMake zweimal zu verwenden, benutze es einmal in einer Variablen und benutze es erneut, da die Zuweisung von Männern leicht zu besteuern ist, obwohl es mit einer kleinen Struktur so ist, dass es wahrscheinlich keine Rolle spielt. Wenn Sie den Kontext zuweisen, verwenden Sie die Variablengröße anstelle der Zuweisung einer neuen CGSize. – Ben