Converting UIImage image representation - iphone

I am getting an UIImage from UIGraphicsGetImageFromCurrentImageContext, but they are very heavyweight memory wise.
UIGraphicsBeginImageContext([self bounds].size);
// CGContext procedures
_cacheImage = UIGraphicsGetImageFromCurrentImageContext();
the size of the image is almost as the size of the iPad screen, (a little smaller), and when I do something like this:
NSData *data = UIImagePNGRepresentation(_cacheImage)
NSLog(#"%i", data.lenght);
It gives me like 700,000 in lenght. I'm guessing its a .7MB file?
Anyway if there is some way to reduce the image size, please let me know.

If you wish to reduce quality, try using
NSData * UIImageJPEGRepresentation (
UIImage *image,
CGFloat compressionQuality
);
Pass compressionQuality == 0.0 for maximum quality or compressionQuality == 1.0 for maximum compression.

Related

Enhance image quality after resizing

Can anyone suggest methods to enhance the quality of an image, being resized to a larger size?
On resizing, the resultant image pixelates. I need this pixelation to reduce to maximum extent.
You can use the following code for compressing or increasing size of an image.
CGFloat compression = 222.0f;
CGFloat maxCompression = 202.1f;
int maxFileSize = 160*165; //fill your size need
NSData *imageDat = UIImageJPEGRepresentation(image.image, compression);
while ([imageDat length] > maxFileSize && compression > maxCompression)
{
compression -= 0.1222;
imageDat = UIImageJPEGRepresentation(decodedimage.image, compression);
}
NSLog(#"image compressed success");
[image setImage:[UIImage imageWithData:imageDat]];
You can use the following code for compressing or increasing size of an image.
image1 = [self imageWithImage:image1 convertToSize:CGSizeMake(100, 100)];
// For convert the image to fix size
- (UIImage *)imageWithImage:(UIImage *)image convertToSize:(CGSize)size
{
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, 320,460)];
UIImage *destImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return destImage;
}
There is an Article called : Resize a UIImage the right way , you should Read and Understand each and every aspects given there. I think it will give Answers of Every Questions arises in your mind. I think it's a beautiful Article with proper Graphical Representation (means Less Boring at Reading).

Coverflow crashes on loading high resolution images

I am trying to implement a Coverflow ( iCarousel ) with AsyncImageView ( https://github.com/nicklockwood/AsyncImageView ) as cover. It works well with images of size upto 4 MB. But the app crashes when trying to load images of size more than 10 MB. My question is -
1 ) Can i load a image of size 10 MB without tiling ? Since the source of image is from device camera, is it possible to tile those images and then load those images. If so can you share some ideas/code blocks on tiling a large image ?
P.s : I have tried compressing the images, by using UIImageJPEGRepresentation(image,scale), although the image size got reduced from 10 MB to 100 KB, but when i try to load the compressed images, memory issues shows up again. (Looks like iOS decompresses to some extent)
You are confused with the dimensions of the image and its size on disk.
In memory an image take WIDTH*HEIGHT*4 pixels, so let's say your image is 1000x1000px you end up using 4Mb ram.
UIImageJPEGRepresentation save the image with a compression factor, so you end up with a smaller image on disk, but the image has still the same dimensions.
To solve your problem you need to scale the image you downloaded to the correct dimension for your coverflow item.
You can do this using ImageIO framework :
Create a CGImageSource from the downloaded data
Call CGImageSourceCreateThumbnailAtIndex with the 2 properties kCGImageSourceCreateThumbnailFromImageIfAbsent and kCGImageSourceThumbnailMaxPixelSize
Here is the working code
UIImage *result = nil;
if ([data length]) { // NSData of the image
CGImageSourceRef sourceRef = CGImageSourceCreateWithData((CFDataRef)data, nil);
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:(id)kCFBooleanTrue forKey:(id)kCGImageSourceCreateThumbnailFromImageIfAbsent];
[options setObject:[NSNumber numberWithInt:400] forKey:(id)kCGImageSourceThumbnailMaxPixelSize];
CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(sourceRef, 0, (CFDictionaryRef)options);
if (imageRef) {
result = [UIImage imageWithCGImage:imageRef]; //Resulting image
CGImageRelease(imageRef);
}
if (sourceRef) CFRelease(sourceRef);

