I have an image in an UIScrollView, that can be scrolled and zoomed.
When the user presses a button, I want the code to create an image from whatever part of the UIScrollView is inside an area I specify with a CGRect.
I've seen code to crop UIImages, but I can't adapt it to do the same for a view, because it uses CGContextDrawImage.
Any thoughts?
Cheers,
Andre
I've managed to get it.
Here's my solution, based on a few different ones from the web:
- (UIImage *)imageByCropping:(UIScrollView *)imageToCrop toRect:(CGRect)rect
{
CGSize pageSize = rect.size;
UIGraphicsBeginImageContext(pageSize);
CGContextRef resizedContext = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(resizedContext, -imageToCrop.contentOffset.x, -imageToCrop.contentOffset.y);
[imageToCrop.layer renderInContext:resizedContext];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
which you call by using:
CGRect clippedRect = CGRectMake(0, 0, 320, 300);
picture.image = [self imageByCropping:myScrollView toRect:clippedRect];
Related
I am interested in building a Collage style app for the IPhone and IPad. I have been looking at other apps and trying to work out the method that they use to create the final image.
I am guessing that the app has a UIView and then each individual image is a UIImageView and is a subview of the main UIView. The user is then able to move each UIImageView and position them as they intend.
Now my question is, after the user has positioned all the UIImageViews on screen how do you then create the final image from what is on the screen. This of course takes into account that you will be upscaling the images to create lets say an A4 sized final print.
Can anyone share some information?
Thanks
You should take a look at CGContext Reference. You can do something like the following to combine imageView 1 and 2 to imageView 3.
Sample Code :
UIGraphicsBeginImageContext(imageView1.image.size);
CGRect rect = CGRectMake(0, 0, imageView1.image.size.width, imageView1.image.size.height);
[imageView1.image drawInRect:rect];
[imageView2.image drawInRect:rect blendMode:kCGBlendModeScreen alpha:0.5];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[imageView3 setImage:resultingImage];
GoodLuck !!!
If you use an UIView to include more 2 Images to merge, that you can try to capture the view to be an image to use.
//Capture View to Image
-(UIImage *)captureImageFromView
{
UIView *theView = self; //self extends UIView
if( NULL != UIGraphicsBeginImageContextWithOptions )
{
UIGraphicsBeginImageContextWithOptions(theView.bounds.size, NO, 2.0f);
}
else
{
//iOS 4.0
UIGraphicsBeginImageContext(theView.frame.size);
}
[theView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *captureImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return captureImage;
}
//Merge 2 Images to be an Image.
-(UIImage *)mergeBaseImage:(UIImage *)_baseImage
underImage:(UIImage *)_underImage
matchBaseImageSize:(BOOL)_matchBaseImageSize
{
UIGraphicsBeginImageContext(_baseImage.size);
[_baseImage drawInRect:CGRectMake(0, 0, _baseImage.size.width, _baseImage.size.height)];
if( _matchBaseImageSize )
{
[_underImage drawInRect:CGRectMake(0, 0, _baseImage.size.width, _baseImage.size.height)];
}
else
{
[_underImage drawInRect:CGRectMake(0, 0, _underImage.size.width, _underImage.size.height)];
}
UIImage *_mergedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return _mergedImage;
}
Wish it can help you.
I have got a UITableView, and I want to capture the visible portion of it, and put it into a UIImage. Any way of doing this?
EDIT
Self-answered below
Thanks for the replies. All of the answers would work with a UIView, but not with a UITableView - at least not when the table has scrolled. When scrolled, the captured image would appear black or transparent. I had tried similar solutions as the ones below before. I guess people assumed the answer was obvious, and that's why I was down-voted - for being naughty enough to ask such an obvious question.
Anyway, the real solution is that you have to use the table's contentOffset:
- (UIImage *) imageWithTableView:(UITableView *)tableView
{
UIView *renderedView = tableView;
CGPoint tableContentOffset = tableView.contentOffset;
UIGraphicsBeginImageContextWithOptions(renderedView.bounds.size, renderedView.opaque, 0.0);
CGContextRef contextRef = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(contextRef, 0, -tableContentOffset.y);
[tableView.layer renderInContext:contextRef];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
UIGraphicsBeginImageContext(someView.bounds.size);
[someView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Taken from this question.
- (UIImage *)captureView {
//hide controls if needed
CGRect rect = [yourTableView bounds];
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[yourTableview.layer renderInContext:context];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
UIGraphicsBeginImageContext(tableView.bounds.size);
[tableView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Maybe those posts will be helpful
Rendering UIView with its children
Saving UIView contents in iOS 4 with real size of the images inside (i.e. scale contentes up for save)
Safe way to render UIVIew to an image on background thread?
I am working on creating an image gallery which has thumbnails in different sizes. I want to convert these rectangle thumbnails to square size so that all of them could appear similar in size. I dont mind cropping it from extended portion but I am not sure how to do it. can anyone please help me?
Thanks
Pankaj
You need to use the image in rect method passing in the image and the required bounds...
CGImageRef imageRef = CGImageCreateWithImageInRect([anImage CGImage], requiredBounds);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
I have added this to a UIImage category (UIImage+Resize) in the following post, you can download the source code as well - Categories example
Well if you use an UIImageView to display your images (wich I am more than sure that you do) you can set it's contentMode property to UIViewContentModeScaleAspectFill. This should 'crop' your image to the boundaries of your UIImageView. In case your image will go out of the boundaries of the UIImageView make sure clipsToBounds is also set to YES.
Let me know if that helps.
I'm using the next method. The input are the UIImage to scale and the size of the UIImageView's frame where the UIImage is. It works when the frame's height and width are equal.
One important thing: I keep the image's ratio. I don't expand the image to cover the full square. If you want to do it you have to change the 'drawInRect' line for [self drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; and remove the if-else.
- (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
CGFloat scaleRatio;
if (image.size.width > image.size.height) {
scaleRatio = image.size.height/image.size.width;
}else{
scaleRatio = image.size.width/image.size.height;
}
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(scaleRatio, scaleRatio);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextConcatCTM(context, scaleTransform);
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
if (image.size.width > image.size.height) {
[image drawInRect:CGRectMake(0, (newSize.height/2)-(newSize.height*scaleRatio/2), newSize.width, newSize.height*scaleRatio)];
}else{
[image drawInRect:CGRectMake((newSize.width/2)-(newSize.width*scaleRatio/2), 0, newSize.width*scaleRatio, newSize.height)];
}
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
I have a UIImageView that I want to resize when you press a button. I haven't been able to find any on other forums or sources.
Any help appreciated,
user826671
Let me google it for you http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/
I have made a sample using slider control.
You can activate this slider on your button press and use it to increase or decrease the size of the images
https://github.com/manishnath/Code/tree/master/zommin
-(void) onButtonClick
{
CGRect frameRect = temp.frame; //temp ur UIMAGEVIEW
frameRect.size.width= your_width;
frameRect.size.height= height;
temp.frame=frameRect;
}
If its about UIImage, you can do it by this way. For UIImageView you can change its frame size.
- (UIImage *) resizeImage:(UIImage *)image newWidth:(CGFloat)width
newHeight: (CGFloat)height
{
CGRect area = CGRectMake(0, 0, width,height);
CGSize size = area.size;
UIGraphicsBeginImageContext(size);
[image drawInRect:area];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
If you want to resize the image view itself, do like
CGRect newRect = imageView.frame;
newRect.size.width = reqWidth;
newRect.size.height = reqHeight;
imageView.frame = newRect;
The image will also be resized if the imageview has the contentMode property UIViewContentModeScaleAspectFit.
I want to know, how can I erase a custom rect (with, for example, an UIView in IB or something else) of an UIImageView in order to display an other UIImageView positioned underneath.
I didn't manage to do it using some response in the forum...
This will clear a rect in an image:
- (UIImage *)clearRect:(CGRect)rect inImage:(UIImage *)image {
if (UIGraphicsBeginImageContextWithOptions != NULL)
UIGraphicsBeginImageContextWithOptions([image size], NO, 0.0);
else
UIGraphicsBeginImageContext([image size]);
CGContextRef context = UIGraphicsGetCurrentContext();
[image drawInRect:CGRectMake(0.0, 0.0, [image size].width, [image size].height)];
CGContextClearRect(context, rect);
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
Just load your image and clear the rects before assigning it to the image view:
UIImage *image = [UIImage imageNamed:#"Image.png"];
UIImage *maskedImage = [self clearRect:CGRectMake(10.0, 10.0, 50.0, 50.0) inImage:image];
[imageView setImage:maskedImage];
probably not the best solution but you can do the other way and take the 4 parts around the rect separately and combine them afterwards without the inner rect. You would repeat this as long as you have rect's to crop out.
You cannot clear the UIImageView itself because this just draws the UIImage. So you have erase the rect in the UIImage. Create a bitmap context, draw the image into it. Erase the part you want to "see through" with CGContextClearRect. When create a new new image from the bitmap context.