iOS- How to paint in the within limits - ios

I used the scanning line seed filling algorithm to realize the color filling function.
But I don't know how to do that. When my pen lands in the flower, I need to draw only Inside the black edge of the flower,do not draw in the hair.
I have tried to use :
CALayer *layer = [CALayer layer];
layer.contents = (__bridge id)(image.CGImage);
self.drawView.layer.mask = layer;
But the plan didn't work.
if any one gives solution it would be so great,Thank you.
(English is not my native language; please excuse typing errors.)

Use a two pass approach.
Use the same algorithm as the fill algorithm to create a stencil mask which fills the area you want to allow the pen to draw.
Draw the pen with stencil testing to constrain it to the allowed region.
Similar approach could be used to create an alpha-mask on the fly (e.g. as a texture), and mix that with the pen drawing.

Related

Masking performance

I'm creating an animation that uncovers the underlying image. There's a virtual shape (e.g. star) moving chaotically and uncovering different parts of the image.
So I had two bitmaps so far:
mask (trace of a shape moving here'n'there)
image (underlying image)
So far in every drawRect() I was:
creating a newMask bitmap by copying the current mask
drawing a stamp on a newMask
creating a resulting bitmap (apply newMask onto an image)
drawing a resulting bitmap to screen context
I'm struggling with performance in this approach. Any ideas how to improve it?
In particular:
Is it possible to skip step 1. & 2. and draw onto mask directly (rather than clone it).
Should I start experimenting with CALayer approach (if this kind of masking is at all possible there)
Should I use OpenGL
Is there any other approach to tackle this?
No, you should not manipulate bitmaps. That is likely to be very CPU-intensive as well as jerky (not smooth animation.)
Instead you should use a CAShapeLayer as a mask and Core Animation.
With a shape layer you can install a path (a CGPath, which can be created easily from a UIBezierPath) into the layer. Then you create a CABasicAnimation that switches the path to a new path. The trick is to always keep the same number and type of control points in the starting and ending paths of the animation. (If the number and/or type of control points in the two paths are different you get very, very strange results. Note that the path calls that create arcs of circles actually generate different numbers of control points based on how much of a circle your arc covers, so circle arcs require special handling.)
I have a sample project on Github that demonstrates various Core Animation techniques, including a demonstration of a "clock wipe" animation that reveals/hides and image view much like you describe.
https://github.com/DuncanMC/iOS-CAAnimation-group-demo
The animation looks like this:
Note that the jerky nature of that image is because it's a GIF. The actual animation on a device is buttery-smooth. It's also possible to create very complex smooth animations like this one:
(That isn't a mask animation but it could be.)

Set blendmodes on UIImageViews like Photoshop

I've been trying to apply blend modes to my UIImageViews to replicate a PSD mock up file (sorry can't provide). The PSD file has 3 layers, a base color with 60% normal blend, an image layer with 55% multiply blend and a gradient layer with 35% overlay.
I've been trying several tutorials over the internet but still could not get the colors/image to be exactly the same.
One thing I noticed is that the color of my iPhone is different from my Mac's screen.
I found the documentation for Quartz 2D which I think is the right way to go, but I could not get any sample/tutorial about Using Blend Modes with Images.
https://developer.apple.com/library/mac/documentation/graphicsimaging/conceptual/drawingwithquartz2d/dq_images/dq_images.html#//apple_ref/doc/uid/TP30001066-CH212-CJBIJEFG
Can anyone provide a good tutorial that does the same as the one in the documentation so I could atleast try to mix things up should nobody provide me a straight forward answer to my question.
This question was asked ages ago, but if someone is looking for the same anwser, you can user compositingFilter on the backing layer of your view to get what you want:
overlayView.layer.compositingFilter = "multiplyBlendMode"
Suggested by #SeanA, here: https://stackoverflow.com/a/46676507/1147286
Filters
Complete list of filters is here
Or you can print out the compositing filter types with
print("Filters:\n",CIFilter.filterNames(inCategory: kCICategoryCompositeOperation))
Now built-in to iOS. Historic answer:
You don't want to use UIImageView for this since it doesn't really support blend modes.
Instead, the way to go would be to create a UIView subclass (which will act just like UIImageView). So make a UIView subclass called something like BlendedImageView. It should have an image property, and then in the drawRect: method you can do this:
- (void)drawRect:(CGRect)rect
{
//
// Here you need to calculate a rect based on self.contentMode to replicate UIImageView-behaviour.
// For example, for UIViewContentModeCenter, you want a rect that goes outside 'rect' and centers with it.
//
CGRect actualRect = // ...
[self.image drawInRect:actualRect blendMode:kCGBlendModeOverlay alpha:0.5];
}
Replace alpha and blend mode to fit your preference. Good practice would be to let your BlendedImageView save a blendMode property.
It may be that in your case, you need to do a bit more advanced view that draws all 3 of your images, using the same code as above.

