Is it possible to isolate a single color in an UIImage/CGImageRef - iphone

Wondering if there is a way to isolate a single color in an image either using masks or perhaps even a custom color space. I'm ultimately looking for a fast way to isolate 14 colors out of an image - figured if there was a masking method it might may be faster than walking through the pixels.
Any help is appreciated!

You could use a custom color space (documentation here) and then substitute it for "CGColorSpaceCreateDeviceGray()" in the following code:
- (UIImage *)convertImageToGrayScale:(UIImage *)image
{
// Create image rectangle with current image width/height
CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);
// Grayscale color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); // <- SUBSTITUTE HERE
// Create bitmap content with current image size and grayscale colorspace
CGContextRef context = CGBitmapContextCreate(nil, image.size.width, image.size.height, 8, 0, colorSpace, kCGImageAlphaNone);
// Draw image into current context, with specified rectangle
// using previously defined context (with grayscale colorspace)
CGContextDrawImage(context, imageRect, [image CGImage]);
// Create bitmap image info from pixel data in current context
CGImageRef imageRef = CGBitmapContextCreateImage(context);
// Create a new UIImage object
UIImage *newImage = [UIImage imageWithCGImage:imageRef];
// Release colorspace, context and bitmap information
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
CFRelease(imageRef);
// Return the new grayscale image
return newImage;
}
This code is from this blog which is worth a look at for removing colors from images.

Related

How to know if a UIImage is representable in PNG or JPG?

I got a UIImage from UIImagePickerController, and using the code from this site to resize the image
- (UIImage *)resizedImage:(CGSize)newSize
transform:(CGAffineTransform)transform
drawTransposed:(BOOL)transpose
interpolationQuality:(CGInterpolationQuality)quality {
CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
CGRect transposedRect = CGRectMake(0, 0, newRect.size.height, newRect.size.width);
CGImageRef imageRef = self.CGImage;
// Build a context that's the same dimensions as the new size
CGContextRef bitmap = CGBitmapContextCreate(NULL,
newRect.size.width,
newRect.size.height,
CGImageGetBitsPerComponent(imageRef),
0,
CGImageGetColorSpace(imageRef),
CGImageGetBitmapInfo(imageRef));
// Rotate and/or flip the image if required by its orientation
CGContextConcatCTM(bitmap, transform);
// Set the quality level to use when rescaling
CGContextSetInterpolationQuality(bitmap, quality);
// Draw into the context; this scales the image
CGContextDrawImage(bitmap, transpose ? transposedRect : newRect, imageRef);
// Get the resized image from the context and a UIImage
CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);
UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
// Clean up
CGContextRelease(bitmap);
CGImageRelease(newImageRef);
return newImage;
}
UIImagePNGRepresentation() failed to return NSData on re-sized image, but UIImageJPEGRepresentation() succeed.
How do we know if a UIImage is presentable in PNG or JPEG? What missed in the above code that make the resized image can not be represented in PNG?
According to apple document: "This function may return nil if the image has no data or if the underlying CGImageRef contains data in an unsupported bitmap format."
What bitmap format supported by PNG presentation? How to make an UIImage PNG-supported format?
That was a mistake that in another part of the code the image was rescaled with the following
CGContextRef context = CGBitmapContextCreate(NULL,
size.width,
size.height,
8,
0,
CGImageGetColorSpace(source),
kCGImageAlphaNoneSkipFirst);
Changing kCGImageAlphaNoneSkipFirst to CGImageGetBitmapInfo(source) fixed the problem
go to following link...
How to check if downloaded PNG image is corrupt?
it may help you...
Let me know it is working or not...
Happy Coding!!!!

Objective c - UIImage resizing issue

I have a resource (.png file) that show a picture frame (border).
This .png file is size 100x100px, and the border width is 10px.
My Question:
How can I create another UIImage from this image, with a different size, without ruin the border's width?
The Problem:
When I try to draw the new image from the original image with CGContextDrawImage I get a new image with the new size, but my border proportion is ruin.
CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newWidth, newHeight));
CGImageRef imageRef = //... the image
// Build a context that's the same dimensions as the new size
CGContextRef bitmap = CGBitmapContextCreate(NULL,
newRect.size.width,
newRect.size.height,
CGImageGetBitsPerComponent(imageRef),
0,
CGImageGetColorSpace(imageRef),
CGImageGetBitmapInfo(imageRef));
// Set the quality level to use when rescaling
CGContextSetInterpolationQuality(bitmap, kCGInterpolationHigh);
// Draw into the context; this scales the image
CGContextDrawImage(bitmap, newRect, imageRef);
// Get the resized image from the context and a UIImage
CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);
UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
// Clean up
CGContextRelease(bitmap);
CGImageRelease(newImageRef);
For example, when I tried to create an image size 800x100p, I get an image with very thin top and bottom border.
What I need is that the border will stay the same width
*note
Using resizableImageWithCapInsets: wont help me, because I need a new image with the new size to save on the disc.
You can use resizableImageWithCapInsets:
UIImage *img = [UIImage imageNamed:#"myResource"];
img = [img resizableImageWithCapInsets:UIEdgeInsetsMake(10,10,10,10)];
I've never used this approach with CGContextDrawImage, but it should work.

Change brightness on a greyscale image with transparent background

I use a function to change brightness of a picture (without use openGL), which works well.
I use another function to convert my image in grayscale, which works well too.
But when i combine them, when i apply my brightness function on the grayscale image, i got some stripes on the image, and when the background is transparent (alpha 0) it is replaced by a black background. Do you any have any idea?
Please find below my grayscale function and the brightness function as well :
// ## Brightness without OpenGL call
+(UIImage *) changeImageBrightness:(UIImage *)aInputImage withFactor:(float)aFactor
{
CGImageRef img=aInputImage.CGImage;
CFDataRef dataref = CGDataProviderCopyData(
CGImageGetDataProvider(aInputImage.CGImage));
int length=CFDataGetLength(dataref);
UInt8 *data=(UInt8 *)CFDataGetBytePtr(dataref);
// Perform operation on pixels
for(int index=0;index<length;index+=4) {
// Go For BRIGHTNESS
for(int i=0;i<3;i++) {
if(data[index+i]+aFactor<0) {
data[index+i]=0;
} else {
if(data[index+i]+aFactor>255) {
data[index+i]=255;
} else {
data[index+i]+=aFactor;
}
}
}
}
// .. Take image attributes
size_t width=CGImageGetWidth(img);
size_t height=CGImageGetHeight(img);
size_t bitsPerComponent=CGImageGetBitsPerComponent(img);
size_t bitsPerPixel=CGImageGetBitsPerPixel(img);
size_t bytesPerRow=CGImageGetBytesPerRow(img);
// .. Do the pixel manupulation
CGColorSpaceRef colorspace=CGImageGetColorSpace(img);
CGBitmapInfo bitmapInfo=CGImageGetBitmapInfo(img);
CFDataRef newData=CFDataCreate(NULL,data,length);
CGDataProviderRef provider=CGDataProviderCreateWithCFData(newData);
// .. Get the Image out of this raw data
CGImageRef newImg = CGImageCreate(width, height, bitsPerComponent,
bitsPerPixel, bytesPerRow, colorspace, bitmapInfo, provider,
NULL, true, kCGRenderingIntentDefault);
// .. Prepare the image from raw data
UIImage* rawImage = [[UIImage alloc] initWithCGImage:newImg];
// .. done with all,so release the references
CFRelease(newData);
CGImageRelease(newImg);
CGDataProviderRelease(provider);
CFRelease(dataref);
// return rawImage.CGImage;
UIImage *imageApresFiltreEtRotationCGI = [UIImage
imageWithCGImage:rawImage.CGImage];
return imageApresFiltreEtRotationCGI;
}
+ (UIImage *)convertImageToGrayScale:(UIImage *)image
{
// Create image rectangle with current image width/height
CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);
// Grayscale color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
// Create bitmap content with current image size and grayscale colorspace
CGContextRef context = CGBitmapContextCreate(nil, image.size.width,
image.size.height, 8, 0, colorSpace, kCGImageAlphaNone);
// Draw image into current context, with specified rectangle
// using previously defined context (with grayscale colorspace)
CGContextDrawImage(context, imageRect, [image CGImage]);
/* changes start here */
// Create bitmap image info from pixel data in current context
CGImageRef grayImage = CGBitmapContextCreateImage(context);
// release the colorspace and graphics context
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
// make a new alpha-only graphics context
context = CGBitmapContextCreate(nil, image.size.width,
image.size.height, 8, 0, nil, kCGImageAlphaOnly);
// draw image into context with no colorspace
CGContextDrawImage(context, imageRect, [image CGImage]);
// create alpha bitmap mask from current context
CGImageRef mask = CGBitmapContextCreateImage(context);
// release graphics context
CGContextRelease(context);
// make UIImage from grayscale image with alpha mask
UIImage *grayScaleImage = [UIImage imageWithCGImage:
CGImageCreateWithMask(grayImage, mask) scale:image.scale
orientation:image.imageOrientation];
// release the CG images
CGImageRelease(grayImage);
CGImageRelease(mask);
// return the new grayscale image
return grayScaleImage;
/* changes end here */
}
Here is the picture i got.
The background behind the baby was transparent before i made the grey/scale and light transformation.

