R – In a UIImage (or its derivatives), how can I replace one color with another

colorsiphoneuiimage

For example, I have a UIImage (from which I can get a CGImage, CGLayer, etc., if needed), and I want to replace all of the red pixels (1, 0, 0) with blue (0, 0, 1).

I have code to figure out which pixels are the target color (see this SO question & answer), and I can substitute the appropriate values in rawData but (a) I'm not sure how to get a UIImage back from my rawData buffer and (b) it seems like I might be missing a built-in that will do all of this for me automatically, saving me oodles of grief.

Thanks!

Best Answer

Ok, so we got the UIImage into a rawBits buffer (see link in original question), then we twiddled the data in the buffer to our liking (i.e., set all the red-components (every 4th byte) to 0, as a test), and now need to get a new UIImage representing the twiddled data.

I found the answer in Erica Sudan's iPhone Cookbook, Chapter 7 (images), example 12 (Bitmaps). The relevant call was CGBitmapContextCreate(), and the relevant code was:

+ (UIImage *) imageWithBits: (unsigned char *) bits withSize: (CGSize)  
size
{
    // Create a color space
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    if (colorSpace == NULL)
    {
        fprintf(stderr, "Error allocating color space\n");
        free(bits);
        return nil;
    }

    CGContextRef context = CGBitmapContextCreate (bits, size.width,  
size.height, 8, size.width * 4, colorSpace,  
kCGImageAlphaPremultipliedFirst);
    if (context == NULL)
    {
        fprintf (stderr, "Error: Context not created!");
        free (bits);
        CGColorSpaceRelease(colorSpace );
        return nil;
    }

    CGColorSpaceRelease(colorSpace );
    CGImageRef ref = CGBitmapContextCreateImage(context);
    free(CGBitmapContextGetData(context));
    CGContextRelease(context);

    UIImage *img = [UIImage imageWithCGImage:ref];
    CFRelease(ref);
    return img;
}

Hope that's useful to future site spelunkers!

Related Topic