Orkhan Alizade
Orkhan Alizade

Reputation: 7569

How to get image file size in Swift?

I am using

UIImagePickerControllerDelegate,
UINavigationControllerDelegate,
UIPopoverControllerDelegate

these delegates for choosing image from my gallery or my camera. So, how can I get image file size after choosing an image?

I want to use this:

let filePath = "your path here"
    var fileSize : UInt64 = 0

    do {
        let attr : NSDictionary? = try NSFileManager.defaultManager().attributesOfItemAtPath(filePath)

        if let _attr = attr {
            fileSize = _attr.fileSize();
            print(fileSize)
        }
    } catch {
    }

but here I need a path, but how can I get without a path, just by image file?

Upvotes: 53

Views: 99782

Answers (14)

Mitul Pokiya
Mitul Pokiya

Reputation: 172

try this for getting size from url

func fileSize(url: URL) -> String? {
        
        var fileSize:Int?
        do {
            let resources = try url.resourceValues(forKeys:[.fileSizeKey])
            fileSize = resources.fileSize!
            print ("\(String(describing: fileSize))")
        } catch {
            print("Error: \(error)")
        }
        
        // bytes
        if fileSize! < 999 {
            return String(format: "%lu bytes", CUnsignedLong(bitPattern: fileSize!))
        }
        // KB
        var floatSize = Float(fileSize! / 1000)
        if floatSize < 999 {
            return String(format: "%.1f KB", floatSize)
        }
        // MB
        floatSize = floatSize / 1000
        if floatSize < 999 {
            return String(format: "%.1f MB", floatSize)
        }
        // GB
        floatSize = floatSize / 1000
        return String(format: "%.1f GB", floatSize)
    }

Use Example

let sizeInString = fileSize(url: url)  
print("FileSize = "+sizeInString!)

Upvotes: 2

Dhaivat Vyas
Dhaivat Vyas

Reputation: 2928

Please check the google for 1 kb to bytes it will be 1000.

https://www.google.com/search?q=1+kb+%3D+how+many+bytes&oq=1+kb+%3D+how+many+bytes&aqs=chrome..69i57.8999j0j1&sourceid=chrome&ie=UTF-8


So while getting the proper size I’ve added multiple scenario by adding image in App Bundle and in photos in simulator. Well the image which I took from my Mac was of 299.0 KB.


Scenario 1: Adding image to Application Bundle

On adding image in your Xcode the size of the image will remain same in project directory. But you get it from its path the size will be reduced to 257.0 KB. Which is the actual size of the image used in the device or simulator.

    guard let aStrUrl = Bundle.main.path(forResource: "1", ofType: "png") else { return }

   let aUrl = URL(fileURLWithPath: aStrUrl)
   print("Img size = \((Double(aUrl.fileSize) / 1000.00).rounded()) KB")

   extension URL {
        var attributes: [FileAttributeKey : Any]? {
            do {
                return try FileManager.default.attributesOfItem(atPath: path)
            } catch let error as NSError {
                print("FileAttribute error: \(error)")
            }
            return nil
        }

        var fileSize: UInt64 {
            return attributes?[.size] as? UInt64 ?? UInt64(0)
        }

        var fileSizeString: String {
            return ByteCountFormatter.string(fromByteCount: Int64(fileSize), countStyle: .file)
        }

        var creationDate: Date? {
            return attributes?[.creationDate] as? Date
        }
    }

Scenario 2: Adding image to Photos in Simulator

On adding image to photos in simulator or device the size of the image increased from 299.0 KB to 393.0 KB. Which is the actual size of the image stored in the device or simulator’s document directory.

Swift 4 and earlier

var image = info[UIImagePickerControllerOriginalImage] as! UIImage
var imgData: NSData = NSData(data: UIImageJPEGRepresentation((image), 1)) 
// var imgData: NSData = UIImagePNGRepresentation(image) 
// you can also replace UIImageJPEGRepresentation with UIImagePNGRepresentation.
var imageSize: Int = imgData.count
print("size of image in KB: %f ", Double(imageSize) / 1000.0)

Swift 5

let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage

let imgData = NSData(data: image.jpegData(compressionQuality: 1)!)
var imageSize: Int = imgData.count
print("actual size of image in KB: %f ", Double(imageSize) / 1000.0)   

By adding .rounded() it will give you 393.0 KB and without using it it will give 393.442 KB. So please check the image size manually once using the above code. As the size of image may vary in different devices and mac. I've check it only on mac mini and simulator iPhone XS.

