Proper use of eraser tool above the image while drawing? - ios

I have one UIView in that I have draw image. On this View I am drawing pen tool, rectangle tool and update the new image and draw. Just Like the ACEDrawingView
I am facing one issue with the eraser tool. when I use the eraser the background image color is also gone. Please check the screenshot.
In the above image the black portion is pen drawing and white portion is my eraser drawing. what I want when user do the eraser drawing not to clear the background image. just the drawing.
Redraw Image code
- (void)updateCacheImage:(BOOL)redraw
{
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
if (redraw) {
// erase the previous image
self.image = nil;
// load previous image (if returning to screen)
[[self.prev_image copy] drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
// I need to redraw all the lines
for (id<ACEDrawingTool> tool in self.pathArray) {
[tool draw];
}
} else {
// set the draw point
[self.image drawAtPoint:CGPointZero];
[self.currentTool draw];
}
// store the image
self.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
Eraser tool drawing
- (void)draw
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context, self.path);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGContextSetAlpha(context, self.lineAlpha);
CGContextStrokePath(context);
}

This is because you are using self.lineColor.CGColor which i guess is the last chosen color, which is white in this case. Try replacing the current color with [UIColor clearColor] and add this line of code CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);

I have faced this now ...Just found the solutions like following.Your eraser colour should be like your background view background colour.
example:
CGContextSetStrokeColorWithColor(context, yourviewBackgroundColor);

Related

How to add a stroke around an image?

Question
I have a CGImageRef image. It is actually a image which is going to be used as a mask. So, the "alpha layer" of it is what I really care about. I want to "thicken" the opaque part of the image, as if I would add a stroke around the opaque part. How to do that?
More context
I have an image (a CGImageRef) like that:
It has been created by
mask = CGBitmapContextCreateImage(context);
I'm using it as a mask. The UIView under the mask is the same text. The problem is that the text underneath is not completed covered by the mask. See:
More code
This code is in a UILabel subclass.
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
// Draw text normally
[super drawTextInRect:rect];
if (self.alternativeTextColor) {
CGImageRef mask = NULL;
// Create a mask from the text
mask = CGBitmapContextCreateImage(context);
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0, self.frame.size.height);
CGContextScaleCTM(context, 1.0, (CGFloat) -1.0);
// Clip the current context to our mask
CGContextClipToMask(context, rect, mask);
// Set fill color
CGContextSetFillColorWithColor(context, [self.alternativeTextColor CGColor]);
// Path from mask
CGPathRef path;
if (CGRectIsEmpty(self.maskFrame)) {
path = CGPathCreateMutable();
} else {
UIBezierPath *roundRectBezierPath = [UIBezierPath bezierPathWithRoundedRect:self.maskFrame
cornerRadius:self.maskCornerRadius];
path = CGPathCreateCopy([roundRectBezierPath CGPath]);
}
CGContextAddPath(context, path);
// Fill the path
CGContextFillPath(context);
CFRelease(path);
// Clean up
CGContextRestoreGState(context);
CGImageRelease(mask);
}
}
Link to the project
https://github.com/colasjojo/Test-NYSegmentedControl
If you are trying to clip to text, I'd suggest not doing it via an intermediate bitmap and instead clipping to the paths of the actual text as in the snippet below from SVGgh's GHText class:
CGContextSaveGState(quartzContext);
CGContextSetTextDrawingMode(quartzContext, kCGTextStrokeClip);
CGContextSetLineWidth(quartzContext, strokeWidthToUse);
... Draw Text here ....
CGContextReplacePathWithStrokedPath(quartzContext);
CGContextClip(quartzContext);
... Do clipped drawing here ...
CGContextSetTextDrawingMode(quartzContext, kCGTextFill);
CGContextRestoreGState(quartzContext);
This isn't answering your question, but it's probably what you should do instead. Play around with CGContextSetTextDrawingMode to get the effect you are going for.

Fill image with color by mask

