Skip to content

Commit 5936a04

Browse files
FlexMonkeystephentyrone
authored andcommitted
[Accelerate] [vImage] Swift Overlays (#23592)
* Accelerate vImage Swift Overlays A suite of functions, enumerations, and option sets to make working with vImage in Swift simpler. * vImage_Buffer - new initializers to instantiate and initialize buffers with a single function call. * vImage_Buffer - new functions to copy buffers and create CGImage instances from contents. * vImage_CGImageFormat - new initializers. * vImage_CGImageFormat - new equivalence operator. * vImageConverter - methods to wrap free functions. * vImageConverter - new make and convert functions. * vImageCVImageFormat - new make functions. * vImageCVImageFormat - methods to wrap free functions. * vImage_Error - errorDescription function. * vImage flags as an option set. * Add new methods for generating CV -> CG and CG -> CV converters. * update comments: `height` and `width` to `size`. * `vImage_CGImageFormat.componentCount` should be `Int`. * `vImage_CGImageFormat.componentCount` should be `Int` * Move `self.init()` to after the size check for kvImageNoAllocate init. * Buffer initializers to width and height rather than size. * change vImage_CGImageFormat lightweight initializer to accept Int for `bitsPerComponent` and `bitsPerPixel`. * Flesh out docs for vImage_Buffer.size * Remove faux initializer in favor of new static function: `preferredAlignmentAndRowBytes`. * Change functions to use proper error handling rather than inout error codes. * Removed `flags` from basic init. The only real flag to pass here is print diagnostics to console, and I now throw proper errors. * Tests to check error throwing for buffer copy. * remove unnecessary import, add missing docs. * Add comments to error enums. * Fix bug creating string from format code. * Make `vImageCVImageFormat.formatCode` a `UInt32`. * Remove equivalence operator from `CGImageFormat`.
1 parent e73f505 commit 5936a04

File tree

9 files changed

+2018
-0
lines changed

9 files changed

+2018
-0
lines changed

stdlib/public/Darwin/Accelerate/Accelerate.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
/// An enum that acts as a namespace for Swift overlays to vImage option sets and enums..
14+
public enum vImage {}
15+
1316
/// An enum that acts as a namespace for Swift overlays to vDSP based functions.
1417
public enum vDSP {}
1518

stdlib/public/Darwin/Accelerate/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ include("../../../../cmake/modules/StandaloneOverlay.cmake")
33

44
add_swift_target_library(swiftAccelerate ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
55
Accelerate.swift
6+
vImage_Error.swift
7+
vImage_Options.swift
8+
vImage_Buffer.swift
9+
vImage_CVImageFormat.swift
10+
vImage_CGImageFormat.swift
11+
vImage_Converter.swift
612
AccelerateBuffer.swift
713
Quadrature.swift
814
vDSP_Arithmetic.swift
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
//===----------------------------------------------------------------------===//
14+
//
15+
// vImage_Buffer
16+
//
17+
//===----------------------------------------------------------------------===//
18+
19+
@available(iOS 9999, OSX 9999, tvOS 9999, watchOS 9999, *)
20+
extension vImage_Buffer {
21+
22+
/// The size of the vImage buffer.
23+
///
24+
/// The `CGSize` is rounded down to the nearest representable `CGFloat` that
25+
/// is less than or equal to the actual size of the image. In practice the
26+
/// conversion will always be exact, except for really big images. In that
27+
/// case, some part of the bottom or right edge might be truncated.
28+
public var size: CGSize {
29+
var mutableSelf = self
30+
return vImageBuffer_GetSize(&mutableSelf)
31+
}
32+
33+
//===----------------------------------------------------------------------===//
34+
35+
/// Returns the preferred alignment and row bytes for a specified buffer
36+
/// size and bits-per-pixel.
37+
///
38+
/// - Parameter width: The width of the buffer.
39+
/// - Parameter height: The height of the buffer.
40+
/// - Parameter bitsPerPixel: The number of bits in a pixel of image data.
41+
///
42+
/// - Returns: The preferred alignment and row bytes.
43+
public static func preferredAlignmentAndRowBytes(width: Int,
44+
height: Int,
45+
bitsPerPixel: UInt32) throws -> (alignment: Int, rowBytes: Int) {
46+
47+
if width < 0 || height < 0 {
48+
throw vImage.Error.invalidParameter
49+
}
50+
51+
var buffer = vImage_Buffer()
52+
53+
let error = vImageBuffer_Init(&buffer,
54+
vImagePixelCount(height),
55+
vImagePixelCount(width),
56+
bitsPerPixel,
57+
vImage_Flags(kvImageNoAllocate))
58+
59+
if error < kvImageNoError {
60+
throw vImage.Error(vImageError: error)
61+
} else {
62+
return(alignment: error,
63+
rowBytes: buffer.rowBytes)
64+
}
65+
}
66+
67+
//===----------------------------------------------------------------------===//
68+
//
69+
// Initializers.
70+
//
71+
//===----------------------------------------------------------------------===//
72+
73+
/// Initializes a vImage buffer of a specified size.
74+
///
75+
/// - Parameter width: The width of the buffer.
76+
/// - Parameter height: The height of the buffer.
77+
/// - Parameter bitsPerPixel: The number of bits in a pixel of image data.
78+
///
79+
/// - Returns: An initialized vImage buffer.
80+
public init(width: Int,
81+
height: Int,
82+
bitsPerPixel: UInt32) throws {
83+
84+
if width < 0 || height < 0 {
85+
throw vImage.Error.invalidParameter
86+
}
87+
88+
self.init()
89+
90+
let error = vImageBuffer_Init(&self,
91+
vImagePixelCount(height),
92+
vImagePixelCount(width),
93+
bitsPerPixel,
94+
vImage_Flags(kvImageNoFlags))
95+
96+
if error < kvImageNoError {
97+
throw vImage.Error(vImageError: error)
98+
}
99+
}
100+
101+
public func free() {
102+
Darwin.free(data)
103+
}
104+
}
105+
106+
// MARK: Core Graphics Support
107+
108+
@available(iOS 9999, OSX 9999, tvOS 9999, watchOS 9999, *)
109+
extension vImage_Buffer {
110+
111+
/// Initialize a vImage buffer with the contents of a Core Graphics image.
112+
///
113+
/// - Parameter cgImage: A `CGImage` instance to be used as the source.
114+
/// - Parameter options: The options to use when performing this operation.
115+
///
116+
/// - Returns: An initialized vImage buffer.
117+
///
118+
/// This function will instantiate and initialize a vImage buffer from a `CGImage` using a `CGImageFormat` based on the provided image's properties.
119+
public init(cgImage: CGImage,
120+
flags options: vImage.Options = .noFlags) throws {
121+
122+
self.init()
123+
124+
guard var format = vImage_CGImageFormat(cgImage: cgImage) else {
125+
throw vImage.Error.invalidImageFormat
126+
}
127+
128+
let error = vImageBuffer_InitWithCGImage(&self,
129+
&format,
130+
nil,
131+
cgImage,
132+
options.flags)
133+
134+
if error != kvImageNoError {
135+
throw vImage.Error(vImageError: error)
136+
}
137+
}
138+
139+
//===----------------------------------------------------------------------===//
140+
141+
/// Initialize a vImage buffer with the contents of a Core Graphics image,
142+
/// using a supplied format.
143+
///
144+
/// - Parameter cgImage: A `CGImage` instance to be used as the source.
145+
/// - Parameter format: A `vImage_CGImageFormat` that describes the source image/
146+
/// - Parameter options: The options to use when performing this operation.
147+
///
148+
/// - Returns: An initialized vImage buffer.
149+
///
150+
/// This function will instantiate and initialize a vImage buffer from a `CGImage` using a provided `CGImageFormat`.
151+
public init(cgImage: CGImage,
152+
format: vImage_CGImageFormat,
153+
flags options: vImage.Options = .noFlags) throws {
154+
155+
self.init()
156+
157+
var format = format
158+
let error = vImageBuffer_InitWithCGImage(&self,
159+
&format,
160+
nil,
161+
cgImage,
162+
options.flags)
163+
164+
if error != kvImageNoError {
165+
throw vImage.Error(vImageError: error)
166+
}
167+
}
168+
169+
//===----------------------------------------------------------------------===//
170+
171+
/// Creates a `CGImage` instance from a vImage buffer
172+
///
173+
/// - Parameter format: The image format of this vImage buffer.
174+
/// - Parameter options: The options to use when performing this operation.
175+
///
176+
/// - Returns: A Core Graphics image containing a representation of the vImage buffer.
177+
public func createCGImage(format: vImage_CGImageFormat,
178+
flags options: vImage.Options = .noFlags) throws -> CGImage {
179+
var format = format
180+
var error = kvImageNoError
181+
182+
var cgImage: CGImage?
183+
184+
withUnsafePointer(to: self) {
185+
cgImage = vImageCreateCGImageFromBuffer(
186+
$0,
187+
&format,
188+
nil,
189+
nil,
190+
options.flags,
191+
&error).takeRetainedValue()
192+
}
193+
194+
if error != kvImageNoError {
195+
throw vImage.Error(vImageError: error)
196+
} else if cgImage == nil {
197+
throw vImage.Error.internalError
198+
}
199+
200+
return cgImage!
201+
}
202+
203+
//===----------------------------------------------------------------------===//
204+
205+
/// Copies this buffer to `destinationBuffer`.
206+
///
207+
/// - Parameter destinationBuffer: The destination vImage buffer.
208+
/// - Parameter options: The options to use when performing this operation.
209+
public func copy(destinationBuffer: inout vImage_Buffer,
210+
flags options: vImage.Options = .noFlags) throws {
211+
212+
if Int(width) == 0 {
213+
throw vImage.Error(vImageError: kvImageInvalidParameter)
214+
}
215+
216+
var error = kvImageNoError
217+
218+
_ = withUnsafePointer(to: self) {
219+
error = vImageCopyBuffer($0,
220+
&destinationBuffer,
221+
rowBytes / Int(width),
222+
options.flags)
223+
}
224+
225+
if error != kvImageNoError {
226+
throw vImage.Error(vImageError: error)
227+
}
228+
}
229+
230+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
//===----------------------------------------------------------------------===//
14+
//
15+
// vImage_CGImageFormat
16+
//
17+
//===----------------------------------------------------------------------===//
18+
19+
@available(iOS 9999, OSX 9999, tvOS 9999, watchOS 9999, *)
20+
extension vImage_CGImageFormat {
21+
22+
/// Initializes an image format from a Core Graphics image.
23+
///
24+
/// - Parameter cgImage: The image from which to derive the image format.
25+
///
26+
/// - Returns: An initialized `vImage_CGImageFormat`.
27+
public init?(cgImage: CGImage) {
28+
guard
29+
let colorSpace = cgImage.colorSpace else {
30+
return nil
31+
}
32+
33+
self = vImage_CGImageFormat(
34+
bitsPerComponent: UInt32(cgImage.bitsPerComponent),
35+
bitsPerPixel: UInt32(cgImage.bitsPerPixel),
36+
colorSpace: Unmanaged.passRetained(colorSpace),
37+
bitmapInfo: cgImage.bitmapInfo,
38+
version: 0,
39+
decode: nil,
40+
renderingIntent: cgImage.renderingIntent)
41+
}
42+
43+
/// Initializes an image format.
44+
///
45+
/// - Parameter bitsPerComponent: The number of bits needed to represent one
46+
/// channel of data in one pixel.
47+
/// - Parameter bitsPerPixel: The number of bits needed to represent one pixel.
48+
/// - Parameter colorSpace: The color space for the format.
49+
/// - Parameter bitmapInfo: The component information describing the color channels.
50+
/// - Parameter renderingIntent: A rendering intent constant that specifies how
51+
/// Core Graphics should handle colors that are not located within the gamut of the
52+
/// destination color space of a graphics context.
53+
///
54+
/// - Returns: An initialized `vImage_CGImageFormat`.
55+
public init?(bitsPerComponent: Int,
56+
bitsPerPixel: Int,
57+
colorSpace: CGColorSpace,
58+
bitmapInfo: CGBitmapInfo,
59+
renderingIntent: CGColorRenderingIntent = .defaultIntent) {
60+
61+
if bitsPerComponent < 1 || bitsPerPixel < 0 {
62+
return nil
63+
}
64+
65+
self = vImage_CGImageFormat(
66+
bitsPerComponent: UInt32(bitsPerComponent),
67+
bitsPerPixel: UInt32(bitsPerPixel),
68+
colorSpace: Unmanaged.passRetained(colorSpace),
69+
bitmapInfo: bitmapInfo,
70+
version: 0,
71+
decode: nil,
72+
renderingIntent: renderingIntent)
73+
}
74+
75+
/// The number of color channels.
76+
public var componentCount: Int {
77+
var mutableSelf = self
78+
return Int(vImageCGImageFormat_GetComponentCount(&mutableSelf))
79+
}
80+
}
81+

0 commit comments

Comments
 (0)