I am writing a method that takes a image and a alpha value then return a uiimage with that alpha value.
I have found some code like this
+ (UIImage *)imageByApplyingAlpha:(UIImage*) originalImage andAlpha:(CGFloat) alpha {
UIGraphicsBeginImageContextWithOptions(originalImage.size, NO, 0.0f);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect area = CGRectMake(0, 0, originalImage.size.width, originalImage.size.height);
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -area.size.height);
CGContextSetBlendMode(ctx, kCGBlendModeMultiply);
CGContextSetAlpha(ctx, alpha);
CGContextDrawImage(ctx, area, originalImage.CGImage);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
but this only work on single image. It will generate malformed GIF when I use the returned image to form GIF.
Please help me to find a easy way to get UIImage with alpha.
Thanks all!
Unfortunately, the GIF format doesn't support alpha channels, so you won't be able to set alpha values on one. Transparency in GIF uses index transparency, which is all or nothing.
Related
I am having problem understanding the reason for the following method, to return images that are visibly pixelated. I have double checked the size of the image, and it is fine. What's more, without tinting it, the image edges are smooth, and lack pixelation.
The method for tinting image, based on IOS7 ImageView's tintColor property, works fine, however I would love to find out what is wrong with the following code, because it seems to work for everybody but me. Thanks!
- (UIImage *)imageTintedWithColor:(UIColor *)color
{
if (color) {
UIImage *img = self; // The method is a part of UIImage category, hence the "self"
UIGraphicsBeginImageContext(img.size);
// get a reference to that context we created
CGContextRef context = UIGraphicsGetCurrentContext();
// set the fill color
[color setFill];
// translate/flip the graphics context (for transforming from CG* coords to UI* coords
CGContextTranslateCTM(context, 0, img.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
// set the blend mode to color burn, and the original image
CGContextSetBlendMode(context, kCGBlendModeColorBurn);
CGRect rect = CGRectMake(0, 0, img.size.width, img.size.height);
CGContextDrawImage(context, rect, img.CGImage);
// set a mask that matches the shape of the image, then draw (color burn) a colored rectangle
CGContextSetBlendMode(context, kCGBlendModeSourceIn);
CGContextAddRect(context, rect);
CGContextDrawPath(context,kCGPathFill);
// generate a new UIImage from the graphics context we drew onto
UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//return the color-burned image
return coloredImg;
}
return self;
}
Change this line:
UIGraphicsBeginImageContext(img.size);
to:
UIGraphicsBeginImageContextWithOptions(img.size, NO, 0);
If your images will never have an transparency, change the NO to YES.
I am trying to apply a color fill to the MKAnnotation. I found some code that pretty much works but for some reason the filled image is upside down after applying the fill to it.
Here is the current code that I am running on a map pin.
CGRect rect = CGRectMake(0, 0, self.image.size.width, self.image.size.height);
UIGraphicsBeginImageContext(self.image.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClipToMask(context, rect, self.image.CGImage);
CGContextSetFillColorWithColor(context, [[UIColor grayColor] CGColor]);
CGContextFillRect(context, rect);
CGContextRotateCTM(context, 90);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImage *flippedImage = [UIImage imageWithCGImage:img.CGImage
scale:1.0 orientation:self.image.imageOrientation];
self.image = flippedImage;
Here is what the pins look like after this code runs.
http://d.pr/i/UaPU
I was thinking that if I applied the current image orientation to the flippedImage that would do the trick but that did not work. I also tried setting self.image = img; and removing the flippedImage var completely but the result is still the same.
CGContext coordinate system is flipped vertically in regard to UIView coordinate system.
Just flip it like this:
CGContextTranslateCTM(ctx, 0, imageHeight);,
CGContextScaleCTM(ctx, 1, -1);
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?
I'm working on an App which works with gestureRecognizer. With gestures it is possible to select an UIImage (such as rectangle.png) and it is possible with a UIPopoverView to change the color of that image by selecting a color for the selected image.
This image lay in a UIImageView and I think the best solution is to mask that image and set a colored image with the dame size and frame instead.
Is it the right way? How can I optimize my approach?
Which could be the best practice for this requirement?
(UIImage *)maskImage:(UIColor *)maskColor
{
CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, rect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextClipToMask(context, rect, self.CGImage);
CGContextSetFillColorWithColor(context, maskColor.CGColor);
CGContextFillRect(context, rect);
UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return smallImage;
}
In one class I have an array consisting of five UIImages such as tiangle.png and circle.png.
In the current class I have a list of colors. After clicking to the UIImage and after clicking to one color it is possible to change the color of the current UIImage.
This will be realized by masking the image, set its color and replace the old UIImage with the new one in the selected color.
But there is something wrong in the method, which should change the color:
- (void) changeColor: (UITapGestureRecognizer*) gestureRecognizer{
UIGraphicsBeginImageContext(test.newView.image.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGPoint loc = [gestureRecognizer locationInView:self.view];
CGContextSetFillColorWithColor(context, [[self colorOfPoint:loc]CGColor]);
CGContextTranslateCTM(context, 0, test.newView.image.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGRect rect = CGRectMake(test.newView.frame.origin.x,test.newView.frame.origin.x, test.newView.image.size.width,test.newView.image.size.height);
CGContextSetBlendMode(context, kCGBlendModeColorBurn);
CGContextClipToMask(context, rect, test.newView.image.CGImage);
CGContextAddRect(context, rect);
CGContextDrawPath(context, kCGPathFill);
CGImageRef imgRef = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:imgRef];
CGImageRelease(imgRef);
CGContextRelease(context);
UIGraphicsEndImageContext();
test.newView.image = img;
}
The only thing what is happening is that the clicked UIImage is going to get opaque.
The imageview which is holding the UIImage is in this case not deleted.
I'm not sure that grabbing an imageRef using a CGBitmapContextCreateImage() call is appropriate inside a UIGraphics image context. Every example I've ever seen uses
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
to grab the image before closing the image context. You might try that.