zoukankan      html  css  js  c++  java
  • swift 相册PHAssetCollection,PHAsset

    import Foundation
    import Photos
    /**
     *  相册公用方法类
     */
    class JYAlbumHelpModel: NSObject {
        
        /// 获取所有相册
        ///
        /// - Returns: 返回相册列表集合
        static func getAllAlbumList() -> [PHAssetCollection] {
            
            let smartAlbums: PHFetchResult = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .albumRegular, options: nil)
            guard smartAlbums.count > 0 else {
                return []
            }
            var tempArr: [PHAssetCollection] = []
            
            
            ///创建的相册文件夹
            let topLeveUserCollections = PHCollectionList.fetchTopLevelUserCollections(with: nil)
            if topLeveUserCollections.count > 0 {
                for i in 0 ... topLeveUserCollections.count - 1 {
                    let collection = topLeveUserCollections[i]
                    if collection.isKind(of: PHAssetCollection.self) , let assetCollection = collection as? PHAssetCollection {
                        let fetchResult = PHAsset.fetchAssets(in: assetCollection, options: nil)
                        
                        var isContains: Bool = false
                        if fetchResult.count > 0 {
                            for i in 0 ... fetchResult.count - 1 {
                                let asste = fetchResult[i]
                                if asste.mediaType != .video {
                                    isContains = true
                                    break
                                }
                            }
                        }
                        if isContains {
                            tempArr.append(assetCollection)
                            DDLOG(message:"11111 assetCollectionSubtype =( String(describing: assetCollection.localizedTitle)), assetCollectionType = (assetCollection.assetCollectionType.rawValue), assetCollectionSubtype = (assetCollection.assetCollectionSubtype.rawValue)")
                        }
                    }
                }
            }
            ///得到的结果 和我的相薄 是反的, 需要倒序 排列一下
            tempArr = tempArr.reversed()
            
            
            ///系统创建的文件夹
            for i in 0 ... smartAlbums.count - 1 {
                let collection = smartAlbums[i] as PHCollection
                if collection.isKind(of: PHAssetCollection.self) , let assetCollection = collection as? PHAssetCollection , assetCollection.assetCollectionType != .moment {
                    let fetchResult = PHAsset.fetchAssets(in: assetCollection, options: nil)
                    var isContains: Bool = false
                    if fetchResult.count > 0 {
                        for i in 0 ... fetchResult.count - 1 {
                            let asste = fetchResult[i]
                            if asste.mediaType != .video {
                                isContains = true
                                break
                            }
                        }
                    }
                    
                    ///最近项目/相机胶卷/所有照片放到第一位
                    if isContains {
                        if assetCollection.localizedTitle == "相机胶卷" || assetCollection.localizedTitle == "所有照片" || assetCollection.localizedTitle == "最近项目" {
                            tempArr.insert(assetCollection, at: 0)
                            
                            ///不添加 已删除和已隐藏
                        }else if assetCollection.localizedTitle == "最近删除" || assetCollection.localizedTitle == "已隐藏"{
                            
                        }else{
                            tempArr.append(assetCollection)
                            DDLOG(message:"22222 localizedTitle =( String(describing: assetCollection.localizedTitle)), assetCollectionType = (assetCollection.assetCollectionType.rawValue), assetCollectionSubtype = (assetCollection.assetCollectionSubtype.rawValue)")
                        }
                    }
                }
            }
            
            ///个人收藏放到第二位
            if tempArr.count > 2 , let index = tempArr.firstIndex(where: {$0.localizedTitle == "个人收藏"}) , index != 1 {
                let temp = tempArr.remove(at: index)
                tempArr.insert(temp, at: 1)
            }
            
            ///最近项目和最近添加一样的, 删除最近添加
            for (index, assetCollection) in tempArr.enumerated(){
                if assetCollection.localizedTitle == "最近添加",
                    let firstTitle = tempArr.first?.localizedTitle,
                    firstTitle == "最近项目"{
                    tempArr.remove(at: index)
                }
            }
            
            tempArr.forEach { (assetCollection) in
                DDLOG(message:"reversed tempArr444 =( String(describing: assetCollection.localizedTitle))")
            }
            return tempArr
        }
        
        //// 获取多张图片
        static func asyncGetImageArr(by assetArr: [PHAsset] ,tageSize: CGSize = CGSize( JYScreenWidth * 3 , height: JYScreenHeight * 3), resultHandle:((_ imageArr: [UIImage]) -> Void)? , progressHandle: ((_ progress: Double , _ err: String?) -> Void)?) {
            let quenueGroup = DispatchGroup()
            let semphore = DispatchSemaphore(value: 1)
            let quenue = DispatchQueue.global(qos: DispatchQoS.QoSClass.background)
            var temImageArr: [UIImage] = []
            for asset in assetArr {
                quenueGroup.enter()
                quenue.async{
                    semphore.wait()
                    DDLOG(message: "开始获取")
                    asyncGetImage(by: asset, tageSize: tageSize, resultHandle: { (image) in
                        if let res = image{
                            temImageArr.append(res)
                        }else {
                            DispatchQueue.main.async {
                                progressHandle?(0, "获取图片失败")
                            }
                        }
                        DDLOG(message: "获取成功")
                        semphore.signal()
                        quenueGroup.leave()
                    }, progressHandle: { (progress, err) in
                        DispatchQueue.main.async {
                            progressHandle?(progress , err?.localizedDescription)
                        }
                    })
                }
            }
            quenueGroup.notify(queue: .main) {
                DDLOG(message: Thread.current)
                resultHandle?(temImageArr)
            }
        }
        
        /// 获取单张指定大小的图片
        static func asyncGetImage(by asset: PHAsset ,tageSize: CGSize , resultHandle:((_ imageArr: UIImage?) -> Void)? , progressHandle: ((_ progress: Double , _ err: Error?) -> Void)?) {
            let option = PHImageRequestOptions()
            option.resizeMode = .fast
            option.deliveryMode = .highQualityFormat
            option.isNetworkAccessAllowed = true
            option.progressHandler = { (progress ,err , stop , info) in
                progressHandle?(progress,err)
            }
            PHImageManager.default().requestImage(for: asset, targetSize: tageSize, contentMode: PHImageContentMode.aspectFit, options: option) { (result, info) in
                if let degrade = info?[PHImageResultIsDegradedKey] as? Bool , degrade == false , let image = result {
                    resultHandle?(image)
                }else if result == nil {
                    resultHandle?(nil)
                    JYLogsModel.JYLog(logType: JYLogsModel.JYLogType.errorType, logStr: "获取指定大小本地相册图片失败")
                }
            }
        }
        
        /// 获取单张原图data
        static func asynGetOriginImageData(asset: PHAsset , resulrHandle:((_ data: Data?) -> Void)?) {
            let option = PHImageRequestOptions()
            option.resizeMode = .fast
            option.deliveryMode = .highQualityFormat
            option.isNetworkAccessAllowed = true
            PHImageManager.default().requestImageData(for: asset, options: option) { (data, dataUTI, orientation, info) in
                if let degrade = info?[PHImageResultIsDegradedKey] as? Bool , degrade == false {
                    if let _data = data, UIImage(data: _data) == nil {
                        asyncGetImage(by: asset, tageSize: CGSize( JYScreenWidth * 2, height: JYScreenHeight * 2), resultHandle: { (image) in
                            if let data = image?.jpegData(compressionQuality: 1.0) {
                                resulrHandle?(data)
                            }else {
                                resulrHandle?(nil)
                            }
                        }, progressHandle: nil)
                    }else {
                        resulrHandle?(data)
                    }
                }else {
                    resulrHandle?(data)
                    JYLogsModel.JYLog(logType: JYLogsModel.JYLogType.errorType, logStr: "获取单张原图失败")
                }
            }
        }
        
        
        /// 处理imageData(heic)
        ///
        /// - Parameter imageData: 图片二进制流
        /// - Returns: 压缩后的图片二进制流
        static func handleHEICImageData(imageData: Data , type: JYSelectPhotoType) -> Data {
            if #available(iOS 11.0, *) {
                if let sour = CGImageSourceCreateWithData(imageData as CFData, nil) ,  let _type = CGImageSourceGetType(sour) as String? {
                    if _type == AVFileType.heic.rawValue || _type == AVFileType.heif.rawValue {
                        if let ciimage = CIImage(data: imageData) , let color = ciimage.colorSpace {
                            let context = CIContext()
                            if let jpgData = context.jpegRepresentation(of: ciimage, colorSpace: color, options:[: ]) {
                                return scaleImage(imageData: jpgData , type: type)
                            }
                        }else {
                            if let image = UIImage(data: imageData) , let _jpgData = image.jpegData(compressionQuality: 1.0) {
                                return scaleImage(imageData: _jpgData ,  type: type)
                            }
                        }
                    }
                }
            }
            return scaleImage(imageData: imageData , type: type)
        }
        
        
        /// 不同图片压缩的大小不一致
        ///
        /// - Parameter imageData: 图片二进制流
        /// - Returns: 压缩后的图片
        private static func scaleImage(imageData: Data , type: JYSelectPhotoType) -> Data {
            guard type != .uploadCertificateOriginType else {
                // 压缩证件
                return JYAlbumHelpModel.handleCerImage(data: imageData)
            }
            let imageCount = Double(imageData.count)
            if imageCount > 1.5 * 1024 * 1024 , imageCount <= 3.0 * 1024 * 1024 {
                /// 压缩到1.0M
                let data = compressBySizeWithMaxLength(maxCount: 1024 * 1024, imageData: imageData)
                DDLOG(message: "压缩1后的大小为:(data.count)")
                return data
            }else if imageCount > 3.0 * 1024 * 1024 , imageCount <= 8 * 1024 * 1024 {
                /// 压缩到1.2M
                let data = compressBySizeWithMaxLength(maxCount: Int64(1.2 * 1024 * 1024), imageData: imageData)
                DDLOG(message: "压缩2后的大小为:(data.count)")
                return data
            }else if imageCount > 8 * 1024 * 1024 {
                // 压缩到1.5M
                let data = compressBySizeWithMaxLength(maxCount: Int64(1.5 * 1024 * 1024), imageData: imageData)
                DDLOG(message: "压缩3后的大小为:(data.count)")
                return data
            }
            return imageData
        }
        
        /// 二分法压缩图片
        private static func compressBySizeWithMaxLength(maxCount: Int64 , imageData: Data) -> Data {
            guard imageData.count > maxCount else {
                return imageData
            }
            var data = imageData
            if let resultImage = UIImage(data: imageData) {
                var min: CGFloat = 0.0 ; var max: CGFloat = 1.0 ; var compression: CGFloat = 1.0
                for _ in 0 ... 6 {
                    compression = (min + max)/2
                    data = resultImage.jpegData(compressionQuality: compression) ?? data
                    // 此处设置误差范围为0 - 0.1
                    if Double(data.count) > Double(maxCount) * 1.1 {
                        max = compression
                    }else if Double(data.count) < Double(maxCount) {
                        min = compression
                    }else {
                        break
                    }
                }
            }
            return data
        }
        
        /// 处理证件图片大小
        private static func handleCerImage(data: Data) -> Data{
            guard data.count > 1024 * 1024 else {
                return data
            }
            let s = CGFloat(sqrtf(Float(data.count)/Float((1024 * 1024))))
            if let image = UIImage(data: data) , let newImage = image.jy.imageWithScale( image.size.width/s){
                DDLOG(message: "原大小:(data.count) , 尺寸压缩:(s) ,原图尺寸:(image.size) , 新图片尺寸:(newImage.size)")
                if let newData = newImage.jpegData(compressionQuality: 1.0) {
                    DDLOG(message: "新图片大小:(newData.count)")
                    return compressBySizeWithMaxLength(maxCount: 1024 * 1024, imageData: newData)
                }
                
            }
            return data
        }
        
    }
  • 相关阅读:
    解决Access查询不区分大小写问题
    截取控件为图片
    解决VS+opencv中Debug版本与Release版本lib切换的问题
    OpenCv Mat操作总结
    机器学习实战-python相关软件库的安装
    图像数据归一化
    图像分割算法-GraphSeg算法
    Image Blending
    图像分割-图割理论与应用学习
    如何查看OpenCv的源代码
  • 原文地址:https://www.cnblogs.com/qingzZ/p/13594518.html
Copyright © 2011-2022 走看看