Rounding corner causes top edge to blur - ios

I have a UIButton subclass that I am rounding the corners of. Using either the usual cornerRadius property on its layer, or creating a rounded mask and applying that to the layer, I always get the effect shown in the image below (blown up so you can see it clearly). The top pixel is slightly transparent, making the edge look soft. If I remove the rounded corners, the edge goes back to solid (like the bottom edge in the image), so I know it's not just trying to draw the view between pixels.
Any ideas?

Be sure that the frame and the mask are fully composed of integers not floats, in case use floor or ceil to get the closest integer rounding by low or top.
With frames CGRectIntegral is very helpful. Floats values automatically create a sort of antialiasing while rendering on screen.

What you see is anti-aliasing (on by default) to make the edges look smooth. This is the only way to make rounded corners look smooth and not stair stepped. If you want rough edges, set the allowsEdgeAntialiasing and edgeAntialiasingMask

Related

UIBezierPath combine shapes

This is not asking the same question as How can I combine UIBezierPath drawings? even though the name is similar
I have a shape that needs to be able to scale vertically and on one side of it are rounded corners and the other side is some other path. I have drawn the following image to show what I am talking about, but this is not the exact shape I am making, but conceptually it is the same idea.
In this image, the left side is half of a rounded rectangle and the right side is half of a circle.
So I am wanting to take and essentially cut a rounded rectangle in half and basically "merge" it with another path. How can I do this?
I guess one way would be to have two layers: the top layer contains the shape on the right and the bottom layer contains the rounded rectangle, and the top layer occludes half of the rectangle. But I was hoping to not have to use two different layers, and instead be able to put all of this in one layer, so I was wondering if it was possible to merge the shapes like I mentioned.

Keeping Squares Along A Circle's Circumference

I'm drawing squares along a circular path for an iOS application. However, at certain points along the circle, the squares start to go out of the circle's circumference. How do I make sure that the squares stay inside?
Here's an illustration I made. The green squares represent the positions I need the squares to actually be in. The red squares are where they actually appear given the following values for each square's upper-left corner:
x = origin.x + radius * cos(DEGREES_TO_RADIANS(angle));
y = origin.y + radius * sin(DEGREES_TO_RADIANS(angle));
Origin refers to the center of the circle. I have a loop that repeats this for every angle from 1 till 360 degrees.
EDIT: I've changed my design to position the centers of the squares along the circular path rather than their upper left corners.
why not just draw the centers of the squares along a smaller circle inside of the bigger one?
You could do the math to figure out exactly what the radius would have to be to ensure an exact fit, but you could probably trial and error your way there quickly too.
Doing it this way ensures that your objects would end up laid out in an actual circle too, which is not the case if you were merely making sure that one and only one corner of each square touched the larger bounding circle (that would create a slightly octagonal shape instead of a circle)
ryan cumley's answer made me realize how dumb I was all along. I just needed to change each square's anchor point to its center & that solved it. Now every calculated value for x & y would position every square's center exactly on the circular path.
Option 1) You could always find the diameter of the circle and then using Pythagorean Theorem, you could create a square that would fit perfectly within the circle. You could then loop through the square that was just made in the circle to create smaller squares, but I doubt this is what you are aiming for.
Option2) Find out what half of the length of one of the diagonals of the squares should be, and create a ring within the first ring. Then lay down squares at key points (like ever 30 degrees or 15 degrees, etc) along the inner path. Ex: http://i.imgur.com/1XYhoQ0.png
As you can see, the smaller (inner) circle is in the center of each green square, and that ensures that the corners of each square just touches the larger (outer) circle. Obviously my cheaply made picture in paint is not perfect, but mathematically it will work.

why resizableImageWithCapInsets's best performance is tiled by 1x1 rather than block by block

UIImage resizableImageWithCapInsets official document description are below.
During scaling or resizing of the image, areas covered by a cap are not scaled or resized. Instead, the pixel area not covered by the cap in each direction is tiled, left-to-right and top-to-bottom, to resize the image. This technique is often used to create variable-width buttons, which retain the same rounded corners but whose center region grows or shrinks as needed. For best performance, use a tiled area that is a 1x1 pixel area in size.
I don't understand why use 1x1 pixel tiled area is the best performance. I think tiled block by block, the performance is better than 1x1 area. In theory, block by block is fast than point by point, is that right? who can told me the implementation of this in machine?
#jhabbott makes a good guess in his comment on the accepted answer to the question How does UIEdgeInsetsMake work?
So, I think if the tiled area is just 1x1 pixel. Then, resizableImageWithCapInsets: can just use that pixel's color as the fill color. That way, it doesn't have to do any tiling at all. So, essentially, it's like setting view.backgroundColor = color. Have you ever written any drawing code? Basically, I think filling an area with a color is easier than tiling that area with a rectangle of pixels, since the latter probably takes more calculations, like where to position the next tile, etc. But, I'm just guessing here. But, if you try to write the drawing code to fill a rect with a color vs to tile a rect of pixels onto another rect, you'll see where I'm coming from.