Can a CAShapeLayer be passed to CGContextDrawLayerAtPoint?

I've got a CAShapeLayer and was trying to draw it by passing it to CGContextDrawLayerAtPoint but get an error about passing a retainable parameter of CAShapeLayer *__strong to a function expecting a CGLayerRef.
I've done some browsing but can't figure out how to convert it/bridge the CAShapeLayer to the CGLayerRef.
If its not possible to convert, then can a CAShapeLayer be created using CGLayerCreateWithContext?
What I'm doing is creating a drawing with a UIBezierPath, then creating a CAShapeLayer and setting its path to the UIBezierPath then I want to display it. I could use addSublayer to display the shape layer however I'm going to display the same shape at multiple different points so rather than add multiple sublayers I was planning on using CGContextDrawLayerAtPoint to display it at different points.
Short answer: no.
Long answer: CAShapeLayer is a Core Animation layer (CALayer). You put it into your interface and it draws itself.
I know it's confusing, the way they use the word "layer", but CGContextDrawLayerAtPoint has nothing to do with that (it's using the word "layer" in a totally different way, referring to a CGLayer, which is completely different and is used utterly differently). You've gone down the wrong rabbit hole here.
I could use addSublayer: to display the shape layer
Not could. Must. That is what you do with a CAShapeLayer.
The alternative you are looking for would be to pull the CGPath out of the CAShapeLayer and assign that path and stroke it, multiple times in multiple places, in a CGContext. But there is really no need to do that. iOS drawing is all about layers; don't be afraid of having multiple sublayers.

How to paint using brush with particular area...

I want to fill each and every part with different colours like circle with other colour and each leave with different colour and stick with different colours. I have bunch of colours. You can fidn similar apps like Toonia Color book on apple app store...
I am unable to get bounds of particular part in image.
I searched a whole day before writing this question. Every one is saying just look for flood fill and Quick Fill algorithms but i am not able to solve this problem.
In Toonia Colorbook this is done using vector graphics and masks. Every shape is described as a bezier curve that masks a drawing layer.
check out CAShapeLayer and CALayer for further details

drawRect: How do I do an "inverted clip"

I am creating an iOS user interface to allow a user to pick a rectangle within an existing image, dragging the corners of that rectangle to the desired size. I now have four custom UIButtons (30% alpha) and a custom view (also with 30% alpha) that draws the dashed lines between the four corner buttons.
To "improve" the interface, I would like my drawRect code to make the cropped portion of the image appear "normal" while everything outside the cropped region is washed out (filled with white color, which will give me the correct effect since the UIView is set to 30% alpha).
The obvious algorithm would be:
Fill the entire image with [UIColor whiteColor] fill
Draw the four dashed lines with a [UIColor clearColor] fill
When I do this, the clear fill isn't showing up. I believe this is because the "fill" of the clear color in step #2 isn't being seen because the pixels were already set to white in step #1. Perhaps there's a blend mode that will allow me to see the transparency of the second rectangle? I'm not sure about the various blend modes.
My second attempt, which works, does the following:
Draw the four dashed lines with [UIColor clearColor] fill
Draw four additional rectangles with [UIColor whiteColor] fill, each representing the portions to the left, right, above, and below the cropped region.
As I mention, this method works, but seems to me there should be a simpler way instead of me having to calculate these four additional rectangles each and every time.
There is a similar question on SO Create layer mask with custom-shaped hole that uses CALayer and masks, but this seems to be overkill for what I need.
Does anybody have any suggestions on how to improve this?
You can set the blend mode to kCGBlendModeCopy and use clearColor to reset a pixel's alpha to zero. You can presumably also use kCGBlendModeClear but I haven't tested that.
You can also set the clipping path to just contain the pixels you want cleared and call CGContextClearRect(gc, CGRectInfinite).
If you want to use a clipping mask with a hole in it, you can do so without using a CALayer, and you can build it a little more simply than in the answer you linked, by using the even-odd rule and CGRectInfinite:
CGContextSaveGState(GC); {
CGContextBeginPath(gc);
CGContextAddRect(gc, myRect); // or whatever simple path you want here
CGContextAddRect(gc, CGRectInfinite);
CGContextEOClip(gc);
// drawing code here is clipped to the exterior of myRect
} CGContextRestoreGState(gc);

Resources