iphone sdk get actual size of image in bytes - ios

How to get actual size of image ?
I am using
NSInteger actualSize = CGImageGetHeight(image.CGImage) * CGImageGetBytesPerRow(image.CGImage);
or
NSData *imageData2 = UIImageJPEGRepresentation(image, 1.0);
[imageData2 length];
but I don't get the actual size of image it is either larger of smaller compared to the size on the disk (as I am using simulator).
Is there any way to get actual size of the image?

It depends upon what you mean by "size".
If you want the amount of memory used while the image is loaded into memory and used by the app, the bytes-per-row times height is the way to go. This captures the amount of memory used by the uncompressed pixel buffer while the image is actively used by the app.
If you want the number of bytes used in persistent storage when you save the image (generally enjoying some compression), then grab the the original asset's NSData and examine its length. Note, though, if you load an image and then use UIImageJPEGRepresentation with a quality of 1, you'll generally get a size a good deal larger than the original compressed file.
Bottom line, standard JPEG and PNG files enjoy some compression, but when the image is loaded into memory it is uncompressed. You can't generally infer the original file size from a UIImage object. You have to look at the original asset.

Try this (for iOS 6.0 or later and OS X 10.8):
NSLog(#"%#",[NSByteCountFormatter stringFromByteCount:imageData2.length countStyle:NSByteCountFormatterCountStyleFile]);
UPDATE:
Question: Can you post code where you initialise your image?
Above solution did not work for you. Let's try something else. You could try to check directly image file size:
NSError* error;
NSDictionary *fileDictionary = [[NSFileManager defaultManager] attributesOfItemAtPath:mediaURL error: &error];
NSNumber *size = [fileDictionary objectForKey:NSFileSize];

Related

UIImagePNGRepresentation returns inappropriately large data

We have an UIImage of size 1280*854 and we are trying to save it in png format.
NSData *pngData = UIImagePNGRepresentation(img);
The problem is that the size of pngData is 9551944 which is inappropriately large for the input image size. Even considering 24 bit PNG, at the max it should be 1280*854*3 (3 for 24 bit png).
BTW, this is only happening with images scaled with UIGraphicsGetImageFromCurrentImageContext. We also noticed that image._scale is set to 2.0 in image returned by UIGraphicsGetImageFromCurrentImageContext.
Any idea what's wrong.

iOS returning image with different size?

I want to upload an image up to 8 mb. so for testing I have added image in my photo gallery of size 4.2 mb (dimension : 3264 X 2443). But when I am picking that image for uploading, I have checked size of image. But it returning 9840076 bytes i.e. 9.3842 mb which is 4.2 mb in actual. So image of size 4.2 mb is not able to upload.
I have used below method to calculate size of image, and this is returning 9840076 bytes.
[UIImageJPEGRepresentation(imageRerurnedFromPhotoGallery , 1.0) length];
Am I doing something wrong in calculating size of image?
Please suggest me the proper way.
Thanks in advance!
why dont you try like this?
you will get size in bytes
NSData *data = [[NSData alloc] initWithData:UIImageJPEGRepresentation((Your Image), 0.5)];
int imageSize = data.length;
NSLog(#"size of image is: %i ", imageSize);
You are decoding and then re-encoding the image, which is why the file size may be different. If you don't need to modify the image at all, use ALAssetsLibrary to get the image as an NSData object rather than a UIImage object. Then, when you look at the NSData's length property, your file size will match exactly. See Using ALAssetsLibrary and ALAsset take out Image as NSData for some sample code.

NSData length of an Image compressed with UIImageJPEGRepresentation()

We know the image can be compressed with the Method UIImageJPEGRepresentation() as in the following codes.
NSData *imgData = UIImageJPEGRepresentation(imageResized, 0.5);
NSLog(#"imgData.length :%d",imgData.length);
imageResized = [UIImage imageWithData:imgData];
NSData *imgData2 = UIImageJPEGRepresentation(imageResized, 1);
NSLog(#"imgData2.length :%d",imgData2.length);
The log is:
2013-02-25 00:33:14.756 MyApp[1119:440b] imgData.length :371155
2013-02-25 00:33:20.988 MyApp[1119:440b] imgData2.length :1308415
What Im confused is that why the length of imgData and imgData2 are different. In my App, the image should be uploaded to the server. Should I upload the NSData to the server for saving storage? Is it possible for an Android phone to download the NSData and convert it to an image? Any help will be appreciated!
You start with a UIImage of some size (say 1024x768). This takes 1024x768x4 byes in memory. Then you compress it with a factor of 0.5 and get 371,155 bytes.
You then create a new UIImage with the compressed data. This is still a 1024x768 (or whatever) UIImage so it now takes the same amount of memory (1024x768x4) as the original image. You then convert it to a new JPG with less compression giving you 1,308,415 bytes.
Even though you create an uncompressed version of the compressed image, the number of bytes comes from converting the full sized UIImage. The 2nd, uncompressed image, though bigger, will still have the same lower quality of the compressed image.
Since your data represents a JPG, anything that downloads the data will be able to treat the data as a JPG, including an Android phone.
The number of bytes is bigger for the second image because you passed a much higher compression quality value to UIImageJPEGRepresentation. Higher quality takes more bytes.
The file once uploaded to a server will be a standard JPEG file, viewable by any device, including Android.

memory size of UIImageView

I'd like to know the memory size for a UIImageView object as I need to show some large image and I need to handle the memory. I guess it is decided by the image property. But I'm not sure how to calculate the actuarial memory size,and below is the code I write to test:
//1.jpg has a size of 4016X2657 and 2.1MB
NSData *imageData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"1" ofType:#"jpg"]];
NSLog(#"imageData:%d",[imageData length]);
The console shows:
imageData:2070461
This is exactly the size of 2.1MB.
However, in my opinion the UIImageViewshould know the each pixel to show the image and in other words it should have a memory of :
4016*2657*4/1024/1024 = 40.7+MB
It is so large and I don't know whether iOS will do some optimization or not.And I also can't find any relevant in the document.
Could anyone help me what is the exactly memory size of a UIImageView object?
It is described in the question. The memory is the actuarial size of the photo and UIImage will not do optimization.

How to determine the number of bytes used by a UIImage?

I would like to be able to calculate the total number of bytes a UIImage uses in memory.
I can make a rough estimate by multiplying the width by the height and then by a multiplier number of bytes, but I'd like to calculate the size exactly if possible.
In general, objects don't have a single meaningful "size", since they can allocate and release any number of other objects privately as needed. sizeof(*myObj) only gives you the size of the top level structure, not a very useful number. If you need the complete memory impact of allocating and using an object, run under Instruments and watch allocations.
For a UIImage, its practical size is the size of whatever is backing it, typically either an NSData containing a PNG, or a CGimageRef, plus the object overhead. (There's also the pixel buffer when it gets rendered to the screen or other context; but that buffer belongs to the view or context in question, not the UIImage. If a UIView is doing the rendering then that buffer is likely in GL texture memory anyway.)
[UIImage imageWithData:[NSData dataWithContentsOfFile:#"foo.png"]] gives you a UIImage that is the same size as the foo.png file, plus some inconsequential overhead. [UIImage imageNamed:#"foo.png"] does the same thing, except that the class maintains a cache table of one object per filename, and will cause that object to dump its memory copy of the png in low-memory situations, reducing its "size" to just the overhead.
imageWithCGImage: and variants give you an UIImage that uses a CGImage reference as its backing store, and CGImages can be any number of things depending on their source. If you've been painting in one, it's probably an uncompressed pixel buffer. Calculate its size exactly as you propose above. If you need what its size "would be" if it were from a file, inspect the result of the UIImagePNGRepresentation or UIImageJPEGRepresentation functions.
Width * height * 4 will get you close. I'm not sure there's a way to get the exact size, since width is rounded out to an arbitrary, undocumented boundary (at least 4 pixels or 16 bytes, I gather), and there are several extra internal pieces of the object that you'd need to count. Plus likely there are internal attributes that are hung on the object or not, based on its use.
I had to solve this for a twitter app I was writing. Twitter rejects images larger than 3MB, so I needed to compress the image just enough to get below the 3MB limit. Here is the code snippet I used:
float compression = 1.0f;
NSData* data = UIImageJPEGRepresentation(photo, compression);
while(data.length > 3145728) //3MB
{
compression -= .1f;
NSLog(#"Compressing Image to: %lf", compression);
data = UIImageJPEGRepresentation(photo, compression);
NSLog(#"Image Bytes: %i", data.length);
}
The compression algorithm I used is non-optimized.
So, What is it doing?
Good question! The UIImageJPEGRepresentation method returns a byte array. To get the size, simply check the length of the array!
There is also a UIImagePNGRepresentation method. Keep in mind, these method are having to build byte arrays, and if needed convert the binary representation of the data. This can take a bit of time. Luckily in my case, most images taken by the iPhone are already less than 3MB, and will only need the compression if there is a wide range of colors; but calling the UIImageJPEGRepresentation method repeatedly (which could happen in my posted code) can take some time.

Resources