Rotate UIImage custom degree - iphone

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..

Related

iPhone programmatically crop a square image to appear as circle

I'm trying to create an image for a custom style UIButton using an image from the camera roll on iPhone. The button has a circular background and effectively appears as a circle. Now I need an image to go in the middle of the button that also appears round.
How do I cut a square UIImage to appear round with transparency outside of the round area?
If masking is involved, do I need to pre-render a mask or can I create one programmatically(ex: a circle)?
Thank you!
I have never done anything like that, but try using QuartzCore framework and its' cornerRadius property. Example:
#import <QuartzCore/QuartzCore.h>
//some other code ...
UIImageView *imgView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
imgView.layer.cornerRadius = 10.0f;
play around with it a bit and you will get what you want.
Hope it helps
Yes you can use CoreGraphics to draw the mask dynamically.
Then you can create the masked image.
Example for masking:
- (UIImage*) maskImage:(UIImage *)image withMask:(UIImage *)maskImage
{
CGImageRef maskRef = maskImage.CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
CGImageRef maskedImageRef = CGImageCreateWithMask([image CGImage], mask);
UIImage *maskedImage = [UIImage imageWithCGImage:maskedImageRef];
CGImageRelease(maskedImageRef);
CGImageRelease(mask);
return maskedImage;
}
I started looking into this a couple of weeks back. I tried all the suggestions here, none of which worked well. In the great tradition of RTFM I went and read Apple's documentation on Quartz 2D Programming and came up with this. Please try it out and let me know how you go.
The code could be fairly easily altered to crop to an elipse, or any other shape defined by a path.
Make sure you include Quartz 2D in your project.
#include <math.h>
+ (UIImage*)circularScaleNCrop:(UIImage*)image: (CGRect) rect{
// This function returns a newImage, based on image, that has been:
// - scaled to fit in (CGRect) rect
// - and cropped within a circle of radius: rectWidth/2
//Create the bitmap graphics context
UIGraphicsBeginImageContextWithOptions(CGSizeMake(rect.size.width, rect.size.height), NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
//Get the width and heights
CGFloat imageWidth = image.size.width;
CGFloat imageHeight = image.size.height;
CGFloat rectWidth = rect.size.width;
CGFloat rectHeight = rect.size.height;
//Calculate the scale factor
CGFloat scaleFactorX = rectWidth/imageWidth;
CGFloat scaleFactorY = rectHeight/imageHeight;
//Calculate the centre of the circle
CGFloat imageCentreX = rectWidth/2;
CGFloat imageCentreY = rectHeight/2;
// Create and CLIP to a CIRCULAR Path
// (This could be replaced with any closed path if you want a different shaped clip)
CGFloat radius = rectWidth/2;
CGContextBeginPath (context);
CGContextAddArc (context, imageCentreX, imageCentreY, radius, 0, 2*M_PI, 0);
CGContextClosePath (context);
CGContextClip (context);
//Set the SCALE factor for the graphics context
//All future draw calls will be scaled by this factor
CGContextScaleCTM (context, scaleFactorX, scaleFactorY);
// Draw the IMAGE
CGRect myRect = CGRectMake(0, 0, imageWidth, imageHeight);
[image drawInRect:myRect];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Include the following code in your UIView class replacing "monk2.png" with your own image name.
- (void)drawRect:(CGRect)rect
{
UIImage *originalImage = [UIImage imageNamed:[NSString stringWithFormat:#"monk2.png"]];
CGFloat oImageWidth = originalImage.size.width;
CGFloat oImageHeight = originalImage.size.height;
// Draw the original image at the origin
CGRect oRect = CGRectMake(0, 0, oImageWidth, oImageHeight);
[originalImage drawInRect:oRect];
// Set the newRect to half the size of the original image
CGRect newRect = CGRectMake(0, 0, oImageWidth/2, oImageHeight/2);
UIImage *newImage = [self circularScaleNCrop:originalImage :newRect];
CGFloat nImageWidth = newImage.size.width;
CGFloat nImageHeight = newImage.size.height;
//Draw the scaled and cropped image
CGRect thisRect = CGRectMake(oImageWidth+10, 0, nImageWidth, nImageHeight);
[newImage drawInRect:thisRect];
}
Here is a quick way to create rounded corners on a square ImageView to make it look like a perfect circle. Basically you apply a corner radius equal to 1/2 the width (width == height on a square image).
#import <QuartzCore/QuartzCore.h> //you need QuartzCore
...
float width = imageView.bounds.size.width; // we can also use the frame property instead of bounds since we just care about the Size and don't care about position
imageView.layer.cornerRadius = width/2;
{
imageView.layer.cornerRadius = imageView.frame.size.height /2;
imageView.layer.masksToBounds = YES;
imageView.layer.borderWidth = 0;
}
UIImage category to mask an image with a circle:
UIImage *originalImage = [UIImage imageNamed:#"myimage.png"];
UImage *myRoundedImage = [UIImage roundedImageWithImage:originalImage];
Get it here.
I have another solution:
- (UIImage *)roundedImageWithRect:(CGRect)rect radius:(CGFloat)radius
{
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, rect.size.width, rect.size.height) cornerRadius:radius];
CGFloat imageRatio = self.size.width / self.size.height;
CGSize imageSize = CGSizeMake(rect.size.height * imageRatio, rect.size.height);
CGRect imageRect = CGRectMake(0, 0, imageSize.width, imageSize.height);
[path addClip];
[self drawInRect:imageRect];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
This variant is better for performance than set cornerRadius directly.
Personally, I'd create a transparent circle image with opaque corners to overlay the photo. This solution is only suitable where you will be placing the image in one place on the UI, and assumes the opaque corners will blend in with the background.
Following is the answer I given in How to crop UIImage on oval shape or circle shape? to make the image circle. It works for me..
Download the Support archive file
#import "UIImage+RoundedCorner.h"
#import "UIImage+Resize.h"
Following lines used to resize the image and convert in to round with radius
UIImage *mask = [UIImage imageNamed:#"mask.jpg"];
mask = [mask resizedImage:CGSizeMake(47, 47) interpolationQuality:kCGInterpolationHigh ];
mask = [mask roundedCornerImage:23.5 borderSize:1];
Just use
_profilePictureImgView.layer.cornerRadius = 32.0f;
_profilePictureImgView.layer.masksToBounds = YES;

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 !

Help rotating a UIImage

I have to rotate a UIImage before I save it out to file. I've tried a number of methods, some of which seem to work for other people, but all it seems to do it turn my image solid white. Here's my code:
CGFloat radians = 90.0f * M_PI/180;
UIGraphicsBeginImageContext(image.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextConcatCTM(ctx, CGAffineTransformMakeRotation(radians));
CGContextDrawImage(ctx, CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Can anyone spot what I'm doing wrong? The variable "image" is a UIImage.
- (UIImage *)imageRotatedByRadians:(CGFloat)radians
{
// calculate the size of the rotated view's containing box for our drawing space
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.size.width, self.size.height)];
CGAffineTransform t = CGAffineTransformMakeRotation(radians);
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, radians);
// 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]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
I believe you are not taking into account that the coordinate system for iPhone and Quartz Coordinate system are different.
try putting these two lines before CGContextConcatCTM.
// to account for Quartz coordinate system.
CGContextScaleCTM(cx, 1, -1);
CGContextTranslateCTM(ctx, 0, -longerSide); // width or height depending on the orientation
I suggest to put your image in UIImageView and then use following code:
- (void)setupRotatingButtons
{
// call this method once; make sure "self.view" is not nil or the button
// won't appear. the below variables are needed in the #interface.
// center: the center of rotation
// radius: the radius
// time: a CGFloat that determines where in the cycle the button is located at
// (note: it will keep increasing indefinitely; you need to use
// modulus to find a meaningful value for the current position, if
// needed)
// speed: the speed of the rotation, where 2 * 3.1415 is **roughly** 1 lap a
// second
center = CGPointMake(240, 160);
radius = 110;
time = 0;
speed = .3 * 3.1415; // <-- will rotate CW 360 degrees per .3 SECOND (1 "lap"/s)
CADisplayLink *dl = [CADisplayLink displayLinkWithTarget:self selector:#selector(continueCircling:)];
[dl addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
- (void)continueCircling:(CADisplayLink *)dl
{
time += speed * dl.duration;
//here rotate your image view
yourImageView.transform = CGAffineTransformMakeRotation(time);
}
Use following code to rotate:
UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"image1.png"]];
[imageView setFrame:CGRectMake(0.0f, 0.0f,100.0f, 100.0f)];
[self.view addSubview:imageView];
self.imageView.transform = CGAffineTransformMakeRotation((90.0f * M_PI) / 180.0f);

UIImage iPhone Rotate 37.8 degrees

After I load an image from the device, I need to rotate it 37.8 degrees then display it on a View.
Is there an function in Objective-C that can do the image rotation?
Ian
To rotate the view:
imageView.transform = CGAffineTransformMakeRotation(37.8°);
To rotate the image,
Calculate the width and height will be occupied by the image after rotation.
Create a CGContext by UIGraphicsBeginImageContext.
CGContextRotateCTM(UIGraphicsGetCurrentContext(), 37.8°);
[yourImage drawAtPoint:...];
UIGraphicsGetImageFromCurrentImageContext(); and use this image instead.
Release the context.
Yes, see my answer to this question: Question about rotating a slider
To convert degrees to radians (for the positionInRadians arg) use this function:
CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};
To rotate the image, try this:
-(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);
}
This method allows you to rotate an image an arbitrary amount:
- (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;
}
See this link for more information.

UIImage rounded corners

I try to get rounded corners on a UIImage, what I read so far, the easiest way is to use a mask images. For this I used code from TheElements iPhone Example and some image resize code I found. My problem is that resizedImage is always nil and I don't find the error...
- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize
{
CGSize imageSize = [self size];
float width = imageSize.width;
float height = imageSize.height;
// scaleFactor will be the fraction that we'll
// use to adjust the size. For example, if we shrink
// an image by half, scaleFactor will be 0.5. the
// scaledWidth and scaledHeight will be the original,
// multiplied by the scaleFactor.
//
// IMPORTANT: the "targetHeight" is the size of the space
// we're drawing into. The "scaledHeight" is the height that
// the image actually is drawn at, once we take into
// account the ideal of maintaining proportions
float scaleFactor = 0.0;
float scaledWidth = targetSize.width;
float scaledHeight = targetSize.height;
CGPoint thumbnailPoint = CGPointMake(0,0);
// since not all images are square, we want to scale
// proportionately. To do this, we find the longest
// edge and use that as a guide.
if ( CGSizeEqualToSize(imageSize, targetSize) == NO )
{
// use the longeset edge as a guide. if the
// image is wider than tall, we'll figure out
// the scale factor by dividing it by the
// intended width. Otherwise, we'll use the
// height.
float widthFactor = targetSize.width / width;
float heightFactor = targetSize.height / height;
if ( widthFactor < heightFactor )
scaleFactor = widthFactor;
else
scaleFactor = heightFactor;
// ex: 500 * 0.5 = 250 (newWidth)
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
// center the thumbnail in the frame. if
// wider than tall, we need to adjust the
// vertical drawing point (y axis)
if ( widthFactor < heightFactor )
thumbnailPoint.y = (targetSize.height - scaledHeight) * 0.5;
else if ( widthFactor > heightFactor )
thumbnailPoint.x = (targetSize.width - scaledWidth) * 0.5;
}
CGContextRef mainViewContentContext;
CGColorSpaceRef colorSpace;
colorSpace = CGColorSpaceCreateDeviceRGB();
// create a bitmap graphics context the size of the image
mainViewContentContext = CGBitmapContextCreate (NULL, targetSize.width, targetSize.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
// free the rgb colorspace
CGColorSpaceRelease(colorSpace);
if (mainViewContentContext==NULL)
return NULL;
//CGContextSetFillColorWithColor(mainViewContentContext, [[UIColor whiteColor] CGColor]);
//CGContextFillRect(mainViewContentContext, CGRectMake(0, 0, targetSize.width, targetSize.height));
CGContextDrawImage(mainViewContentContext, CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledWidth, scaledHeight), self.CGImage);
// Create CGImageRef of the main view bitmap content, and then
// release that bitmap context
CGImageRef mainViewContentBitmapContext = CGBitmapContextCreateImage(mainViewContentContext);
CGContextRelease(mainViewContentContext);
CGImageRef maskImage = [[UIImage imageNamed:#"Mask.png"] CGImage];
CGImageRef resizedImage = CGImageCreateWithMask(mainViewContentBitmapContext, maskImage);
CGImageRelease(mainViewContentBitmapContext);
// convert the finished resized image to a UIImage
UIImage *theImage = [UIImage imageWithCGImage:resizedImage];
// image is retained by the property setting above, so we can
// release the original
CGImageRelease(resizedImage);
// return the image
return theImage;
}
If you are using a UIImageView to display the image you can simply do the following:
imageView.layer.cornerRadius = 5.0;
imageView.layer.masksToBounds = YES;
And to add a border:
imageView.layer.borderColor = [UIColor lightGrayColor].CGColor;
imageView.layer.borderWidth = 1.0;
I believe that you'll have to import <QuartzCore/QuartzCore.h> and link against it for the above code to work.
How about these lines...
// Get your image somehow
UIImage *image = [UIImage imageNamed:#"image.jpg"];
// Begin a new image that will be the new image with the rounded corners
// (here with the size of an UIImageView)
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);
// Add a clip before drawing anything, in the shape of an rounded rect
[[UIBezierPath bezierPathWithRoundedRect:imageView.bounds
cornerRadius:10.0] addClip];
// Draw your image
[image drawInRect:imageView.bounds];
// Get the image, here setting the UIImageView image
imageView.image = UIGraphicsGetImageFromCurrentImageContext();
// Lets forget about that we were drawing
UIGraphicsEndImageContext();
I created an UIImage-extension in swift, based on #epatel's great answer:
extension UIImage{
var roundedImage: UIImage {
let rect = CGRect(origin:CGPoint(x: 0, y: 0), size: self.size)
UIGraphicsBeginImageContextWithOptions(self.size, false, 1)
defer {
// End context after returning to avoid memory leak
UIGraphicsEndImageContext()
}
UIBezierPath(
roundedRect: rect,
cornerRadius: self.size.height
).addClip()
self.drawInRect(rect)
return UIGraphicsGetImageFromCurrentImageContext()
}
}
Tested in a storyboard:
The problem was the use of CGImageCreateWithMask which returned an all black image. The solution I found was to use CGContextClipToMask instead:
CGContextRef mainViewContentContext;
CGColorSpaceRef colorSpace;
colorSpace = CGColorSpaceCreateDeviceRGB();
// create a bitmap graphics context the size of the image
mainViewContentContext = CGBitmapContextCreate (NULL, targetSize.width, targetSize.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
// free the rgb colorspace
CGColorSpaceRelease(colorSpace);
if (mainViewContentContext==NULL)
return NULL;
CGImageRef maskImage = [[UIImage imageNamed:#"mask.png"] CGImage];
CGContextClipToMask(mainViewContentContext, CGRectMake(0, 0, targetSize.width, targetSize.height), maskImage);
CGContextDrawImage(mainViewContentContext, CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledWidth, scaledHeight), self.CGImage);
// Create CGImageRef of the main view bitmap content, and then
// release that bitmap context
CGImageRef mainViewContentBitmapContext = CGBitmapContextCreateImage(mainViewContentContext);
CGContextRelease(mainViewContentContext);
// convert the finished resized image to a UIImage
UIImage *theImage = [UIImage imageWithCGImage:mainViewContentBitmapContext];
// image is retained by the property setting above, so we can
// release the original
CGImageRelease(mainViewContentBitmapContext);
// return the image
return theImage;
Extending Besi's excellent answer, with correct scale, in Swift 4:
extension UIImage {
public func rounded(radius: CGFloat) -> UIImage {
let rect = CGRect(origin: .zero, size: size)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
UIBezierPath(roundedRect: rect, cornerRadius: radius).addClip()
draw(in: rect)
return UIGraphicsGetImageFromCurrentImageContext()!
}
}
You aren't actually doing anything other than scaling there. What you need to do is to "mask" the corners of the image by clipping it with a CGPath. For instance -
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextBeginTransparencyLayerWithRect(context, self.frame, NULL);
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGFloat roundRadius = (radius) ? radius : 12.0;
CGFloat minx = CGRectGetMinX(self.frame), midx = CGRectGetMidX(self.frame), maxx = CGRectGetMaxX(self.frame);
CGFloat miny = CGRectGetMinY(self.frame), midy = CGRectGetMidY(self.frame), maxy = CGRectGetMaxY(self.frame);
// draw the arcs, handle paths
CGContextMoveToPoint(context, minx, midy);
CGContextAddArcToPoint(context, minx, miny, midx, miny, roundRadius);
CGContextAddArcToPoint(context, maxx, miny, maxx, midy, roundRadius);
CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, roundRadius);
CGContextAddArcToPoint(context, minx, maxy, minx, midy, roundRadius);
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFill);
CGContextEndTransparencyLayer(context);
}
I suggest checking out the Quartz 2D programming guide or some other samples.
static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight)
{
float fw, fh;
if (ovalWidth == 0 || ovalHeight == 0) {
CGContextAddRect(context, rect);
return;
}
CGContextSaveGState(context);
CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect));
CGContextScaleCTM (context, ovalWidth, ovalHeight);
fw = CGRectGetWidth (rect) / ovalWidth;
fh = CGRectGetHeight (rect) / ovalHeight;
CGContextMoveToPoint(context, fw, fh/2);
CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
CGContextClosePath(context);
CGContextRestoreGState(context);
}
+ (UIImage *)imageWithRoundCorner:(UIImage*)img andCornerSize:(CGSize)size
{
UIImage * newImage = nil;
if( nil != img)
{
#autoreleasepool {
int w = img.size.width;
int h = img.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextBeginPath(context);
CGRect rect = CGRectMake(0, 0, img.size.width, img.size.height);
addRoundedRectToPath(context, rect, size.width, size.height);
CGContextClosePath(context);
CGContextClip(context);
CGContextDrawImage(context, CGRectMake(0, 0, w, h), img.CGImage);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
[img release];
newImage = [[UIImage imageWithCGImage:imageMasked] retain];
CGImageRelease(imageMasked);
}
}
return newImage;
}
I think this could be very related:
In iOS 11 there is a very elgant way of rounding each single corner of a (Image)View.
let imageView = UIImageView(image: UIImage(named: "myImage"))
imageView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
imageView.layer.cornerRadius = 10.0
I liked the answer of #samwize, however it caused me nasty memory leaks when used with collectionView.
To fix it I found that UIGraphicsEndImageContext() was missing
extension UIImage {
/**
Rounds corners of UIImage
- Parameter proportion: Proportion to minimum paramter (width or height)
in order to have the same look of corner radius independetly
from aspect ratio and actual size
*/
func roundCorners(proportion: CGFloat) -> UIImage {
let minValue = min(self.size.width, self.size.height)
let radius = minValue/proportion
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: self.size)
UIGraphicsBeginImageContextWithOptions(self.size, false, 1)
UIBezierPath(roundedRect: rect, cornerRadius: radius).addClip()
self.draw(in: rect)
let image = UIGraphicsGetImageFromCurrentImageContext() ?? self
UIGraphicsEndImageContext()
return image
}
}
Feel free to just pass the radius instead of proportion. proportion is used because I have collectionView scroll and images have different sizes, therefore when using constant radius it actually looks different in terms of proprtions (example: two images, one is 1000x1000 and another 2000x2000, corner radius of 30 will look different on each one of them)
So if you do image.roundCorners(proportion: 20) all the pictures look like the have the same corner radius.
This answer is also an updated version.
The reason it worked with clipping, not with masking, seems to be the color space.
Apple Documentation's below.
mask
A mask. If the mask is an image, it must be in the DeviceGray color space, must not have an alpha component, and may not itself be masked by an image mask or a masking color. If the mask is not the same size as the image specified by the image parameter, then Quartz scales the mask to fit the image.
Hi guys try this code,
+ (UIImage *)roundedRectImageFromImage:(UIImage *)image withRadious:(CGFloat)radious {
if(radious == 0.0f)
return image;
if( image != nil) {
CGFloat imageWidth = image.size.width;
CGFloat imageHeight = image.size.height;
CGRect rect = CGRectMake(0.0f, 0.0f, imageWidth, imageHeight);
UIWindow *window = [[[UIApplication sharedApplication] windows] objectAtIndex:0];
const CGFloat scale = window.screen.scale;
UIGraphicsBeginImageContextWithOptions(rect.size, NO, scale);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextBeginPath(context);
CGContextSaveGState(context);
CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect));
CGContextScaleCTM (context, radious, radious);
CGFloat rectWidth = CGRectGetWidth (rect)/radious;
CGFloat rectHeight = CGRectGetHeight (rect)/radious;
CGContextMoveToPoint(context, rectWidth, rectHeight/2.0f);
CGContextAddArcToPoint(context, rectWidth, rectHeight, rectWidth/2.0f, rectHeight, radious);
CGContextAddArcToPoint(context, 0.0f, rectHeight, 0.0f, rectHeight/2.0f, radious);
CGContextAddArcToPoint(context, 0.0f, 0.0f, rectWidth/2.0f, 0.0f, radious);
CGContextAddArcToPoint(context, rectWidth, 0.0f, rectWidth, rectHeight/2.0f, radious);
CGContextRestoreGState(context);
CGContextClosePath(context);
CGContextClip(context);
[image drawInRect:CGRectMake(0.0f, 0.0f, imageWidth, imageHeight)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
return nil;
}
Cheers !!!
It's very easy to create a rounded image when you make use of the image dimension.
cell.messageImage.layer.cornerRadius = image.size.width / 2
cell.messageImage.layer.masksToBounds = true
Found out the best and simple way of doing it is as follows (no answer did that):
UIImageView *imageView;
imageView.layer.cornerRadius = imageView.frame.size.width/2.0f;
imageView.layer.masksToBounds = TRUE;
Pretty simple and done this right.
See here...
IMO unless you absolutely need to do it in code, just overlay an image on top.
Something along the lines of...
- (void)drawRect:(CGRect)rect
{
// Drawing code
[backgroundImage drawInRect:rect];
[buttonOverlay drawInRect:rect];
}
For Creating a Round Corner image we can use quartzcore.
First How to add QuartzCore framework?
Click project -Targets
->project
->BuildPhase
->Link Binary with Libraries
->Then click + symbol finally select from list and add it
or else
Click project -Targets
->Targets
->general
->Linked Frameworks and Libraries
->Then click + symbol finally select from list and add the QuartzCore framework
Now import
#import <QuartzCore/QuartzCore.h>
in your ViewController
Then in viewDidLoad method
self.yourImageView.layer.cornerRadius = 5.0;
self.yourImageView.layer.borderWidth = 1.0f;
self.yourImageView.layer.borderColor = [UIColor blackColor].CGColor;
self.yourImageView.layer.masksToBounds = YES;
I was struggling to round the corners of a UIImage box in my storyboard. I had a IBOutlet for my UIImage called image. After reading a bunch of posts on here, I simply added 3 lines and that worked perfectly.
import UIKit
Then in viewDidLoad:
image.layer.cornerRadius = 20.0
image.layer.masksToBounds = true
This is for iOS 11.1 in Xcode 9.