34471


AVCapturePhotoCaptureDelegateを使用してカメラ機能を実装しておりますが、撮影した画像を正方形にリサイズしたいです。

撮影時にはpreviewとして正方形にしたUIViewに以下のプロパティを指定しております。

[code]

    previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
    
[/code]

撮影時、previewでは正方形のUIImageViewを配置しているため、正方形のpreviewが表示されますが、撮影するとカメラサイズの長方形になってしまいます。  
previewで表示されている画像にリサイズする方法をご教授いただきたいです。

■実際のソースコード

[code]

    import UIKit    
    import AVFoundation
    
    class ViewController: UIViewController, AVCapturePhotoCaptureDelegate {
    
        @IBOutlet weak var cameraView: UIImageView!
    
        var captureSesssion: AVCaptureSession!
        var stillImageOutput: AVCapturePhotoOutput?
        var previewLayer: AVCaptureVideoPreviewLayer?
    
        @IBAction func takeIt(_ sender: Any) {
            // フラッシュとかカメラの細かな設定
            let settingsForMonitoring = AVCapturePhotoSettings()
            settingsForMonitoring.flashMode = .auto
            settingsForMonitoring.isAutoStillImageStabilizationEnabled = true
            settingsForMonitoring.isHighResolutionPhotoEnabled = false
            // シャッターを切る
            stillImageOutput?.capturePhoto(with: settingsForMonitoring, delegate: self)
    
        }
    
        override func viewWillAppear(_ animated: Bool) {
            captureSesssion = AVCaptureSession()
            stillImageOutput = AVCapturePhotoOutput()
    
            captureSesssion.sessionPreset = AVCaptureSessionPreset1920x1080// 解像度の設定
    
            let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
    
            do {
                let input = try AVCaptureDeviceInput(device: device)
    
                // 入力
                if (captureSesssion.canAddInput(input)) {
                    captureSesssion.addInput(input)
    
                    // 出力
                    if (captureSesssion.canAddOutput(stillImageOutput)) {
                        captureSesssion.addOutput(stillImageOutput)
                        captureSesssion.startRunning() // カメラ起動
    
                        previewLayer = AVCaptureVideoPreviewLayer(session: captureSesssion)
                        previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill // アスペクトフィット
                        previewLayer?.connection.videoOrientation = AVCaptureVideoOrientation.portrait // カメラの向き
    
                        cameraView.layer.addSublayer(previewLayer!)
                        // ビューのサイズの調整
                        previewLayer?.frame = CGRect(x:0,y:0,width:UIScreen.main.bounds.width,height:UIScreen.main.bounds.height/1.5)
                    }
                }
            }
            catch {
                print(error)
            }
        }
    
        // デリゲート。カメラで撮影が完了した後呼ばれる。JPEG形式でフォトライブラリに保存。
        func capture(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhotoSampleBuffer photoSampleBuffer: CMSampleBuffer?, previewPhotoSampleBuffer:     CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) {
    
            if let photoSampleBuffer = photoSampleBuffer {
                // JPEG形式で画像データを取得
                let photoData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: photoSampleBuffer, previewPhotoSampleBuffer:     previewPhotoSampleBuffer)
                let image = UIImage(data: photoData!)
    
                // フォトライブラリに保存
                UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
            }
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
[/code]

■参考にしたサイト  
iOS10カスタムカメラ - Swift 3  
<http://qiita.com/tfutada/items/3e415cbe176d6f801b1d>

AVCaptureMovieFileOutputで撮影した動画を正方形にリサイズしたい  
[AVCaptureMovieFileOutputで撮影した動画を正方形にリサイズしたい](https://ja.stackoverflow.com/questions/28555/avcapturemoviefileoutput%E3%81%A7%E6%92%AE%E5%BD%B1%E3%81%97%E3%81%9F%E5%8B%95%E7%94%BB%E3%82%92%E6%AD%A3%E6%96%B9%E5%BD%A2%E3%81%AB%E3%83%AA%E3%82%B5%E3%82%A4%E3%82%BA%E3%81%97%E3%81%9F%E3%81%84)


CC BY-SA 3.0
2017-05-05T08:21:19.363
34466
2017-05-05T12:47:19.110
8489
question
swift swift3
AVCapturePhotoCaptureDelegateを使用して撮影した画像を正方形にしたい

[code]

    // デリゲート。カメラで撮影が完了した後呼ばれる。JPEG形式でフォトライブラリに保存。
    func capture(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhotoSampleBuffer photoSampleBuffer: CMSampleBuffer?, previewPhotoSampleBuffer:     CMSampleBuffer?, resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Error?) {
    
        if let photoSampleBuffer = photoSampleBuffer {
            // JPEG形式で画像データを取得
            let photoData = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: photoSampleBuffer, previewPhotoSampleBuffer:     previewPhotoSampleBuffer)
            let image = UIImage(data: photoData!)
    // ここに、コードを追加する。
    
            // フォトライブラリに保存
            UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil)
        }
    }
    
