UIGraphicsBeginImageContextWithOptions casue black edge - ios

UIGraphicsBeginImageContextWithOptions(size, YES, [UIScreen mainScreen].scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
[[UIColor whiteColor] set];
CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));
CGContextRestoreGState(context);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
I am using this code above to generate a image. when I use UIGraphicsBeginImageContextWithOptions(size, ***YES***, [UIScreen mainScreen].scale)
and set the opaque property to YES. I get an image with black edge in right and bottom.
I have no idea why the black edge appears. Why does this appear and how to avoid this?

Related

Overlay alpha colour to UIImage

I'm using the following code to overlay 0.5 alpha colour to UIImage. But it seems to be lagging. My image has the size of 2000x1500.
Are there any other ways to overlay alpha colour to UIImage fast?
Thanks.
// Tint the image
- (UIImage *)imageWithTint:(UIColor *)tintColor alpha:(CGFloat)alpha {
UIImage *image = self;
CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, [UIScreen mainScreen].scale);
CGContextRef c = UIGraphicsGetCurrentContext();
[image drawInRect:rect];
CGContextSetFillColorWithColor(c, [[tintColor colorWithAlphaComponent:0.25] CGColor]);
CGContextSetBlendMode(c, kCGBlendModeSourceAtop);
CGContextFillRect(c, rect);
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}

UIImage Add Grey tranparency

