12

I want to determine the memory size of the image accessed through the PHAsset. This size is so that we know how much memory it occupies on the device. Which method does this?

var imageSize = Float(imageData.length)

var image = UIImage(data: imageData)
var jpegSize = UIImageJPEGRepresentation(image, 1)
var pngSize = UIImagePNGRepresentation(image)
var pixelsMultiplied = asset.pixelHeight * asset.pixelWidth

println("regular data: \(imageSize)\nJPEG Size: \(jpegSize.length)\nPNG Size: \(pngSize.length)\nPixel multiplied: \(pixelsMultiplied)")

Results in:

regular data: 1576960.0
JPEG Size: 4604156
PNG Size: 14005689
Pixel multiplied: 7990272

Which one of these values actually represents the amount it occupies on the device?

fatihyildizhan
  • 8,614
  • 7
  • 64
  • 88
William Falcon
  • 9,813
  • 14
  • 67
  • 110

2 Answers2

9

After emailing the picture to myself and checking the size on the system, it turns out approach ONE is the closest to the actual size.

To get the size of a PHAsset (Image type), I used the following method:

var asset = self.fetchResults[index] as PHAsset

self.imageManager.requestImageDataForAsset(asset, options: nil) { (data:NSData!, string:String!, orientation:UIImageOrientation, object:[NSObject : AnyObject]!) -> Void in
    //transform into image
    var image = UIImage(data: data)

    //Get bytes size of image
    var imageSize = Float(data.length)

    //Transform into Megabytes
    imageSize = imageSize/(1024*1024)
 }

Command + I on my macbook shows the image size as 1,575,062 bytes.
imageSize in my program shows the size at 1,576,960 bytes.
I tested with five other images and the two sizes reported were just as close.

William Falcon
  • 9,813
  • 14
  • 67
  • 110
  • I would like to draw your attention to all cruel comment on this similar answer: https://stackoverflow.com/a/14957522/656600 – rptwsthi Aug 22 '17 at 10:50
4

The NSData approach becomes precarious when data is prohibitively large. You can use the below as an alternative:

[[PHImageManager defaultManager] requestAVAssetForVideo:self.phAsset options:nil resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {

    CGFloat rawSize = 0;

    if ([asset isKindOfClass:[AVURLAsset class]])
    {
        AVURLAsset *URLAsset = (AVURLAsset *)asset;
        NSNumber *size;
        [URLAsset.URL getResourceValue:&size forKey:NSURLFileSizeKey error:nil];
        rawSize = [size floatValue] / (1024.0 * 1024.0);
    }
    else if ([asset isKindOfClass:[AVComposition class]])
    {
        // Asset is an AVComposition (e.g. slomo video)

        float estimatedSize = 0.0;

        NSArray *tracks = [self tracks];
        for (AVAssetTrack * track in tracks)
        {
            float rate = [track estimatedDataRate] / 8.0f; // convert bits per second to bytes per second
            float seconds = CMTimeGetSeconds([track timeRange].duration);
            estimatedSize += seconds * rate;
        }

        rawSize = estimatedSize;
    }

    if (completionBlock)
    {
        NSError *error = info[PHImageErrorKey];
        completionBlock(rawSize, error);
    }

}];

Or for ALAssets, something like this:

        [[[ALAssetsLibrary alloc] init] assetForURL:asset.URL resultBlock:^(ALAsset *asset) {

            long long sizeBytes = [[asset defaultRepresentation] size];

            if (completionBlock)
            {
                completionBlock(sizeBytes, nil);
            }

        } failureBlock:^(NSError *error) {

            if (completionBlock)
            {
                completionBlock(0, error);
            }

        }];
Alfie Hanssen
  • 16,964
  • 12
  • 68
  • 74
  • 6
    Is there any way to do this for images? – Danny Jul 26 '15 at 20:04
  • and also AVComposition.. it's ridiculous how hard it is to just get a file size without loading all the data – Danny Jul 27 '15 at 02:08
  • Your answer *may* be correct, but the question specifically asks for **Swift** code examples, not Objective-C. Please edit. Thanks! – Eric Aya Jun 28 '16 at 12:46