(iphone) grayscaled image is too dark, can I change the opacity of gray scale image?

I use the following code to turn color image to grayscale image.
The resulting image is gray, but too dark.
Can I change the opacity of it? (not sure if the term "opacity" is the right word for it)
+ (UIImage *)convertImageToGrayScale: (UIImage*) image
{
// Create image rectangle with current image width/height
CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);
// Grayscale color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
// Create bitmap content with current image size and grayscale colorspace
CGContextRef context = CGBitmapContextCreate(nil, image.size.width, image.size.height, 8, 0, colorSpace, kCGImageAlphaNone);
// Draw image into current context, with specified rectangle
// using previously defined context (with grayscale colorspace)
CGContextDrawImage(context, imageRect, [image CGImage]);
// Create bitmap image info from pixel data in current context
CGImageRef imageRef = CGBitmapContextCreateImage(context);
// Create a new UIImage object
UIImage *newImage = [UIImage imageWithCGImage:imageRef];
// Release colorspace, context and bitmap information
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
CFRelease(imageRef);
// Return the new grayscale image
return newImage;
}
Just converting to grayscale can sometimes cause your image to be too dark because the RGB->Grayscale conversion may not preserve luminosity (perceived brightness) of the image. You have two options: (1) brighten the image after conversion to greyscale (you could try simple-iphone-image-processing); and (2) convert the image preserving luminosity.
One common way to convert from RGB to grayscale while preserving luminosity is to set your gray value (Y) according to the following function:
Y = 0.30 x Red + 0.59 x Green + 0.11 x Blue
This works because the human eye perceives a given intensity of green to be "brighter" than the same intensity of red or blue (in approximately that ratio).

Flatten subviews

I have a graphics app I am writing that has a UIView that has several UIImageViews as subviews added to it over time.
I want to flatten all these subviews for performance reasons as it is slowing down over time. What is the simplest way to "flatten" these layers.
Create a new bitmap context:
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
CGContextRef newContext =
CGBitmapContextCreate(
NULL,
viewContainingAllUIImageViews.frame.size.width,
vViewContainingAllUIImageViews.frame.size.height,
8,
viewContainingAllUIImageViews.frame.size.width,
colorspace,
0);
CGColorSpaceRelease(colorspace);
Paint the appropriate background into the context:
CGContextSetRGBFillColor(newContext, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(newContext, CGRectMake(0, 0, viewContainingAllUIImageViews.frame.size.width, vViewContainingAllUIImageViews.frame.size.height));
Get the CGImage property of each image that your UIImageView contains and draw all of the images into this single image:
CGContextDrawImage(newContext, oneOfTheSubImageViews.frame, oneOfTheSubImageViews.image.CGImage);
Convert the bitmap context back into an image:
CGImageRef newImage = CGBitmapContextCreateImage(newContext);
UIImage *flattenedImage = [UIImage imageWithCGImage:newImage];
Then CFRelease newContext, newImage, use the UIImage in a UIImageView and discard all other UIImageViews.