在 swift 中以编程方式获取图像文件类型

Get image file type programmatically in swift

我正在使用 PNG 和 JPEG 文件从 parse 下载图像。

当图像下载到应用程序时,我需要确定文件类型是什么,以便我可以相应地处理图像。

查看了 API 的 uiimageview 并进行了搜索,但在 swift 中找不到任何解决方案。

感谢任何意见

正在尝试从 PFFIle 中获取 url §:

let imageURLFromParse = NSURL(string : caseImageFile2.url);

// Error here: 'NSURL?' does not have a member named 'pathExtension'                   
if(imageURLFromParse.pathExtension!.lowercaseString == ".jpg" || imageURLFromParse.pathExtension.lowercaseString == ".jpeg"){

  println("Parse image ext is a jpg: \(imageURLFromParse.pathExtension.lowercaseString)");

  fileExtenion = ".jpg";

} else {                        
  println("Parse image is a png: \(imageURLFromParse.pathExtension.lowercaseString)");

  fileExtenion = ".png";                           
}

您必须以二进制形式获取图像的第一个字节。该字节表示图像类型。这是我在我的项目中使用的代码,但在 Objective-c:

uint8_t c;
        [_receivedData getBytes:&c length:1];

        NSString *extension = @"jpg";

        switch (c) {
            case 0xFF:
            {
                extension = @"jpg";
            }
            case 0x89:
            {
                extension = @"png";
            }
                break;
            case 0x47:
            {
                extension = @"gif";
            }
                break;
            case 0x49:
            case 0x4D:
            {
                extension = @"tiff";
            }
                break;
            default:
                FLog(@"unknown image type");
        }

在 swift 中尝试这个(1.2,否则你必须使用 var ext):

func imageType(imgData : NSData) -> String
{
    var c = [UInt8](count: 1, repeatedValue: 0)
    imgData.getBytes(&c, length: 1)

    let ext : String

    switch (c[0]) {
    case 0xFF:

        ext = "jpg"

    case 0x89:

        ext = "png"
    case 0x47:

        ext = "gif"
    case 0x49, 0x4D :
        ext = "tiff"
    default:
        ext = "" //unknown
    }

    return ext
}