Upvotes: 101

Coder ACJHP
Coder ACJHP

Reputation: 2224

extension UIImage {

    public enum DataUnits: String {
        case byte, kilobyte, megabyte, gigabyte
    }

    func getSizeIn(_ type: DataUnits)-> String {

        guard let data = self.pngData() else {
            return ""
        }

        var size: Double = 0.0

        switch type {
        case .byte:
            size = Double(data.count)
        case .kilobyte:
            size = Double(data.count) / 1024
        case .megabyte:
            size = Double(data.count) / 1024 / 1024
        case .gigabyte:
            size = Double(data.count) / 1024 / 1024 / 1024
        }

        return String(format: "%.2f", size)
    }
}

Usage example : print("Image size \(yourImage.getSizeIn(.megabyte)) mb")

Upvotes: 22

Mir
Mir

Reputation: 469

I make work around data units conversion :

Bytes -> KB -> MB -> GB -> ... -> Extremest Monster Data

enum dataUnits:CaseIterable {
case B      //Byte
case KB     //kilobyte
case MB     //megabyte
case GB     //gigabyte
case TB     //terabyte
case PB     //petabyte
case EB     //exabyte
case ZB     //zettabyte
case YB     //yottabyte
case BD     //Big Data
case BBx    // Extra Big Bytes
case BBxx   // 2 time Extra Big Bytes
case BBxxx  // 3 time Extra Big Bytes
case BBxxxx // 4 time Extra Big Bytes
case MBB    // Monster Big Bytes 
}
func convertStorageUnit(data n:Double,inputDataUnit unitLevel:Int,roundPoint:Int = 2,nG:Double = 1000.0)->String{
if(n>=nG){
    return convertStorageUnit(data:n/1024,inputDataUnit:unitLevel+1) 
}else{
    let ut = unitLevel > dataUnits.allCases.count + 1 ? "Extreme Monster Data" : dataUnits.allCases.map{"\($0)"}[unitLevel]

   return "\(String(format:"%.\(roundPoint)f",n)) \(ut)"
}

}

print(
convertStorageUnit(data:99922323343439789798789898989897987945454545920,
inputDataUnit:dataUnits.allCases.firstIndex(of: .B)!,roundPoint: 0)
)

output : 8.87 PB

Note: Input data length should be less than 64-bit OR Change data type According

Upvotes: 0

Kundan
Kundan

Reputation: 31

//Swift 4

if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
        ///check image Size
       let imgData = NSData(data: UIImageJPEGRepresentation((pickedImage), 1)!)
       let imageSize: Int = imgData.count
       print("size of image in KB: %f ", Double(imageSize) / 1024.0)
       print("size of image in MB: %f ", Double(imageSize) / 1024.0 / 1024)    

    }

Upvotes: 0

Govind Prajapati
Govind Prajapati

Reputation: 957

Try this code (Swift 4.2)

extension URL {
    var attributes: [FileAttributeKey : Any]? {
        do {
            return try FileManager.default.attributesOfItem(atPath: path)
        } catch let error as NSError {
            print("FileAttribute error: \(error)")
        }
        return nil
    }

    var fileSize: UInt64 {
        return attributes?[.size] as? UInt64 ?? UInt64(0)
    }

    var fileSizeString: String {
        return ByteCountFormatter.string(fromByteCount: Int64(fileSize), countStyle: .file)
    }

    var creationDate: Date? {
        return attributes?[.creationDate] as? Date
    }
}

And use example

guard let aStrUrl = Bundle.main.path(forResource: "example_image", ofType: "jpg") else { return }

        let aUrl = URL(fileURLWithPath: aStrUrl)

        print("Img size = \((Double(aUrl.fileSize) / 1000.00).rounded()) KB")

Upvotes: 0

Vasily  Bodnarchuk
Vasily Bodnarchuk

Reputation: 25304

Details

  • Xcode 10.2.1 (10E1001), Swift 5

Solution

extension String {
    func getNumbers() -> [NSNumber] {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        let charset = CharacterSet.init(charactersIn: " ,.")
        return matches(for: "[+-]?([0-9]+([., ][0-9]*)*|[.][0-9]+)").compactMap { string in
            return formatter.number(from: string.trimmingCharacters(in: charset))
        }
    }

    // https://stackoverflow.com/a/54900097/4488252
    func matches(for regex: String) -> [String] {
        guard let regex = try? NSRegularExpression(pattern: regex, options: [.caseInsensitive]) else { return [] }
        let matches  = regex.matches(in: self, options: [], range: NSMakeRange(0, self.count))
        return matches.compactMap { match in
            guard let range = Range(match.range, in: self) else { return nil }
            return String(self[range])
        }
    }
}

