How to compress image size using UIImagePNGRepresentation - iOS? - ios

I'm using UIImagePNGRepresentation to save an image. The result image is of size 30+ KB and this is BIG in my case.
I tried using UIImageJPEGRepresentation and it allows to compress image, so image saves in < 5KB size, which is great, but saving it in JPEG gives it white background, which i don't want (my image is circular, so I need to save it with transparent background).
How can I compress image size, using UIImagePNGRepresentation?

PNG uses lossless compression, that's why UIImagePNGRepresentation does not accept compressionQuality parameter like UIImageJPEGRepresentation does. You might get a bit smaller PNG file with different tools, but nothing like with JPEG.

May be this will help you out:
- (void)resizeImage:(UIImage*)image{
NSData *finalData = nil;
NSData *unscaledData = UIImagePNGRepresentation(image);
if (unscaledData.length > 5000.0f ) {
//if image size is greater than 5KB dividing its height and width maintaining proportions
UIImage *scaledImage = [self imageWithImage:image andWidth:image.size.width/2 andHeight:image.size.height/2];
finalData = UIImagePNGRepresentation(scaledImage);
if (finalData.length > 5000.0f ) {
[self resizeImage:scaledImage];
}
//scaled image will be your final image
}
}
Resizing image
- (UIImage*)imageWithImage:(UIImage*)image andWidth:(CGFloat)width andHeight:(CGFloat)height
{
UIGraphicsBeginImageContext( CGSizeMake(width, height));
[image drawInRect:CGRectMake(0,0,width,height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext() ;
return newImage;
}

Related

UIImage picker changes image size

I have an application in which I am scanning text from a picture. I am using OCR. Now the problem is my source image size is 3024*3024. I have copied the image into iPhone 6 Simulator in Xcode. Now when I uploaded the image using uiimagepicker controller the image was resized to 748*748 and its quality is not same.
When I tried to increase image size the image's quality is not the same.
What I need is image in its actual size and quality/resolution should not change.
try this code to resize image
- (UIImage*)imageWithImage:(UIImage*)img scaledToSize:(CGSize)newSize;{
UIGraphicsBeginImageContext( newSize );
[img drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImg;
}
and For the compression of images
NSData *dataForJPEGFile = UIImageJPEGRepresentation(theImage, 0.6);
Thanks
Did you set the qualityType property of your UIImagePickerController to UIImagePickerControllerQualityTypeHigh? The default is medium.

Resizing UIImage to pre-defined pixel dimension

I have a simple method that I'm using to resize images. I need to create 2200 x 2200 px images and upload them to a server. I have a working solution but I it doesn't works properly. I think there's something wrong where I set the size for the image because the result is bigger then 10 MB.
- (void) uploadImage {
NSData *imageData = UIImageJPEGRepresentation([self resizeImage:self.uploadImg.image reSize:CGSizeMake(2200, 2200)], 1.0);
...
}
- (UIImage*)resizeImage:(UIImage*)aImage reSize:(CGSize)newSize
{
UIGraphicsBeginImageContextWithOptions(newSize, YES, [UIScreen mainScreen].scale);
[aImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Is it a right implementation? The CGSizeMake(2200, 2200) is equal to 2200x2200 pixel? If yes, what indicates the 10MB+ file size? It shouldn't be bigger then 1-2MB.

Scale an image to a given NSData byte size - PNG compression [duplicate]

This question already has answers here:
How to downscale a UIImage in IOS by the Data size
(5 answers)
Closed 8 years ago.
If I have a UIImage and I convert is to NSData I can see how many bytes it is.
If I have a variable requiredSize and I want to set that UIImage to a certain length and width so that when it is rendered as a PNG-file NSData UIImagePNGRepresentation(); it is a certain byte-size (requiredSize). How do I go about doing this.
I know how to get the current byte size [NSData length];
And I know how to downscale a UIImage (If there's a better way please tell me)
//UIImage *tempImage = whateverTheImagePointerIs;
int tempWidth = tempImage.size.width/2;//50% width of original
int tempHeight = tempImage.size.height/2;//50% height of original
UIImageView *tempImageRender = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, tempWidth, tempHeight)];
tempImageRender.image = tempImage;
UIGraphicsBeginImageContextWithOptions(tempImageRender.bounds.size, tempImageRender.opaque, 1.0);
[tempImageRender.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *tempFinalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
But when I scale it by 50% on width and 50% on height (25% net-total) the final bytes of the new rendered scaled image (when converted to PNG using UIImagePNGRepresentation();) is not 25% of the original bytes... it seems to just be random (I'm sure this is happening because PNG compression algorithms change with image quality/size.)
Is there no way to resize an image to a given byte size?
See this answer for how to scale an image fairly effectively:
As you've discovered, there really isn't a direct correlation between image size and data size when compressed, you'll just have to do it iteratively:
-(NSData*)pngRepresentationWithMaxSize:(NSInteger)maxSize
{
UIImage* image = self;
while(1)
{
NSData* data = UIImagePNGRepresentation(image);
if(data.length < maxSize)
return data;
CGSize size = image.size;
image = [UIImage imageScaledToSize:CGSizeMake(image.size.width / 2., image.size.height / 2.)];
}
return nil;
}
Note that I assume you change the referenced scaling code to be a category method on UIImage and put the method above into a UIImage category as well.

Compressing UIImage into JPEG image data multiple times

I am debugging a piece of code where an UIImage may be gone through UIImageJPEGRepresentation multiple times, I thought that must be a bug and the image quality will get worsen, but surprisingly we can't see the difference visually.
So I did a test, loading an image, and try to let it go through UIImageJPEGRepresentation 1000 times, surprisingly, whether 1 or 1000 times doesn't really make a difference in the image quality visually, why is that so?
This is the testing code:
UIImage *image = [UIImage imageNamed:#"photo.jpeg"];
// Create a data reference here for the for loop later
// First JPEG compression here
// I would imagine the data here already has low image quality
NSData *data = UIImageJPEGRepresentation(image, 0);
for(int i=0; i<1000; i++)
{
// Convert the data with low image quality to UIImage
UIImage *image = [UIImage imageWithData:data];
// Compress the image into a low quality data again
// at this point i would imagine the image get even more low quality, like u resaved a jpeg twice in phootshop
data = UIImageJPEGRepresentation(image, 0);
}
// up to this point I would imagine the "data" has gone through JPEG compression 1000 times
// like you resave a jpeg as a jpeg in photoshop 1000 times, it should look like a piece of crap
UIImage *imageFinal = [UIImage imageWithData:data];
UIImageView *view = [[UIImageView alloc] initWithImage:imageFinal];
[self.view addSubview:view];
// but it didn't, the final image looks like it has only gone through the jpeg compression once.
EDIT: my doubt can be summarised into a simpler code, if you do this in objectiveC:
UIImage *image1 = an image..
NSData *data1 = UIImageJPEGRepresentation(image1, 0);
UIImage *image2 = [UIImage imageWithData:data1];
NSData *data2 = UIImageJPEGRepresentation(image2, 0);
UIImage *imageFinal = [UIImage imageWithData:data2];
Did imageFinal gone through JPEG compression twice?
As you know, JPG compression works by altering the image to produce smaller file size. The reason why you don't see progressively worse quality is because you're using the same compression setting each time.
The algorithm alters the source image just enough to fit into the compression profile - in other words, compressing the result of 50% JPG again at 50% will produce the same image, because the image doesn't need to be altered any more.
You can test this in Photoshop - save a photo out at say 30% quality JPG. Reopen the file you just saved, and go to Save for Web - flip between PNG (uncompressed/original) and JPG 30% - there will be no difference.
Hope this helps.
All types of compression will ideally reduce the size of an image. There are two types of compression which describes how they affects images:
Lossy Compression:
Lossy compression will reduces the size of the image by removing some data from it. This generally cause, effect the quality of the image, which means it reduce your image quality
Lossless Compression:
Lossless compression reduce the size of the image by changing the way in which the data is stored. Therefore this type of compression will make no change in the image quality.
Please check out the compression type you are using.
This may help you in decrease the image size. put the number from yourself how many times you want to perform loop;
UIImage *image = [UIImage imageNamed:#"photo.jpeg"];
for(int i=100; i>0; i--)
{
UIImage *image = [UIImage imageWithData:data];
NSData *data = UIImageJPEGRepresentation(image, (0.1 * i);
NSLog(#"%d",data.length);
}

Is there any way to dynamically compress an UIImage in iPhone [duplicate]

I m taking images from photo library.I have large images of 4-5 mb but i want to compress those images.As i need to store those images in local memory of iphone.for using less memory or for getting less memory warning i need to compress those images.
I don't know how to compress images and videos.So i want to know hot to compress images?
UIImage *image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
NSData* data = UIImageJPEGRepresentation(image,1.0);
NSLog(#"found an image");
NSString *path = [destinationPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.jpeg", name]];
[data writeToFile:path atomically:YES];
This is the code for saving my image. I dont want to store the whole image as its too big. So, I want to compress it to a much smaller size as I'll need to attach multiple images.
Thanks for the reply.
You can choose a lower quality for JPEG encoding
NSData* data = UIImageJPEGRepresentation(image, 0.8);
Something like 0.8 shouldn't be too noticeable, and should really improve file sizes.
On top of this, look into resizing the image before making the JPEG representation, using a method like this:
+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Source: The simplest way to resize an UIImage?
UIImageJPEGRepresentation(UIImage,Quality);
1.0 means maximum Quality and 0 means minimum quality.
SO change the quality parameter in below line to reduce file size of the image
NSData* data = UIImageJPEGRepresentation(image,1.0);
NSData *UIImageJPEGRepresentation(UIImage *image, CGFloat compressionQuality);
OR
NSData *image_Data=UIImageJPEGRepresentation(image_Name,compressionQuality);
return image as JPEG. May return nil if image has no CGImageRef or invalid bitmap format. compressionQuality is 0(most) & 1(least).

Resources