I have some transformable UIImageViews (decorates on a photo), which user can drag, pinch and rotate. After editing, I want the app to generate the final image. How can I draw the UIImageViews with their transform property considered.
My first solution is using renderInContext, but it can only generate a 320x480 image. Can I generate an image with any resolution?
Then I use code as follows:
UIGraphicsBeginImageContext(CGSizeMake(640.0f, 896.0f));
CGContextRef currentContext = UIGraphicsGetCurrentContext();
UIImage *backgroundImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"fittingBackground" ofType:#"jpg"]];
[backgroundImage drawInRect:CGRectMake(0.0f, 0.0f, 640.0f, 896.0f)];
CGContextSaveGState(currentContext);
CGContextConcatCTM(currentContext, self.photoImageView.transform);
CGRect photoFrame = self.photoImageView.frame;
[self.photoImageView.image drawInRect:CGRectMake(photoFrame.origin.x * 2, photoFrame.origin.y * 2, photoFrame.size.width * 2, photoFrame.size.height * 2)];
CGContextRestoreGState(currentContext);
CGContextSaveGState(currentContext);
CGContextConcatCTM(currentContext, self.productImageView.transform);
CGRect productFrame = self.productImageView.frame;
[self.productImageView.image drawInRect:CGRectMake(productFrame.origin.x * 2, productFrame.origin.y * 2, productFrame.size.width * 2, productFrame.size.height * 2)];
CGContextRestoreGState(currentContext);
UIImage *resultImage = [UIImage imageWithCGImage:CGBitmapContextCreateImage(currentContext)];
UIGraphicsEndImageContext();
However, the result seems to be weird. And I've logged the frame, bounds and center. I don't know which Rect should I use in drawInRect after applying transform?
Try this,
-(void)drawBackgroundInLayer:(CALayer*)destinationLayer {
CGFloat scaledFactor = [[UIScreen mainScreen] scale];
CGRect layerFrame = destinationLayer.frame;
CGRect scaledRect = CGRectMake(layerFrame.origin.x,
layerFrame.origin.y,
(layerFrame.size.width)*scaledFactor,
(layerFrame.size.height)*scaledFactor);
// Get the size and do some drawings
CGSize sizeBack = CGSizeMake(layerFrame.size.width*scaledFactor, layerFrame.size.height*scaledFactor);
UIGraphicsBeginImageContext(sizeBack);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(context, 0., 0., 0., 1.);
drawBorder(context, scaledRect);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (destinationLayer) {
[destinationLayer setContents:(id)img.CGImage];
}
}
The most important lines are
UIGraphicsBeginImageContext(sizeBack);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
Related
Currently I'm applying a corner radius and shadow to multiple UIView's in a scrollview. I've noticed that adding a corner radius and shadow makes the scrollview lag like crazy whenever I scroll. How can I apply these affects without having my performance suffer?
Try by setting also the shadowPath of the layer:
view.layer.cornerRadius=6.0f;
view.layer.borderWidth=2.0f;
view.layer.borderColor=[UIColor grayColor].CGColor;
view.layer.shadowColor = [UIColor blackColor].CGColor;
view.layer.shadowOpacity = 0.3f;
view.layer.shadowOffset = CGSizeMake(0, 0.0f);
view.layer.masksToBounds = NO;
UIBezierPath *path = [UIBezierPath bezierPathWithRect:view.bounds];
view.layer.shadowPath = path.CGPath;
+(UIImage *)makeRoundCornerImage : (UIImage*) img : (int) cornerWidth : (int) cornerHeight
{
UIImage * newImage = nil;
if( nil != img)
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
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, cornerWidth, cornerHeight);
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);
[pool release];
}
return newImage;
}
// With the help of This method we can create the round corner of any PNG file
UIImage *imageFromFile = [UIImage imageNamed:#"FilterFields.png"];
imageFromFile = [ImageManipulator
makeRoundCornerImage:imageFromFile : 10 : 10];
[SmallTable setImage:imageFromFile];
Problem: I have an three UIImageViews. One has an UIImage and the other two are namely - leftImageView & rightImageView. The leftImageView has the left half of the image and the right one has the other. I am trying to achieve this using Coregraphics, i.e. drawing an image in the two imageviews.
But the right imageview isn't showing up. Refer to the code below:
UIImage *image = imgView.image;
CGSize sz = [image size];
CGRect leftRect = CGRectMake(0, 0, imgView.frame.size.width/2, imgView.frame.size.height);
CGRect rightRect = CGRectMake(imgView.frame.size.width/2, 0, imgView.frame.size.width/2, imgView.frame.size.height);
CGImageRef leftReference = CGImageCreateWithImageInRect([image CGImage], leftRect);
CGImageRef rightReference = CGImageCreateWithImageInRect([image CGImage], rightRect);
// Left Image ...
UIGraphicsBeginImageContextWithOptions(CGSizeMake(leftRect.size.width, leftRect.size.height), NO, 0);
CGContextRef con = UIGraphicsGetCurrentContext();
CGContextDrawImage(con, leftRect,flip(leftReference));
imgViewLeft = [[UIImageView alloc] initWithImage:UIGraphicsGetImageFromCurrentImageContext()];
UIGraphicsEndImageContext();
[self.view addSubview:imgViewLeft];
// Right Image ...
UIGraphicsBeginImageContextWithOptions(CGSizeMake(rightRect.size.width, rightRect.size.height), NO, 0);
con = UIGraphicsGetCurrentContext();
CGContextDrawImage(con, rightRect,flip(rightReference));
imgViewRight = [[UIImageView alloc] initWithImage:UIGraphicsGetImageFromCurrentImageContext()];
UIGraphicsEndImageContext();
[self.view addSubview:imgViewRight];
I think that you can use the following code part.
UIImage *image = [UIImage imageNamed:#"xxx.png"]; // You can change this line.
BOOL isLeft = YES; // You can change this variable(isLeft = YES : left piece, NO : right piece).
UIGraphicsBeginImageContext(CGSizeMake(image.size.width / 2, image.size.height));
CGContextRef context = UIGraphicsGetCurrentContext();
if (isLeft)
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, image.size.width, image.size.height), image.CGImage);
else
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(- image.size.width / 2, 0, image.size.width, image.size.height), image.CGImage);
UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageCopy;
I couldn't launch this code now, but I think that my code is almost correct. Please try this.
Edit :
In your code :
// Right Image ...
UIGraphicsBeginImageContextWithOptions(CGSizeMake(rightRect.size.width, rightRect.size.height), NO, 0);
con = UIGraphicsGetCurrentContext();
CGContextDrawImage(con, rightRect,flip(rightReference));
imgViewRight = [[UIImageView alloc] initWithImage:UIGraphicsGetImageFromCurrentImageContext()];
UIGraphicsEndImageContext();
There is a wrong part in the third line :
CGContextDrawImage(con, rightRect,flip(rightReference));
It should be
CGContextDrawImage(con, leftRect,flip(rightReference));
rotateI am trying to rotate my images by 90 degrees. It works without the rotate, but when I rotate and translate it doesn't show. What am i doing wrong?
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"check" ofType:#"jpg"];
UIImage *newImage = [[UIImage alloc] initWithContentsOfFile:filePath];
UIGraphicsBeginImageContext(newImage.size);
//CGContextRef c = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), newImage.size.width, 0);
//CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, newImage.size.width);
//CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0);
CGContextRotateCTM(UIGraphicsGetCurrentContext(), 90);
CGRect imageRect = CGRectMake(0, 0, newImage.size.height, newImage.size.width);
CGContextDrawImage(UIGraphicsGetCurrentContext(), imageRect, newImage.CGImage);
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
ImageView.image = viewImage;
I would suggest using image view and use it's transform like so:
UIImage *newImage = [[UIImage alloc] initWithContentsOfFile:filePath];
UIImageView *newImageView = [[UIImageView alloc] initWithImage:newImage];
newImageView.transform = CGAffineTransformMakeRotation(M_PI_2);
You should do:
UIGraphicsBeginImageContext(newImage.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextRotateCTM (context, 90* M_PI/180); //Degrees should be in radians.
[newImage drawAtPoint:CGPointMake(0, 0)];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
Good luck.
UPDATE:
Actually, this is a duplicate from How to Rotate a UIImage 90 degrees?
The problem was my define statement and I needed to flip the image. Here is the completed code: ( The image has to be perfect because an OCR process the image and if it's even a little off, it gets rejected.
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSaveGState(c);
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"check" ofType:#"jpg"];
UIImage *newImage = [[UIImage alloc] initWithContentsOfFile:filePath];
NSLog(#"Rect width: %#", NSStringFromCGSize(newImage.size) );
UIGraphicsBeginImageContext(newImage.size);
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, newImage.size.width);
CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0);
CGContextTranslateCTM( UIGraphicsGetCurrentContext(), 0.5f * newImage.size.width, 0.5f * newImage.size.height ) ;
CGContextRotateCTM( UIGraphicsGetCurrentContext(), radians( -90 ) ) ;
CGRect imageRect = CGRectMake(-(newImage.size.height* 0.5f) + 200, -(0.5f * newImage.size.width) + 200 , newImage.size.height - 200, newImage.size.width - 200);
CGContextDrawImage(UIGraphicsGetCurrentContext(), imageRect, newImage.CGImage);
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
ImageView.image = viewImage;
CGContextRestoreGState(c);
I am performing rotation on an UIImageView and then i try to crop a part of it and save it as an UIImage. The UIImageView rotates however it always crops the same part of the photo. So the cropping does not take into account the image rotation. What am i doing wrong?
//rotate image
CGRect new = CGRectMake(0, 0, 100, 50);
CGAffineTransform rotation = CGAffineTransformMakeRotation(5);
[photo setTransform:rotation];
// crop image
CGImageRef imageRef = CGImageCreateWithImageInRect([photo.image CGImage], new);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
// display crop bounds
UIView* faceBounds = [[UIView alloc] initWithFrame:new];
faceBounds.layer.borderWidth = 2;
faceBounds.layer.borderColor = [[UIColor redColor] CGColor];
Use the following snippet for rotating image data.
The input data is inAngle (angle in radians) and inImage (UIImage instance).
What this does, it creates an image context, applies the transformation to it and draws the original image into that context. The resulting image data will now be stored in resultImage.
The first three lines handle the calculation of the bounding result image frame.
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, inImage.size.width, inImage.size.height)];
rotatedViewBox.transform = CGAffineTransformMakeRotation(inAngle);
CGSize rotatedSize = rotatedViewBox.frame.size;
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(bitmap, rotatedSize.width / 2.0f, rotatedSize.height / 2.0f);
CGContextRotateCTM(bitmap, inAngle);
CGContextScaleCTM(bitmap, 1.0f, -1.0f);
CGContextDrawImage(bitmap, CGRectMake(-inImage.size.width / 2.0f,
-inImage.size.height / 2.0f,
inImage.size.width,
inImage.size.height),
inImage.CGImage);
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
This is too late for now but For now someone can try this
I have a problem regarding irregular shape. I searched a lot but nothing was useful for me. I have a number of frames of irregular shape and each frame is again divided into sub areas. I want to fit images from photo library in each sub areas of frame. But i am unable to get location of each sub areas and since shape is also irregular so again another problem to fit image in that area. Can anyone help me !! This is an example of that frame.
You can never have irregular shaped frames. Frames will always in rect shape.
You can have it done by detecting transparent areas.
Refer this link. It will give you idea how to do that :)
Do you want to clip the various images by the arc of the circle? For example, here is a screen snapshot with four images (just random images I got from a search for dogs on http://images.google.com):
And here are the same four images cropped by a circle (or more accurately, each of the four images were separately cropped by the same circle path):
Here is the code that does that
- (UIImage *)cropImage:(UIImage *)image locatedAt:(CGRect)imageFrame byCircleAt:(CGPoint)center withRadius:(float)radius
{
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, imageFrame.size.width, imageFrame.size.height, 8, 4 * imageFrame.size.width, colorSpace, kCGImageAlphaPremultipliedFirst);
CGContextBeginPath(context);
CGRect ellipseFrame = CGRectMake(center.x - imageFrame.origin.x - radius, imageFrame.size.height - (center.y - imageFrame.origin.y - radius) - radius * 2.0, radius * 2.0, radius * 2.0);
CGContextAddEllipseInRect(context, ellipseFrame);
CGContextClosePath(context);
CGContextClip(context);
CGContextDrawImage(context, CGRectMake(0, 0, imageFrame.size.width, imageFrame.size.height), image.CGImage);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
UIImage *newImage = [UIImage imageWithCGImage:imageMasked];
CGImageRelease(imageMasked);
return newImage;
}
- (void)addSingleCroppedImage:(UIImage *)image at:(CGRect)imageFrame byCircleAt:(CGPoint)center withRadius:(float)radius
{
UIImage *newImage = [self cropImage:image locatedAt:imageFrame byCircleAt:center withRadius:radius];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:imageFrame];
imageView.image = newImage;
[self.view addSubview:imageView];
}
- (void)addCroppedImages
{
NSString *bundlePath = [[NSBundle mainBundle] resourcePath];
CGPoint center = CGPointMake(self.view.frame.size.width / 2.0, self.view.frame.size.width / 2.0);
float radius = 150.0;
UIImage *dog1 = [UIImage imageWithContentsOfFile:[bundlePath stringByAppendingPathComponent:#"imgres-1.jpg"]];
UIImage *dog2 = [UIImage imageWithContentsOfFile:[bundlePath stringByAppendingPathComponent:#"imgres-2.jpg"]];
UIImage *dog3 = [UIImage imageWithContentsOfFile:[bundlePath stringByAppendingPathComponent:#"imgres-3.jpg"]];
UIImage *dog4 = [UIImage imageWithContentsOfFile:[bundlePath stringByAppendingPathComponent:#"imgres-4.jpg"]];
CGRect frame;
UIImage *currentImage;
// upper left
currentImage = dog1;
frame = CGRectMake(center.x - currentImage.size.width, center.y - currentImage.size.height, currentImage.size.width, currentImage.size.height);
[self addSingleCroppedImage:currentImage at:frame byCircleAt:center withRadius:radius];
// upper right
currentImage = dog2;
frame = CGRectMake(center.x, center.y - currentImage.size.height, currentImage.size.width, currentImage.size.height);
[self addSingleCroppedImage:currentImage at:frame byCircleAt:center withRadius:radius];
// lower left
currentImage = dog3;
frame = CGRectMake(center.x - currentImage.size.width, center.y, currentImage.size.width, currentImage.size.height);
[self addSingleCroppedImage:currentImage at:frame byCircleAt:center withRadius:radius];
// lower right
currentImage = dog4;
frame = CGRectMake(center.x, center.y, currentImage.size.width, currentImage.size.height);
[self addSingleCroppedImage:currentImage at:frame byCircleAt:center withRadius:radius];
}