[iOS][Swift] Detect ảnh từ Camera roll hay từ ứng dụng thứ 3

Mở đầu

Đột nhiên 1 ngày, tôi nhận được 1 câu hỏi từ khách hàng "Làm sao để detect được 1 bức ảnh vừa được lưu vào Photo Library này là chụp từ camera roll (ứng dụng chụp ảnh mặc định của iOS) hay chụp từ các app khác (Facebook, Twitter, ...)". Cùng khám phá xem trong 1 bức ảnh nó có những gì mà chúng ta không bao giờ để ý đến không nhé 😄

Demo

Dĩ nhiên, dù không liên quan lắm, nhưng để đọc thông tin từ ảnh, chúng ta phải đọc được ảnh từ Photo Library trước. Trước đây chúng ta vẫn quen sử dụng ALAssetsLibrary nhưng từ iOS 8, Apple đã khuyến khích việc sử dụng Photo Framework thay thế để tăng performance. Và từ iOS 9 trở đi, ALAssetsLibrary đã bị deprecated nên việc chuyển đổi là điều hoàn toàn bắt buộc. Nhân tiện đây, tôi sẽ giới thiệu qua cái Photo Framework luôn cho bài viết thêm dài

1. Lấy thông tin ảnh từ Photo Library

Như thường lệ, khi làm việc với các Framework có can thiệp vào phần cứng của device, điều đầu tiên chúng ta cần làm là xin quyền

    func requestPhotoAuthorization() -> Bool {
        let status = PHPhotoLibrary.authorizationStatus()
        switch status {
        case .Authorized:
            return true
        case .Restricted, .Denied:
            Utils.showAlert("Access Denied", message: "You must enable the Photo permission for this app",
                fromViewController: self, actionTitle: "Setting", action: { (action) in
                if let settingsURL = NSURL(string: UIApplicationOpenSettingsURLString) {
                    UIApplication.sharedApplication().openURL(settingsURL)
                }
            })
            return false
        default:
            break
        }

        PHPhotoLibrary.requestAuthorization { (status) in
            switch status {
            case .Authorized:
                self.getAlbumList()
                self.tableView.reloadData()
                break
            case .Restricted, .Denied:
                Utils.showAlert("Access Denied", message: "You must enable the Photo permission for this app",
                    fromViewController: self, actionTitle: "Setting", action: { (action) in
                    if let settingsURL = NSURL(string: UIApplicationOpenSettingsURLString) {
                        UIApplication.sharedApplication().openURL(settingsURL)
                    }
                })
                break
            default:
                break
            }
        }
        return false
    }

Khi đã được cấp quyền, chúng ta có thể thoải mái lấy ảnh từ Photo Library thôi. Bạn có thể lấy tất cả các ảnh, hoặc lấy ảnh từ 1 album như tôi sẽ làm tiếp đây

    func getAlbumList() {
        let option = PHFetchOptions()
        let sort = NSSortDescriptor(key: "localizedTitle", ascending: true)
        option.sortDescriptors = [sort]
        self.albumsFetch = PHAssetCollection.fetchAssetCollectionsWithType(.SmartAlbum, subtype: .AlbumRegular, options: option)
    }

IMG_0927.PNG

Từ Album, việc lấy ảnh ra cũng tương tự như việc lấy Album thôi, thậm chí còn dễ hơn rất nhiều

    private func getPhotoList() {
        self.photoFetch = PHAsset.fetchAssetsInAssetCollection(self.albumID, options: nil)
    }

IMG_0928.PNG

2. Get Image Info

        let requestOption = PHImageRequestOptions()
        requestOption.resizeMode = .Exact
        requestOption.deliveryMode = .HighQualityFormat
        requestOption.synchronous = true;
        PHImageManager.defaultManager().requestImageDataForAsset(asset, options: requestOption) { (data, string, orientation, info) in
            guard data != nil else {
                return
            }
            let pngCFData = CFDataCreate(kCFAllocatorDefault, UnsafePointer<UInt8>(data!.bytes), data!.length)
            let sourceRef = CGImageSourceCreateWithData(pngCFData, nil)
            guard sourceRef != nil else {
                return
            }
            let metaData = CGImageSourceCopyPropertiesAtIndex(sourceRef!, 0, nil)
            guard metaData != nil else {
                return
            }
            let metaDataDic = metaData! as NSDictionary
            self.TIFFdata = metaDataDic[kCGImagePropertyTIFFDictionary as String] as? NSDictionary
        }

Công việc tưởng chừng như quá rắc rối lại được giải quyết 1 cách cực kỳ đơn giản phải không. Cùng để ý đến các thông số bé nhỏ trong cái Info của nó, bạn sẽ giải quyết được những vấn đề rất lớn đấy 😄

IMG_0929.PNG

Kết

Với phần Info Image đã list ra, bạn có thể detect xem ảnh đó là chụp từ Camera Roll hay chụp từ phần chụp ảnh của Facebook, Twitter, ... Tuy nó không chính xác hoàn toàn 100% nhưng hi vọng là nó đã có thể giúp bạn detect được ảnh 1 cách tương đối. Còn rất nhiều thuộc tính của ảnh ở đây mà bạn có thể sử dụng https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CGImageProperties_Reference/

Nếu bạn cần demo, tôi cũng đã tạo sẵn ở đây 1 ứng dụng demo, fell free to using it https://github.com/quocnb/PhotoInforReader