replacing specific color in a uiimage - iphone

Assuming I would like to change just a specific color (per pixel) in a given UIImageView.
How would I use the following code to change all white pixels to darkGray ?
- (UIImage *) changeColorForImage:(UIImage *)image toColor:(UIColor*)color {
UIGraphicsBeginImageContext(image.size);
CGRect contextRect;
contextRect.origin.x = 0.0f;
contextRect.origin.y = 0.0f;
contextRect.size = [image size];
// Retrieve source image and begin image context
CGSize itemImageSize = [image size];
CGPoint itemImagePosition;
itemImagePosition.x = ceilf((contextRect.size.width - itemImageSize.width) / 2);
itemImagePosition.y = ceilf((contextRect.size.height - itemImageSize.height) );
UIGraphicsBeginImageContext(contextRect.size);
CGContextRef c = UIGraphicsGetCurrentContext();
// Setup shadow
// Setup transparency layer and clip to mask
CGContextBeginTransparencyLayer(c, NULL);
CGContextScaleCTM(c, 1.0, -1.0);
CGContextClipToMask(c, CGRectMake(itemImagePosition.x, -itemImagePosition.y, itemImageSize.width, -itemImageSize.height), [image CGImage]);
// Fill and end the transparency layer
const float* colors = CGColorGetComponents( color.CGColor );
CGContextSetRGBFillColor(c, colors[0], colors[1], colors[2], .75);
contextRect.size.height = -contextRect.size.height;
contextRect.size.height -= 15;
CGContextFillRect(c, contextRect);
CGContextEndTransparencyLayer(c);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Now that I know this simple code, I can even create idiotic methods like:
- (UIColor*) oppositeColor:(UIColor*)color {
const float* colors = CGColorGetComponents(color.CGColor);
return [UIColor colorWithRed:1-colors[0] green:1-colors[1] blue:1-colors[2] alpha:1];
}

Related

Drag drop colors on a png image

In an iOS application. I want to drag and drop images on my UIImageView where i have placed a png image. I just want these colors inside the image but not in transparent area. Attached images can explain my question more good
I want to drag an image from bottom and drop on the image and it should looks like this.
These colors on bottom may be considered as UIImageViews
- (UIImage *) changeColorForImage:(UIImage *)image toColor:(UIColor*)color {
UIGraphicsBeginImageContext(image.size);
CGRect contextRect;
contextRect.origin.x = 0.0f;
contextRect.origin.y = 0.0f;
contextRect.size = [image size];
// Retrieve source image and begin image context
CGSize itemImageSize = [image size];
CGPoint itemImagePosition;
itemImagePosition.x = ceilf((contextRect.size.width - itemImageSize.width) / 2);
itemImagePosition.y = ceilf((contextRect.size.height - itemImageSize.height) );
UIGraphicsBeginImageContext(contextRect.size);
CGContextRef c = UIGraphicsGetCurrentContext();
// Setup shadow
// Setup transparency layer and clip to mask
CGContextBeginTransparencyLayer(c, NULL);
CGContextScaleCTM(c, 1.0, -1.0);
CGContextClipToMask(c, CGRectMake(itemImagePosition.x, -itemImagePosition.y, itemImageSize.width, -itemImageSize.height), [image CGImage]);
// Fill and end the transparency layer
CGContextSetBlendMode(c, kCGBlendModeColorDodge);
CGContextSetFillColorWithColor(c, color.CGColor);
contextRect.size.height = - contextRect.size.height;
contextRect.size.height -= 15;
CGContextFillRect(c, contextRect);
CGContextEndTransparencyLayer(c);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
I believe it'll help you.

drawRect at double the size

If I override drawRect in order to display an image and place a dinamically-generated overlay on it (see code), whenever I scale up the image it is drawn in a very blurry way as the result of the scaling.
The image is composed of two pieces, an image drawn from a png (whose original size is 2x the wanted one, so it should not give problems when scaled, but it does) and the other is dinamically generated according to the rect size, so it should also adapt to the current rect size, but it doesn't.
Any help?
- (void) drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextDrawImage(ctx, CGRectMake(0, 0, rect.size.width, rect.size.height), [UIImage imageNamed:#"actionBg.png"].CGImage);
// generate the overlay
if ([self isActive] == NO && self.fullDelay != 0) { // TODO: remove fullDelay check!
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0);
CGContextRef overlayCtx = UIGraphicsGetCurrentContext();
int segmentSize = (rect.size.height / [self fullDelay]);
for (int i=0; i<[self fullDelay]; i++) {
float alpha = 0.9 - (([self fullDelay] * 0.1) - (i * 0.1));
[[UIColor colorWithRed:120.0/255.0 green:14.0/255.0 blue:14.0/255.0 alpha:alpha] setFill];
if (currentDelay > i) {
CGRect r = CGRectMake(0, i * segmentSize, rect.size.width, segmentSize);
CGContextFillRect(overlayCtx, r);
}
[[UIColor colorWithRed:1 green:1 blue:1 alpha:0.3] setFill];
CGRect line = CGRectMake(0, (i * segmentSize) + segmentSize - 1 , rect.size.width, 1);
CGContextFillRect(overlayCtx, line);
}
UIImage *overlay = UIGraphicsGetImageFromCurrentImageContext();
UIImage *overlayMasked = [TDUtilities maskImage:overlay withMask:[UIImage imageNamed:#"actionMask.png"]];
// prevent the drawings to be flipped
CGContextTranslateCTM(overlayCtx, 0, rect.size.height);
CGContextScaleCTM(overlayCtx, 1.0, -1.0);
CGContextSetBlendMode(ctx, kCGBlendModeMultiply);
CGContextDrawImage(ctx, rect, overlayMasked.CGImage);
CGContextSetBlendMode(ctx, kCGBlendModeNormal);
UIGraphicsEndImageContext();
}
The problem is that you are drawing overlayMasked as a CGImage with CGContextDrawImage, which knows nothing of scale. Either you will have to double the size yourself manually if you're in a double-scale situation, or you should use UIImage, which knows about scale.

Draw the highlight blue color using UIImage or Code

From http://replyz.com/c/1244746-does-anyone-know-the-exact-cgcolorref-used-to-create-the-selection-highlight-when-using-uitableviewcellselectionstyleblue#
I saw someone did it with Code and he said the highlighted color is from a UIImage.
Where can I find the image?
(I want to highlight a UIButton with the UITableViewCellSelectionStyleBlue color)
I found the link http://replyz.com/c/1244746-does-anyone-know-the-exact-cgcolorref-used-to-create-the-selection-highlight-when-using-uitableviewcellselectionstyleblue# including some code which can be used to create the highlight. And I create a new UIImage with the Code.
Here is the code:
+ (UIImage *) imageForSelectedBlue {
CGRect rect = CGRectMake(0, 0, 10, 10);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 0.021, 0.548, 0.962, 1.000, 0.008, 0.364, 0.900, 1.000 };
CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef selectionGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextDrawLinearGradient(context, selectionGradient, startPoint, endPoint, 0);
CGGradientRelease(selectionGradient);
CGColorSpaceRelease(rgbColorspace);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Actually, you can set the background image of the button. It is more efficient.
[button setBackgroundImage:buttonBackgroundPressed forState:UIControlStateHighlighted];

How can i change uiimage color in iphone sdk xcode

I am using different images and i want to include change color option. But i cant. Any body help me?
If you want to do image tinting, see UIImage+Tint.m in kballard/MGImageUtilities. If you want wholesale color replacement (e.g. treat an image as a silhouette and change the entire color to one flat color), see UIImage+Tint.m in mattgemmell/MGImageUtilities.
Its latest and most simple way to do it.
theImageView.image = [theImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[theImageView setTintColor:[UIColor redColor]];
One way to accomplish this is to desaturate your image, and add a tint on top of that image with the color you desire.
Desaturate
-(UIImage *) getImageWithUnsaturatedPixelsOfImage:(UIImage *)image {
const int RED = 1, GREEN = 2, BLUE = 3;
CGRect imageRect = CGRectMake(0, 0, image.size.width*2, image.size.height*2);
int width = imageRect.size.width, height = imageRect.size.height;
uint32_t * pixels = (uint32_t *) malloc(width*height*sizeof(uint32_t));
memset(pixels, 0, width * height * sizeof(uint32_t));
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width * sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), [image CGImage]);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
uint8_t * rgbaPixel = (uint8_t *) &pixels[y*width+x];
uint32_t gray = (0.3*rgbaPixel[RED]+0.59*rgbaPixel[GREEN]+0.11*rgbaPixel[BLUE]);
rgbaPixel[RED] = gray;
rgbaPixel[GREEN] = gray;
rgbaPixel[BLUE] = gray;
}
}
CGImageRef newImage = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
free(pixels);
UIImage * resultUIImage = [UIImage imageWithCGImage:newImage scale:2 orientation:0];
CGImageRelease(newImage);
return resultUIImage;
}
Overlay With Color
-(UIImage *) getImageWithTintedColor:(UIImage *)image withTint:(UIColor *)color withIntensity:(float)alpha {
CGSize size = image.size;
UIGraphicsBeginImageContextWithOptions(size, FALSE, 2);
CGContextRef context = UIGraphicsGetCurrentContext();
[image drawAtPoint:CGPointZero blendMode:kCGBlendModeNormal alpha:1.0];
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextSetBlendMode(context, kCGBlendModeOverlay);
CGContextSetAlpha(context, alpha);
CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(CGPointZero.x, CGPointZero.y, image.size.width, image.size.height));
UIImage * tintedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return tintedImage;
}
How-To
//For a UIImageView
yourImageView.image = [self getImageWithUnsaturatedPixelsOfImage:yourImageView.image];
yourImageView.image = [atom getImageWithTintedColor:yourImageView.image withTint:[UIColor redColor] withIntensity:0.7];
//For a UIImage
yourImage = [self getImageWithUnsaturatedPixelsOfImage:yourImage];
yourImage = [atom getImageWithTintedColor:yourImageView.image withTint:[UIColor redColor] withIntensity:0.7];
You can change the color of the tint to whatever you desire.

UIImage color changing?

How can I change the UIImage's color through programming, any help please? If I send a UIImage, its color needs to change any help please? If I change the RGB color through bitmaphandling, it does not work.
If you only need it to look different, just use imageView.tintColor (iOS 7+). Catch is, setting tintColor doesn't do anything by default:
To make it work, use imageWithRenderingMode:
var image = UIImage(named: "stackoverflow")!
image = image.imageWithRenderingMode(.AlwaysTemplate)
let imageView = ...
imageView.tintColor = UIColor(red: 0.35, green: 0.85, blue: 0.91, alpha: 1)
imageView.image = image
And now it will work:
Link to documentation.
Performance
Setting the image after configuring the UIImageView avoids repeating expensive operations:
// Good usage
let imageView = ...
imageView.tintColor = yourTintColor
var image = UIImage(named: "stackoverflow")!
image = image.imageWithRenderingMode(.AlwaysTemplate)
imageView.image = image // Expensive
// Bad usage
var image = UIImage(named: "stackoverflow")!
image = image.imageWithRenderingMode(.AlwaysTemplate)
let imageView = ...
imageView.image = image // Expensive
imageView.frame = ... // Expensive
imageView.tintColor = yourTint // Expensive
Getting & setting the image asynchronously reduces scrolling and animation lag (especially when tinting an image inside of a UICollectionViewCell or UITableViewCell):
let imageView = cell.yourImageView
imageView.image = nil // Clear out old image
imageView.tintColor = UIColor(red: 0.35, green: 0.85, blue: 0.91, alpha: 1)
// Setting the image asynchronously reduces stuttering
// while scrolling. Remember, the image should be set as
// late as possible to avoid repeating expensive operations
// unnecessarily.
dispatch_async(dispatch_get_main_queue(), { () -> Void in
var image = UIImage(named: "stackoverflow")!
image = image.imageWithRenderingMode(.AlwaysTemplate)
imageView.image = image
})
One way to accomplish this is to desaturate your image, and add a tint on top of that image with the color you desire.
Desaturate
-(UIImage *) getImageWithUnsaturatedPixelsOfImage:(UIImage *)image {
const int RED = 1, GREEN = 2, BLUE = 3;
CGRect imageRect = CGRectMake(0, 0, image.size.width*2, image.size.height*2);
int width = imageRect.size.width, height = imageRect.size.height;
uint32_t * pixels = (uint32_t *) malloc(width*height*sizeof(uint32_t));
memset(pixels, 0, width * height * sizeof(uint32_t));
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, width * sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), [image CGImage]);
for(int y = 0; y < height; y++) {
for(int x = 0; x < width; x++) {
uint8_t * rgbaPixel = (uint8_t *) &pixels[y*width+x];
uint32_t gray = (0.3*rgbaPixel[RED]+0.59*rgbaPixel[GREEN]+0.11*rgbaPixel[BLUE]);
rgbaPixel[RED] = gray;
rgbaPixel[GREEN] = gray;
rgbaPixel[BLUE] = gray;
}
}
CGImageRef newImage = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
free(pixels);
UIImage * resultUIImage = [UIImage imageWithCGImage:newImage scale:2 orientation:0];
CGImageRelease(newImage);
return resultUIImage;
}
Overlay With Color
-(UIImage *) getImageWithTintedColor:(UIImage *)image withTint:(UIColor *)color withIntensity:(float)alpha {
CGSize size = image.size;
UIGraphicsBeginImageContextWithOptions(size, FALSE, 2);
CGContextRef context = UIGraphicsGetCurrentContext();
[image drawAtPoint:CGPointZero blendMode:kCGBlendModeNormal alpha:1.0];
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextSetBlendMode(context, kCGBlendModeOverlay);
CGContextSetAlpha(context, alpha);
CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(CGPointZero.x, CGPointZero.y, image.size.width, image.size.height));
UIImage * tintedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return tintedImage;
}
How-To
//For a UIImageView
yourImageView.image = [self getImageWithUnsaturatedPixelsOfImage:yourImageView.image];
yourImageView.image = [atom getImageWithTintedColor:yourImageView.image withTint:[UIColor redColor] withIntensity:0.7];
//For a UIImage
yourImage = [self getImageWithUnsaturatedPixelsOfImage:yourImage];
yourImage = [atom getImageWithTintedColor:yourImageView.image withTint:[UIColor redColor] withIntensity:0.7];
You can change the color of the tint to whatever you desire.
There's a great post about this here:
http://coffeeshopped.com/2010/09/iphone-how-to-dynamically-color-a-uiimage
The one caveat that I have with the current code is that using it on retina images will result in a loss of the higher 'resolution' for these images. I am currently looking for a solution for this...
Check out my post (mostly just remixing code).
Edit: This code basically creates a new CGContext, draws a layer on it with the new color, and returns a new UIImage from that. I haven't gone in depth on this code in a while, but it seems to just draw a UIImage with the same shape as the original, so that's a limit (loses any detail in the image).
If you need high performance, I strongly recommend you to use GPUImage.
You may download it at https://github.com/BradLarson/GPUImage
The RGB data you are operating on is just a copy. After you finish making changes, you need to turn that data back into an image.
I first make a new bitmap:
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
ctx = CGBitmapContextCreate( malloc(dataSize), width, height,
8, // CGImageGetBitsPerComponent(cgImage),
bytesPerRow, //CGImageGetBytesPerRow(cgImage),
space,
//kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big );
kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little);
//kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
CGColorSpaceRelease( space );
// now draw the image into the context
CGRect rect = CGRectMake( 0, 0, CGImageGetWidth(cgImage), CGImageGetHeight(cgImage) );
CGContextDrawImage( ctx, rect, cgImage );
And get the pixels:
pixels = CGBitmapContextGetData( ctx );
Assuming that your pixel data came from pixels = CGBitmapContextGetData( ctx ); then take that context and build a new image from it:
CGImageRef newImg = CGBitmapContextCreateImage(ctx);
[[UIImage imageWithCGImage:newImg] drawInRect:rect];
CGImageRelease(newImg);
I think you can create another context with setting there context color to RGB you want to color your picture. Then draw your UIImage into that context and use that context instead of using directly your picture. This is a concept. This way you're creating offscreen buffer with a colored image. I didn't try this in cocoa, only in carbon, but i suppose it will work in the same way.
Hmmm -- isn't the order of the bytes supposed to be RGBA? You are setting them as ARGB...
try this
- (UIImage *)imageWithOverlayColor:(UIColor *)color
{
CGRect rect = CGRectMake(0.0f, 0.0f, self.size.width, self.size.height);
if (UIGraphicsBeginImageContextWithOptions) {
CGFloat imageScale = 1.0f;
if ([self respondsToSelector:#selector(scale)]) // The scale property is new with iOS4.
imageScale = self.scale;
UIGraphicsBeginImageContextWithOptions(self.size, NO, imageScale);
}
else {
UIGraphicsBeginImageContext(self.size);
}
[self drawInRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(context, kCGBlendModeSourceIn);
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
The great post mentioned by user576924 worked great for me:
iPhone: How to Dynamically Color a UIImage
and in swift:
extension UIImage {
func imageWithColor( color : UIColor ) -> UIImage {
// begin a new image context, to draw our colored image onto
UIGraphicsBeginImageContext(self.size)
// get a reference to that context we created
let context = UIGraphicsGetCurrentContext();
// set the fill color
color.setFill()
// translate/flip the graphics context (for transforming from CG* coords to UI* coords
CGContextTranslateCTM(context, 0, self.size.height)
CGContextScaleCTM(context, 1.0, -1.0)
// set the blend mode to color burn, and the original image
CGContextSetBlendMode(context, kCGBlendModeColor)
let rect = CGRect(origin: CGPointZero, size: self.size)
CGContextDrawImage(context, rect, self.CGImage)
// set a mask that matches the shape of the image, then draw (color burn) a colored rectangle
CGContextClipToMask(context, rect, self.CGImage)
CGContextAddRect(context, rect)
CGContextDrawPath(context,kCGPathFill)
// generate a new UIImage from the graphics context we drew onto
let coloredImg = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
//return the color-burned image
return coloredImg
}
}
Note that I also changed "kCGBlendModeColorBurn" to "kCGBlendModeColor" as mentioned in the post's comments section.
For me this worked:
extension UIImage {
class func image(image: UIImage, withColor color: UIColor) -> UIImage {
UIGraphicsBeginImageContextWithOptions(CGSizeMake(image.size.width, image.size.height), false, image.scale)
let context = UIGraphicsGetCurrentContext()
color.set()
CGContextTranslateCTM(context, 0, image.size.height)
CGContextScaleCTM(context, 1, -1)
let rect = CGRectMake(0, 0, image.size.width, image.size.height)
CGContextClipToMask(context, rect, image.CGImage)
CGContextFillRect(context, rect)
let coloredImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return coloredImage
}
}