【问题标题】:How to get image file size in Swift?如何在 Swift 中获取图像文件大小?
【发布时间】:2016-03-19 16:24:02
【问题描述】:

我正在使用

UIImagePickerControllerDelegate,
UINavigationControllerDelegate,
UIPopoverControllerDelegate

这些代表用于从我的画廊或相机中选择图像。那么,选择图片后如何获取图片文件大小呢?

我想用这个:

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 {
    }

但是这里我需要一个路径,但是没有路径我怎么能得到,只是通过图像文件呢?

【问题讨论】:

标签: ios swift uiimageview uiimagepickercontroller


【解决方案1】:

请在 google 上查看 1 kb 到 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


因此,在获得适当尺寸的同时,我通过在 App Bundle 中添加图像和在模拟器中的照片中添加了多个场景。 嗯,我从我的 Mac 上截取的图像是 299.0 KB。


场景 1: 将图像添加到应用程序包

在您的 Xcode 中添加图像时,图像的大小将在项目目录中保持不变。但是你从它的路径中得到它的大小会减少到 257.0 KB。这是设备或模拟器中使用的图像的实际大小。

    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
        }
    }

场景2:在模拟器中添加图片到照片

在模拟器或设备中向照片添加图像时,图像大小从 299.0 KB 增加到 393.0 KB。设备或模拟器的文档目录中存储的图片的实际大小。

Swift 4 及更早版本

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)

斯威夫特 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)   

通过添加 .rounded() 它将为您提供 393.0 KB,如果不使用它,它将为您提供 393.442 KB。因此,请使用上述代码手动检查图像大小。由于图像的大小在不同的设备和 mac 中可能会有所不同。我只在 mac mini 和模拟器 iPhone XS 上检查过。

【讨论】:

  • 你认为图像压缩后 (UIImageJPEGRepresentation((image), 0.5)) 你会得到正确的尺寸吗?
  • 它将为您提供图像的当前大小。但是您也可以将压缩设置为 1,然后它将为您提供未经压缩的原始图像的大小。
  • @DhaivatVyas 压缩怎么样?它会使我的图像质量变差还是正常?我现在正在寻找它的压缩方法,如果这个方法是好的,那我就给你吧
  • 压缩会影响你使用UIImageJPEGRepresentation的图像质量。但是如果您使用UIImagePNGRepresentation,它将占用更多空间。因为通过降低图像质量会丢失一些数据并且它的质量会受到影响。如果您使用 JPEGRepresentation,请尽量不要低于 0.7,在某些情况下不要低于 0.5。因为质量会受到更大的影响。但同样,您需要根据您在应用程序中对图像的要求,通过反复试验进行检查。
  • 您还可以根据您需要的文件大小降低图像质量。 EX:如果您当前的图像大小为 10 MB,并且您只需要 1 MB 的最大图像大小,那么也可以这样做。访问此网址:“stackoverflow.com/a/613380/4101371”和“stackoverflow.com/a/29137723/4101371”。这也会有所帮助。您也可以在此 url 中将 obj-C 代码转换为 swift:“objectivec2swift.com/#/converter/code”。
【解决方案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)
    }
}

使用示例:print("Image size \(yourImage.getSizeIn(.megabyte)) mb")

【讨论】:

  • 它给出的尺寸与原始尺寸不同。
  • @aqsaarshad 我认为这是因为数据转换,此代码将任何类型的 UIImage 转换为 PNG 数据以获取大小,当您的图像为 JPEG 时,数据大小可能会发生变化?我不确定。
【解决方案3】:

我解决了数据单位转换问题:

字节 -> KB -> MB -> GB -> ... -> 极限怪物数据

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)
)

输出:8.87 PB

注意:输入数据长度应小于 64 位根据数据类型更改数据类型

【讨论】:

    【解决方案4】:

    //斯威夫特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)    
    
        }
    

    【讨论】:

      【解决方案5】:

      试试这个代码 (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
          }
      }
      

      并使用示例

      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")
      

      【讨论】:

        【解决方案6】:

        详情

        • Xcode 10.2.1 (10E1001)、Swift 5

        解决方案

        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))
            }
        }
        

        用法

        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
        }
        

        【讨论】:

          【解决方案7】:

          斯威夫特 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)
          

          【讨论】:

            【解决方案8】:
            let imageData = UIImageJPEGRepresentation(image, 1)
            let imageSize = imageData?.count
            

            UIImageJPEGRepresentation — 以 JPEG 格式返回指定图像的 Data 对象。值 1.0 表示最小压缩(接近原始图像)

            imageData?.count — 返回数据长度(字符数等于字节)

            重要! UIImageJPEGRepresentationUIImagePNGRepresentation 不会返回原始图像。但是如果使用给定的数据作为上传源 - 文件大小与服务器上的相同(即使使用压缩)。

            【讨论】:

            • 您可能想为您的回答提供一些背景信息。
            【解决方案9】:
            let data = UIImageJPEGRepresentation(image, 1)
            let imageSize = data?.count
            

            How to get the size of a UIImage in KB? 的副本

            【讨论】:

              【解决方案10】:

              斯威夫特 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
              }
              

              请注意 kB 和 KB 之间的区别。在这里回答是因为在我的情况下我们遇到了一个问题,我们将千字节视为 1024 字节,但服务器端将其视为 1000 字节,这导致了问题。 Link 了解更多。

              PS。几乎可以肯定你会选择 kB (1000)。

              【讨论】:

                【解决方案11】:

                斯威夫特 3

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

                【讨论】:

                • uploadData.count 和array.count 有什么区别?我需要转换为 [UInt8] 吗?
                • 没有得到实际尺寸。
                • Uint8 会限制任何大文件
                【解决方案12】:
                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)
                

                【讨论】:

                  【解决方案13】:

                  试试这个

                  import Darwin
                  
                  ...    
                  
                  let size = malloc_size(&_attr)
                  

                  【讨论】:

                  • 什么是&_attr?
                  猜你喜欢
                  • 1970-01-01
                  • 2015-03-31
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多