How to get image file size in Swift?
Solution 1:
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.
Solution 2:
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")
Solution 3:
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).
Solution 4:
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
}
Solution 5:
Swift 3
let uploadData = UIImagePNGRepresentation(image)
let array = [UInt8](uploadData)
print("Image size in bytes:\(array.count)")