diff --git a/SCNVideoWriter/Classes/Error.swift b/SCNVideoWriter/Classes/Error.swift new file mode 100644 index 0000000..d509e56 --- /dev/null +++ b/SCNVideoWriter/Classes/Error.swift @@ -0,0 +1,13 @@ +// +// Error.swift +// Pods-SCNVideoWriter_Example +// +// Created by Tomoya Hirano on 2017/08/20. +// + +import UIKit + +extension SCNVideoWriter { + public struct VideoSizeError: Error {} +} + diff --git a/SCNVideoWriter/Classes/Options.swift b/SCNVideoWriter/Classes/Options.swift new file mode 100644 index 0000000..c8df7cf --- /dev/null +++ b/SCNVideoWriter/Classes/Options.swift @@ -0,0 +1,49 @@ +// +// Options.swift +// Pods-SCNVideoWriter_Example +// +// Created by Tomoya Hirano on 2017/08/20. +// + +import UIKit +import AVFoundation + +extension SCNVideoWriter { + public struct Options { + public var timeScale: Int32 + public var renderSize: CGSize + public var videoSize: CGSize + public var fps: Int + public var outputUrl: URL + public var fileType: String + public var codec: String + public var deleteFileIfExists: Bool + + public static var `default`: Options { + return Options(timeScale: 600, + renderSize: CGSize(width: 640, height: 640), + videoSize: CGSize(width: 1280, height: 720), + fps: 60, + outputUrl: URL(fileURLWithPath: NSTemporaryDirectory() + "output.mp4"), + fileType: AVFileTypeAppleM4V, + codec: AVVideoCodecH264, + deleteFileIfExists: true) + } + + var assetWriterInputSettings: [String : Any] { + return [ + AVVideoCodecKey: codec, + AVVideoWidthKey: videoSize.width, + AVVideoHeightKey: videoSize.height + ] + } + var sourcePixelBufferAttributes: [String : Any] { + return [ + kCVPixelBufferPixelFormatTypeKey as String: NSNumber(value: kCVPixelFormatType_32ARGB), + kCVPixelBufferWidthKey as String: videoSize.width, + kCVPixelBufferHeightKey as String: videoSize.height, + ] + } + } +} + diff --git a/SCNVideoWriter/Classes/SCNVideoWriter.swift b/SCNVideoWriter/Classes/SCNVideoWriter.swift index c518e80..2b9ee93 100644 --- a/SCNVideoWriter/Classes/SCNVideoWriter.swift +++ b/SCNVideoWriter/Classes/SCNVideoWriter.swift @@ -43,7 +43,6 @@ public class SCNVideoWriter { fileType: options.fileType) self.input = AVAssetWriterInput(mediaType: AVMediaTypeVideo, outputSettings: options.assetWriterInputSettings) - //input.expectsMediaDataInRealTime = true self.pixelBufferAdaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: input, sourcePixelBufferAttributes: options.sourcePixelBufferAttributes) prepare(with: options) @@ -102,7 +101,7 @@ public class SCNVideoWriter { autoreleasepool { currentTime = CFAbsoluteTimeGetCurrent() - initialTime let image = renderer.snapshot(atTime: currentTime, with: renderSize, antialiasingMode: .multisampling4X) - let croppedImage = image.crop(at: videoSize) + guard let croppedImage = image.fill(at: videoSize) else { return } guard let pixelBuffer = PixelBufferFactory.make(with: videoSize, from: croppedImage, usingBuffer: pool) else { return } let value: Int64 = Int64(currentTime * CFTimeInterval(options.timeScale)) let presentationTime = CMTimeMake(value, options.timeScale) @@ -117,41 +116,4 @@ public class SCNVideoWriter { } } -extension SCNVideoWriter { - public struct Options { - public var timeScale: Int32 - public var renderSize: CGSize - public var videoSize: CGSize - public var fps: Int - public var outputUrl: URL - public var fileType: String - public var codec: String - public var deleteFileIfExists: Bool - - public static var `default`: Options { - return Options(timeScale: 600, - renderSize: CGSize(width: 640, height: 640), - videoSize: CGSize(width: 640, height: 640), - fps: 60, - outputUrl: URL(fileURLWithPath: NSTemporaryDirectory() + "output.mp4"), - fileType: AVFileTypeAppleM4V, - codec: AVVideoCodecH264, - deleteFileIfExists: true) - } - - var assetWriterInputSettings: [String : Any] { - return [ - AVVideoCodecKey: codec, - AVVideoWidthKey: videoSize.width, - AVVideoHeightKey: videoSize.height - ] - } - var sourcePixelBufferAttributes: [String : Any] { - return [ - kCVPixelBufferPixelFormatTypeKey as String: NSNumber(value: kCVPixelFormatType_32ARGB), - kCVPixelBufferWidthKey as String: videoSize.width, - kCVPixelBufferHeightKey as String: videoSize.height - ] - } - } -} + diff --git a/SCNVideoWriter/Classes/UIImage+Extensions.swift b/SCNVideoWriter/Classes/UIImage+Extensions.swift index 2157910..4262f04 100644 --- a/SCNVideoWriter/Classes/UIImage+Extensions.swift +++ b/SCNVideoWriter/Classes/UIImage+Extensions.swift @@ -8,17 +8,52 @@ import UIKit extension UIImage { - func crop(at size: CGSize) -> UIImage { + func fill(at targetSize: CGSize) -> UIImage? { let imageSize = self.size - let cropSize = size - let x = (imageSize.width - cropSize.width) / 2.0 - let y = (imageSize.height - cropSize.height) / 2.0 - let cropRect = CGRect(x: x, y: y, width: size.width, height: size.height) - return crop(to: cropRect) - } - - func crop(to rect: CGRect) -> UIImage { - guard let croppedImageRef = cgImage?.cropping(to: rect) else { return UIImage() } - return UIImage(cgImage: croppedImageRef, scale: scale, orientation: .up) + let width = imageSize.width + let height = imageSize.height + let targetWidth = targetSize.width + let targetHeight = targetSize.height + var scaleFactor: CGFloat = 0.0 + var scaledWidth = targetWidth + var scaledHeight = targetHeight + var thumbnailPoint = CGPoint(x: 0, y: 0) + + if imageSize != targetSize { + let widthFactor = targetWidth / width + let heightFactor = targetHeight / height + + if widthFactor > heightFactor { + scaleFactor = widthFactor + } else { + scaleFactor = heightFactor + } + + scaledWidth = width * scaleFactor + scaledHeight = height * scaleFactor + + if widthFactor > heightFactor { + thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5 + } else { + if widthFactor < heightFactor { + thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5 + } + } + } + + UIGraphicsBeginImageContext(targetSize) + + var thumbnailRect = CGRect.zero + thumbnailRect.origin = thumbnailPoint + thumbnailRect.size.width = scaledWidth + thumbnailRect.size.height = scaledHeight + + draw(in: thumbnailRect) + + let newImage = UIGraphicsGetImageFromCurrentImageContext() + + UIGraphicsEndImageContext() + + return newImage } }