Created
October 18, 2015 00:45
-
-
Save indragiek/31e3b3b995deb8a7f5d5 to your computer and use it in GitHub Desktop.
vImage_Buffer wrapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright © 2015 Indragie Karunaratne. All rights reserved. | |
import Foundation | |
import Accelerate | |
public class Image { | |
private var buffer: vImage_Buffer | |
public var size: CGSize { | |
return vImageBuffer_GetSize(&buffer) | |
} | |
public var integralSize: (width: Int, height: Int) { | |
let size = self.size | |
return (Int(size.width), Int(size.height)) | |
} | |
// MARK: Initialization | |
private init(buffer: vImage_Buffer) { | |
self.buffer = buffer | |
} | |
public convenience init(CGImage: CGImageRef) throws { | |
var format = ARGBFFFFFormat.vImageFormat | |
var inBuf = vImage_Buffer() | |
try handleError(vImageBuffer_InitWithCGImage(&inBuf, &format, nil, CGImage, UInt32(kvImageNoFlags))) | |
self.init(buffer: inBuf) | |
} | |
private convenience init(imageSource: CGImageSourceRef) throws { | |
if let image = CGImageSourceCreateImageAtIndex(imageSource, 0, nil) { | |
try self.init(CGImage: image) | |
} else { | |
throw ImageProcessingError.InvalidImageObject | |
} | |
} | |
public convenience init(data: NSData) throws { | |
if let source = CGImageSourceCreateWithData(data, nil) { | |
try self.init(imageSource: source) | |
} else { | |
throw ImageProcessingError.InvalidImageObject | |
} | |
} | |
public convenience init(URL: NSURL) throws { | |
if let source = CGImageSourceCreateWithURL(URL, nil) { | |
try self.init(imageSource: source) | |
} else { | |
throw ImageProcessingError.InvalidImageObject | |
} | |
} | |
deinit { | |
free(buffer.data) | |
} | |
// MARK: Transformations | |
internal func transform(width width: Int, height: Int, transform: (inBuf: inout vImage_Buffer, outBuf: inout vImage_Buffer) throws -> ()) rethrows -> Image { | |
let bytesPerRow = ARGBFFFFFormat.BytesPerPixel * width | |
let data = calloc(width * height * ARGBFFFFFormat.BytesPerPixel, sizeof(Float)) | |
var outBuffer = vImage_Buffer(data: data, height: UInt(height), width: UInt(width), rowBytes: bytesPerRow) | |
try transform(inBuf: &buffer, outBuf: &outBuffer) | |
return Image(buffer: outBuffer) | |
} | |
public func toCGImage() throws -> CGImageRef { | |
var format = ARGBFFFFFormat.vImageFormat | |
var rawError: vImage_Error = kvImageNoError | |
let image = vImageCreateCGImageFromBuffer(&buffer, &format, nil, nil, UInt32(kvImageNoFlags), &rawError) | |
try handleError(rawError) | |
return image.takeRetainedValue() | |
} | |
} | |
private struct ARGBFFFFFormat { | |
static let BitsPerComponent = 32 | |
static let BytesPerPixel = 16 | |
static let BitmapInfo = CGBitmapInfo(rawValue: | |
CGBitmapInfo.ByteOrder32Little.rawValue | |
| CGBitmapInfo.FloatComponents.rawValue | |
| CGImageAlphaInfo.PremultipliedFirst.rawValue | |
) | |
static let vImageFormat: vImage_CGImageFormat = { | |
var format = vImage_CGImageFormat() | |
format.bitsPerComponent = UInt32(ARGBFFFFFormat.BitsPerComponent) | |
format.bitsPerPixel = UInt32(ARGBFFFFFormat.BytesPerPixel) * 8 | |
format.bitmapInfo = ARGBFFFFFormat.BitmapInfo | |
return format | |
}() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment