cgcontext rotate rectangle - ios

guys!
I need to draw some image to CGContext.This is the relevant code:
CGContextSaveGState(UIGraphicsGetCurrentContext());
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect rect = r;
CGContextRotateCTM(ctx, DEGREES_TO_RADIANS(350));
[image drawInRect:r];
CGContextRestoreGState(UIGraphicsGetCurrentContext());
Actually,the rectangle is rotate and display on a area what is not my purpose.I just want to
rotate the image and display on the same position.
Any ideas ?????

Rotation is about the context's origin, which is the same point that rectangles are relative to. If you imagine a sheet of graph paper in the background, you can see what's going on more clearly:
The line is the “bottom” (y=0) of your window/view/layer/context. Of course, you can draw below the bottom if you want, and if your context is transformed the right way, you might even be able to see it.
Anyway, I'm assuming that what you want to do is rotate the rectangle in place, relative to an unrotated world, not rotate the world and everything in it.
The only way to rotate anything is to rotate the world, so that's how you need to do it:
Save the graphics state.
Translate the origin to the point where you want to draw the rectangle. (You probably want to translate to its center point, not the rectangle's origin.)
Rotate the context.
Draw the rectangle centered on the origin. In other words, your rectangle's origin point should be negative half its width and negative half its height (i.e., (CGPoint){ width / -2.0, height / -2.0 })—don't use the origin it had before, because you already used that in the translate step.
Restore the gstate so that future drawing isn't rotated.

What worked for me was to first use a rotation matrix to calculate the amount of translation required to keep your image centered. Below I assume you've already calculated centerX and centerY to be the center of your drawing frame and 'theta' is your desired rotation angle in radians.
let newX = centerX*cos(theta) - centerY*sin(theta)
let newY = centerX*sin(theta) + centerY*cos(theta)
CGContextTranslateCTM(context,newX,newY)
CGContextRotateCTM(context,theta)
<redraw your image here>
Worked just fine for me. Hope it helps.

use following code to rotate your image
// convert degrees to Radians
CGFloat DegreesToRadians(CGFloat degrees)
{
return degrees * M_PI / 180;
};
write it in drawRect method
// create new context
CGContextRef context = UIGraphicsGetCurrentContext();
// define rotation angle
CGContextRotateCTM(context, DegreesToRadians(45));
// get your UIImage
UIImage *img = [UIImage imageNamed:#"yourImageName"];
// Draw your image at rect
CGContextDrawImage(context, CGRectMake(100, 0, 100, 100), [img CGImage]);
// draw context
UIGraphicsGetImageFromCurrentImageContext();

Related

Transform a CGRect in Core Graphic coordinates

Is there a way to transform a CGRect with UIView system coordinates into Core Graphics coordinates, where the origin is in the lower-left corner?
Sure. You just have to subtract the y-origin and the height of the rect away from the view's height.
rect.origin.y = view.frame.size.height-(rect.origin.y+rect.size.height)
You can represent this with a CGAffineTransform like so:
CGAffineTransformMakeTranslation(0, view.size.height-((rect.origin.y*2.0)+rect.size.height))
You subtract the origin twice as you're now working with a relative value, instead of an absolute one.
However, if you only want to flip a context to work in UIView coordinates you'd want:
CGFloat ctxHeight = CGContextGetClipBoundingBox(c).size.height;
CGContextScaleCTM(c, 1, -1);
CGContextTranslateCTM(c, 0, -ctxHeight);

iOS - Draw image with CGContext and transform

I am trying to draw an image on top of another image. I have the image's size, transform and origin. My code below shows correct size and transform angle but not at the correct point.
Code:
UIGraphicsBeginImageContextWithOptions(backgroundImage.size, NO, [[UIScreen mainScreen] scale]);
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect baseRect = CGRectMake(0, 0, backgroundImage.size.width, backgroundImage.size.height);
[backgroundImage drawInRect:baseRect];
CGRect newRect = CGRectMake(x, y, width, height);
CGContextTranslateCTM(context, x, y);
CGContextConcatCTM(context, watermarkImageView.transform);
CGContextTranslateCTM(context, -x, -y);
[watermarkImageView.image drawInRect:newRect];
UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
The watermark image should be placed like this:
But currently its looking like this:
What did I miss?
Thanks in advance
EDIT
The x,y is the edge of the bounding box
Your code doesn't show what watermarkImageView.transform is and that is important because when you concat transformations, the effects of previous transformations will also effect all the following transformations.
E.g. a translation that moves the object 10 pixels along the x-axis will move the object 10 pixels to the right. However, if you first have a rotation that rotates the object by 45 degrees and then add a translation that moves 10 pixels along the x-axis, the object will not move 10 pixels to the right, it will move 10 pixels along a line that is 45 degrees rotated, which means it will move about 7 pixels up and 7 pixels to the right. That's because a rotation does not really rotate the object itself, it actually rotates the whole coordinate system which causes the object to be drawn rotated.
See this image:
Initially the translation coordinate system (red lines) matches the "real coordinate" system. But after the rotation by 45 degrees, the translation coordinate system has been rotated and now translating across the red lines moves the object diagonally.
Think about a sheet of paper and a stamp. The stamp always has the same position and the same orientation, you cannot move or rotate the stamp. But you can move and rotate the sheet of paper below the stamp! And that's what your transformations do. They transform the sheet before the stamp is pressed upon it.
For most people it is very hard to imagine the effects of transforming the whole space, it's much easier for them to think about transforming the object. The trick is: You must read your transformations in the opposite order than you wrote them. I guess what you want to do is actually:
CGContextTranslateCTM(context, x, y);
CGContextConcatCTM(context, watermarkImageView.transform);
CGContextTranslateCTM(context,
-watermarkImageView.size.with * 0.5,
-watermarkImageView.size.height * 0.5
);
Now read them in the opposite order (from bottom to top). First you center the watermark around (0,0) by moving it up half the height and left half the width. Now the center of your watermark is exactly at (0,0). Then you rotate it as desired. Finally you move it to the desired position. Of course you wrote all transformations the other way round but that's only because you are transforming the coordinate space, not the object.
Centering your watermark prior to rotation is important because rotation always rotates around (0,0) coordinates. If you'd just rotate, the rotation looks like this:
That's not what you want as it will not just rotate the object but also changes its position. If you center the image around (0,0) first, the rotation looks like this instead:
The answer to my question was
I had to translate to the centre of where I want to draw the context.
CGContextTranslateCTM(context, imageView.center.x, imageView.center.y);
Then rotate context.
CGFloat angle = [(NSNumber *)[imageView valueForKeyPath:#"layer.transform.rotation.z"] floatValue];
CGContextRotateCTM(context, angle);
Then draw
[imageView.image drawInRect:CGRectMake(-width * 0.5f, -height * 0.5f, width, height)];

Rotating CIImage around a point

I would like to rotate a UIImage from file (a jpeg on the file system) a computed amount of radians, but I would like to rotate it around a point in the image, as well as keep the original size of the image (with transparent gaps in the image where image data no longer exists, as well as cropping image data that has moved outside of the original frame). I would like to then store and display the resulting UIImage. I haven't found any resources for this task, any help would be much appreciated!
The closest thing I have found so far (with some slight modifications) is as follows:
-(UIImage*)rotateImage:(UIImage*)image aroundPoint:(CGPoint)point radians:(float)radians newSize:(CGRect)newSize
{
CGRect imageRect = { point, image.size };
UIGraphicsBeginImageContext(image.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, imageRect.origin.x, imageRect.origin.y);
CGContextRotateCTM(context, radians);
CGContextTranslateCTM(context, -imageRect.origin.x, -imageRect.origin.y);
CGContextDrawImage(context, (CGRect){ CGPointZero, imageRect.size }, [image CGImage]);
UIImage *returnImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return returnImg;
}
Unfortunately, this rotates the image incorrectly (in my tests, somewhere in the neighborhood of 180 degrees more than desired).
to rotate that UIImage image, lets say 90 degrees, you can easily do:
imageView.transform = CGAffineTransformMakeRotation(M_PI/2);
to rotate it multiple times you can use:
UIView animateKeyframesWithDuration method
and to anchor it to some point you can use:
[image.layer setAnchorPoint:CGPointMake(....)];

CGcontext origin after rotation

I am trying to rotate an image about the center then place the rotated image's center over a point. When I draw it on the context after rotatoin it does not draw where i expect...
CGContextTranslateCTM( context, xOffset, yOffset);
CGContextRotateCTM(context, radiansOffset);
CGContextTranslateCTM( context, -xOffset, -yOffset)
[backgroundimage drawInRect:CGRectMake( x, y, width, height)];
When i place the image without rotation, it is placed where i want, but after rotation as above, it is placed almost as if its still being rotated around a point outside of the image itself.

iOS: Rotating with CGContextRotate

Im trying to rotate an image, that i want to draw on a image file (to the context.
Everything works fine, except when i rotate the image.
Basically i have an image; i want to scale and resize the image and then clip it to a rect and finaly draw it to the UICurrentContext;
//create a new graphic context
UIGraphicsBeginImageContext(CGSizeMake(500, 500));
CGContextRef graphicContext = UIGraphicsGetCurrentContext();
CGContextDrawImage(graphicContext, CGRectMake(0, 0, rect.size.width, rect.size.height), image.CGImage);
CGContextRotateCTM(graphicContext, 45 * M_PI/180.0);
UIImage* editedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//draw it to the current context
[editedImage drawAtPoint:CGPointMake(0,0)];
The thing is when i rotate the image, i dont have a clue what the new size of the imagecontext would be. Next to that, the image in the edited image is not rotated..
You need to rotate the context before you draw. I know this seems silly, but to use the analogy of a piece of paper...this is a piece of paper that cannot move. Instead you must move yourself around it and then draw.
This way, your size will never change because anything too big will just simply be cut off.
EDIT Also, this function takes radians, not degrees, so you don't need to convert as you are doing. If you want 45 degrees it will just be PI / 4 (which is stored as the constant M_PI_4 in math.h).

Resources