I have four points and I would like to draw an UIImageView with corners in those four points.
The four points represent an arbitrary rectangle (might be a trapez or a parallelogram).
I guess I somehow need to make a transform from those four points, but I'm not quite sure how.
Any suggestions?
Other solutions?
Look at https://math.stackexchange.com/questions/169176/2d-transformation-matrix-to-make-a-trapezoid-out-of-a-rectangle to determine your transformation matrix.
Note that you cannot use a 2D matrix so you have to use a CATransform3D.
CATransform3D transform = CATransform3DIdentity;
// update transform elements, .m11, .m12, .m13, etc.
imageView.layer.transform = transform;
Related
I have a simple UIImageView in my view, but I can't seem to find any feature in Apple's documentation to change the UV Coordinates of this UIImageView, to convey my idea to you, this GIF file should preview how changing 4 vertices coordinates can change how the image gets viewed on the final UIImageView.
I tried to find a solution online too (other than documentation) and found none.
I use Swift.
You can achieve that very animation using UIView.transform or CALayer.transform. You'll need basic geometry to convert UV coordinates to a CGAffineTransform or CATransform3D.
I made an assumption that affine transform would suffice because in your animation the transform is affine (parallel lines stay parallel). In that case, 3 vertices are free -- the 4th one is constrained by the other 3.
If you have 3 vertices, you can compute the affine transform matrix using: Affine transformation algorithm
To achieve the infinite repeat, use UIImageResizingMode.Tile.
Is it possible to use a normalized coordinate system (from 0.0 to 1.0) instead of using pixel coordinates when drawing stuff with CoreGraphics? It would certainly make a lot of things easier...
Yes, use a CGAffineTransform. I do this in an app. keep all coordinates normalized to -1.0 to 1.0, create a transform based on the size of the view I am drawing into.
Example:
CGAffineTransform translateTransform = CGAffineTransformMakeTranslation(offset.x, offset.y);
One can transform each point or create a path and transform the entire path:
CGMutablePathRef transformedPath = CGPathCreateMutable();
CGPathAddPath(transformedPath, &transform, path);
As #yurish points out one can also use CGContextScaleCTM, CGContextTranslateCTM, etc. instead of scaling the points/path if that works better for you.
Core graphics does not use pixel coordinates. It uses abstract points that are converted to pixels using current transformation matrix (CTM). You can use the normalized coordinate system if you adjust CTM appropriately (CGContextScaleCTM etc) .
I want to create the same transforming effect on XNA 4 as Photoshop does:
Transform tool is used to scale, rotate, skew, and just distort the perspective of any graphic you’re working with in general
This is what all the things i want to do in XNA with any textures http://www.tutorial9.net/tutorials/photoshop-tutorials/using-transform-in-photoshop/
Skew: Skew transformations slant objects either vertically or horizontally.
Distort: Distort transformations allow you to stretch an image in ANY direction freely.
Perspective: The Perspective transformation allows you to add perspective to an object.
Warping an Object(Im interesting the most).
Hope you can help me with some tutorial or somwthing already made :D, iam think vertex has the solution but maybe.
Thanks.
Probably the easiest way to do this in XNA is to pass a Matrix to SpriteBatch.Begin. This is the overload you want to use: MSDN (the transformMatrix argument).
You can also do this with raw vertices, with an effect like BasicEffect by setting its World matrix. Or by setting vertex positions manually, perhaps transforming them with Vector3.Transform().
Most of the transformation matrices you want are provided by the Matrix.Create*() methods (MSDN). For example, CreateScale and CreateRotationZ.
There is no provided method for creating a skew matrix. It should be something like this:
Matrix skew = Matrix.Identity;
skew.M12 = (float)Math.Tan(MathHelper.ToRadians(36.87f));
(That is to skew by 36.87f degrees, which I pulled off this old answer of mine. You should be able to find the full maths for a skew matrix via Google.)
Remember that transformations happen around the origin of world space (0,0). If you want to, for example, scale around the centre of your sprite, you need to translate that sprite's centre to the origin, apply a scale, and then translate it back again. You can combine matrix transforms by multiplying them. This example (untested) will scale a 200x200 image around its centre:
Matrix myMatrix = Matrix.CreateTranslation(-100, -100, 0)
* Matrix.CreateScale(2f, 0.5f, 1f)
* Matrix.CreateTranslation(100, 100, 0);
Note: avoid scaling the Z axis to 0, even in 2D.
For perspective there is CreatePerspective. This creates a projection matrix, which is a specific kind of matrix for projecting a 3D scene onto a 2D display, so it is better used with vertices when setting (for example) BasicEffect.Projection. In this case you're best off doing proper 3D rendering.
For distort, just use vertices and place them manually wherever you need them.
I'm trying to transform a rectangle to an quadrilateral and created a CATransform3D projection matrix as described by hfossli here.
The matrix works with a CALayer with out problem, but i would like/have to use it with GPUImage and the GPUImageTransformFilter, which takes a CATransform3D.
It doesn't really work.
The scaling doesn't fit, which means my transformed image gets cut of or points are not "stretched" to the position they should be. There are some threads which describe the translation from a OpenGL projection to a proper CATransform3D projection matrix like here.
It involves some scaling and y-flipping.
So I tried to scale and flip in reversed order in the hope to be able to use this CATransform3D matrix with the GPUImageTransformFilter, but couldn't really get it to work.
Did maybe someone solve this?
I am trying to transform a Sprite into a trapezoid, I don't really care about the interpolation even though I know without it my image will lose detail. All I really want to do is Transform my rectangular Sprite into a trapezoid like this:
/ \
/ \
/__________\
Has anyone done this with CGAffineTransforms or with cocos2d?
The transformation you're proposing is not affine. Affine transformations have to be undoable. So they can typically:
Scale
Rotate
Shear (make lopsided, like square -> parallelogram)
Translate
But they cannot "squeeze". Notice that the left and right sides of your trapezoid, if extended, would intersect at a particular spot. They're not parallel anymore. So you couldn't "undo" the transformation, because if there was anything to transform at that spot, you couldn't decide where they would transform to. In other words, if a transformation doesn't preserve parallelism, it pinches space, can't be undone, and isn't affine.
I don't know that much about transformations in Core Animation, so I hope that mathy stuff helps you find an alternative.
But I do know how you could do it in OpenGL, but it would require you to start over on how you draw your application:
If I'm envisioning the result you want correctly, you want to build your rectangle in 3D, use an affine transformation to rotate it away a little bit, and use a (non-affine) projection transformation to flatten it into a 2D image.
If you're not looking for a 3D effect, but you really just want to pinch in the corners, then you can specify a GL_RECT with the points of your trapezoid and map your sprite onto it as a texture.
The easiest thing might be to pre-squeeze your image in a photo editor, save it as a .png with transparency, and draw a rectangle with that image.
You need to apply a CATransform3D to the layer of the UIView.
To find out the right one, it is easier to use AGGeometryKit.
#import <AGGeometryKit/AGGeometryKit.h>
UIView *view = ...; // create a view
view.layer.anchorPoint = CGPointZero;
AGKQuad quad = view.layer.quadrilateral;
quad.tl.x += 20; // shift top left x-value with 20 pixels
quad.tr.x -= 20; // shift top right x-value with 20 pixels
view.layer.quadrilateral = quad; // the quad is converted to CATransform3D and applied