Last active
December 13, 2015 19:09
-
-
Save PMUNOZ08/4960995 to your computer and use it in GitHub Desktop.
Given an UIImage return a new UIImage with the colors inverted
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| - (UIImage *)negativeImage:(UIImage *)img | |
| { | |
| // 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 | |
| CGImageRef imageRef = [img CGImage]; | |
| int widthI = CGImageGetWidth(imageRef); | |
| int heightI = CGImageGetHeight(imageRef); | |
| // Create a suitable RGB+alpha bitmap context in BGRA colour space | |
| CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); | |
| unsigned char *memoryPool = (unsigned char *)calloc(widthI*heightI*4, 1); | |
| CGContextRef context = CGBitmapContextCreate(memoryPool, widthI, heightI, 8, widthI * 4, colourSpace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast); | |
| CGColorSpaceRelease(colourSpace); | |
| // draw the current image to the newly created context | |
| CGContextDrawImage(context, CGRectMake(0, 0, widthI, heightI), [img CGImage]); | |
| // run through every pixel, a scan line at a time... | |
| for(int y = 0; y < heightI; y++) | |
| { | |
| // get a pointer to the start of this scan line | |
| unsigned char *linePointer = &memoryPool[y * widthI * 4]; | |
| // step through the pixels one by one... | |
| for(int x = 0; x < widthI; 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:image scale:1.0 orientation:img.imageOrientation]; | |
| // clean up | |
| CGImageRelease(cgImage); | |
| CGContextRelease(context); | |
| free(memoryPool); | |
| // and return | |
| return returnImage; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment