Formatting CIColorCube data
Asked Answered
K

3

3

Recently, I've been trying to set up a CIColorCube on a CIImage to create a custom effect. Here's what I have now:

uint8_t color_cube_data[8*4] = {
    0, 0, 0, 1,
    255, 0, 0, 1,
    0, 255, 0, 1,
    255, 255, 0, 1,
    0, 0, 255, 1,
    255, 0, 255, 1,
    0, 255, 255, 1,
    255, 255, 255, 1
};
NSData * cube_data =[NSData dataWithBytes:color_cube_data length:8*4*sizeof(uint8_t)];
CIFilter *filter = [CIFilter filterWithName:@"CIColorCube"];
[filter setValue:beginImage forKey:kCIInputImageKey];
[filter setValue:@2 forKey:@"inputCubeDimension"];
[filter setValue:cube_data forKey:@"inputCubeData"];
outputImage = [filter outputImage];

I've checked out the WWDC 2012 Core Image session, and what I have still doesn't work. I've also checked the web, and there are very few resources available on this issue. My code above just returns a black image.

In Apple's developer library, it says:

This filter applies a mapping from RGB space to new color values that are defined in inputCubeData. For each RGBA pixel in inputImage the filter uses the R,G and B values to index into a thee dimensional texture represented by inputCubeData. inputCubeData contains floating point RGBA cells that contain linear premultiplied values. The data is organized into inputCubeDimension number of xy planes, with each plane of size inputCubeDimension by inputCubeDimension. Input pixel components R and G are used to index the data in x and y respectively, and B is used to index in z. In inputCubeData the R component varies fastest, followed by G, then B.

However, this makes no sense to me. How does my inputCubeData need to be formatted?

Karim answered 3/4, 2013 at 21:20 Comment(0)
K
2

I found the issue... I have updated my question if anyone has the same problem!

The input float array had to be pre-divided out of 255.

The original used 255:

uint8_t color_cube_data[8*4] = {
    0, 0, 0, 1,
    255, 0, 0, 1,
    0, 255, 0, 1,
    255, 255, 0, 1,
    0, 0, 255, 1,
    255, 0, 255, 1,
    0, 255, 255, 1,
    255, 255, 255, 1
};

It should look like this instead:

uint8_t color_cube_data[8*4] = {
    0, 0, 0, 1,
    1, 0, 0, 1,
    0, 1, 0, 1,
    1, 1, 0, 1,
    0, 0, 1, 1,
    1, 0, 1, 1,
    0, 1, 1, 1,
    1, 1, 1, 1
};
Karim answered 7/4, 2013 at 2:48 Comment(0)
E
4

The accepted answer is incorrect. While the cube data is indeed supposed to be scaled to [0 .. 1], it's supposed to be float, not int.

float color_cube_data[8*4] = { 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 };

(Technically, you don't have to put the ".0" on each number, the compiler knows how to handle it.)

Ecosphere answered 4/5, 2014 at 5:22 Comment(0)
K
2

I found the issue... I have updated my question if anyone has the same problem!

The input float array had to be pre-divided out of 255.

The original used 255:

uint8_t color_cube_data[8*4] = {
    0, 0, 0, 1,
    255, 0, 0, 1,
    0, 255, 0, 1,
    255, 255, 0, 1,
    0, 0, 255, 1,
    255, 0, 255, 1,
    0, 255, 255, 1,
    255, 255, 255, 1
};

It should look like this instead:

uint8_t color_cube_data[8*4] = {
    0, 0, 0, 1,
    1, 0, 0, 1,
    0, 1, 0, 1,
    1, 1, 0, 1,
    0, 0, 1, 1,
    1, 0, 1, 1,
    0, 1, 1, 1,
    1, 1, 1, 1
};
Karim answered 7/4, 2013 at 2:48 Comment(0)
H
1

Your problem is that you are using value 1(which is next to zero) for alpha channel, max for uint8_t is 255

See example below:

CIFilter *cubeHeatmapLookupFilter = [CIFilter filterWithName:@"CIColorCube"];

int dimension = 4;  // Must be power of 2, max of 128
int cubeDataSize = 4 * dimension * dimension * dimension;

unsigned char cubeDataBytes[cubeDataSize];

//cubeDataBytes[cubeDataSize]
unsigned char cubeDataBytes[4*4*4*4] = {
    0,      0,      0,      0,
    255,    0,      0,      170,
    255,    250,    0,      200,
    255,    255,    255,    255
};

NSData *cube_data = [NSData dataWithBytes:cubeDataBytes length:(cubeDataSize*sizeof(char))];

//applying
[cubeHeatmapLookupFilter setValue:myImage forKey:@"inputImage"];
[cubeHeatmapLookupFilter setValue:cube_data forKey:@"inputCubeData"];
[cubeHeatmapLookupFilter setValue:@(dimension) forKey:@"inputCubeDimension"];

This is link to full project https://github.com/knerush/heatMap

Horbal answered 12/9, 2015 at 13:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.