mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
A buffer's `rowBytes` doesn't have a direct relationship with its `height`, so `rowBytes / Int(width)` isn't a good way to calculate pixel size. To resolve this, I've added `pixelSize` as a parameter to `vImage_Buffer.copy`.
233 lines
8.5 KiB
Swift
233 lines
8.5 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// vImage_Buffer
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
@available(iOS 9999, OSX 9999, tvOS 9999, watchOS 9999, *)
|
|
extension vImage_Buffer {
|
|
|
|
/// The size of the vImage buffer.
|
|
///
|
|
/// The `CGSize` is rounded down to the nearest representable `CGFloat` that
|
|
/// is less than or equal to the actual size of the image. In practice the
|
|
/// conversion will always be exact, except for really big images. In that
|
|
/// case, some part of the bottom or right edge might be truncated.
|
|
public var size: CGSize {
|
|
var mutableSelf = self
|
|
return vImageBuffer_GetSize(&mutableSelf)
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Returns the preferred alignment and row bytes for a specified buffer
|
|
/// size and bits-per-pixel.
|
|
///
|
|
/// - Parameter width: The width of the buffer.
|
|
/// - Parameter height: The height of the buffer.
|
|
/// - Parameter bitsPerPixel: The number of bits in a pixel of image data.
|
|
///
|
|
/// - Returns: The preferred alignment and row bytes.
|
|
public static func preferredAlignmentAndRowBytes(width: Int,
|
|
height: Int,
|
|
bitsPerPixel: UInt32) throws -> (alignment: Int, rowBytes: Int) {
|
|
|
|
if width < 0 || height < 0 {
|
|
throw vImage.Error.invalidParameter
|
|
}
|
|
|
|
var buffer = vImage_Buffer()
|
|
|
|
let error = vImageBuffer_Init(&buffer,
|
|
vImagePixelCount(height),
|
|
vImagePixelCount(width),
|
|
bitsPerPixel,
|
|
vImage_Flags(kvImageNoAllocate))
|
|
|
|
if error < kvImageNoError {
|
|
throw vImage.Error(vImageError: error)
|
|
} else {
|
|
return(alignment: error,
|
|
rowBytes: buffer.rowBytes)
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Initializers.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Initializes a vImage buffer of a specified size.
|
|
///
|
|
/// - Parameter width: The width of the buffer.
|
|
/// - Parameter height: The height of the buffer.
|
|
/// - Parameter bitsPerPixel: The number of bits in a pixel of image data.
|
|
///
|
|
/// - Returns: An initialized vImage buffer.
|
|
public init(width: Int,
|
|
height: Int,
|
|
bitsPerPixel: UInt32) throws {
|
|
|
|
if width < 0 || height < 0 {
|
|
throw vImage.Error.invalidParameter
|
|
}
|
|
|
|
self.init()
|
|
|
|
let error = vImageBuffer_Init(&self,
|
|
vImagePixelCount(height),
|
|
vImagePixelCount(width),
|
|
bitsPerPixel,
|
|
vImage_Flags(kvImageNoFlags))
|
|
|
|
if error < kvImageNoError {
|
|
throw vImage.Error(vImageError: error)
|
|
}
|
|
}
|
|
|
|
public func free() {
|
|
Darwin.free(data)
|
|
}
|
|
}
|
|
|
|
// MARK: Core Graphics Support
|
|
|
|
@available(iOS 9999, OSX 9999, tvOS 9999, watchOS 9999, *)
|
|
extension vImage_Buffer {
|
|
|
|
/// Initialize a vImage buffer with the contents of a Core Graphics image.
|
|
///
|
|
/// - Parameter cgImage: A `CGImage` instance to be used as the source.
|
|
/// - Parameter options: The options to use when performing this operation.
|
|
///
|
|
/// - Returns: An initialized vImage buffer.
|
|
///
|
|
/// This function will instantiate and initialize a vImage buffer from a `CGImage` using a `CGImageFormat` based on the provided image's properties.
|
|
public init(cgImage: CGImage,
|
|
flags options: vImage.Options = .noFlags) throws {
|
|
|
|
self.init()
|
|
|
|
guard var format = vImage_CGImageFormat(cgImage: cgImage) else {
|
|
throw vImage.Error.invalidImageFormat
|
|
}
|
|
|
|
let error = vImageBuffer_InitWithCGImage(&self,
|
|
&format,
|
|
nil,
|
|
cgImage,
|
|
options.flags)
|
|
|
|
if error != kvImageNoError {
|
|
throw vImage.Error(vImageError: error)
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Initialize a vImage buffer with the contents of a Core Graphics image,
|
|
/// using a supplied format.
|
|
///
|
|
/// - Parameter cgImage: A `CGImage` instance to be used as the source.
|
|
/// - Parameter format: A `vImage_CGImageFormat` that describes the source image/
|
|
/// - Parameter options: The options to use when performing this operation.
|
|
///
|
|
/// - Returns: An initialized vImage buffer.
|
|
///
|
|
/// This function will instantiate and initialize a vImage buffer from a `CGImage` using a provided `CGImageFormat`.
|
|
public init(cgImage: CGImage,
|
|
format: vImage_CGImageFormat,
|
|
flags options: vImage.Options = .noFlags) throws {
|
|
|
|
self.init()
|
|
|
|
var format = format
|
|
let error = vImageBuffer_InitWithCGImage(&self,
|
|
&format,
|
|
nil,
|
|
cgImage,
|
|
options.flags)
|
|
|
|
if error != kvImageNoError {
|
|
throw vImage.Error(vImageError: error)
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Creates a `CGImage` instance from a vImage buffer
|
|
///
|
|
/// - Parameter format: The image format of this vImage buffer.
|
|
/// - Parameter options: The options to use when performing this operation.
|
|
///
|
|
/// - Returns: A Core Graphics image containing a representation of the vImage buffer.
|
|
public func createCGImage(format: vImage_CGImageFormat,
|
|
flags options: vImage.Options = .noFlags) throws -> CGImage {
|
|
var format = format
|
|
var error = kvImageNoError
|
|
|
|
var cgImage: CGImage?
|
|
|
|
withUnsafePointer(to: self) {
|
|
cgImage = vImageCreateCGImageFromBuffer(
|
|
$0,
|
|
&format,
|
|
nil,
|
|
nil,
|
|
options.flags,
|
|
&error).takeRetainedValue()
|
|
}
|
|
|
|
if error != kvImageNoError {
|
|
throw vImage.Error(vImageError: error)
|
|
} else if cgImage == nil {
|
|
throw vImage.Error.internalError
|
|
}
|
|
|
|
return cgImage!
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Copies this buffer to `destinationBuffer`.
|
|
///
|
|
/// - Parameter destinationBuffer: The destination vImage buffer.
|
|
/// - Parameter pixelSize: The number of bytes for one pixel.
|
|
/// - Parameter options: The options to use when performing this operation.
|
|
public func copy(destinationBuffer: inout vImage_Buffer,
|
|
pixelSize: Int,
|
|
flags options: vImage.Options = .noFlags) throws {
|
|
|
|
if Int(width) == 0 {
|
|
throw vImage.Error(vImageError: kvImageInvalidParameter)
|
|
}
|
|
|
|
var error = kvImageNoError
|
|
|
|
_ = withUnsafePointer(to: self) {
|
|
error = vImageCopyBuffer($0,
|
|
&destinationBuffer,
|
|
pixelSize,
|
|
options.flags)
|
|
}
|
|
|
|
if error != kvImageNoError {
|
|
throw vImage.Error(vImageError: error)
|
|
}
|
|
}
|
|
|
|
}
|