// // ColorCubeHelper.swift // // Created by Joshua Sullivan on 10/01/16. // Copyright © 2016 Joshua Sullivan. All rights reserved. // import UIKit import Accelerate public final class ColorCubeHelper { public enum ColorCubeError: ErrorType { case IncorrectImageSize case MissingImageData case UnableToCreateDataProvider } public static func createColorCubeData(inputImage image: UIImage, cubeDimension: Int) throws -> NSData { // Set up some variables for calculating memory size. let imageSize = image.size let dim = Int(imageSize.width) let pixels = dim * dim let channels = 4 // If the number of pixels doesn't match what's needed for the supplied cube dimension, abort. guard pixels == cubeDimension * cubeDimension * cubeDimension else { throw ColorCubeError.IncorrectImageSize } // We don't need a sizeof() because uint_8t is explicitly 1 byte. let memSize = pixels * channels // Get the UIImage's backing CGImageRef guard let img = image.CGImage else { throw ColorCubeError.MissingImageData } // Get a reference to the CGImage's data provider. guard let inProvider = CGImageGetDataProvider(img) else { throw ColorCubeError.UnableToCreateDataProvider } let inBitmapData = CGDataProviderCopyData(inProvider) let inBuffer = CFDataGetBytePtr(inBitmapData) // Calculate the size of the float buffer and allocate it. let floatSize = memSize * sizeof(Float.self) let finalBuffer = unsafeBitCast(malloc(floatSize), UnsafeMutablePointer.self) // Convert the uint_8t to float. Note: a uint of 255 will convert to 255.0f. vDSP_vfltu8(inBuffer, 1, finalBuffer, 1, UInt(memSize)) // Divide each float by 255.0 to get the 0-1 range we are looking for. var divisor = Float(255.0) vDSP_vsdiv(finalBuffer, 1, &divisor, finalBuffer, 1, UInt(memSize)) // Don't copy the bytes, just have the NSData take ownership of the buffer. let cubeData = NSData(bytesNoCopy: finalBuffer, length: floatSize, freeWhenDone: true) return cubeData } }