iPhone: CALayer + rotate in 3D + antialias? - iphone

An iPhone SDK question: I'm drawing a UIImageView on the screen. I've rotated it in 3D and provided a bit of perspective, so the image looks like it's pointing into the screen at an angle. That all works fine. Now the problem is the edges of the resulting picture don't seem to be antialiased at all. Anybody know how to make it so?
Essentially, I'm implementing my own version of CoverFlow (yeah yeah, design patent blah blah) using quartz 3d transformations to do everything. It works fine, except that each cover isn't antialiased, and Apples version is.
I've tried messing around with the edgeAntialisingMask of the CALayer, but that didn't help - the defaults are that every edge should be antialiased...
thanks!

If you rotate only one image, than one trick will resolve the problem. Try to set
layer.shadowOpacity = 0.01;
After that picture will look smoother after 3D Rotation

The Gloomcore answer give a really neat result.
however this sometime make things really LAGGY !
Adding rasterization help a little bit:
.layer.shadowOpacity = 0.01;
.layer.shouldRasterize = YES;
I know the question/answer is old, but hey i just found it.

You could try adding some transparent pixels around the edge of the image, either by putting the UIImageView in a slightly larger empty view that you apply rotation to, or by changing the source images.

I had a similar issue that was solved by only setting shouldRasterize = YES, however because I was re-using my views (and layers), the shouldRasterize = YES killed the performance.
Fortunately I found a solution by turning shouldRasterize = NO at the right time to restore performance in my app's case.
I posted a solution here: Antialiasing edges of UIView after transformation using CALayer's transform

You can try this
Method: Using layer.shouldRasterize
Create a superlayer/superview which is 1 pixel bigger in all 4 directions
Do the transform on the superlayer/superview
Enable layer.shouldRasterize on the original layer/view
Method: Drawing to a UIImage
Draw your content to a UIImage
Make sure that you have a transparent border of 1 pixel around the content
Display the image
Reference: http://darknoon.com/2012/05/18/the-transparent-border-trick/

Related

image coming blurred and screwed after applying rotation on image view

I am stuck with a strange problem that,
I have a image view which has to shown at some angle approx 5 degree.For that I rotate my UIImageView to 5 degree but the image in UIImageView not coming proper as it was before transformation.
For more understanding see images
You can see the second image is looking like clipped from corners and looks some blur also.
My code for rotation:-
myimageView.transform = CGAffineTransformMakeRotation(radians(5));
Please suggest me how to solve this problem.
Thanks in advance.
Looks like there are several solutions located in this similar SO Q&A:
Any quick and dirty anti-aliasing techniques for a rotated UIImageView?
If it is, in fact, just the edges that are jagged, try adding a 1px transparent border around in image content (this is a suggestion in the above link).
Have you tried using CGContextRotateCTM(context, radians); and [sourceImage drawInRect:rect];?

How to rotate a UIImageView

I have a UIImageView that is an image of the star. The problem is I want the star to rotate when I move it. How can I rotate a UIImageView to make it look like it is spinning for 3 seconds. I want it to spin 720 degrees.
For a very simple approach, you can use
imageView.transform = CGAffineTransformMakeRotation(radianRotation);
where radianRotation is a float, e.g. 4*pi for 720 degrees. You can play with basic animations and changing the rotation however you like.
However, if you want a more sophisticated solution, then I highly recommend you look at the answers to this related post: how to rotate UIIMageVIew with fix point?
Also, see the myriad related posts linked on the right hand side of your screen. Many have all the code you need (barring going around in a circle twice).
You can also use
[imageView layer].transform = CATransform3DMakeRotation(variables);
For your commodity, additionally to PengOne's answer you can use M_PI, M_PI_2, M_PI_4 constants that are available in math.h.

The antialias of rotated CGImage/CGlayer seems jaggy, UIImageView's is not

