2012-05-29 33 views
6

Tôi đang hợp nhất hai UIImages vào một ngữ cảnh. Nó hoạt động, nhưng nó thực hiện khá chậm và tôi đang cần một giải pháp nhanh hơn. Theo giải pháp của tôi là phải mất khoảng 400ms để thực hiện cuộc gọi mergeImage: withImage: trên iPad 1G.Hợp nhất hai UIImages nhanh hơn CGContextDrawImage

Dưới đây là những gì tôi làm:

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

Và đây là những phương pháp tĩnh từ lớp 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); 
} 

Mọi góp ý để nâng cao hiệu suất?

+0

Bạn có thể đo lường mỗi phương pháp mất bao lâu? – EmilioPelaez

+0

Các cuộc gọi drawImage mất khoảng 400 ms, phần còn lại của các phương pháp dưới 10ms mỗi. –

+0

Những hình ảnh này mà bạn có thể kết hợp trước và giao hàng với ứng dụng của mình không? Hiệu suất hit rất có thể là do một số combo của không gian màu của bạn và premultiplying alpha. Chơi xung quanh với những người một chút. –

Trả lời

0

Tôi không quản lý để tìm cách hợp nhất các hình ảnh nhanh hơn. Tôi đã giảm kích thước hình ảnh để làm cho hoạt động nhanh hơn.

0

Tôi chắc chắn sẽ khuyên bạn nên sử dụng Công cụ để cấu hình thông điệp nào chiếm nhiều thời gian nhất để bạn có thể thực sự phá vỡ nó. Ngoài ra, tôi đã viết một vài phương pháp mà tôi nghĩ rằng nên làm điều tương tự với mã ít hơn nhiều, nhưng bạn phải có mọi thứ được viết ra theo cách bạn làm để thực sự giữ cho mọi thứ có thể tùy chỉnh. Dưới đây chúng anyways:

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

Hoặc nếu bạn muốn hình ảnh kết hợp ngay lập tức:

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

Tôi không có ý tưởng nếu họ sẽ nhanh hơn hay không, nhưng tôi thực sự không biết làm thế nào để tăng tốc độ những gì bạn có rất dễ dàng trừ khi bạn có hồ sơ công cụ bị hỏng.

Trong mọi trường hợp, tôi hy vọng điều này sẽ hữu ích.

+0

Tôi chỉ nhận ra rằng có thể có tất cả các loại vấn đề bộ nhớ câm với các phương pháp của tôi nhưng chúng là các bản sửa lỗi đơn giản. Bạn có thể dễ dàng giữ lại bối cảnh nếu bạn cần hoặc những gì không. Nhưng bạn hiểu ý rồi đấy. – Ben

+0

Giải pháp của bạn không hoạt động nếu không có cuộc gọi CGContextDrawImage. Bạn sẽ phải tạo một CGContextDrawImage sau các cuộc gọi drawInRect. Nhưng tôi đã có thể nhận được thời gian thực hiện của các phương thức: drawInRect tự lấy 400ms, kết thúc bằng 200ms trên img_decode_stage và 200ms trên img_interpolate_read. –

+0

Ahh có bạn có thể dễ dàng sử dụng thay vì drawInRect. Chỉ cần đi để cho thấy rằng ít hơn không phải lúc nào cũng tốt hơn với mã. Rõ ràng trong bất kỳ giải pháp nào, các thông điệp sẽ mất nhiều thời gian nhất là các bản vẽ thực tế. Đối với của bạn, bạn sẽ phải nhận được picky nit nếu bạn thực sự muốn ép ra hiệu suất. Ví dụ: thay vì sử dụng CGRectMake hai lần sử dụng nó một lần trong một var và tái sử dụng nó, kể từ khi phân bổ nam giới là hơi thuế mặc dù với một cấu trúc nhỏ như vậy nó có thể sẽ không quan trọng. Khi bạn chỉ định ngữ cảnh, hãy sử dụng kích thước var thay vì Phân bổ một CGSize mới. – Ben