Compress UIImage - ios

I need help resizing a UIImage.
For example: I'm displaying a lot images in a UICollection View, but the size of those images is 2 to 4 MB. I need compress or resize those images.
I found this: How to compress/resize image on iPhone OS SDK before uploading to a server? but I don't understand how to implement it.

Not quite sure if you want to resize or compress or both.
Below is the code for just compression :
Use JPEG Compression in two simple steps:
1) Convert UIImage to NSData
UIImage *rainyImage =[UImage imageNamed:#"rainy.jpg"];
NSData *imgData= UIImageJPEGRepresentation(rainyImage,0.1 /*compressionQuality*/);
this is lossy compression and image size is reduced.
2) Convert back to UIImage;
UIImage *image=[UIImage imageWithData:imgData];
For scaling you can use answer provided by Matteo Gobbi. But scaling might not be a the best alternative. You would rather prefer to have a thumbnail of the actual image by compression because scaling might make look your image bad on a retina display device.

I wrote this function to scale an image:
- (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)newSize {
CGSize actSize = image.size;
float scale = actSize.width/actSize.height;
if (scale < 1) {
newSize.height = newSize.width/scale;
} else {
newSize.width = newSize.height*scale;
}
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
The use is easy, for example:
[self scaleImage:yourUIImage toSize:CGMakeSize(300,300)];

lowResImage = [UIImage imageWithData:UIImageJPEGRepresentation(highResImage, quality)];

-(UIImage *) resizeImage:(UIImage *)orginalImage resizeSize:(CGSize)size
{
CGFloat actualHeight = orginalImage.size.height;
CGFloat actualWidth = orginalImage.size.width;
float oldRatio = actualWidth/actualHeight;
float newRatio = size.width/size.height;
if(oldRatio < newRatio)
{
oldRatio = size.height/actualHeight;
actualWidth = oldRatio * actualWidth;
actualHeight = size.height;
}
else
{
oldRatio = size.width/actualWidth;
actualHeight = oldRatio * actualHeight;
actualWidth = size.width;
}
CGRect rect = CGRectMake(0.0,0.0,actualWidth,actualHeight);
UIGraphicsBeginImageContext(rect.size);
[orginalImage drawInRect:rect];
orginalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return orginalImage;
}
//this image you can add it to imageview.....

Related

IOS How to resize image according to actual image ratio and give custom size?

Resize UIImage with custom size by checking actual image ratio for reducing image size. I have already tried this UIImageJPEGRepresentation(Image, 0.8); but problem with this is that image quality is reducing. Any help would be really appreciated. Thank you
Pass UIImage to below method which resize your image with custom height/width and you can also give compression value of image for reducing image size and Check image size before and after resizing.
Here is sample method-
-(UIImage *)resizeImage:(UIImage *)image
{
NSInteger imageActualSize = UIImageJPEGRepresentation(image,1).length;
NSLog(#"size of IMAGE before resizing: %# ", [NSByteCountFormatter stringFromByteCount:imageActualSize countStyle:NSByteCountFormatterCountStyleFile]);
float actualHeight = image.size.height;
float actualWidth = image.size.width;
float maxHeight = 400.0; // your custom height
float maxWidth = 350; // your custom width
float imgRatio = actualWidth/actualHeight;
float maxRatio = maxWidth/maxHeight;
float compressionQuality = 0.5;//50 percent compression
if (actualHeight > maxHeight || actualWidth > maxWidth)
{
if(imgRatio < maxRatio)
{
//adjust width according to maxHeight
imgRatio = maxHeight / actualHeight;
actualWidth = imgRatio * actualWidth;
actualHeight = maxHeight;
}
else if(imgRatio > maxRatio)
{
//adjust height according to maxWidth
imgRatio = maxWidth / actualWidth;
actualHeight = imgRatio * actualHeight;
actualWidth = maxWidth;
}
else
{
actualHeight = maxHeight;
actualWidth = maxWidth;
}
}
CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
UIGraphicsBeginImageContext(rect.size);
[image drawInRect:rect];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
NSData *imageData = UIImageJPEGRepresentation(img, compressionQuality);
UIGraphicsEndImageContext();
NSInteger imageReduceSize = imageData.length;
NSLog(#"size of IMAGE after resizing: %# ",[NSByteCountFormatter stringFromByteCount:imageReduceSize countStyle:NSByteCountFormatterCountStyleFile]);
return [UIImage imageWithData:imageData];
}
This will help you..:)
+ (UIImage *)resizeImage:(UIImage *)image toSize:(CGSize)newSize {
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
very easy way to do this.

Resizing UIImage height while keeping it's aspect ratio (iOS) [duplicate]

This question already has answers here:
Resize UIImage by keeping Aspect ratio and width
(19 answers)
Closed 7 years ago.
I'm using the UIImagePickerController to chose an image from my library and uploading it to Parse. How can I resize my image's height only? I want the image to keep it's aspect ratio but I don't want the height to be taller than 1000px.
Right now I'm resizing both the width and height to a fixed number with this code:
ViewController.h
- (UIImage *)resizeImage:(UIImage *)image toWidth:(float)width andHeight:(float)height;
ViewController.h
- (UIImage *)resizeImage:(UIImage *)image toWidth:(float)width andHeight:(float)height {
CGSize newSize = CGSizeMake(width, height);
CGRect newRectangle = CGRectMake(0, 0, width, height);
UIGraphicsBeginImageContext(newSize);
[self.image drawInRect:newRectangle];
UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resizedImage;
}
- (IBAction)createProduct:(id)sender {
UIImage *newImage = [self resizeImage:self.image toWidth:750.0f andHeight:1000.0f];
NSData *imageData = UIImagePNGRepresentation(newImage);
PFFile *imageFile = [PFFile fileWithName:#"image.jpg" data:imageData];
}
Thanks.
+(UIImage*)imageWithImage: (UIImage*) sourceImage scaledToHeight: (float) i_height
{
float oldHeight = sourceImage.size.height;
float scaleFactor = i_height / oldHeight;
float newWidth = sourceImage.size.width* scaleFactor;
float newHeight = oldHeight * scaleFactor;
UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
[sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
You will have to get the aspect ration of the original dimensions and multiply that with your new height
Pseudocode
if (height > 1000){
aspectRatio = width/height;
height = 1000;
width = height * aspectRatio
}
- (IBAction)createProduct:(id)sender {
UIImage *newImage;
if (self.image.size.height > 1000){
CGFloat aspectRatio = self.image.size.width/self.image.size.height;
CGFloat height = 1000;
CGFloat width = height * aspectRatio;
newImage = [self resizeImage:self.image toWidth:width andHeight:height];
} else {
newImage = self.image;
}
NSData *imageData = UIImagePNGRepresentation(newImage);
PFFile *imageFile = [PFFile fileWithName:#"image.jpg" data:imageData];
}

Crop an image to a square in iOS

In my app I import an image from either the camera or the photo library using a UIImagePickerController. Than I save the imported image to the app documents directory. This all works fine, however I would like to save the image cropped as a square(like on instagram) instead of it's original size.The square should be the size of either the width of the image or the height of it(depending on which is the smaller one). I figured that maybe a CGRect would be useful here, but I have no idea how to crop a CGRect out of an image..I have looked at countless tutorials but none of them seemed to work or they were all too complicated..
-(UIImage *)squareImage:(UIImage *)image
{
if (image.size.width>=image.size.height)
{
image=[self imageWithImage:image scaledToHeight:100];
}
else
{
image=[self imageWithImage:image scaledToWidth:100];
}
return image;
}
-(UIImage*)imageWithImage:(UIImage*)sourceImage scaledToWidth:(float)width
{
float oldWidth = sourceImage.size.width;
float scaleFactor = width / oldWidth;
float newHeight = sourceImage.size.height * scaleFactor;
float newWidth = oldWidth * scaleFactor;
UIGraphicsBeginImageContext(CGSizeMake(newWidth, newWidth));
[sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
-(UIImage*)imageWithImage:(UIImage*)sourceImage scaledToHeight:(float)height
{
float oldHeight = sourceImage.size.height;
float scaleFactor = height / oldHeight;
float newWidth = sourceImage.size.width * scaleFactor;
float newHeight = oldHeight * scaleFactor;
UIGraphicsBeginImageContext(CGSizeMake(newHeight, newHeight));
[sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
above method will help you to scale image proportionately and scaling image in square..for rotation you can search on google.

Compress images to reduce file size

I'm building an app that lets the user take a photo or select one from the library on the iPhone and upload it to the Parse backend.
The problem I'm facing is regarding to the size of the file.
I've read about what big players like Facebook, Twitter, Instagram, and Google do regarding resolution and file size but I can't get close to that.
I'm sure they have the best code and tools to do that but I'll be happy to implement it as good as possible with iOS regular processes.
This is what I'm doing right now:
- (UIImage *)normalResImageForAsset:(ALAsset*)asset
{
// Convert ALAsset to UIImage
UIImage *image = [self highResImageForAsset:asset];
// Determine output size
CGFloat maxSize = 1024.0f;
CGFloat width = image.size.width;
CGFloat height = image.size.height;
CGFloat newWidth = width;
CGFloat newHeight = height;
// If any side exceeds the maximun size, reduce the greater side to 1200px and proportionately the other one
if (width > maxSize || height > maxSize) {
if (width > height) {
newWidth = maxSize;
newHeight = (height*maxSize)/width;
} else {
newHeight = maxSize;
newWidth = (width*maxSize)/height;
}
}
// Resize the image
CGSize newSize = CGSizeMake(newWidth, newHeight);
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Set maximun compression in order to decrease file size and enable faster uploads & downloads
NSData *imageData = UIImageJPEGRepresentation(newImage, 0.0f);
UIImage *processedImage = [UIImage imageWithData:imageData];
return processedImage;
}
I'm trying to make 1024px the maximun allowed size (both with ot height) to start some restrictions there and then I'm applying maximun compression to reduce size.
This works and cuts aproximately 50% of the image size without really damaging JPEGs but it's still a lot. Specially if photos are taken with the phone's camera and uploaded. The processed image can still easly have 1MB size which is way too much.
I'm guessing that I could be missing some useful step or using the wrong technique.
Any feedback would be greatly appreciated.
I had a similar problem and I also thought that the compression wasn't working. It turned out elsewhere in my code I was writing the file out to disk using different compression. You might be doing the same thing with the data this function returns. A good way to check that indeed the compression is effective is to do something like this:
NSData *imgData1 = UIImageJPEGRepresentation(newImage, 1.0f);
NSLog(#"1.0 size: %d", imgData1.length);
NSData *imgData2 = UIImageJPEGRepresentation(newImage, 0.7f);
NSLog(#"0.7 size: %d", imgData2.length);
NSData *imgData3 = UIImageJPEGRepresentation(newImage, 0.4f);
NSLog(#"0.4 size: %d", imgData3.length);
NSData *imgData4 = UIImageJPEGRepresentation(newImage, 0.0f);
NSLog(#"0.0 size: %d", imgData4.length);
// Don't convert NSData back to UIImage before writing to disk
[imgData4 writeToFile:imagePath atomically:YES];
I'm using an image that is 640x480 and I get file sizes ranging from 325 kB (for 1.0) down to 18 kB (for 0.0)
Swift-3 Version of #codeMonkey :-
It work perfect in compression of image .
func compressImage() -> UIImage {
let oldImage = UIImage(named: "background.jpg")
var imageData = Data(UIImagePNGRepresentation(oldImage!)! )
print("***** Uncompressed Size \(imageData.description) **** ")
imageData = UIImageJPEGRepresentation(oldImage!, 0.025)!
print("***** Compressed Size \(imageData.description) **** ")
let image = UIImage(data: imageData)
return image!
}
Please Try below answer.
+(UIImage *)compressImage:(UIImage *)image{
float actualHeight = image.size.height;
float actualWidth = image.size.width;
float maxHeight = 1136.0f;
float maxWidth = 640.0f;
float imgRatio = actualWidth/actualHeight;
float maxRatio = maxWidth/maxHeight;
float compressionQuality = 1;//50 percent compression
if (actualHeight > maxHeight || actualWidth > maxWidth){
if(imgRatio < maxRatio){
//adjust width according to maxHeight
imgRatio = maxHeight / actualHeight;
actualWidth = imgRatio * actualWidth;
actualHeight = maxHeight;
}
else if(imgRatio > maxRatio){
//adjust height according to maxWidth
imgRatio = maxWidth / actualWidth;
actualHeight = imgRatio * actualHeight;
actualWidth = maxWidth;
}
else{
actualHeight = maxHeight;
actualWidth = maxWidth;
}
}else{
actualHeight = maxHeight;
actualWidth = maxWidth;
compressionQuality = 1;
}
CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
UIGraphicsBeginImageContext(rect.size);
[image drawInRect:rect];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
NSData *imageData = UIImageJPEGRepresentation(img, compressionQuality);
UIGraphicsEndImageContext();
return [UIImage imageWithData:imageData];
}

How can I resize the UIImage to specific size

In my app, I am taking picture with camera and displaying it in 320*320 UIView. But as the image resolution is more than that of UIView its kinda look squeezed. Is there any way I can resize that image?
Here's how you can resize the image while preserving its aspect ratio. The code below is from a category for UIImage:
+ (UIImage*)imageWithImage:(UIImage *)image
scaledToSize:(CGSize)newSize
{
float heightToWidthRatio = image.size.height / image.size.width;
float scaleFactor = 1;
if(heightToWidthRatio > 0) {
scaleFactor = newSize.height / image.size.height;
} else {
scaleFactor = newSize.width / image.size.width;
}
CGSize newSize2 = newSize;
newSize2.width = image.size.width * scaleFactor;
newSize2.height = image.size.height * scaleFactor;
UIGraphicsBeginImageContext(newSize2);
[image drawInRect:CGRectMake(0,0,newSize2.width,newSize2.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
I do this, but first I enable the photo picker to editable so it is default 1:1 aspect, like so:
imgPicker.allowsImageEditing = YES; //I think this is what you're really looking for
then I resize the image using this method:
-(UIImage*)resizeImage:(UIImage*)image{
CGSize newSize = CGSizeMake(480.0, 480.0);
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

Resources