0

In my project I am trying to get the average color of a series of UIImage objects. So I implemented a category UIImage(AverageColor) to calculate the average color.

Here's how I do it with the GPUImage library:

- (void)averageColor:(void (^)(UIColor *))handler {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        GPUImagePicture *picture = [[GPUImagePicture alloc] initWithImage:self];
        GPUImageAverageColor *averageColorFilter = [GPUImageAverageColor new];
        [averageColorFilter setColorAverageProcessingFinishedBlock:^(CGFloat r, CGFloat g, CGFloat b, CGFloat a, CMTime frameTime) {
            UIColor *color = [UIColor colorWithRed:r green:g blue:b alpha:a];
            dispatch_async(dispatch_get_main_queue(), ^{
                handler(color);
            });
        }];
    
        [picture addTarget:averageColorFilter];
        [picture useNextFrameForImageCapture];
        [picture processImage];
    });
}

I've also tried the approach (pure CPU one I think?) in this answer. Then I test these two methods with the same UIImage and log out the time used in each methods. And here's the result:

cpu time: 0.102402

gpu time: 0.414044

I am surprised that the CPU one runs much faster. So what's the problem here? Am I using GPUImage in a wrong way?


Edit:

The above result was got from iOS simulator. When testing on real device (iPhone6s) the difference is even greater:

cpu time: 0.019034

gpu time: 0.137635

Community
  • 1
  • 1
hklel
  • 1,624
  • 23
  • 45

1 Answers1

0

It's not the color averaging that's slow, it's because there's a large amount of overhead in the creation of a GPUImagePicture from a UIImage. Instantiating a GPUImagePicture from a UIImage currently requires a re-render of that image via Core Graphics into a texture and the upload of that to the GPU.

This is a slow process, and if you can I'd recommend creating a GPUImagePicture once and reusing it, or avoiding dealing with UIImages altogether (grabbing directly from the camera, working with raw bytes, etc.). I've been working on direct decoding of JPEG and PNG images to raw bytes within the framework to avoid this, but haven't had much time to complete this.

As for the color averaging itself, it generally will significantly outpace raw pixel-by-pixel calculations, but there may be ways to improve upon this. See my answer here and the comments that follow for more discussion about this.

Community
  • 1
  • 1
Brad Larson
  • 170,088
  • 45
  • 397
  • 571