How to animate arc/donut segment stroke and length change

I need to animate arcs (a.k.a donut segments) in the following scenarios where the arc maintains a constant radius r to the imaginary circle center (the arc sits right outside the circle).
1) Animate the arc stroke width from x to y, while maintaining a radius r and angle alpha.
2) Animate the arc angle from alpha to beta while maintaining a constant stroke width and radius.
3) do 1 and 2 together but possibly with independent animations/timings.
Here's what I have so far:
I’ve implemented the arc drawing as a custom view that simply draws the arc with CGContextAddArc. This is fine for a static arc but it doesn’t animate anything.
Also, I know how to draw clipped images with things like [UIBezierPath addClip].
The latter is interesting because I think that for scenario 1, I can achieve the desired effect in two ways: either keep drawing an arc and modify both stroke and radius to maintain the same perceived inner circle radius (which I’m not optimistic about, I’m afraid that the radius will “jiggle”), or draw a segment of a circle that grows in size (maybe by simply modifying the scale with an affine transform) and is then clipped by a static circular mask.
Now, how do I take all these concepts and nail them down into some actual drawing code? I don’t need real code (though that would be fine too), but more like a conceptual approach, like, can I do this all with a UIView with custom drawing, or do we need to talk about custom key animations that I understand involve CALayers and such. In other words, what’s the right architecture to do all this that would be easiest to code while being efficient from a compositing perspective for smooth animation?
You can already do this with a CAShapeLayer by creating the path for the arc and then animate different stroke properties. You could create the path for the full circle and use the strokeStart and strokeEnd properties to only stroke a certain part of the circle. It is worth noting that the shape layer is center stroked so they increase equally inwards and outwards as you increase the line width. To counter this you could either mask it with the same circle shape and double the line width or animate the path so that the radius increases by half of the line width increase so that the inner most point has the same distance to the center at all times.
The first example can be done by animating the lineWidth property and the second can be done by animating the strokeStart and strokeEnd properties
You should implement this using custom animatable properties on a CALayer subclass. This tutorial (with source here) is for creating animated pie charts and looks pretty good. You should be able to modify it for your requirements.

what is the relationship between image edges and gradient?

Is there anybody can help me interpret
"Edge points may be located by the maxima of the
module of the gradient, and the direction of edge contour is orthogonal to the direction of the gradient."
Paul R has given you an answer, so I'll just add some images to help make the point.
In image processing, when we refer to a "gradient" we usually mean the change in brightness over a series of pixels. You can create gradient images using software such as GIMP or Photoshop.
Here's an example of a linear gradient from black (left) to white (right):
The gradient is "linear" meaning that the change in intensity is directly proportional to the distance between pixels. This particular gradient is smooth, and we wouldn't say there is an "edge" in this image.
If we plot the brightness of the gradient vs. X-position (left to right), we get a plot that looks like this:
Here's an example of an object on a background. The edges are a bit fuzzy, but this is common in images of real objects. The pixel brightness does not change from black to white from one pixel to the next: there is a gradient that includes shades of gray. This is not obvious since you typically have to zoom into a photo to see the fuzzy edge.
In image processing we can find those edges by looking at sharp transitions (sharp gradients) from one brightness to another. If we zoom into the upper left corner of that box, we can see that there is a transition from white to black over just a few pixels. This transition is a gradient, too. The difference is that the gradient is located between two regions of constant color: white on the left, black on the right.
The red arrow shows the direction of the gradient from background to foreground: pixels are light on the left, and as we move in the +x direction the pixels become darker. If we plot the brightness sampled along the arrow, we'll get something like the following plot, with red squares representing the brightness for a specific pixel. The change isn't linear, but instead will look like one side of a bell curve:
The blue line segment is a rough approximation of the slope of the curve at its steepest. The "true" edge point is the point at which slope is steepest along the gradient corresponding to the edge of an object.
Gradient magnitude and direction can be calculated using horizontal and vertical Sobel filters. You can then calculate the direction of the gradient as:
gradientAngle = arctan(gradientY / gradientX)
The gradient will be steepest when it is perpendicular to the edge of the object.
If you look at some black and white images of real scenes, you can zoom in, look at individual pixel values, and develop a good sense of how these principles apply.
Object edges typically result in a step change in intensity. So if you take the derivative of intensity it will have a large (positive or negative) value at edges and a smaller value elsewhere. If you can identify the direction of steepest gradient then this will be at right angles to (orthogonal to) the object edge.

Resources