[/code]

上のコードの「// ここに、コードを追加する。」の箇所に、以下のコードを追加します。  
プログラムの流れは、(1) `UIIMage`を、`CGImage`に変換する。(2)
`CGImage`クラスのインスタンスメソッド`cropping(to:)`を使って、イメージをトリミングする。(3) `UIImage`に戻す。(4)
保存用イメージとして、次のコードに渡す。- となります。

[code]

    guard let cgImage = image.cgImage else {
        return
    }
    
    let srcSize = CGSize(width: cgImage.width, height: cgImage.height
    let dstOrigin = CGPoint(x: (srcSize.width - srcSize.height) / 2.0, y: 0.0)
    let dstSize = CGSize(width: srcSize.height, height: src.height)
    let rect = CGRect(origin: dstOrigin, size: dstSize)
    guard let croppedImage = cgImage.cropping(to: rect) else {
        return
    }
    let dstImage = UIImage(cgImage: croppedImage)
    
    // フォトライブラリに保存
    UIImageWriteToSavedPhotosAlbum(dstImage, nil, nil, nil)
    
[/code]

* * *

画像の処理を、多少なりとも行うことがあるなら、CoreGraphicsフレームワーク、CoreImageフレームワークのリファレンスに目を通すようにしましょう。


CC BY-SA 3.0
2017-05-05T12:47:05.523
34470
2017-05-05T12:47:05.523
18540
34466
answer


`AVCaptureSession`に対して`startRunning()`しているのに、`stopRunning()`がどこにもないなど、気になる部分もあるんですが、単純化されたサンプルコードのようですので、その辺は別件として解決していただくと言うことで。

`AVLayerVideoGravityResizeAspectFill`で表示されている画像は実画像の中央部分の正方形(これも別件かもしれませんが、`UIScreen.main.bounds.height/1.5`を`height:`に指定すると、一部の機種を除いて正方形にはならないのではないかと思います)になりますので、`UIImage`の中央部分の正方形を切り取って、そちらを保存してやれば良いのではないでしょうか。

こんなextensionを用意して:

[code]

    extension UIImage {
        func croppingToCenterSquare() -> UIImage {
            let cgImage = self.cgImage!
            var newWidth = CGFloat(cgImage.width)
            var newHeight = CGFloat(cgImage.height)
            if newWidth > newHeight {
                newWidth = newHeight
            } else {
                newHeight = newWidth
            }
            let x = (CGFloat(cgImage.width) - newWidth)/2
            let y = (CGFloat(cgImage.height) - newHeight)/2
            let rect = CGRect(x: x, y: y, width: newWidth, height: newHeight)
            let croppedCGImage = cgImage.cropping(to: rect)!
            return UIImage(cgImage: croppedCGImage, scale: self.scale, orientation: self.imageOrientation)
        }
    }
    
[/code]

(ネタ元は[こちら](https://stackoverflow.com/q/14203951/6541007)。Swift, Objective-
C合わせて色々なコードが紹介されているのですが、こちらの環境(Xcode 8.3.2, iPhone 7 plus/iOS
10.3.1)で動作確認しながら、確実に動くように作り直しました。)

「フォトライブラリに保存」の部分で切り取った後の画像を保存してやるだけです。

[code]

    UIImageWriteToSavedPhotosAlbum(image!.croppingToCenterSquare(), nil, nil, nil)
    
[/code]


CC BY-SA 3.0
2017-05-05T12:47:19.110
34471
2017-05-05T12:47:19.110
2017-05-23T12:38:55.307
-1
13972
34466
answer