crop a zoomed image in ImageView inside scrollView - iphone

I already do Lot of efforts from my Side. finally I need help. thanks
Goal :
1) How I fit imageView inside ScrollView
2) How I crop a zoomed Image in inside scrollView.
I have a imageView inside Scroll View. I wants crop image after zoomed which is display inside scrollview boundary. I cropped image already but it not exactly same which i wants.
Here I set backgroundColor Black to my scrollView. And when I place imageView inside it, it's not fit.
after zoom image inside scroll view is
and after crop image is
and my code is here :
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect frame1 = CGRectMake(50,50,200,200);
CGRect frame2 = CGRectMake(50,50,200,200);
imageView1=[[UIImageView alloc]initWithFrame:frame1];
imageView1.image= [UIImage imageNamed:#"back.jpeg"];
imageView1.backgroundColor=[UIColor brownColor];
imageView1.contentMode = UIViewContentModeScaleAspectFit;
scroll=[[UIScrollView alloc]initWithFrame:frame2];
scroll.backgroundColor=[UIColor blackColor];
[scroll addSubview:imageView1];
scroll.delegate=self;
[self.view addSubview:scroll];
[self setContentSizeForScrollView];
self.imageView1.userInteractionEnabled = YES;
}
setting scroll view contentSize
-(void)setContentSizeForScrollView
{
// scroll.contentSize = CGSizeMake(imageView1.frame.size.width,imageView1.frame.size.height);
scroll.contentSize = CGSizeMake(200, 200);
scroll.minimumZoomScale = .50;
scroll.maximumZoomScale = 1.5;
}
and my crop logic is
-(IBAction)cropButtonClicked
{
//Calculate the required area from the scrollview
CGRect rect = CGRectMake(50, 50, 200,200);
UIImage *image = [self imageByCropping:imageView1.image toRect:rect];
imageView1.image=image;
imageView1.contentMode = UIViewContentModeScaleAspectFit;
}
And this method crop image :
- (UIImage*)imageByCropping:(UIImage *)myImage toRect:(CGRect)cropToArea{
CGImageRef cropImageRef = CGImageCreateWithImageInRect(myImage.CGImage, cropToArea);
UIImage* cropped = [UIImage imageWithCGImage:cropImageRef];
CGImageRelease(cropImageRef);
return cropped;
}