我想知道我的图片在选择后是什么扩展名。我用过这个:

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
  if (!(picker.sourceType == UIImagePickerControllerSourceType.Camera)) {
    let assetPath = info[UIImagePickerControllerReferenceURL] as! NSURL
    if assetPath.absoluteString.hasSuffix("JPG") {

更新 Swift 3.0.2

基于 Hoa 的回答和 Kingfisher library

import UIKit
import ImageIO

struct ImageHeaderData{
    static var PNG: [UInt8] = [0x89]
    static var JPEG: [UInt8] = [0xFF]
    static var GIF: [UInt8] = [0x47]
    static var TIFF_01: [UInt8] = [0x49]
    static var TIFF_02: [UInt8] = [0x4D]
}

enum ImageFormat{
    case Unknown, PNG, JPEG, GIF, TIFF
}


extension NSData{
    var imageFormat: ImageFormat{
        var buffer = [UInt8](repeating: 0, count: 1)
        self.getBytes(&buffer, range: NSRange(location: 0,length: 1))
        if buffer == ImageHeaderData.PNG
        {
            return .PNG
        } else if buffer == ImageHeaderData.JPEG
        {
            return .JPEG
        } else if buffer == ImageHeaderData.GIF
        {
            return .GIF
        } else if buffer == ImageHeaderData.TIFF_01 || buffer == ImageHeaderData.TIFF_02{
            return .TIFF
        } else{
            return .Unknown
        }
    }
}

用法

let imageURLFromParse = NSURL(string : "https://i.stack.imgur.com/R64uj.jpg")
let imageData = NSData(contentsOf: imageURLFromParse! as URL)
print(imageData!.imageFormat)

您可以将其用于本地和在线图像。

为什么不简单地执行以下操作:

let ext = NSURL(fileURLWithPath: path/of/your/file as! String).pathExtension
print(ext!)

这将为您提供文件的扩展名。

您可以在项目中测试https://github.com/bonyadmitr/ImageFormat

添加到项目

import Foundation

/// can be done "heic", "heix", "hevc", "hevx"
enum ImageFormat: String {
    case png, jpg, gif, tiff, webp, heic, unknown
}

extension ImageFormat {
    static func get(from data: Data) -> ImageFormat {
        switch data[0] {
        case 0x89:
            return .png
        case 0xFF:
            return .jpg
        case 0x47:
            return .gif 
        case 0x49, 0x4D:
            return .tiff 
        case 0x52 where data.count >= 12:
            let subdata = data[0...11]

            if let dataString = String(data: subdata, encoding: .ascii),
                dataString.hasPrefix("RIFF"),
                dataString.hasSuffix("WEBP")
            {    
                return .webp
            }

        case 0x00 where data.count >= 12 :
            let subdata = data[8...11]

            if let dataString = String(data: subdata, encoding: .ascii),
                Set(["heic", "heix", "hevc", "hevx"]).contains(dataString)
                ///OLD: "ftypheic", "ftypheix", "ftyphevc", "ftyphevx"
            {    
                return .heic
            }
        default:
            break
        }
        return .unknown
    } 

    var contentType: String {
        return "image/\(rawValue)"
    }
}

正在使用

for file in ["1.jpg", "2.png", "3.gif", "4.svg", "5.TIF", "6.webp", "7.HEIC"] {
    if let data = Data(bundleFileName: file) {
        print(file, ImageFormat.get(from: data))
    }
}

/// Result
/// 1.jpg jpg
/// 2.png png
/// 3.gif gif
/// 4.svg unknown
/// 5.TIF tiff
/// 6.webp webp
/// 7.HEIC heic

@XueYu 的回答对我帮助很大。 这是 Data 而不是 NSData

的更新
struct ImageHeaderData {
    static var PNG: [UInt8] = [0x89]
    static var JPEG: [UInt8] = [0xFF]
    static var GIF: [UInt8] = [0x47]
    static var TIFF_01: [UInt8] = [0x49]
    static var TIFF_02: [UInt8] = [0x4D]
}
enum ImageFormat {
    case Unknown, PNG, JPEG, GIF, TIFF
}
extension Data {
    var imageFormat: ImageFormat {
        var buffer = [UInt8](repeating: 0, count: 1)
        copyBytes(to: &buffer, from: 0..<1)
        if buffer == ImageHeaderData.PNG { return .PNG }
        if buffer == ImageHeaderData.JPEG { return .JPEG }
        if buffer == ImageHeaderData.GIF { return .GIF }
        if buffer == ImageHeaderData.TIFF_01 || 
           buffer == ImageHeaderData.TIFF_02 {
            return .TIFF
        }
        return .Unknown
    }
}

此代码将用于 Swift 5iOS 12。如果我们使用这段代码,我们可以获得 DocumentsImages File type

import UIKit
import Photos

class ViewController {

     let imagePicker = UIImagePickerController()

     override func viewDidLoad() {
        super.viewDidLoad()

        checkPermission()
     }
}

extension ViewController : UINavigationControllerDelegate, UIImagePickerControllerDelegate, UIDocumentPickerDelegate {

     func checkPermission() {

         let photoAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
         switch photoAuthorizationStatus {
         case .authorized:
             print("Access is granted by user")
             accessDocsAndImages()
         case .notDetermined:
             PHPhotoLibrary.requestAuthorization({ newStatus in
                 print("status is \(newStatus)")
                 if newStatus == PHAuthorizationStatus.authorized {
                     /* do stuff here */
                     print("success")
                 }
             })
         case .restricted:
             print("User do not have access to photo album.")
         case .denied:
             print("User has denied the permission.")
         @unknown default:
             print("Defults")
         }   
     }

     func accessDocsAndImages() {

         imagePicker.allowsEditing = true
         imagePicker.delegate = self
         let optionMenu = UIAlertController(title: nil, message: "Choose Option", preferredStyle: .alert)
         let openCameraAction = UIAlertAction(title: "Camera", style: .default, handler: {
             (alert: UIAlertAction!) -> Void in
             return
         })

         let openGalleryAction = UIAlertAction(title: "Open Gallery", style: .default, handler: {
             (alert: UIAlertAction!) -> Void in
             self.imagePicker.sourceType = .photoLibrary
             self.present(self.imagePicker, animated: true, completion: nil)
             print("Opened gallery")
         })
         let openDocAction = UIAlertAction(title: "Open Documents", style: .default, handler: {
             (alert: UIAlertAction!) -> Void in
             print("Opened gallery")
             let documentPicker = UIDocumentPickerViewController(documentTypes: ["public.content", "public.item", "public.composite-content", "public.data", "public.database", "public.calendar-event", "public.message", "public.presentation", "public.contact", "public.archive", "public.disk-image", "public.text", "public.plain-text", "public.utf8-plain-text", "public.utf16-external-plain-​text", "public.utf16-plain-text", "com.apple.traditional-mac-​plain-text", "public.rtf","public.pdf", "public.movie", "public.audiovisual-content", "public.video", "public.audio"], in: .import)
             documentPicker.delegate = self
             //documentPicker.modalPresentationStyle = .formSheet
             documentPicker.allowsMultipleSelection = true
             self.present(documentPicker, animated: true, completion: nil)
         })
         let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: {
             (alert: UIAlertAction!) -> Void in
             print("cancelled")
         })
         optionMenu.addAction(openGalleryAction)
         optionMenu.addAction(openCameraAction)
         optionMenu.addAction(openDocAction)
         optionMenu.addAction(cancelAction)
         self.present(optionMenu, animated: true, completion: nil)
     }

     func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

         if let asset = info[UIImagePickerController.InfoKey.phAsset] as? PHAsset {
             let assetResources = PHAssetResource.assetResources(for: asset)

             print(assetResources.first!.originalFilename)

             if (assetResources.first!.originalFilename.hasSuffix("JPG")) {
                 print("jpg")
             } else if (assetResources.first!.originalFilename.hasSuffix("JPEG")) {
                 print("jpeg")
             } else if (assetResources.first!.originalFilename.hasSuffix("PNG")) {
                 print("png")
             } else if (assetResources.first!.originalFilename.hasSuffix("GIF")) {
                 print("gif")
             } else if (assetResources.first!.originalFilename.hasSuffix("TIFF")) {
                 print("tiff")
             } else if (assetResources.first!.originalFilename.hasSuffix("WEBP")) {
                 print("webp")
             } else if (assetResources.first!.originalFilename.hasSuffix("HEIC")) {
                 print("heic")
             } else if (assetResources.first!.originalFilename.hasSuffix("HEIX")) {
                 print("heix")
             } else if (assetResources.first!.originalFilename.hasSuffix("HEVC")) {
                 print("hevc")
             } else if (assetResources.first!.originalFilename.hasSuffix("HEVX")) {
                 print("hevx")
             } else {
                 print("Unknown")
             }
         }
         dismiss(animated: true, completion: nil)
     }

     private func imagePickerControllerDidCancel(picker: UIImagePickerController) {

         dismiss(animated: true, completion: nil)
     }

     func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {

         print(url)
     }

     func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {

         let cico = urls[0] as URL
         print(cico)
         print(urls[0])
         print(urls[0].lastPathComponent)
         print(urls[0].pathExtension)
         let urlWithoutFileExtension: URL =  urls[0].deletingPathExtension()
         let fileNameWithoutExtension: String = urlWithoutFileExtension.lastPathComponent
         print(fileNameWithoutExtension)
         dismiss(animated: true, completion: nil)
     }

     func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {

         print(" cancelled by user")

     }
 }