how to compress image in iphone?

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).

Does it matter what color format an image has when saving it as PNG?

I am creating tiles for a larger image and I'm saving them to disk. Question: Is there any way I can optimize the image so that reading and decompressing the PNG from disk is faster? Possibly by changing the order or color bytes in the color space on a custom bitmap context from which the image is saved?
UIImage *fullSizeImage = [self cachedImageWithURL:imageURL];
CGRect tileRect = (CGRect){{column*tileSize.width, row*tileSize.height}, {tileSize.width, tileSize.height}};
CGRect totalRect = (CGRect){CGPointZero, fullSizeImage.size};
tileRect = CGRectIntersection(tileRect, totalRect);
CGImageRef tileImage = CGImageCreateWithImageInRect([fullSizeImage CGImage], tileRect);
UIImage *retImage = [UIImage imageWithCGImage:tileImage];
[self.cache setObject:retImage forKey:cacheURL cost:0];
[retImage savePNGAsyncToURL:cacheURL];
I've benchmarked this, and it looks that speed is closely correlated to file size (smaller file is faster):
http://imageoptim.com/tweetbot.html
If you're OK with lossy compression, then use pngquant to create those files. At 8bpp they'll have 1/4th of data to begin with.

Get image width and height before loading it completely in iPhone

I am loading an image in my UITableViewCell using
[NSData dataWithContentsOfURL:imageUrl]
For setting custom height for my tableview cell , i need the actual size of the image that am loading.
Can we get the width and height of an image before loading it completely ? Thanks in advance.
Try the Image I/O interface as done below. This will allow you to get the image size without having to load the entire file:
#import <ImageIO/ImageIO.h>
NSMutableString *imageURL = [NSMutableString stringWithFormat:#"http://www.myimageurl.com/image.png"];
CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)[NSURL URLWithString:imageURL], NULL);
NSDictionary* imageHeader = (__bridge NSDictionary*) CGImageSourceCopyPropertiesAtIndex(source, 0, NULL);
NSLog(#"Image header %#",imageHeader);
NSLog(#"PixelHeight %#",[imageHeader objectForKey:#"PixelHeight"]);
you can do it like this:
NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
UIImage *image = [UIImage imageWithData:imageData];
NSLog(#"image height: %f",image.size.height);
NSLog(#"image width: %f",image.size.width);
Take a look at this Question How do I extract the width and height of a PNG from looking at the header in objective c which shares how is it possible to parse image Meta-data.
I have a created OpenSource project Ottran that extracts the image size and type of a remote image by downloading as little as possible, which supports PNG, JPEG , BMP and GIF formats.
NSData is an "opaque" data, so you cannot do much with it before converting it to something more "useful" (e.g., creating an UIImage by means of it -initWithData: method). At that moment you could enquiry the image size, but it would be late for you.
The only approach I see, if you really need knowing the image size before the image is fully downloaded, is implementing a minimal server-side API so that you can ask for the image size before trying to download it.
Anyway, why do you need to know the image size before it is actually downloaded? Could you not set the row height at the moment when it has been downloaded (i.e., from your request delegate method)?
dataWithContentsOfURL is synchronous it will block your UI until its download complete, so please use header content to get resolution, Below is Swift 3.0 code
if let imageSource = CGImageSourceCreateWithURL(url! as CFURL, nil) {
if let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as Dictionary? {
let pixelWidth = imageProperties[kCGImagePropertyPixelWidth] as! Int
let pixelHeight = imageProperties[kCGImagePropertyPixelHeight] as! Int
print("the image width is: \(pixelWidth)")
print("the image height is: \(pixelHeight)")
}
}