churabou / iOS-develop-blog

0 stars 0 forks source link

4月24日(火) (カメラロールの画像を取得) #10

Open churabou opened 6 years ago

churabou commented 6 years ago

image.draw in resizeする image.draw at

CIGaussianGradient CIMaskedVariableBlur

churabou commented 6 years ago

import SnapKit
import Photos

class PhotoPickerView: UIViewController {

    private lazy var layout: UICollectionViewFlowLayout = {
        let l = UICollectionViewFlowLayout()
        l.itemSize = CGSize(width: view.bounds.width / 3 - 4,
                            height: view.bounds.width / 3 - 4)
        l.sectionInset = UIEdgeInsets(top: 8, left: 1, bottom: 0, right: 1)
        l.minimumInteritemSpacing = 1
        l.minimumLineSpacing = 1
        return l
    }()

    private lazy var collectionView: UICollectionView = {
        let v = UICollectionView(frame: view.frame, collectionViewLayout: layout)
        v.setAutoLayout()
        v.dataSource = self
        v.delegate = self
        v.register(CameraRollCollectionViewCell.self, forCellWithReuseIdentifier: "cell")
        return v
    }()

    fileprivate var photoAssets: [PHAsset] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(collectionView)
        collectionView.snp.makeConstraints { (make) in
            make.edges.equalToSuperview()
        }
        libraryRequestAuthorization()
    }

    // カメラロールへのアクセス許可
    fileprivate func libraryRequestAuthorization() {
        PHPhotoLibrary.requestAuthorization({ [weak self] status in
            guard let wself = self else {
                return
            }
            switch status {
            case .authorized:
                wself.getAllPhotosInfo()
            case .denied:
                wself.showDeniedAlert()
            case .notDetermined:
                print("NotDetermined")
            case .restricted:
                print("Restricted")
            }
        })
    }

    // カメラロールから全て取得する
    fileprivate func getAllPhotosInfo() {

        let assets: PHFetchResult = PHAsset.fetchAssets(with: .image, options: nil)
        assets.enumerateObjects({ [weak self] (asset, index, stop) -> Void in
            guard let wself = self else {
                return
            }

            DispatchQueue.global(qos: .default).async {
                wself.photoAssets.append(asset as PHAsset)
                print("global \(Date())")
            }
        })

        DispatchQueue.main.async {
            self.collectionView.reloadData()
        }
    }

    // カメラロールへのアクセスが拒否されている場合のアラート
    fileprivate func showDeniedAlert() {
        let alert = UIAlertController(title: "エラー",
                                      message: "「写真」へのアクセスが拒否されています。設定より変更してください。",
                                      preferredStyle: .alert)
        let cancel = UIAlertAction(title: "キャンセル",
                                   style: .cancel,
                                   handler: nil)
        let ok = UIAlertAction(title: "設定画面へ",
                               style: .default,
                               handler: { [weak self] (action) -> Void in
                                guard let wself = self else {
                                    return
                                }
                                wself.transitionToSettingsApplition()
        })
        alert.addAction(cancel)
        alert.addAction(ok)
        present(alert, animated: true, completion: nil)
    }

    fileprivate func transitionToSettingsApplition() {
        if let url = URL(string: UIApplicationOpenSettingsURLString) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        }
    }
}

extension PhotoPickerView : UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return photoAssets.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CameraRollCollectionViewCell
        cell.configure(asset: photoAssets[indexPath.row])
        return cell
    }
}

extension PhotoPickerView: UICollectionViewDelegate {

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        let asset = photoAssets[indexPath.row]
        asset.getOriginalImage(handler: { [weak self] (image, info) in

            let img = self?.resizeMaxSize1920(image!)
            let n = PhotoEditorViewController(image: img!)

            print(image!.size)
            print(img?.size)

            DispatchQueue.main.async {
                self?.present(n, animated: true, completion: nil)
            }
        })
    }

    func resizeMaxSize1920(_ image: UIImage) -> UIImage {

        var ratio: CGFloat = 0
        let maxS: CGFloat = 1920
        if image.size.width > image.size.height {

            if image.size.width >= maxS {
                ratio = maxS / image.size.width
            } else {
                return image
            }
        } else {
            if image.size.height >=  maxS {
                ratio = maxS / image.size.height
            } else {
                return image
            }
        }

        let resize = image.size.multiple(by: ratio)
        UIGraphicsBeginImageContextWithOptions(resize, false, image.scale)
        image.draw(in: CGRect(origin: .zero, size: resize))
        let resized = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return resized!
    }
}
class CameraRollCollectionViewCell: BaseCollectionViewCell {

    let imageView = UIImageView()

    override func initializeView() {
        imageView.setAutoLayout()
        imageView.backgroundColor = .red
        contentView.addSubview(imageView)
    }

    override func initializeConstraints() {
        imageView.snp.makeConstraints { (make) in
            make.edges.equalToSuperview()
        }
    }
    // 画像を表示する
    func configure(asset: PHAsset) {
        asset.getThumbNail(handler: { [weak self] (image, info) in
            self?.imageView.image = image
        })
    }
}

extension PHAsset {

    func getThumbNail(handler: @escaping (UIImage?, [AnyHashable : Any]?) -> Swift.Void) {

        let options = PHImageRequestOptions()
        options.deliveryMode = .highQualityFormat
        options.resizeMode = .exact
        options.isNetworkAccessAllowed = true
        options.isSynchronous = false

        let scale = UIScreen.main.scale
        let width: CGFloat = 100
        let size = CGSize(width: width*scale, height: width*scale)

        PHImageManager
            .default()
            .requestImage(for: self,
                          targetSize: size,
                          contentMode: .aspectFill,
                          options: options,
                          resultHandler: handler)
    }

    func getOriginalImage(handler: @escaping (UIImage?, [AnyHashable : Any]?) -> Swift.Void) {

        let options = PHImageRequestOptions()
        options.deliveryMode = .highQualityFormat
        options.resizeMode = .exact
        options.isNetworkAccessAllowed = true
        options.isSynchronous = false
        let scale: CGFloat = 1 //UIScreen.main.scale
        let size = CGSize(width: CGFloat(pixelWidth)*scale,
                          height: CGFloat(pixelHeight)*scale)

        PHImageManager
            .default()
            .requestImage(for: self,
                          targetSize: size,
                          contentMode: .aspectFill,
                          options: options,
                          resultHandler:  handler)
    }
}

カメラロールを取得して表示したやつ。 reloadDataがmainスレッド以外で呼ばれていたらしい。 GCDについて学ぶ