MKOverlayView draw something with blend mode - ios

I want to draw map overlay with blend mode. But this code just draw white overlay without any blend mode. What I'm doing wrong?
- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
{
UIGraphicsPushContext(context);
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextSetBlendMode(context, kCGBlendModeSaturation);
CGContextFillRect(context, [self rectForMapRect:mapRect]);
UIGraphicsPopContext();
}
Here is result that I want. I make it in Photoshop with three layers:
original google map.
black layer with saturation blend mode.
white layer with exclusion blend mode.

I would recommend to design your own maps with openstreetmap and a wms server or with a service like mapbox and than add this custom map as overlay.
Here is an example on how to add other maps as overlays: https://github.com/mtigas/iOS-MapLayerDemo

I guess you cannot acces the real mapview context directly. So probably you have to take a "screenshot" of the map and draw it again in your context. After that you can apply your effects of course.

Related

How to draw a sequence of lines with different opacities without blending overlaps but blending with the background?

I am trying to add basic pressure sensitivity to a drawing app.
I am running into an issue when I try to draw strokes, where the opacity depends on the pressure - the point of overlap of the line segments blends the two lines, which creates darker spots:
This is my code:
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, path.thickness);
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
for (Segment *segment in segments) {
CGContextMoveToPoint(context, segment.start.x, segment.start.y);
CGContextAddLineToPoint(context, segment.end.x, segment.end.y);
CGContextSetAlpha(context, segment.alpha);
CGContextStrokePath(context);
}
I want avoid the circles where the line caps meet, but still be able to have transparency over the background.
I have experimented with the context blend modes, but nothing is completely satisfactory - kCGBlendModeDestinationAtop gave me smooth lines, but there is an artifact at the very end of the line and I lose blending with the background.
The banding is not an issue.
In case anyone has the same problem, the way I solved it was to draw the line segments into CGLayer (Core Graphics layer - not Core Animation layer and not Core Graphics Transparency layer).
I set the CGLayer context blend mode to DestinationAtop and then rendered the CGLayer in my real CGContext with normal blending.
Worked like a charm.

Fill color on specific portion of image?

I want to fill specific color on specific area of an image.
EX:
In above Joker image, If touch on hair of Joker then fill specific color on hair Or touch on nose then fill specific color on nose.. etc. I hope may you understand what I am trying to say.
After googling it's may be achieve by use of UIBezierPath or CGContext Reference but I am very new for it, I tried to read this documentation but I do not understand (take more time) anything also I have limit of time for this Project. So I can not spend more time on it.
Also I found that we can use Flood fill algorithm. But I don't know how to use in my case.
NOTE: I don't want to divide original image (such like hair. nose, cap,...etc) because If I will do then there will be so many images in bundle so I need to handle it for both normal and retina device so this option is not helpful for me.
So please give me your valuable suggestion and also tell me which is best for me UIBezierPath or CGContext Reference? How can I fill color on specific portion of image? and/or can we fill color under the black border of area ? Because I am new at Quartz 2D Programming.
Use the Github library below. The post uses the flood fill algorithm : UIImageScanlineFloodfill
Objective C description : ObjFloodFill
If you want to look at detailed explanation of the algorithm : Recursion Explained with the Flood Fill Algorithm (and Zombies and Cats)
few of the other tutorials in other languages : Lode's Computer Graphics Tutorial : Flood Fill
Rather than attempting to flood fill an area of a raster-based image, a better approach (and much smaller amount of data) would be to create vector images. Once you have a vector image, you can stroke the outline to draw it uncolored, or you can fill the outline to draw it colored.
I recommend using CoreGraphics calls like CGContextStrokePath() and CGContextFillPath() to do the drawing. This will likely look better than using the flood fill because you will get nicely anti-aliased edges.
Apple has some good documentation on how to draw with Quartz 2D. Particularly the section on Paths is useful to what you're trying to do.
You can Clip the context based on image Alpha transparency
I have created a quick image with black color and alpha
Then using the below Code
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext(); // Get the context
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor); // Set the fill color to be blue
// Flip the context so that the image is not flipped
CGContextTranslateCTM(context, 0, rect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
// Clip the context by a mask created from the image
UIImage *image = [UIImage imageNamed:#"image.png"];
CGImageRef cgImage = image.CGImage;
CGContextClipToMask(context, rect, cgImage);
// Finally fill the context with the color and mask you set earlier
CGContextFillRect(context, rect);
}
The result
This is a quick hint of what you can do. However you need now to convert your image to add alpha transparent to the parts you need to remove
After a quick search I found these links
How can I change the color 'white' from a UIImage to transparent
How to make one colour transparent in UIImage
If You create your image as SVG vector base image, it will be very light (less than png, jpg) and really easy to manage via Quartz 2D using bezier paths. Bezier paths can be filled (white at starting). UIBezierPath have a method (containsPoint:) that help define if you click inside.

iOS using blend modes with cgcontext

I'm using CGContextSetBlendMode to try color blend a gradient (stored in gradient) with several shapes (black with some transparency). I attached an image with the result. It's easy to see what is going wrong. Somehow artifacts show up.
what I try to do seems to work partially, but I'm not sure if my approach is correct. I first draw the shapes, then set the blend mode of the context and then draw my gradient.
Also weird is that when I for example use kCGBlendModeColorBurn instead of kCGBlendModeColor the artifacts don't show up. I'm also not drawing anything else in the layer.
I can't really get a hold on how the blend modes work. I can't find any good documentation.
CGRect rectangle = CGRectMake(60,170,200,200);
CGContextAddEllipseInRect(context, rectangle);
CGContextFillPath(context);
CGRect rectangle2 = CGRectMake(40,120,100,100);
CGContextAddEllipseInRect(context, rectangle2);
CGContextFillPath(context);
CGContextSetBlendMode( context, kCGBlendModeColor);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);

OpenGL ES 1.1 clearColor drawing

How can I draw with [UIColor clearColor] in OpenGL ES 1.1? I want to create eraser tool...
You can create a masked image. There are many ways to do this and here is what worked for me:
I created an image that has a black circle and all the rest is transparent. I create a texture from this image and draw it as a simple textured square but using this blend func:
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
Do not forget to enable blend and after the draw call is done restore your blend func (or disable the blend if you don't use it anywhere else)

How to draw a stroke outline using CGContext API?

I have an icon image I would like to draw a 1px, colored 0.5 opacity line around, inside the image (similar to Stroke layer style with position:inside in Photoshop). So far I've tried this:
UIGraphicsBeginImageContextWithOptions(inCompositeSize, NO, inBaseImage.scale);
context = UIGraphicsGetCurrentContext();
CGContextDrawImage(context, frame, image.CGImage);
CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
CGContextSetStrokeColorSpace(context, cs);
CGColorSpaceRelease(cs);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextStrokePath(context);
//...
This seems to have no effect. I'm guessing this is because I'm working with an image and not a path. How can I produce an outline stroke effect on the image?
Clarification: I'm trying to draw an outline on the opaque icon area only. The icon background is 0 alpha.
StrokePath strokes a path, and you haven't plotted a path. That's why it strokes nothing.
You need to do either of two things:
Vectorize the raster image and stroke that path. Core Image's edge-detection filter will help, but even so, this is hard. There is no built-in API for this; you'll have to find a library that does it or do it yourself.
Fake it by drawing the image with a shadow. Note that shadows can be any color; it doesn't have to look like a shadow.

Resources