开发者

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

开发者 https://www.devze.com 2023-03-16 18:37 出处:网络
I would like to be able to calculate th开发者_C百科e total number of bytes a UIImage uses in memory.

I would like to be able to calculate th开发者_C百科e 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.

0

精彩评论

暂无评论...
验证码 换一张
取 消