UIImage Rotation Offset - iphone

I have the following code
- (void)ComputeRotationWithRadians:(CGFloat)rad {
CGFloat width = exportImage.size.width;
CGFloat height = exportImage.size.height;
UIGraphicsBeginImageContext(CGSizeMake(width, height));
CGContextRef ctxt = UIGraphicsGetCurrentContext();
CGContextScaleCTM(ctxt, 1.0, -1.0);
CGContextTranslateCTM(ctxt, 0.0, -exportImage.size.height);
CGContextRotateCTM(ctxt, rad);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), exportImage.CGImage);
exportImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[imageView setImage:exportImage];
}
The issue is that the rotation happens around the bottom left corner, when it has been calculated around the center. Is there anyway to change this?

Your code is translating the matrix before rotating it. Try flipping the calls to CGContextConcatCTM and CGContextTranslateCTM so you rotate first. Or perhaps you are looking for something else?

Related

Find new coordinates after using CGAffineTransformMakeRotation on an object

This is a simple issue, which is bugging me ...
So, I have an object of UIImageView over which, I use
-(void)rotate {
// ...
CGAffineTransform transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(180));
self.image.transform = transform; // image is a property.
}
So, when I call this method once, it rotates the object !. When I call the method again, I expect the object to be rotated again - but it is not rotating by another 180 degrees. After messing with the coordinates and moving the image, I can understand that the -perspective of the object has also be rotated by 180 degrees and all coordinates have been inverted as well.
I want the object's perspective to be restored (although it's been rotated by some angle) such that, I can continue to rotate and move it just like before !
Any ideas ?
Anyways, this code works:
UIImage* rotateUIImage(const UIImage* src, float angleDegrees) {
UIView* rotatedViewBox = [[UIView alloc] initWithFrame: CGRectMake(0, 0, src.size.width, src.size.height)];
float angleRadians = angleDegrees * ((float)M_PI / 180.0f);
CGAffineTransform t = CGAffineTransformMakeRotation(angleRadians);
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
CGContextRotateCTM(bitmap, angleRadians);
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-src.size.width / 2, -src.size.height / 2, src.size.width, src.size.height), [src CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Solved the problem with CABasicAnimation !

Rotate UIImage custom degree

I want to rotate an UIImage (not UIImageView) in custom degree
I followed this post but it didn't work for me.
Anyone can help? Thanks.
UPDATE:
The code below does some of the job, but I lose some of the image after rotating it:
What should I change to get it right? (btw the yellow color in the screenshots is my UIImageView bg)
- (UIImage *) rotate: (UIImage *) image
{
double angle = 20;
CGSize s = {image.size.width, image.size.height};
UIGraphicsBeginImageContext(s);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, 0,image.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
CGContextRotateCTM(ctx, 2*M_PI*angle/360);
CGContextDrawImage(ctx,CGRectMake(0,0,image.size.width, image.size.height),image.CGImage);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
This method return you image on your angle of rotate
#pragma mark -
#pragma mark Rotate Image
- (UIImage *)scaleAndRotateImage:(UIImage *)image {
CGImageRef imgRef = image.CGImage;
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGAffineTransform transform = CGAffineTransformIdentity;
CGRect bounds = CGRectMake(0, 0, width, height);
CGFloat boundHeight;
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeScale(-1.0, 1.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0); //use angle/360 *MPI
UIGraphicsBeginImageContext(bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextConcatCTM(context, transform);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imgRef);
UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageCopy;
}
- (UIImage *)rotate:(UIImage *)image radians:(float)rads
{
float newSide = MAX([image size].width, [image size].height);
CGSize size = CGSizeMake(newSide, newSide);
UIGraphicsBeginImageContext(size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, newSide/2, newSide/2);
CGContextRotateCTM(ctx, rads);
CGContextDrawImage(UIGraphicsGetCurrentContext(),CGRectMake(-[image size].width/2,-[image size].height/2,size.width, size.height),image.CGImage);
//CGContextTranslateCTM(ctx, [image size].width/2, [image size].height/2);
UIImage *i = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return i;
}
this function rotates any image on its center, but the image becomes a square so I would suggest referencing the image center when drawing it after this function.
You need to address two things to make this work.
You are rotating about the bottom corner of the image instead of the centre
The bounding rectangle of the resulting image needs to be larger now the image is rotated for it to fit in.
To solve the rotation about the centre, first perform a translate to the centre, then rotate, then translate back.
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformTranslate(transform, boundingRect.size.width/2, boundingRect.size.height/2);
transform = CGAffineTransformRotate(transform, angle);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
CGContextConcatCTM(context, transform);
// Draw the image into the context
CGContextDrawImage(context, CGRectMake(-imageView.image.size.width/2, -imageView.image.size.height/2, imageView.image.size.width, imageView.image.size.height), imageView.image.CGImage);
// Get an image from the context
rotatedImage = [UIImage imageWithCGImage: CGBitmapContextCreateImage(context)];
To calculate the size of the bounding rectangle you'd need to fit the new rotated image into use this:
- (CGRect) getBoundingRectAfterRotation: (CGRect) rectangle byAngle: (CGFloat) angleOfRotation {
// Calculate the width and height of the bounding rectangle using basic trig
CGFloat newWidth = rectangle.size.width * fabs(cosf(angleOfRotation)) + rectangle.size.height * fabs(sinf(angleOfRotation));
CGFloat newHeight = rectangle.size.height * fabs(cosf(angleOfRotation)) + rectangle.size.width * fabs(sinf(angleOfRotation));
// Calculate the position of the origin
CGFloat newX = rectangle.origin.x + ((rectangle.size.width - newWidth) / 2);
CGFloat newY = rectangle.origin.y + ((rectangle.size.height - newHeight) / 2);
// Return the rectangle
return CGRectMake(newX, newY, newWidth, newHeight);
}
You can find these techniques in my previous posts and answers here:
Creating a UIImage from a rotated UIImageView
and here:
Saving 2 UIImages
Hope this helps,
Dave
for rotate image.. you can use this IBAction ... for each and every button click, the image will be rotate by 90 degree...
-(IBAction)rotateImageClick:(id)sender{
UIImage *image2=[[UIImage alloc]init];
image2 = [self imageRotatedByDegrees:self.roateImageView.image deg:(90)]; //Angle by 90 degree
self.roateImageView.image = image2;
imgData= UIImageJPEGRepresentation(image2,0.9f);
}
for rotating image u only have to pass UIimage and rotating degrees for the following method
- (UIImage *)imageRotatedByDegrees:(UIImage*)oldImage deg:(CGFloat)degrees
//------------------------------------------------------------------------
#pragma mark - imageRotatedByDegrees Method
- (UIImage *)imageRotatedByDegrees:(UIImage*)oldImage deg:(CGFloat)degrees{
// calculate the size of the rotated view's containing box for our drawing space
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,oldImage.size.width, oldImage.size.height)];
CGAffineTransform t = CGAffineTransformMakeRotation(degrees * M_PI / 180);
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
// Create the bitmap context
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
// Move the origin to the middle of the image so we will rotate and scale around the center.
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
// // Rotate the image context
CGContextRotateCTM(bitmap, (degrees * M_PI / 180));
// Now, draw the rotated/scaled image into the context
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-oldImage.size.width / 2, -oldImage.size.height / 2, oldImage.size.width, oldImage.size.height), [oldImage CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
I think this link will be help.......! Rotate Original Image by clicking button in Objective C
http://adrianmobileapplication.blogspot.com/2015/03/rotate-original-image-by-clicking.html
You have to do some thing like this
YourContainer.transform = CGAffineTransformMakeRotation( 270.0/180*M_PI );
I think rest of the thing you can figured out..

How to rotate UIImage in image center

double angle = -15;
UIImage *image = [UIImage imageNamed:#"test.jpg"];
CGSize s = {image.size.width, image.size.height};
UIGraphicsBeginImageContext(s);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, 0,image.size.height);
CGContextScaleCTM(ctx, 1.0, -1.0);
CGContextRotateCTM(ctx, 2*M_PI*angle/360);
CGContextDrawImage(ctx,CGRectMake(0,0,image.size.width, image.size.height),image.CGImage);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Hi,I wont to rotate UIImage in image center point. I can rotate UIImage with this code,but not in center point.
Please help me.
Use Core Animation. You can say
UIView.layer.anchor = aPoint;
Then, preform the rotation using the CA framework, and it will happen around that anchor.
This code will work but only with UIImageOrientation = 0,
// Move the origin to the middle of the image so we will rotate and scale around the center.
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
//Rotate the image context
CGContextRotateCTM(bitmap, rad(degrees));
// Now, draw the rotated/scaled image into the context
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-self.size.width / 2, -self.size.height / 2, self.size.width, self.size.height), [self CGImage]);

How to save an image using UIImageWriteToSavedPhotosAlbum after it is transformed

Ok I have searched all over and I can't not seem to find the answer I need. :-(
Here is what I am doing and what I need to happen. I have a UIImageView that I am able to transfrom using UIPanGestureRecognizer, UIRotationGestureRecognizer, and UIPinchGestureRecognizer all that works great. The problem comes when it is time to save those transfomations to my PhotoAlbum. The results are not what i am expecting. So far here is the code that i am using (al-be-it very incomplete)
-(IBAction)saveface:(id)sender
{
static int kMaxResolution = 640;
CGImageRef imgRef = face.image.CGImage;
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGRect bounds = CGRectMake(0, 0, width, height);
if (width > kMaxResolution || height > kMaxResolution) {
CGFloat ratio = width/height;
if (ratio > 1) {
bounds.size.width = kMaxResolution;
bounds.size.height = bounds.size.width / ratio;
} else {
bounds.size.height = kMaxResolution;
bounds.size.width = bounds.size.height * ratio;
}
}
UIGraphicsBeginImageContext(bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextScaleCTM(context, 1, -1);
CGContextTranslateCTM(context, 0, -height);
NSLog(#"SAVE TX:%f TY:%f A:%f B:%f C:%f D:%f", face.transform.tx, face.transform.ty, face.transform.a,face.transform.b,face.transform.c,face.transform.d);
CGFloat x = face.transform.tx;
CGFloat y = face.transform.ty;
CGContextTranslateCTM (context, x,-y);
CGContextConcatCTM(context, face.transform);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(imageCopy, self, nil, nil);
}
From this method I am able to save the image however the coordinates are way off. I can see any scaling I did that works ok. I see my rotation but it seems to be backwards and the paning is WAY off.
The coords are all wrong and for the life of me I can't figure out what is wrong. I admit I am new to Objective-C and I have never used Quartz 2D before and my understanding of the transform matrixes is limited. I do understand that my transformations are not on the image data itself as trying to save the image out right with out applying this context to it does nothing. So please can anyone set me straight on this?
You generally want to translate before you scale.
You've flipped your coordinate system but you still assign the old x and y values. I think you should have:
CGFloat y = face.transform.tx;
CGFloat x = face.transform.ty;
The face object is not defined in this code. If it is off, everything else will be off. If it is a property you should use the self.face reference form to make sure it is accessed properly.
I would recommend performing the scale transform last.
If none of this works. Comment out all but one transform and see if that single transform works. Then add the others in until it fails.
This kind of work is much easier if you the image in a UIView, transform, scale and then render the layer. It saves all kinds of hassle later.
Something like:
CGSize vscaledSize = myOriginalImage.size;
//add in the scaled bits of the view
//scaling
CGFloat wratio = vscaledSize.width/self.pictureView.frame.size.width;
CGFloat vhightScaled = self.pictureView.frame.size.height * wratio;
vscaledSize.height = vhightScaled;
CGFloat hratio = vscaledSize.height/self.pictureView.frame.size.height;
//create context
UIGraphicsBeginImageContext(myOriginalImage.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context); //1 original context
// translate/flip the graphics context (for transforming from CG* coords to UI* coords
CGContextTranslateCTM(context, 0, vscaledSize.height);
CGContextScaleCTM(context, 1.0, -1.0);
//original image
CGContextDrawImage(context, CGRectMake(0,0,vscaledSize.width,vscaledSize.height), myOriginalImage.CGImage);
CGContextRestoreGState(context);//1 restore to original;
//scale context to match view size
CGContextSaveGState(context); //1 pre-scaled size
CGContextScaleCTM(context, wratio, hratio);
//render
[self.pictureView.layer renderInContext:context];
CGContextRestoreGState(context);//1 restore to pre-scaled size;
UIImage *exportImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
You'll notice that I flip the coord system for the image render, but restore it to the original coordinate system for the UIView.layer render.
Hope this helps

How can i take an UIImage and give it a black border programmatically?

How can i take an UIImage and give it a black border programmatically?
If i can receive code, it will be great.
tnx
If you only need to display the border you can do that with Core Animation on the UIImageView's layer. If you need to do it on the image itself then you will need to create a new image, draw the old image into the new image and then draw a rect on top of it.
- (UIImage*)imageWithBorderFromImage:(UIImage*)source;
{
CGSize size = [source size];
UIGraphicsBeginImageContext(size);
CGRect rect = CGRectMake(0, 0, size.width, size.height);
[source drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 1.0, 0.5, 1.0, 1.0);
CGContextStrokeRect(context, rect);
UIImage *testImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return testImg;
}
This will put a pink border on an image and return the new image.
I'd have a look at this:
Can I Edit the Pixels of the UIImage's Property CGImage
As for the black border part, I assume you can figure that one out. Just iterate along each side and change the pixels to (0,0,0,255) for a certain amount.