extension UIImage {
    func getFileSizeInfo(allowedUnits: ByteCountFormatter.Units = .useMB,
                         countStyle: ByteCountFormatter.CountStyle = .file) -> String? {
        // https://developer.apple.com/documentation/foundation/bytecountformatter
        let formatter = ByteCountFormatter()
        formatter.allowedUnits = allowedUnits
        formatter.countStyle = countStyle
        return getSizeInfo(formatter: formatter)
    }

    func getFileSize(allowedUnits: ByteCountFormatter.Units = .useMB,
                     countStyle: ByteCountFormatter.CountStyle = .memory) -> Double? {
        guard let num = getFileSizeInfo(allowedUnits: allowedUnits, countStyle: countStyle)?.getNumbers().first else { return nil }
        return Double(truncating: num)
    }

    func getSizeInfo(formatter: ByteCountFormatter, compressionQuality: CGFloat = 1.0) -> String? {
        guard let imageData = jpegData(compressionQuality: compressionQuality) else { return nil }
        return formatter.string(fromByteCount: Int64(imageData.count))
    }
}

Usage

guard let image = UIImage(named: "img") else { return }
if let imageSizeInfo = image.getFileSizeInfo() {
    print("\(imageSizeInfo), \(type(of: imageSizeInfo))") // 51.9 MB, String
}

if let imageSizeInfo = image.getFileSizeInfo(allowedUnits: .useBytes, countStyle: .file) {
    print("\(imageSizeInfo), \(type(of: imageSizeInfo))") // 54,411,697 bytes, String
}

if let imageSizeInfo = image.getFileSizeInfo(allowedUnits: .useKB, countStyle: .decimal) {
    print("\(imageSizeInfo), \(type(of: imageSizeInfo))") // 54,412 KB, String
}

if let size = image.getFileSize() {
    print("\(size), \(type(of: size))") // 51.9, Double
}

Upvotes: 4

PinkeshGjr
PinkeshGjr

Reputation: 8680

Swift 4.2

let jpegData = image.jpegData(compressionQuality: 1.0)
let jpegSize: Int = jpegData?.count ?? 0
print("size of jpeg image in KB: %f ", Double(jpegSize) / 1024.0)

Upvotes: 1

Kirill Artemenko
Kirill Artemenko

Reputation: 173

let imageData = UIImageJPEGRepresentation(image, 1)
let imageSize = imageData?.count

UIImageJPEGRepresentation — returns the Data object for the specified image in JPEG format. The value 1.0 represents the least compression (close to original image).

imageData?.count — return data length (chars count equals bytes).

Important! UIImageJPEGRepresentation or UIImagePNGRepresentation will not return the original image. But if use given Data as source for uploading - than file size be the same as on the server (even using compression).

Upvotes: 1

efremidze
efremidze

Reputation: 2862

let data = UIImageJPEGRepresentation(image, 1)
let imageSize = data?.count

Duplicate of How to get the size of a UIImage in KB?

Upvotes: 1

Tung Fam
Tung Fam

Reputation: 8167

Swift 3/4:

if let imageData = UIImagePNGRepresentation(image) {
     let bytes = imageData.count
     let kB = Double(bytes) / 1000.0 // Note the difference
     let KB = Double(bytes) / 1024.0 // Note the difference
}

Please note the difference between kB and KB. Answering here because in my case we had an issue while we considered kilobyte as 1024 bytes but server side considered it as 1000 bytes which caused an issue. Link to learn more.

PS. Almost sure you'll go with kB (1000).

Upvotes: 12

JP Aquino
JP Aquino

Reputation: 4066

Swift 3

let uploadData = UIImagePNGRepresentation(image)
let array = [UInt8](uploadData)
print("Image size in bytes:\(array.count)")

Upvotes: 2

Adarsh G J
Adarsh G J

Reputation: 2684

let selectedImage = info[UIImagePickerControllerOriginalImage] as!  UIImage 
let selectedImageData: NSData = NSData(data:UIImageJPEGRepresentation((selectedImage), 1)) 
let selectedImageSize:Int = selectedImageData.length 
print("Image Size: %f KB", selectedImageSize /1024.0)

Upvotes: 1

evnaz
evnaz

Reputation: 190

Try this

import Darwin

...    

let size = malloc_size(&_attr)

Upvotes: -3

Related Questions