Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 293 Vote(s) - 3.4 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to easily resize/optimize an image size with iOS?

#1
My application is downloading a set of image files from the network, and saving them to the local iPhone disk. Some of those images are pretty big in size (widths larger than 500 pixels, for instance). Since the iPhone doesn't even have a big enough display to show the image in its original size, I'm planning on resizing the image to something a bit smaller to save on space/performance.

Also, some of those images are JPEGs and they are not saved as the usual 60% quality setting.

How can I resize a picture with the iPhone SDK, and how can I change the quality setting of a JPEG image?
Reply

#2
A couple of suggestions are provided as answers to [this question][1]. I had suggested the technique described in [this post][2], with the relevant code:

+ (UIImage*)imageWithImage:(UIImage*)image
scaledToSize:(CGSize)newSize;
{
UIGraphicsBeginImageContext( newSize );
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return newImage;
}

As far as storage of the image, the fastest image format to use with the iPhone is PNG, because it has optimizations for that format. However, if you want to store these images as JPEGs, you can take your UIImage and do the following:

NSData *dataForJPEGFile = UIImageJPEGRepresentation(theImage, 0.6);

This creates an NSData instance containing the raw bytes for a JPEG image at a 60% quality setting. The contents of that NSData instance can then be written to disk or cached in memory.

[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply

#3
The easiest and most straightforward way to resize your images would be this

float actualHeight = image.size.height;
float actualWidth = image.size.width;
float imgRatio = actualWidth/actualHeight;
float maxRatio = 320.0/480.0;

if(imgRatio!=maxRatio){
if(imgRatio < maxRatio){
imgRatio = 480.0 / actualHeight;
actualWidth = imgRatio * actualWidth;
actualHeight = 480.0;
}
else{
imgRatio = 320.0 / actualWidth;
actualHeight = imgRatio * actualHeight;
actualWidth = 320.0;
}
}
CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
UIGraphicsBeginImageContext(rect.size);
[image drawInRect:rect];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Reply

#4
Best way to scale images without losing the aspect ratio (i.e. without stretching the imgage) is to use this method:

//to scale images without changing aspect ratio
+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize {

float width = newSize.width;
float height = newSize.height;

UIGraphicsBeginImageContext(newSize);
CGRect rect = CGRectMake(0, 0, width, height);

float widthRatio = image.size.width / width;
float heightRatio = image.size.height / height;
float divisor = widthRatio > heightRatio ? widthRatio : heightRatio;

width = image.size.width / divisor;
height = image.size.height / divisor;

rect.size.width = width;
rect.size.height = height;

//indent in case of width or height difference
float offset = (width - height) / 2;
if (offset > 0) {
rect.origin.y = offset;
}
else {
rect.origin.x = -offset;
}

[image drawInRect: rect];

UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return smallImage;

}

Add this method to your Utility class so you can use it throughout your project, and access it like so:

xyzImageView.image = [Utility scaleImage:yourUIImage toSize:xyzImageView.frame.size];


This method takes care of scaling while maintaining aspect ratio.
It also adds indents to the image in case the scaled down image has more width than height (or vice versa).
Reply

#5
If you have control over the server, I would strongly recommend resizing the images server side with [ImageMagik](

[To see links please register here]

). Downloading large images and resizing them on the phone is a waste of many precious resources - bandwidth, battery and memory. All of which are scarce on phones.
Reply

#6
To resize an image I have better (graphical) results by using this function in stead of DrawInRect:


- (UIImage*) reduceImageSize:(UIImage*) pImage newwidth:(float) pWidth
{
float lScale = pWidth / pImage.size.width;
CGImageRef cgImage = pImage.CGImage;
UIImage *lResult = [UIImage imageWithCGImage:cgImage scale:lScale
orientation:UIImageOrientationRight];
return lResult;
}

Aspect ratio is taken care for automatically
Reply

#7
The above methods work well for small images, but when you try to resize a very large image, you will quickly run out of memory and crash the app. A much better way is to use `CGImageSourceCreateThumbnailAtIndex`to resize the image without completely decoding it first.

If you have the path to the image you want to resize, you can use this:

- (void)resizeImageAtPath:(NSString *)imagePath {
// Create the image source (from path)
CGImageSourceRef src = CGImageSourceCreateWithURL((__bridge CFURLRef) [NSURL fileURLWithPath:imagePath], NULL);

// To create image source from UIImage, use this
// NSData* pngData = UIImagePNGRepresentation(image);
// CGImageSourceRef src = CGImageSourceCreateWithData((CFDataRef)pngData, NULL);

// Create thumbnail options
CFDictionaryRef options = (__bridge CFDictionaryRef) @{
(id) kCGImageSourceCreateThumbnailWithTransform : @YES,
(id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
(id) kCGImageSourceThumbnailMaxPixelSize : @(640)
};
// Generate the thumbnail
CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options);
CFRelease(src);
// Write the thumbnail at path
CGImageWriteToFile(thumbnail, imagePath);
}

More details [here][1].


[1]:

[To see links please register here]

Reply

#8
If anyone still looking for better option

-(UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)targetSize {


UIImage *sourceImage = image;
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;
else
scaleFactor = heightFactor;

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;
}
}


// this is actually the interesting part:

UIGraphicsBeginImageContext(targetSize);

CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width = scaledWidth;
thumbnailRect.size.height = scaledHeight;

[sourceImage drawInRect:thumbnailRect];

newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

if(newImage == nil) NSLog(@"could not scale image");


return newImage ;

}
Reply

#9
A problem that might occur on retina displays is that the scale of the image is set by ImageCapture or so. The resize functions above will not change that. In these cases the resize will work not properly.

In the code below, the scale is set to 1 (not scaled) and the returned image has the size that you would expect. This is done in the `UIGraphicsBeginImageContextWithOptions` call.

-(UIImage *)resizeImage :(UIImage *)theImage :(CGSize)theNewSize {
UIGraphicsBeginImageContextWithOptions(theNewSize, NO, 1.0);
[theImage drawInRect:CGRectMake(0, 0, theNewSize.width, theNewSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Reply

#10
I ended up using Brads technique to create a `scaleToFitWidth` method in `UIImage+Extensions` if that's useful to anyone...

-(UIImage *)scaleToFitWidth:(CGFloat)width
{
CGFloat ratio = width / self.size.width;
CGFloat height = self.size.height * ratio;

NSLog(@"W:%f H:%f",width,height);

UIGraphicsBeginImageContext(CGSizeMake(width, height));
[self drawInRect:CGRectMake(0.0f,0.0f,width,height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return newImage;
}

then wherever you like

`#import "UIImage+Extensions.h"`

`UIImage *newImage = [image scaleToFitWidth:100.0f];`

Also worth noting you could move this further down into a `UIView+Extensions` class if you want to render images from a UIView
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through