I have an origin vehicle image and what I need to implement is fill this with different colors:
http://image.openlan.ru/images/25842748100117640420.png
I've tried to reach it using code below:
- (UIImage *) coloredImageWithColor:(UIColor *)color
{
UIGraphicsBeginImageContext(self.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, self.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetBlendMode(context, kCGBlendModeDarken);
CGRect rect = (CGRect){ CGPointZero, self.size };
CGContextDrawImage(context, rect, self.CGImage);
CGContextClipToMask(context, rect, self.CGImage);
[color set];
CGContextFillRect(context, rect);
// wheel
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:(CGRect){ 700, 200, 200, 200 }];
CGContextSetBlendMode(context, kCGBlendModeClear);
[path fill];
UIImage *coloredImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return coloredImage;
}
And of course it's not what I expected:
http://image.openlan.ru/images/05312201634158625573.png
Currently I've encountered with two problems. First of all I'd like to figure out how to reveal filled background in some area like wheels, as instance. And the second one is how to create the most similar colored vehicle images.
Your going to want to do most of this in Photoshop. You need a base image that is transparent in the places that you want to show through. Then you want to create a mask image that shows where you want color (using alpha to indicate how much tint to use). Then you'll mask the image and draw it on your background.
I assume a PhotoShop file with a layer mask was used to create the tinted vehicles in your initial example. You'll want those two layers (the base layer and the mask) as separate PNG files. Whoever created the original Photoshop file should be able to provide those.
Trying to do this programmatically from a single, flat image is unlikely to give you the kind of results you'd want.

Tint an Image (there must be a simpler way)

I have looked at the various ways people are using to tint an image (I want to apply a red layer) and the only one I have go to work is ridiculously elaborate. Is there a simpler way?
// 1. Tint the Image
NSString *name = #"Skyline.png";
UIImage *imgBottomCrop = [UIImage imageNamed:name];
// begin a new image context, to draw our colored image onto
UIGraphicsBeginImageContext(imgBottomCrop.size);
// get a reference to that context we created
CGContextRef context = UIGraphicsGetCurrentContext();
// set the fill color
[[UIColor redColor] setFill];
// translate/flip the graphics context (for transforming from CG* coords to UI* coords
CGContextTranslateCTM(context, 0, imgBottomCrop.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
// set the blend mode to color burn, and the original image
CGContextSetBlendMode(context, kCGBlendModeColorBurn);
CGRect rectBottomCrop = CGRectMake(0, 0, img.size.width, img.size.height);
CGContextDrawImage(context, rectBottomCrop, imgBottomCrop.CGImage);
// set a mask that matches the shape of the image, then draw (color burn) a colored rectangle
CGContextClipToMask(context, rectBottomCrop, imgBottomCrop.CGImage);
CGContextAddRect(context, rectBottomCrop);
CGContextDrawPath(context,kCGPathFill);
// generate a new UIImage from the graphics context we drew onto
UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Display Image
displayPicture2.image = coloredImg;
If the image is static (doesn't change while the application is running) the easiest way would be to have another image stored and just load it.
If it's not static - You're doing it correctly. Another way i can think of is just having a half-transparent red image stored and displaying it over Your image.

Create image on top of another uiimage

I am not able to draw image on top of another image. Below if the code I am using:
-(void)createImage
{
// create a new bitmap image context at the device resolution (retina/non-retina)
UIGraphicsBeginImageContextWithOptions(imgVw_noHair_.frame.size, YES, 0.0);
// get context
CGContextRef context = UIGraphicsGetCurrentContext();
// push context to make it current
// (need to do this manually because we are not drawing in a UIView)
UIGraphicsPushContext(context);
// drawing code comes here- look at CGContext reference
// for available operations
// this example draws the inputImage into the context
[eraser drawAtPoint:CGPointMake(50, 50)];
// pop context
UIGraphicsPopContext();
UIImage _image_ = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
The image which I get from the current context is a black image. I want to draw eraser image on the image which I get from the context.
This is updated code which is working in my side.
-(void)createImage
{
//Create context in which you have to draw
UIGraphicsBeginImageContextWithOptions(imgvwImage.image.size, YES, 0.0);
// get context
CGContextRef context = UIGraphicsGetCurrentContext();
// push context to make it current
// (need to do this manually because we are not drawing in a UIView)
UIGraphicsPushContext(context);
//draw the old image in that context
[imgvwImage.image drawInRect:CGRectMake(0, 0, 200, 200)];
UIImage *img=[UIImage imageNamed:#"img.png"];
//Draw your image in that context
[img drawAtPoint:CGPointMake(50, 50)];
// pop context
UIGraphicsPopContext();
UIImage *image_ = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//Get that image
imgvwImage.image=image_;
}
try to draw your eraser image in rect instead of AtPoint
[eraser drawInRect:CGRectMake(50, 50, width, height)];
You forgot to draw the bottom image into the context, hence you are drawing your eraser image on top of an uninitialized (black) background. You need to add some code to first draw your desired background image.

Color tinted UIImages gets pixelated

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.

Resources