根据 XueYu 的上述回答,但是您不需要导入 UIKit 或 ImageIO... 只需导入 Foundation,这反过来也使其跨平台。

import Foundation

enum ImageFormat: RawRepresentable {
  case unknown, png, jpeg, gif, tiff1, tiff2
  
  init?(rawValue: [UInt8]) {
    switch rawValue {
    case [0x89]: self = .png
    case [0xFF]: self = .jpeg
    case [0x47]: self = .gif
    case [0x49]: self = .tiff1
    case [0x4D]: self = .tiff2
    default: return nil
    }
  }
  
  var rawValue: [UInt8] {
    switch self {
    case .png: return [0x89]
    case .jpeg: return [0xFF]
    case .gif: return [0x47]
    case .tiff1: return [0x49]
    case .tiff2: return [0x4D]
    case .unknown: return []
    }
  }
}


extension NSData {
  var imageFormat: ImageFormat {
    var buffer = [UInt8](repeating: 0, count: 1)
    self.getBytes(&buffer, range: NSRange(location: 0,length: 1))
    return ImageFormat(rawValue: buffer) ?? .unknown
  }
}

extension Data {
  var imageFormat: ImageFormat {
    (self as NSData?)?.imageFormat ?? .unknown
  }
}

用法:

let imgUrl = URL(string : "https://i.stack.imgur.com/R64uj.jpg")!
let imgData = try! Data(contentsOf: imgUrl)
let imgFormat = imgData.imageFormat