Last active
September 12, 2024 10:24
-
-
Save JoshuaSullivan/b575d96bfd8a4177d8d46352e5f36458 to your computer and use it in GitHub Desktop.
Here are the Swift 2.3 and Swift 3.0 versions of the ColorCubeHelper class.
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
// | |
// 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<Float>.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 | |
} | |
} |
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
// | |
// ColorCubeHelper.swift | |
// | |
// Created by Joshua Sullivan on 10/10/16. | |
// Copyright © 2016 Joshua Sullivan. All rights reserved. | |
// | |
import UIKit | |
import Accelerate | |
public class ColorCubeHelper { | |
public enum ColorCubeError: Error { | |
case incorrectImageSize | |
case missingImageData | |
case unableToCreateDataProvider | |
case unableToGetBitmpaDataBuffer | |
} | |
public static func createColorCubeData(inputImage image: UIImage, cubeDimension: Int) throws -> Data { | |
// 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 = img.dataProvider else { | |
throw ColorCubeError.unableToCreateDataProvider | |
} | |
let inBitmapData = inProvider.data | |
guard let inBuffer = CFDataGetBytePtr(inBitmapData) else { | |
throw ColorCubeError.unableToGetBitmpaDataBuffer | |
} | |
// Calculate the size of the float buffer and allocate it. | |
let floatSize = memSize * MemoryLayout<Float>.size | |
let finalBuffer = unsafeBitCast(malloc(floatSize), to:UnsafeMutablePointer<Float>.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 as Data | |
} | |
} |
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
guard let colorCubeImage = UIImage(named: "MyColorEffect-64.png") else { | |
preconditionFailure("Couldn't load the cube data image.") | |
} | |
do { | |
let data = try ColorCubeHelper.createColorCubeData(inputImage: colorCubeImage, cubeDimension: 64) | |
let params: [String : Any] = [ "inputCubeData" : data ] | |
let filter = CIFilter(name: "CIColorCube", withInputParameters: params) | |
// Now you can use the filter. | |
} catch { | |
debugPrint("Unable to create cube data: \(error)") | |
} |
I'm working on this FluidGroup/Brightroom#78
@JoshuaSullivan
I have another question.
Your code uses CIColorCube, but we have also CIColorCubeWithColorSpace.
Do you know the differences between them?
I don't know the technical differences between them, but when I use CIColorCubeWithColorSpace the results are the expected and when I use CIColorCube they aren't.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@JoshuaSullivan
I have another question.
Your code uses CIColorCube, but we have also CIColorCubeWithColorSpace.
Do you know the differences between them?