I need to mask a "texture" image with a rotated greyscale image.
I found out, that I have to do it with CGImages or CGlayers (if there is a simplier way using UIImageViews only, please let me know about it).
My problem is simple:
The antialias of any
rotation-transformed CG stuff is quiet
jaggy...
... but the antialias of a rotation-transformed UIImageView is kinda perfect. How can I produce that beautiful antialiased rotations?
I've uploaded a "proof" involving actual iPhone Simulator screenshots, to see what am I talkin' about: http://gotoandplay.freeblog.hu/files/Proof.png
I've tried to use CGImages, CGLayers, UIImageViews "captured" with renderInContext, I've tried to CGContextSetInterpolationQuality to high, and also tried to set CGContextSetAllowsAntialiasing - CGContextSetShouldAntialias, but every case returned the same jaggy result.
I'm planning to learn using OpenGL next year, but this development should released using CoreGraphics only. Please let me know how to get a perfectly rendered rotated image, I just can't accept it's impossible.
To add 1px transparent border to your image use this
CGRect imageRect = CGRectMake(0, 0, image.size.width, image.size.height);
UIGraphicsBeginImageContext( imageRect.size );
[image drawInRect:CGRectMake(1,1,image.size.width-2,image.size.height-2)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Have you tried adding a clear, 1 pixel border around your image? I've heard of that recommended as a trick to avoid aliasing, by giving CoreGraphics some room to work with when blending the edges.
I am having a similar problem, looks like I'm going to move it over to OpenGL ES as well. I can't nail down an effective solution that doesn't hurt performance.
For reference of future CoreGraphics explorers, putting a 1-pixel transparent border did make for a noticeable improvement in my experiments, but it appears that as Eonil mentioned, you end up with multiple stages of antialiasing/smoothing/interpolation working against each other. IE: CGLayer does some interpolation for it's rotation, then context it's being drawn to will do some interpolation/antialiasing, so on so forth until it ends up looking pretty rough.
I actually ended up with better results by disabling interpolation and antialiasing on the destination context, though it was still obviously jaggy (less artifacts overall though). I was able to achieve the best overall appearance by enabling interpolation and antialiasing when constructing the CGLayer, and disabling it for the destination context when re-drawing it. This approach, obviously, is fraught with other problems.

How to create image slideshow effect

I m trying to do slideshow effect in iPhone as like in iTunes. One Image at the middle and the others at the left and ride side arranged in the manner of floppies in rack. but I not even a single clue for that. Can any one help me out?
I'm guessing that you're talking about "coverflow" rather than "slideshow"... if that's right, there are some libraries to help you: here's one I found by searching for "coverflow replacement":
http://apparentlogic.com/openflow/
You can achieve this effect using the .transform property of CALayers. All iPhone UIViews have a CALayer, and you can apply 3D perspective transformations using a transform matrix like this:
CATransform3D m = CATransform3DIdentity;
m.m34 = -0.006;
[[containerView layer] setSublayerTransform: m];
The views within containerView will now have a perspective distortion applied! Instant coverflow affect. Just move the views to the left and right by changing their frames.

UIImageView scaling/interpolation

I have a small IPhone app that I am working on and I am displaying an image with a UIImageView. I am scaling it up using the Aspect Fit mode. I would like to have the image scale up with no interpolation/smoothing (I want it to look pixellated). Is there any way I can change this behavior?
A little more general question would be can I implement my own scaling algorithm, or are there other built in ones that I can select?
You would need to set the magnificationFilter property on the view's layer to the nearest neighbour filter:
[[view layer] setMagnificationFilter:kCAFilterNearest]
Make sure you include the line
#import <QuartzCore/CALayer.h>
At the top of the file containing the call to setMagnificationFilter or it won't compile.
Swift
imageView.layer.magnificationFilter = kCAFilterNearest
imageView.layer.shouldRasterize = true
There are two ways you could do this. You can either implement a rescaling algrorithm without interpolation. If this is to much work you could rescale the image in another application like gimp or photoshop. This would work unless you needed to change the size dynamically in your application.