Slightly-transparent white line around UIImage after adding overlays? - objective-c

I have a function that will overlay images over another image and return as a UIImage. However, a white line-ish thing comes up on it. Here's what I have
- (UIImage * ) romanticFilterImage: (UIImage *) imageA {
UIImage *vintageOne = [UIImage imageNamed:#"filter_vintage_1.png"];
UIImage *vintageTwo= [UIImage imageNamed:#"filter_vintage_2.png"];
UIImage *vintageThree = [UIImage imageNamed:#"filter_vintage_3.png"];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(imageA.size.width, imageA.size.height), YES, 0.0);
[imageA drawAtPoint: CGPointMake(0,0)];
[vintageThree drawInRect:CGRectMake(0, 0, imageA.size.width, imageA.size.height) blendMode: kCGBlendModeMultiply alpha: 1.0];
[vintageTwo drawInRect:CGRectMake(0, 0, imageA.size.width + 2, imageA.size.height + 2) blendMode: kCGBlendModeColorBurn alpha: 1.0];
[vintageOne drawInRect:CGRectMake(0, 0, imageA.size.width, imageA.size.height) blendMode: kCGBlendModeMultiply alpha: 1.0];
UIImage *source = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGSize size = [source size];
UIGraphicsBeginImageContext(size);
CGRect rect = CGRectMake(0, 0, size.width, size.height);
[source drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 5.0, 5.0, 5.0, 5.0);
CGContextStrokeRect(context, rect);
UIImage *testImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return testImg;
}
Here is a screenshot: (I have added a black background to enhance the slighly transparent border.

Aren't you stroking the image white in these lines?
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 5.0, 5.0, 5.0, 5.0);
CGContextStrokeRect(context, rect);
UIImage *testImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Although I am not sure if you intended GContextSetRGBStrokeColor(context, 5.0, 5.0, 5.0, 5.0); as 1.0 is the maximum value for the rgba values in the function.

Related

The rounded pure color image created by code is blur

In objective-c, I make a circle shape programmatically by following codes:
+(UIImage *)makeRoundedImage:(CGSize) size backgroundColor:(UIColor *) backgroundColor cornerRadius:(int) cornerRadius
{
UIImage* bgImage = [self imageWithColor:backgroundColor andSize:size];;
CALayer *imageLayer = [CALayer layer];
imageLayer.frame = CGRectMake(0, 0, size.width, size.height);
imageLayer.contents = (id) bgImage.CGImage;
imageLayer.masksToBounds = YES;
imageLayer.cornerRadius = cornerRadius;
UIGraphicsBeginImageContext(bgImage.size);
[imageLayer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return roundedImage;
}
The imageWithColor method is as following:
+(UIImage *)imageWithColor:(UIColor *)color andSize:(CGSize)size
{
//quick fix, or pop up CG invalid context 0x0 bug
if(size.width == 0) size.width = 1;
if(size.height == 0) size.height = 1;
//---quick fix
UIImage *img = nil;
CGRect rect = CGRectMake(0, 0, size.width, size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context,
color.CGColor);
CGContextFillRect(context, rect);
img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Then I used it to create a pure color circle shape image, but what I found is the circle image is not perfect rounded. As an example, please see following code:
CGSize size = CGSizeMake(diameter, diameter);
int r = ceil((float)diameter/2.0);
UIImage *imageNormal = [self makeRoundedImage:size backgroundColor:backgroundColor cornerRadius:r];
[slider setThumbImage:imageNormal forState:UIControlStateNormal];
First I created a circle image, then I set the image as the thumb to a UISlider. But what shown is as the picture shown below:
You can see the circle is not an exact circle. I'm thinking probably it caused by the screen resolution issue? Because if I use an image resource for the thumb, I need add #2x. Anybody know the reason? Thanx in advance.
updated on 8th Aug 2015.
Further to this question and the answer from #Noah Witherspoon, I found the blurry edge issue has been solved. But still, the circle looks like being cut. I used the code as following:
CGRect rect = CGRectMake(0.0f, 0.0f, radius*2.0f, radius*2.0f);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillEllipseInRect(context, rect);
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
And the circle looks like:
You can see the edge has been cut.
I changed the code as following:
CGRect rect = CGRectMake(0.0f, 0.0f, radius*2.0f+4, radius*2.0f+4);
CGRect rectmin = CGRectMake(2.0f, 2.0f, radius*2, radius*2);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillEllipseInRect(context, rectmin);
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
You can see the circle looks better(The top edge and the bottom edge):
I made the fill rect size smaller, and the edge looks better, but I don't think it's a nice solution. Still, does anybody know why this happen?
From your screenshot it looks like you do actually have a circular image, but its scale is wrong—it’s not Retina—so it looks blurry and not-circular. The key thing is that instead of using UIGraphicsBeginImageContext which defaults to a scale of 1.0 (as compared to your screen, which is at a scale of 2.0 or 3.0), you should be using UIGraphicsBeginImageContextWithOptions. Also, you don’t need to make a layer or a view to draw a circle in an image context.
+ (UIImage *)makeCircleImageWithDiameter:(CGFloat)diameter color:(UIColor *)color {
UIGraphicsBeginImageContextWithOptions(CGSizeMake(diameter, diameter), NO, 0 /* scale (0 means “use the current screen’s scale”) */);
[color setFill];
CGContextFillEllipseInRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, diameter, diameter));
UIImage *image = UIGraphicsGetImageFromCurrentContext();
UIGraphicsEndImageContext();
return image;
}
If you want to get a circle every time try this:
- (UIImage *)makeCircularImage:(CGSize)size backgroundColor:(UIColor *)backgroundColor {
CGSize squareSize = CGSizeMake((size.width > size.height) ? size.width : size.height,
(size.width > size.height) ? size.width : size.height);
UIView *circleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, squareSize.width, squareSize.height)];
circleView.layer.cornerRadius = circleView.frame.size.height * 0.5f;
circleView.backgroundColor = backgroundColor;
circleView.opaque = NO;
UIGraphicsBeginImageContextWithOptions(circleView.bounds.size, circleView.opaque, 0.0);
[circleView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}

How to capture UIView as UIImage in particular frame?

Hi i want to covert my UIView to UIImage in particular frame size kindly help me.
I have 'UITableView` which is added as subview of 'UIScrollView' for horizontal scroll, my table view frame size is (0, 0, 12000, 768).
I want to convert the current visible are of my UITableView as UIImage after scrolling.
Example:
if i scrolled my table view horizontally some distance means that current visible are is (150,0,1200,768) that means full device screen.
if i use the following code:
UIGraphicsBeginImageContext(self.frame.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *backgroundImage = UIGraphicsGetImageFromCurrentImageContext();
its capturing always the frame size of (0, 0, 1200, 768) only.
so, how can i set the origin of image capturing.
Kindly help me out.... Thanks in advance....
- (UIImage *)rasterizedImageInView:(UIView *)view atRect:(CGRect)rect {
UIGraphicsBeginImageContextWithOptions(rect.size, view.opaque, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, -rect.origin.x, -rect.origin.y);
[view.layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
This will allow you to capture a UIImage from a particular region within a UIView as defined by a CGRect.
CGRect rect = [self.view bounds];
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.view.layer renderInContext:context];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Try this.
UIView *viewprint=[[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
viewprint.backgroundColor=[UIColor whiteColor];
tableView.frame = CGRectMake(0, 0, width, height);
[viewprint addSubview:tableView];
UIGraphicsBeginImageContext(viewprint.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

How to make UIImage darker?

I can find many tutorial on the net which make UIImage grayscale. But I just want the UIImage slightly darker and still colorful. Is this possible? If yes, please give me some sample sources.
Thanks.
You should investigate Core Image filters - here are the Apple Docs
(...or you could just follow Attila's answer, much simpler!)
Thank to Zenox, this solution works fine:
+ (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;
}

Add text to UIImage with CoreGraphics

I just have to add a green text to UIImage I get from the database, how is it done? Here is what I have so far, something is missing for sure:
UIImage *img=[UIImage imageWithData:data];
UIGraphicsBeginImageContext(CGSizeMake(360, 270));
CGImageRef imageCon=[img CGImage];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSelectFont(context, "Helvetica", 12, NSMacOSRomanStringEncoding);
CGContextSetTextDrawingMode(context, kCGTextFill);
CGContextSetFillColor(context, CGColorGetComponents([[UIColor whiteColor] CGColor]));
CGAffineTransform xform = CGAffineTransformMake( 1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
CGContextSetTextMatrix(context, xform);
CGContextShowTextAtPoint(context, 100.0f, 180.0f, "test", strlen("test"));
UIImage *imgToAdd=[UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];
[arr addObject:imgToAdd];

How to erase some portion of a UIImageView's image on iOS?

I have a view with UIImageView and an image set to it. I want to erase the image as something like we do in photoshop with an eraser. How do I achieve this? Also, how do I undo erase?
If you know what area you want to erase, you can create a new image of the same size, set the mask to the full image minus the area you want to erase, draw the full image into the new image, and use that as the new image. To undo, simply use the previous image.
Edit
Sample code. Say the area you want to erase from image view imgView is specified with by erasePath:
- (void) clipImage
{
UIImage *img = imgView.image;
CGSize s = img.size;
UIGraphicsBeginImageContext(s);
CGContextRef g = UIGraphicsGetCurrentContext();
CGContextAddPath(g,erasePath);
CGContextAddRect(g,CGRectMake(0,0,s.width,s.height));
CGContextEOClip(g);
[img drawAtPoint:CGPointZero];
imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
UIGraphicsBeginImageContext(imgBlankView.frame.size);
[imgBlankView.image drawInRect:CGRectMake(0, 0, imgBlankView.frame.size.width, imgBlankView.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(),lineWidth);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextSetShouldAntialias(UIGraphicsGetCurrentContext(), YES);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint1.x, lastPoint1.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
imgBlankView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Swift 5.2 Version
UIGraphicsBeginImageContextWithOptions(imageView.frame.size, false, 1.0)
let currentContext = UIGraphicsGetCurrentContext()
currentContext?.addPath(shapeLayer.path!)
currentContext?.addRect(CGRect(x: 0, y: 0, width: imageView.frame.size.width, height: imageView.frame.size.height))
currentContext?.clip(using: .evenOdd)
imageView.image?.draw(at: .zero)
let imageTeemp = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext()