Get image file type programmatically in swift
Asked Answered
V

8

19

I am downloading images from parse with file totes PNG and JPEG.

When image is downloaded to the app I need to determine what the file type is so I can handle image accordingly.

Had a look at API for uiimageview and did a search but can't find any solution in swift.

Any input appreciated

Trying to get url from PFFIle §:

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";                           
}
Vanderbilt answered 15/4, 2015 at 7:32 Comment(1)
Bummer. After I download the image I save the image locally on device then save URL to core data, it's here I need to identify wether it's a PNG or JPGVanderbilt
T
26

Update for Swift 3.0.2

Based on Hoa's answer and 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
        }
    }
}

Usage

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

You can use this with Both local and online images.

Tyne answered 8/2, 2017 at 4:10 Comment(2)
How can I use for local images ?Julie
Pass the contentsOf function a URL for a file on diskPakistan
P
7

You can test in project https://github.com/bonyadmitr/ImageFormat

Add to project

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

Using

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
Pilfer answered 17/2, 2018 at 15:31 Comment(1)
Voted because of HEIC! Annoyingly you need 12 bytes...Rollicking
F
4

You have to get the first byte of your image in binary. This byte indicate which kind of image type. Here is the code that I've used for my project but in 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");
        }

Try with this in swift (1.2, else you have to use 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
}
Faze answered 15/4, 2015 at 8:21 Comment(3)
Thanks will try convert to swift and have a lookVanderbilt
You can find more info here: #4147811Faze
Hi, I tried your solution and it worked after I changed: var c = [UInt8]() to var c = [UInt8](count: 1, repeatedValue: 0) The array has to have space for at least one byte.Fahlband
G
3

This code will use for Swift 5 And iOS 12. If we use this code we can get Documents and Images 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")

     }
 }
Gamo answered 1/12, 2019 at 16:14 Comment(4)
When I selected jpg file then it is working properly and while selecting the rest of the image format then unknown displayedCenozoic
@Ronak it’s working. May be check your side, whether your your selecting png or not. Before posted this answer checked I have checked with all Images file types.Gamo
I have dragged png and gif photos from the library and still not getting. May i should try to pass the format/extension like this hasSuffix('png')Cenozoic
@Ronak you should pass like hasSuffix('JPEG')Gamo
R
2

I wanted to know what extension is my image after I have picked it. I used this:

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
  if (!(picker.sourceType == UIImagePickerControllerSourceType.Camera)) {
    let assetPath = info[UIImagePickerControllerReferenceURL] as! NSURL
    if assetPath.absoluteString.hasSuffix("JPG") {
Rarefy answered 1/6, 2016 at 14:15 Comment(0)
G
1

Why not simply do the following:

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

This will give you the extension of the file.

Galore answered 18/12, 2017 at 8:43 Comment(0)
A
0

@XueYu's answer helped me out a lot. Heres an update for Data rather than 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
    }
}
Attaway answered 16/10, 2018 at 18:54 Comment(2)
You don't you check just the first byte of the data? Using an array of a single byte is pointless.Capernaum
How can I check UIImage extension? Whether selected image is png or jpg or jpeg ?Julie
H
0

Based on XueYu's answer above, however you don't need to import UIKit or ImageIO… just Foundation, which in turn makes it cross-platform too.

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

Usage:

let imgUrl = URL(string : "https://i.sstatic.net/R64uj.jpg")!
let imgData = try! Data(contentsOf: imgUrl)
let imgFormat = imgData.imageFormat
Human answered 18/9, 2021 at 1:16 Comment(2)
Do you have any solution for knowing the image type of images in the iOS photo gallery? I only found code samples that require to convert the image data to PNG or JPG and obviously that doesn't make much sense.Resistive
@Resistive I don't do much iOS development (I spend most of my time in AppKit) nor have I used the PhotoKit framework extensively… having had a quick refresher flick through the documentation, it seems like you have to request the underlying image data using requestData(for:options:dataReceivedHandler:completionHandler:), then examine the data as per the code sample above. Not sure how efficient it would be, i.e. hopefully it doesn't load the entire file into memory just to have you examine a few bytes to get the image type.Human

© 2022 - 2024 — McMap. All rights reserved.