Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is programmatically inverting the colors of an image possible?

Tags:

I want to take an image and invert the colors in iOS.

like image 247
Brodie Avatar asked Jul 12 '11 23:07

Brodie


People also ask

Can you invert the colors of a picture?

Open Microsoft Paint. Go to “File > Open” or simply press Ctrl + O keys to open an image in Paint. Press Ctrl + A keys to select the entire image. Now, right-click on the image and select the Invert color option.


2 Answers

To expand on quixoto's answer and because I have relevant source code from a project of my own, if you were to need to drop to on-CPU pixel manipulation then the following, which I've added exposition to, should do the trick:

@implementation UIImage (NegativeImage)  - (UIImage *)negativeImage {     // get width and height as integers, since we'll be using them as     // array subscripts, etc, and this'll save a whole lot of casting     CGSize size = self.size;     int width = size.width;     int height = size.height;      // Create a suitable RGB+alpha bitmap context in BGRA colour space     CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();     unsigned char *memoryPool = (unsigned char *)calloc(width*height*4, 1);     CGContextRef context = CGBitmapContextCreate(memoryPool, width, height, 8, width * 4, colourSpace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast);     CGColorSpaceRelease(colourSpace);      // draw the current image to the newly created context     CGContextDrawImage(context, CGRectMake(0, 0, width, height), [self CGImage]);      // run through every pixel, a scan line at a time...     for(int y = 0; y < height; y++)     {         // get a pointer to the start of this scan line         unsigned char *linePointer = &memoryPool[y * width * 4];          // step through the pixels one by one...         for(int x = 0; x < width; x++)         {             // get RGB values. We're dealing with premultiplied alpha             // here, so we need to divide by the alpha channel (if it             // isn't zero, of course) to get uninflected RGB. We             // multiply by 255 to keep precision while still using             // integers             int r, g, b;              if(linePointer[3])             {                 r = linePointer[0] * 255 / linePointer[3];                 g = linePointer[1] * 255 / linePointer[3];                 b = linePointer[2] * 255 / linePointer[3];             }             else                 r = g = b = 0;              // perform the colour inversion             r = 255 - r;             g = 255 - g;             b = 255 - b;              // multiply by alpha again, divide by 255 to undo the             // scaling before, store the new values and advance             // the pointer we're reading pixel data from             linePointer[0] = r * linePointer[3] / 255;             linePointer[1] = g * linePointer[3] / 255;             linePointer[2] = b * linePointer[3] / 255;             linePointer += 4;         }     }      // get a CG image from the context, wrap that into a     // UIImage     CGImageRef cgImage = CGBitmapContextCreateImage(context);     UIImage *returnImage = [UIImage imageWithCGImage:cgImage];      // clean up     CGImageRelease(cgImage);     CGContextRelease(context);     free(memoryPool);      // and return     return returnImage; }  @end 

So that adds a category method to UIImage that:

  1. creates a clear CoreGraphics bitmap context that it can access the memory of
  2. draws the UIImage to it
  3. runs through every pixel, converting from premultiplied alpha to uninflected RGB, inverting each channel separately, multiplying by alpha again and storing back
  4. gets an image from the context and wraps it into a UIImage
  5. cleans up after itself, and returns the UIImage
like image 109
Tommy Avatar answered Oct 13 '22 02:10

Tommy


With CoreImage:

#import <CoreImage/CoreImage.h>  @implementation UIImage (ColorInverse)  + (UIImage *)inverseColor:(UIImage *)image {     CIImage *coreImage = [CIImage imageWithCGImage:image.CGImage];     CIFilter *filter = [CIFilter filterWithName:@"CIColorInvert"];     [filter setValue:coreImage forKey:kCIInputImageKey];     CIImage *result = [filter valueForKey:kCIOutputImageKey];     return [UIImage imageWithCIImage:result]; }  @end 
like image 27
user2704438 Avatar answered Oct 13 '22 02:10

user2704438