I want to do the following:
As you can see one image (selected) does not have a grey fade and the other (nonselected item) does not.
I have tried multiple solutions. Including coloring the images with a grey color
- (UIImage *)colorizeImage:(UIImage *)image withColor:(UIColor *)color {
UIGraphicsBeginImageContext(image.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect area = CGRectMake(0, 0, image.size.width, image.size.height);
CGContextScaleCTM(context, 1, -1);
CGContextTranslateCTM(context, 0, -area.size.height);
CGContextSaveGState(context);
CGContextClipToMask(context, area, image.CGImage);
[color set];
CGContextFillRect(context, area);
CGContextRestoreGState(context);
CGContextSetBlendMode(context, kCGBlendModeMultiply);
CGContextDrawImage(context, area, image.CGImage);
UIImage *colorizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return colorizedImage;
}
However with this approach I run into an issue where if the bg of an image has a transparency the white below it shine through and it looks strange:
How can I detect the transparency and change the transparency to white? Or is there a better solution for doing this?
image = [self imageWithImage:image scaledToSize:CGSizeMake((self.collectionViewContainer.frame.size.width/3),90)];
UIImage *unSelected = [self colorizeImage:image withColor:[[UIColor grayColor] colorWithAlphaComponent:.9]];
UIImageView *imgView = [[UIImageView alloc] initWithImage:unSelected highlightedImage:image];
Since you simply want to apply a gray tint to an image, try it this way:
- (UIImage *)colorizeImage:(UIImage *)image withColor:(UIColor *)color {
UIGraphicsBeginImageContext(image.size, NO, image.scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect area = CGRectMake(0, 0, image.size.width, image.size.height);
[image drawInRect:area];
[color set];
CGContextFillRect(context, area);
UIImage *colorizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return colorizedImage;
}
This draws the image and then draws the color over the image. Assuming the color is partially transparent, the entire new image will be colored.
As you had it originally, you were only coloring the non-transparent parts due to the image clipping.
This update also applies the proper scale to the new image to match the original image.

Draw UIImage on a custom color canvas

I want to draw a image for example on black canvas, but the the result is always white, here is my code
-(UIImage*) renderImage
{
UIGraphicsBeginImageContext(CGSizeMake(300, 300));
[[UIColor blackColor] setFill];
UIImage*resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultImage;
}
for the future i will draw an image inside the canvas, but right now i just want a black filled canvas. why this code is not working
You need to be using CGContextSetFillColorWithColor() to fill the current context with a color. Try this sample code, you give it a color and a size and it will return you a UIImage meeting your criteria.
- (UIImage *)renderImageWithColor:(UIColor *)color inSize:(CGSize)size
{
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}

Image coloring/masking foreground using blending

I'm trying to change the color of an image at runtime. I've seen a couple answers on SO, but they all change the background color and not the foreground, which is what I am trying to do. I've based my code on another SO thread.
Here's the code I have:
#implementation UIImage (Coloring)
-(UIImage*) imageWithColorOverlay:(UIColor*)color
{
//create context
UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
CGContextRef context = UIGraphicsGetCurrentContext();
// drawingcode
//bg
CGRect rect = CGRectMake(0.0, 0.0, self.size.width, self.size.height);
[self drawInRect:rect];
//fg
CGContextSetBlendMode(context, kCGBlendModeMultiply);
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//end
return image;
}
#end
This are the results thus far:
From left to right:
No blending, just the normal asset. The gray bg is from the UIView behind the imageviews, the bg of the image is transparent.
Multiply with kCGBlendModeMultiply
Color burn with kCGBlendModeColorBurn
Is there an CGBlendMode that'll achieve replacing the foreground color? Also, is it possible to replace both the foreground color(white) and the shadow(black)?
After messing around with the different blend options, this code did the trick. The only caveat is that the red tint is shown in the shadow, its not technically correct but its close enuf
#implementation UIImage (Coloring)
-(UIImage*) imageWithColorOverlay:(UIColor*)color
{
//create context
UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
CGContextRef context = UIGraphicsGetCurrentContext();
//drawingcode
//bg
CGRect rect = CGRectMake(0.0, 0.0, self.size.width, self.size.height);
[self drawInRect:rect];
//fg
CGContextSetBlendMode(context, kCGBlendModeMultiply);
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillRect(context, rect);
//mask
[self drawInRect:rect blendMode:kCGBlendModeDestinationIn alpha:1.0];
//end
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}

How to tint the background images of an UIButton programmatically and dynamically?

I am working on an app - or rather on some re-usable "framework" which I am happy to share once it works. Within this app the user should be able to choose from a list of color themes. Therefore the app must be able to tint its UI elements in some rather dynamic way.
For Buttons all the tinting does not work. Properly tinted background images must be supplied here. But preparing one set of background images for each them is just second best. It is not dynamic and flexible enough.
In the end a solution may come down to providing one monochrome (grey) gradiented image for the selected and normal state and tint that image programmatically using CoreGraphics or OpenGL. But frankly, I do not know where to start there. How should the gradient look like and how would I then programmatically tint that in any given color?
Pretty much applies to UISegmentedControls, just a bit more complicated. :) Any generic solution that covers UISegementedControls too is highliy appreciated.
In iOS7 you can use the method imagedWithRenderingMode: in conjunction with the method setTintColor:
But, be sure to use UIImageRenderingModeAlwaysTemplate as it replaces all non-transparent colors on a UIImage with the tint color. The default is UIImageRenderingModeAutomatic.
UIImageRenderingModeAlwaysTemplate
Always draw the image as a template image, ignoring its color information.
Objective-C:
UIImage * image = [myButton.currentImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[myButton setImage:image forState:UIControlStateNormal];
Swift:
let image = myButton.currentImage?.withRenderingMode(.alwaysTemplate)
myButton.setImage(image, for: .normal)
I made a UIImage category following another post that i cant find that takes the image and tints it as follows:
- (UIImage *)tintedImageWithColor:(UIColor *)tintColor {
UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, self.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
// draw alpha-mask
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGContextDrawImage(context, rect, self.CGImage);
// draw tint color, preserving alpha values of original image
CGContextSetBlendMode(context, kCGBlendModeSourceIn);
[tintColor setFill];
CGContextFillRect(context, rect);
UIImage *coloredImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return coloredImage;
}
This will take the image and fill in all of the areas with an alpha value with the given color.
I created a UIButton category using horsejockey's code:
https://github.com/filipstefansson/UITintedButton
Here's the new methods:
-(void)setImageTintColor:(UIColor *)color;
-(void)setBackgroundTintColor:(UIColor *)color forState:(UIControlState)state;
+(void)tintButtonImages:(NSArray *)buttons withColor:(UIColor *)color;
+(void)tintButtonBackgrounds:(NSArray *)buttons withColor:(UIColor *)color forState:(UIControlState)state;
Here is a partial answer to your question. This is a helper method I wrote that tints a grey scale image:
// baseImage is the grey scale image. color is the desired tint color
+ (UIImage *)tintImage:(UIImage *)baseImage withColor:(UIColor *)color {
UIGraphicsBeginImageContextWithOptions(baseImage.size, NO, baseImage.scale);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect area = CGRectMake(0, 0, baseImage.size.width, baseImage.size.height);
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -area.size.height);
CGContextSaveGState(ctx);
CGContextClipToMask(ctx, area, baseImage.CGImage);
[color set];
CGContextFillRect(ctx, area);
CGContextRestoreGState(ctx);
CGContextSetBlendMode(ctx, kCGBlendModeOverlay);
CGContextDrawImage(ctx, area, baseImage.CGImage);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// If the original image was stretchable, make the new image stretchable
if (baseImage.leftCapWidth || baseImage.topCapHeight) {
newImage = [newImage stretchableImageWithLeftCapWidth:baseImage.leftCapWidth topCapHeight:baseImage.topCapHeight];
}
return newImage;
}
I modifie some things from "horsejockey":
+(UIImage *)getTintedImage:(UIImage*)image withColor:(UIColor *)tintColor
{
UIGraphicsBeginImageContextWithOptions(image.size, NO, [[UIScreen mainScreen] scale]);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, image.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
// draw alpha-mask
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGContextDrawImage(context, rect, image.CGImage);
// draw tint color, preserving alpha values of original image
CGContextSetBlendMode(context, kCGBlendModeSourceIn);
[tintColor setFill];
CGContextFillRect(context, rect);
UIImage *coloredImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return coloredImage;
}
I'm refering you to a SO question that seems to be what you are looking for and it's got an answer.
How to tint a transparent PNG image in iPhone?

Resources