Answer of my own Question : After many efforts i found the answer of both of my questions.
and it work good for me. I share here, may be it help someone. :)
1) Fit image View inside Scroll View. I use this link
- (void)centerScrollViewContents {
CGSize boundsSize = scroll.bounds.size;
CGRect contentsFrame = self.imageView1.frame;
if (contentsFrame.size.width < boundsSize.width) {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0f;
}
else {
contentsFrame.origin.x = 0.0f;
}
if (contentsFrame.size.height < boundsSize.height) {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0f;
}
else {
contentsFrame.origin.y = 0.0f;
}
self.imageView1.frame = contentsFrame;
}
2) Crop a zoomed Image in inside scrollView. I use this link
UIGraphicsBeginImageContext(CGSizeMake(200, 200));
[scroll.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *fullScreenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageView1.contentMode = UIViewContentModeScaleAspectFill;
UIImageWriteToSavedPhotosAlbum(fullScreenshot, nil, nil, nil);
return fullScreenshot;

I had a similar problem recently, I got the solution using the relative idea ( Xa,b = Xa,c - Xb,c )
-(IBAction)crop:(id)sender{
// F = frame
// i = image
// iv = imageview
// sv = self.view
// of = offset
//Frame Image in imageView coordinates
CGRect Fi_iv = [self frameForImage:self.image inImageViewAspectFit:self.imageView];
//Frame ImageView in self.view coordinates
CGRect Fiv_sv = self.imageView.frame;
//Frame Image in self.view coordinates
CGRect Fi_sv = CGRectMake(Fi_iv.origin.x + Fiv_sv.origin.x
,Fi_iv.origin.y + Fiv_sv.origin.y,
Fi_iv.size.width, Fi_iv.size.height);
//ScrollView offset
CGPoint offset = self.scrollView.contentOffset;
//Frame Image in offset coordinates
CGRect Fi_of = CGRectMake(Fi_sv.origin.x - offset.x,
Fi_sv.origin.y - offset.y,
Fi_sv.size.width,
Fi_sv.size.height);
CGFloat scale = self.imageView.image.size.width/Fi_of.size.width;
//the crop frame in image offset coordinates
CGRect Fcrop_iof = CGRectMake((self.cropView.frame.origin.x - Fi_of.origin.x)*scale,
(self.cropView.frame.origin.y - Fi_of.origin.y)*scale,
self.cropView.frame.size.width*scale,
self.cropView.frame.size.height*scale);
UIImage *image = [self image:self.imageView.image cropRect:Fcrop_iof];
// Use this crop image...
You can crop the image using:
//Use this code to crop when you have the right frame
-(UIImage*)image:(UIImage *)image cropRect:(CGRect)frame
{
// Create a new UIImage
CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, frame);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return croppedImage;
}
Since you are using the ImageView in Aspect Fit, you need to calculate the image frame inside the imageView
-(CGRect)frameForImage:(UIImage*)image inImageViewAspectFit:(UIImageView*)imageView
{
float imageRatio = image.size.width / image.size.height;
float viewRatio = imageView.frame.size.width / imageView.frame.size.height;
if(imageRatio < viewRatio)
{
float scale = imageView.frame.size.height / image.size.height;
float width = scale * image.size.width;
float topLeftX = (imageView.frame.size.width - width) * 0.5;
return CGRectMake(topLeftX, 0, width, imageView.frame.size.height);
}
else
{
float scale = imageView.frame.size.width / image.size.width;
float height = scale * image.size.height;
float topLeftY = (imageView.frame.size.height - height) * 0.5;
return CGRectMake(0, topLeftY, imageView.frame.size.width, height);
}
}
I hope this code can work for you as it worked for me.
Best,
Rafael.

Related

Get the size of an image after resizing in iPhone sdk

I have image view on which i am displaying image selected from library. To display the fine quality picture i used to rescale the picture using below method. The image quality i am getting is perfect but i need to set the imageView frame according to the size of newly created image. but when i use newImage.size.width it is giving me the width of original image view. Please help me to set the image view frame according to displayed image size. Thanks in advance
-(UIImage *)scaleImage:(UIImage *)img toRectSize:(CGRect)screenRect
{
UIGraphicsBeginImageContext(screenRect.size);
float hfactor = img.size.width / screenRect.size.width;
float vfactor = img.size.height / screenRect.size.height;
float factor = MAX(hfactor, vfactor);
float newWidth = img.size.width / factor;
float newHeight = img.size.height / factor;
float leftOffset = (screenRect.size.width - newWidth) / 2;
float topOffset = (screenRect.size.height - newHeight) / 2;
CGRect newRect = CGRectMake(leftOffset, topOffset, newWidth, newHeight);
[img drawInRect:newRect blendMode:kCGBlendModePlusDarker alpha:1];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Try this code that I used for resizing image and you will get the new frame as well.The ratio seem to be fixed but you can change it as per your requirement.
-(UIImage*)ImageResize:(UIImage*)image
{
if(image==NULL)
{
return NULL;
}
else
{
float actualHeight = image.size.height;
float actualWidth = image.size.width;
float imgRatio = actualWidth/actualHeight;
float maxRatio = 130.0/160.0;
if(imgRatio!=maxRatio)
{
if(imgRatio < maxRatio)
{
imgRatio = 160.0 / actualHeight;
actualWidth = imgRatio * actualWidth;
actualHeight = 160.0;
}
else
{
imgRatio = 130.0 / actualWidth;
actualHeight = imgRatio * actualHeight;
actualWidth = 130.0;
}
}
CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
UIGraphicsBeginImageContext(rect.size);
[image drawInRect:rect];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
}
The below code can be used for specific image size that you can pass.
-(UIImage *)thumbnailWithImageWithoutScale:(UIImage *)image size:(CGSize)wantSize
{
UIImage * targetImage;
if (nil == image) {
targetImage = nil;
}else{
CGSize size = image.size;
CGRect rect;
if (wantSize.width/wantSize.height > size.width/size.height) {
rect.size.width = wantSize.height*size.width/size.height;
rect.size.height = wantSize.height;
rect.origin.x = (wantSize.width - rect.size.width)/2;
rect.origin.y = 0;
} else{
rect.size.width = wantSize.width;
rect.size.height = wantSize.width*size.height/size.width;
rect.origin.x = 0;
rect.origin.y = (wantSize.height - rect.size.height)/2;
}
UIGraphicsBeginImageContext(wantSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]);
UIRectFill(CGRectMake(0, 0, wantSize.width, wantSize.height));//clear background
[image drawInRect:rect];
targetImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
return targetImage;
}
Try this,
resizedImage = [self imageWithImage:originalImage scaledToSize:CGSizeMake(45,45)];
self.imageView.image = resizedImage;
- (UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize
{
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Are you using Autolayout?
If yes you have to change width and height constraints of your image view not the frame (you can create outlets of them in the same way as you do for other controls).
For autolayout you can change frame in viewDidAppear method (in viewWillAppear or viewWillLoad it may not work.

iOS Custom UIImagePickerController Camera Crop to Square

I'm trying to create a camera like Instagram where the user can see a box and the image would crop to that box. For Some reason the camera doesn't go all the way to the bottom of the screen and cuts off near the end. I'm also wondering how would I go about cropping the image to be 320x320 exactly inside that square?
Here's the easiest way to do it (without reimplementing UIImagePickerController). First, use an overlay to make the camera field look square. Here's an example for 3.5" screens (you'd need to update it to work for iPhone 5):
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.sourceType = source;
if (source == UIImagePickerControllerSourceTypeCamera) {
//Create camera overlay
CGRect f = imagePickerController.view.bounds;
f.size.height -= imagePickerController.navigationBar.bounds.size.height;
CGFloat barHeight = (f.size.height - f.size.width) / 2;
UIGraphicsBeginImageContext(f.size);
[[UIColor colorWithWhite:0 alpha:.5] set];
UIRectFillUsingBlendMode(CGRectMake(0, 0, f.size.width, barHeight), kCGBlendModeNormal);
UIRectFillUsingBlendMode(CGRectMake(0, f.size.height - barHeight, f.size.width, barHeight), kCGBlendModeNormal);
UIImage *overlayImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *overlayIV = [[UIImageView alloc] initWithFrame:f];
overlayIV.image = overlayImage;
[imagePickerController.cameraOverlayView addSubview:overlayIV];
}
imagePickerController.delegate = self;
[self presentViewController:imagePickerController animated:YES completion:nil];
Then, after you get a picture back from the UIImagePickerController, crop it to a square with something like this:
//Crop the image to a square
CGSize imageSize = image.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
if (width != height) {
CGFloat newDimension = MIN(width, height);
CGFloat widthOffset = (width - newDimension) / 2;
CGFloat heightOffset = (height - newDimension) / 2;
UIGraphicsBeginImageContextWithOptions(CGSizeMake(newDimension, newDimension), NO, 0.);
[image drawAtPoint:CGPointMake(-widthOffset, -heightOffset)
blendMode:kCGBlendModeCopy
alpha:1.];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
And you're done.
#Anders answer was very close to correct for me on iPhone 5. I made the following modification to add an overlay hardcoded for iPhone 5:
CGRect f = imagePickerController.view.bounds;
f.size.height -= imagePickerController.navigationBar.bounds.size.height;
UIGraphicsBeginImageContext(f.size);
[[UIColor colorWithWhite:0 alpha:.5] set];
UIRectFillUsingBlendMode(CGRectMake(0, 0, f.size.width, 124.0), kCGBlendModeNormal);
UIRectFillUsingBlendMode(CGRectMake(0, 444, f.size.width, 52), kCGBlendModeNormal);
UIImage *overlayImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *overlayIV = [[UIImageView alloc] initWithFrame:f];
overlayIV.image = overlayImage;
overlayIV.alpha = 0.7f;
[imagePickerController setCameraOverlayView:overlayIV];`
I hope this helps someone.

Resize UIImage and change the size of UIImageView

I have this UIImageView and I have the values of its max height and max width. What I want to achieve is that I want to take the image (with any aspect ratio and any resolution) and I want it to fit in the borders, so the picture does not exceed them, but it can shrink them as it wants. (marked red in the picture):
Right now the image fits the necessary size properly, but I have 2 worries:
1. The UIImageView is not equal the size of the resized image, thus leaving red background (and I don't want that)
2. If the image is smaller that the height of my UIImageView it is not resized to be smaller, it stays the same height.
Here's my code and I know its wrong:
UIImage *actualImage = [attachmentsArray lastObject];
UIImageView *attachmentImageNew = [[UIImageView alloc] initWithFrame:CGRectMake(5.5, 6.5, 245, 134)];
attachmentImageNew.image = actualImage;
attachmentImageNew.backgroundColor = [UIColor redColor];
attachmentImageNew.contentMode = UIViewContentModeScaleAspectFit;
So how do I dynamically change the size not only of the UIImageView.image, but of the whole UIImageView, thus making its size totally adjustable to its content. Any help would be much appreciated, thanks!
When you get the width and height of a resized image Get width of a resized image after UIViewContentModeScaleAspectFit, you can resize your imageView:
imageView.frame = CGRectMake(0, 0, resizedWidth, resizedHeight);
imageView.center = imageView.superview.center;
I haven't checked if it works, but I think all should be OK
- (UIImage *)image:(UIImage*)originalImage scaledToSize:(CGSize)size
{
//avoid redundant drawing
if (CGSizeEqualToSize(originalImage.size, size))
{
return originalImage;
}
//create drawing context
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);
//draw
[originalImage drawInRect:CGRectMake(0.0f, 0.0f, size.width, size.height)];
//capture resultant image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//return image
return image;
}
This is the Swift equivalent for Rajneesh071's answer, using extensions
UIImage {
func scaleToSize(aSize :CGSize) -> UIImage {
if (CGSizeEqualToSize(self.size, aSize)) {
return self
}
UIGraphicsBeginImageContextWithOptions(aSize, false, 0.0)
self.drawInRect(CGRectMake(0.0, 0.0, aSize.width, aSize.height))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
Usage:
let image = UIImage(named: "Icon")
item.icon = image?.scaleToSize(CGSize(width: 30.0, height: 30.0))
Use the category below and then apply border from Quartz into your image:
[yourimage.layer setBorderColor:[[UIColor whiteColor] CGColor]];
[yourimage.layer setBorderWidth:2];
The category:
UIImage+AutoScaleResize.h
#import <Foundation/Foundation.h>
#interface UIImage (AutoScaleResize)
- (UIImage *)imageByScalingAndCroppingForSize:(CGSize)targetSize;
#end
UIImage+AutoScaleResize.m
#import "UIImage+AutoScaleResize.h"
#implementation UIImage (AutoScaleResize)
- (UIImage *)imageByScalingAndCroppingForSize:(CGSize)targetSize
{
UIImage *sourceImage = self;
UIImage *newImage = nil;
CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;
CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;
CGPoint thumbnailPoint = CGPointMake(0.0,0.0);
if (CGSizeEqualToSize(imageSize, targetSize) == NO)
{
CGFloat widthFactor = targetWidth / width;
CGFloat heightFactor = targetHeight / height;
if (widthFactor > heightFactor)
{
scaleFactor = widthFactor; // scale to fit height
}
else
{
scaleFactor = heightFactor; // scale to fit width
}
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
// center the image
if (widthFactor > heightFactor)
{
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
}
else
{
if (widthFactor < heightFactor)
{
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
}
}
}
UIGraphicsBeginImageContext(targetSize); // this will crop
CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width = scaledWidth;
thumbnailRect.size.height = scaledHeight;
[sourceImage drawInRect:thumbnailRect];
newImage = UIGraphicsGetImageFromCurrentImageContext();
if(newImage == nil)
{
NSLog(#"could not scale image");
}
//pop the context to get back to the default
UIGraphicsEndImageContext();
return newImage;
}
#end
If you have the size of the image, why don't you set the frame.size of the image view to be of this size?
EDIT----
Ok, so seeing your comment I propose this:
UIImageView *imageView;
//so let's say you're image view size is set to the maximum size you want
CGFloat maxWidth = imageView.frame.size.width;
CGFloat maxHeight = imageView.frame.size.height;
CGFloat viewRatio = maxWidth / maxHeight;
CGFloat imageRatio = image.size.height / image.size.width;
if (imageRatio > viewRatio) {
CGFloat imageViewHeight = round(maxWidth * imageRatio);
imageView.frame = CGRectMake(0, ceil((self.bounds.size.height - imageViewHeight) / 2.f), maxWidth, imageViewHeight);
}
else if (imageRatio < viewRatio) {
CGFloat imageViewWidth = roundf(maxHeight / imageRatio);
imageView.frame = CGRectMake(ceil((maxWidth - imageViewWidth) / 2.f), 0, imageViewWidth, maxHeight);
} else {
//your image view is already at the good size
}
This code will resize your image view to its image ratio, and also position the image view to the same centre as your "default" position.
PS: I hope you're setting imageView.layer.shouldRasterise = YES
and imageView.layer.rasterizationScale = [UIScreen mainScreen].scale;
if you're using CALayer shadow effect ;) It will greatly improve the performance of your UI.
I think what you want is a different content mode. Try using UIViewContentModeScaleToFill. This will scale the content to fit the size of ur UIImageView by changing the aspect ratio of the content if necessary.
Have a look to the content mode section on the official doc to get a better idea of the different content mode available (it is illustrated with images).
if([[SDWebImageManager sharedManager] diskImageExistsForURL:[NSURL URLWithString:#"URL STRING1"]])
{
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:[NSURL URLWithString:#"URL STRING1"]];
UIImage *tempImage=[self imageWithImage:[[SDImageCache sharedImageCache] imageFromDiskCacheForKey:key] scaledToWidth:cell.imgview.bounds.size.width];
cell.imgview.image=tempImage;
}
else
{
[cell.imgview sd_setImageWithURL:[NSURL URLWithString:#"URL STRING1"] placeholderImage:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL)
{
UIImage *tempImage=[self imageWithImage:image scaledToWidth:cell.imgview.bounds.size.width];
cell.imgview.image=tempImage;
// [tableView beginUpdates];
// [tableView endUpdates];
}];
}

How to center image in a uiimageview/uiscrollview (pre and post zooming)

I am trying to center an image (with respect to the iphone screen) such that when the view is loaded the image is center width/height... In my case my view is loaded at pixel points 0,0 of the image itself and if I zoom out the image appears in the top left corner as opposed to mid-center of the screen/view. Here is what I have so far:
UIImage *image = [UIImage imageNamed: #"t.bmp"];
self.view.backgroundColor = [UIColor blackColor];
self.mi.frame = CGRectMake(0, 0, image.size.width, image.size.height);
self.mi.contentMode = (UIViewContentModeCenter);
self.mi.backgroundColor = [UIColor blackColor];
[self.mi setImage:image];
/* Draw a line here!!
UIGraphicsBeginImageContext(self.mi.frame.size);
[self.mi.image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetLineWidth(context, 20.0);
CGContextBeginPath(context);
CGContextMoveToPoint(context, 0,0);
CGContextAddLineToPoint(context, 200, 200);
CGContextMoveToPoint(context, 200,0);
CGContextAddLineToPoint(context, 0, 200);
CGContextStrokePath(context);
self.mi.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
*/
self.expimg.maximumZoomScale = 2.0;
self.expimg.minimumZoomScale = 0.1;
self.expimg.clipsToBounds = YES;
self.expimg.delegate = self;
[self.expimg setContentSize:self.mi.frame.size];
[self.expimg addSubview: self.mi];
[self.view addSubview: self.expimg];
Thanks!
Edit: mi is a UIImageView and expimg is a UIScrollView (used interface builder). Also, viewForZoomingInScrollView is defined.
You should be able to do this by adjusting the position and size of the image and scroll view on initial load, and as zoom levels change. Make a method that is called on viewDidLoad, and again on the UIScrollViewDelegate method scrollViewDidZoom:.
Something like this should work (where imageView and scrollView are class attributes):
- (void)centerImage {
CGSize screenSize = CGSizeMake(320, 480);
CGSize imageSize = imageView.frame.size;
imageSize.width = imageSize.width * scrollView.zoomScale;
imageSize.height = imageSize.height * scrollView.zoomScale;
CGSize scrollSize = scrollView.frame.size;
CGFloat centerX;
CGFloat centerY;
CGFloat left;
CGFloat top;
if (imageSize.width > screenSize.width) {
scrollSize.width = imageSize.width;
centerX = imageSize.width/2;
left = 0;
} else {
scrollSize.width = screenSize.width;
centerX = screenSize.width/2;
left = centerX - imageSize.width/2;
}
if (imageSize.height > screenSize.height) {
scrollSize.height = imageSize.height;
centerY = imageSize.height/2;
top = 0;
} else {
scrollSize.height = screenSize.height;
centerY = screenSize.width/2;
top = centerY - imageSize.height/2;
}
CGRect scrollFrame = scrollView.frame;
scrollFrame.size = scrollSize;
scrollView.frame = scrollFrame;
CGRect imageFrame = imageView.frame;
imageFrame.origin = CGPointMake(left, top);
scrollView.contentOffset = CGPointMake(centerX-(imageSize.width/2), centerY-(imageSize.height/2));
}
I have not tested this, so some of my math could be wrong. Either way, it will hopefully give you a good idea of what to do.
Step 1: You create an image view property then init it at viewDidLoad and add to scrollView:
self.pictureImage = [[UIImageView alloc]initWithImage:self.picture];
[_scrollView addSubview:_pictureImage];
self.pictureImage.alpha = 0;
_scrollView.delegate = self;
Step 2: Create adjustZoomScale function to get minimum scale
- (CGFloat)adjustZoomScale{
CGFloat scale = self.scrollView.bounds.size.width / self.pictureImage.bounds.size.width;
CGFloat h = scale * self.pictureImage.bounds.size.height;
if (h > self.scrollView.bounds.size.height) {
scale = self.scrollView.bounds.size.height / self.pictureImage.bounds.size.height;
}
return scale;
}
Step 3: Because frame of scroll view will be updated at viewDidAppear so we need to adjust zoom scale here. And set alpha to make image appear smoother:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear: animated];
_scrollView.maximumZoomScale = 1.0;
_scrollView.minimumZoomScale = [self adjustZoomScale];
[_scrollView setZoomScale:_scrollView.minimumZoomScale];
self.pictureImage.alpha = 1;
}
Step 4: Implement viewForZoomingInScrollView (scroll delegate method) and return image view
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return self.pictureImage;
}
Step 5: Implement scrollViewDidZoom (scroll delegate method) and adjust point for image view
- (void)scrollViewDidZoom: (UIScrollView*) scrollView {
CGSize boundsSize = scrollView.bounds.size;
CGRect contentsFrame = _pictureImage.frame;
if (contentsFrame.size.width < boundsSize.width) {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0;
} else {
contentsFrame.origin.x = 0.0;
}
if (contentsFrame.size.height < boundsSize.height) {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0;
} else {
contentsFrame.origin.y = 0.0;
}
_pictureImage.frame = contentsFrame;
}
Thank shawhu at this post for point adjusting for image view while zooming
[scrollView zoomToRect:CGRectMake(x, y, width, height) animated:YES]; will work for you...
Where rect should have those center coordinates as origin.

How to resize the image programmatically in objective-c in iphone

I have an application where I am displaying large images in a small space.
The images are quite large, but I am only displaying them in 100x100 pixel frames.
My app is responding slowly because of the size fo the images I am using.
To improve performance, how can I resize the images programmatically using Objective-C?
Please find the following code.
- (UIImage *)imageWithImage:(UIImage *)image convertToSize:(CGSize)size {
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *destImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return destImage;
}
This code is for just change image scale not for resizing. You have to set CGSize as your image width and hight so the image will not stretch and it arrange at the middle.
- (UIImage *)imageWithImage:(UIImage *)image scaledToFillSize:(CGSize)size
{
CGFloat scale = MAX(size.width/image.size.width, size.height/image.size.height);
CGFloat width = image.size.width * scale;
CGFloat height = image.size.height * scale;
CGRect imageRect = CGRectMake((size.width - width)/2.0f,
(size.height - height)/2.0f,
width,
height);
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
[image drawInRect:imageRect];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
My favorite way to do this is with CGImageSourceCreateThumbnailAtIndex (in the ImageIO framework). The name is a bit misleading.
Here's an excerpt of some code from a recent app of mine.
CGFloat maxw = // whatever;
CGFloat maxh = // whatever;
CGImageSourceRef src = NULL;
if ([imageSource isKindOfClass:[NSURL class]])
src = CGImageSourceCreateWithURL((__bridge CFURLRef)imageSource, nil);
else if ([imageSource isKindOfClass:[NSData class]])
src = CGImageSourceCreateWithData((__bridge CFDataRef)imageSource, nil);
// if at double resolution, double the thumbnail size and use double-resolution image
CGFloat scale = 1;
if ([[UIScreen mainScreen] scale] > 1.0) {
scale = 2;
maxw *= 2;
maxh *= 2;
}
// load the image at the desired size
NSDictionary* d = #{
(id)kCGImageSourceShouldAllowFloat: (id)kCFBooleanTrue,
(id)kCGImageSourceCreateThumbnailWithTransform: (id)kCFBooleanTrue,
(id)kCGImageSourceCreateThumbnailFromImageAlways: (id)kCFBooleanTrue,
(id)kCGImageSourceThumbnailMaxPixelSize: #((int)(maxw > maxh ? maxw : maxh))
};
CGImageRef imref = CGImageSourceCreateThumbnailAtIndex(src, 0, (__bridge CFDictionaryRef)d);
if (NULL != src)
CFRelease(src);
UIImage* im = [UIImage imageWithCGImage:imref scale:scale orientation:UIImageOrientationUp];
if (NULL != imref)
CFRelease(imref);
If you are using a image on different sizes and resizing each time it will degrade your app performance. Solution is don't resize them just use button in place of imageview. and just set the image on button it will resize automatically and you will get great performance.
I was also resizing images while setting it on cell but my app got slow So I used Button in place of imageview (not resizing images programatically button is doing this job) and it is working perfectly fine.
-(UIImage *)scaleImage:(UIImage *)image toSize:. (CGSize)targetSize
{
//If scaleFactor is not touched, no scaling will occur
CGFloat scaleFactor = 1.0;
//Deciding which factor to use to scale the image (factor = targetSize / imageSize)
if (image.size.width > targetSize.width ||
image.size.height > targetSize.height || image.size.width == image.size.height)
if (!((scaleFactor = (targetSize.width /
image.size.width)) > (targetSize.height /
image.size.height))) //scale to fit width, or
scaleFactor = targetSize.height / image.size.height; // scale to fit heigth.
Since the code ran perfectly fine in iOS 4, for backwards compatibility I added a check for OS version and for anything below 5.0 the old code would work.
- (UIImage *)resizedImage:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)quality {
BOOL drawTransposed;
CGAffineTransform transform = CGAffineTransformIdentity;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0) {
// Apprently in iOS 5 the image is already correctly rotated, so we don't need to rotate it manually
drawTransposed = NO;
} else {
switch (self.imageOrientation) {
case UIImageOrientationLeft:
case UIImageOrientationLeftMirrored:
case UIImageOrientationRight:
case UIImageOrientationRightMirrored:
drawTransposed = YES;
break;
default:
drawTransposed = NO;
}
transform = [self transformForOrientation:newSize];
}
return [self resizedImage:newSize
transform:transform
drawTransposed:drawTransposed
interpolationQuality:quality];
}
You can use this.
[m_Image.layer setMinificationFilter:kCAFilterTrilinear];
This thread is old, but it is what I pulled up when trying to solve this problem. Once the image is scaled it was not displaying well in my container even though I turned auto layout off. The easiest way for me to solve this for display in a table row, was to paint the image on a white background that had a fixed size.
Helper function
+(UIImage*)scaleMaintainAspectRatio:(UIImage*)sourceImage :(float)i_width :(float)i_height
{
float newHeight = 0.0;
float newWidth = 0.0;
float oldWidth = sourceImage.size.width;
float widthScaleFactor = i_width / oldWidth;
float oldHeight = sourceImage.size.height;
float heightScaleFactor = i_height / oldHeight;
if (heightScaleFactor > widthScaleFactor) {
newHeight = oldHeight * widthScaleFactor;
newWidth = sourceImage.size.width * widthScaleFactor;
} else {
newHeight = sourceImage.size.height * heightScaleFactor;
newWidth = oldWidth * heightScaleFactor;
}
// return image in white rect
float cxPad = i_width - newWidth;
float cyPad = i_height - newHeight;
if (cyPad > 0) {
cyPad = cyPad / 2.0;
}
if (cxPad > 0) {
cxPad = cxPad / 2.0;
}
CGSize size = CGSizeMake(i_width, i_height);
UIGraphicsBeginImageContextWithOptions(CGSizeMake(size.width, size.height), YES, 0.0);
[[UIColor whiteColor] setFill];
UIRectFill(CGRectMake(0, 0, size.width, size.height));
[sourceImage drawInRect:CGRectMake((int)cxPad, (int)cyPad, newWidth, newHeight)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
// will return scaled image at actual size, not in white rect
// UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
// [sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
// UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
// UIGraphicsEndImageContext();
// return newImage;
}
I called this like this from my table view cellForRowAtIndexPath
PFFile *childsPicture = [object objectForKey:#"picture"];
[childsPicture getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
if (!error) {
UIImage *largePicture = [UIImage imageWithData:imageData];
UIImage *scaledPicture = [Utility scaleMaintainAspectRatio:largePicture :70.0 :70.0 ];
PFImageView *thumbnailImageView = (PFImageView*)[cell viewWithTag:100];
thumbnailImageView.image = scaledPicture;
[self.tableView reloadData];
}
}];
Hello from the end of 2018.
Solved with next solution (you need only last line, first & second are just for explanation):
NSURL *url = [NSURL URLWithString:response.json[0][#"photo_50"]];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data scale:customScale];
'customScale' is scale which you want (>1 if image must be smaller, <1 if image must be bigger).
This c method will resize your image with cornerRadius "Without effecting image's quality" :
UIImage *Resize_Image(UIImage *iImage, CGFloat iSize, CGFloat icornerRadius) {
CGFloat scale = MAX(CGSizeMake(iSize ,iSize).width/iImage.size.width, CGSizeMake(iSize ,iSize).height/iImage.size.height);
CGFloat width = iImage.size.width * scale;
CGFloat height = iImage.size.height * scale;
CGRect imageRect = CGRectMake((CGSizeMake(iSize ,iSize).width - width)/2.0f,(CGSizeMake(iSize ,iSize).height - height)/2.0f,width,height);
UIGraphicsBeginImageContextWithOptions(CGSizeMake(iSize ,iSize), NO, 0);
[[UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:icornerRadius] addClip];
[iImage drawInRect:imageRect];
UIImage *ResizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return ResizedImage;
}
This is how to use :
UIImage *ResizedImage = Resize_Image([UIImage imageNamed:#"image.png"], 64, 14.4);
I do not remember where i took the first 4 lines ..