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?
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.)
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
};
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
Related
image = Image.open(file) # file is 1-bit jpg
image = image.convert('P') # image become 8-bit
colors = [0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 0, 0, 0, 128]
image.putpalette(colors) # why use this code image become 4-bit ?
image.save("1.png",format='PNG') # save image become 4-bit png ????? (-w-)?
i need a 8-bit color png ,can you help me?
I was trying to rotate some path and did not find a snippet and matrix4 in general is not well documented. So in case someone else has this problem, this is what I ended up with
First of all, here is a nice read about the math behind it and how to use matrix4.
In my demo I used an arrow tip. Since sequence matters, I paint it at (0,0), then I rotate it around the z-axis and finally I move the tip to the requested spot.
Path _getArrow (Offset offset, double alpha) {
Path a = Path();
a.moveTo(ARROWSIZE, - ARROWSIZE);
a.lineTo(0, 0);
a.lineTo(ARROWSIZE, ARROWSIZE);
final translateM = Float64List.fromList([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
offset.dx, offset.dy, 0, 1]
);
final rotateM = Float64List.fromList([
cos(alpha), sin(alpha), 0, 0,
-sin(alpha), cos(alpha), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1]
);
final b = a.transform(rotateM);
final c = b.transform(translateM);
return c;
}
I'm a beginner in Paraview. I have a question about displaying CSV file in Paraview. If my data file looked like this
x coord, y coord, z coord, scalar
0, 0, 0, 1
1, 0, 0, 2
0, 1, 0, 3
1, 1, 0, 4
0, 0, 1, 5
1, 0, 1, 6
0, 1, 1, 7
1, 1, 1, 8
It will create a cubic grid. But if I switch the order of points like
x coord, y coord, z coord, scalar
0, 0, 0, 1
1, 0, 0, 2
1, 0, 1, 6
0, 1, 0, 3
1, 1, 1, 8
1, 1, 0, 4
0, 0, 1, 5
0, 1, 1, 7
It will give me a really messy connected wireframe. I want to know what's the order of connection? How does Paraview form those grids?
In ParaView (and indeed in the underlying VTK library it uses), structured grid points are ordered such that the index of the x dimension varies fastest, the index of the y dimension varies second-fastest, and the index of the z dimension varies slowest. Hence, your first example gives the expected result while the second example does not.
I'm using a radial gradient in Cairo, but I'm not getting the expected results. The radial gradient I'm getting is much less fuzzy than I'd expect and I can't seem to fiddle with the color stops in order to get the desired results. Here is the code:
cairo_pattern_t *pat;
pat = cairo_pattern_create_radial(100.0, 100.0, 0.0, 100.0, 100.0, 20.0);
cairo_pattern_add_color_stop_rgba(pat, 0, 0, 0, 0, 1);
cairo_pattern_add_color_stop_rgba(pat, 1, 0, 0, 0, 0);
Here is an image of what I'm talking about.
The #cairo IRC channel suggested (Thanks Company!) to use cairo_mask() instead of cairo_paint() to draw the gradient. That results in a squared instead of linear progression.
I did the following in lua. Sorry for the language, but it's easier to prototype something. This maps 1:1 to the C API and shouldn't be hard to translate:
cairo = require("lgi").cairo
s = cairo.ImageSurface(cairo.Format.ARGB32, 200, 100)
c = cairo.Context(s)
c:set_source_rgb(1, 1, 1)
c:paint()
p = cairo.Pattern.create_radial(50, 50, 0, 50, 50, 20)
p:add_color_stop_rgba(0, 0, 0, 0, 1)
p:add_color_stop_rgba(1, 0, 0, 0, 0)
c:save()
c:rectangle(0, 0, 100, 100)
c:clip()
c.source = p
c:paint()
c:restore()
p = cairo.Pattern.create_radial(50, 50, 2, 50, 50, 25)
p:add_color_stop_rgba(0, 0, 0, 0, 1)
p:add_color_stop_rgba(1, 0, 0, 0, 0)
c:translate(100, 0)
c:save()
c:rectangle(0, 0, 100, 100)
c:clip()
c.source = p
c:mask(p)
c:restore()
s:write_to_png("test.png")
To me, the second circle (The one that was cairo_mask()'d with a black source) looks a lot more like what you want:
I'm doing the following:
static GLfloat vertices[3][3] =
{
{0.0, 1.0, 0.0},
{1.0, 0.0, 0.0},
{-1.0, 0.0, 0.0}
};
glColor4ub(255, 0, 0, 255);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLES, 0, 9);
glDisableClientState(GL_VERTEX_ARRAY);
This works ok:
http://dl.dropbox.com/u/41764/posts/Screen%20shot%202010-03-28%20at%2020.04.56.png
However, if I remove static from vertices and therefore re-create the data on the stack on each rendering, I get the following:
http://dl.dropbox.com/u/41764/posts/Screen%20shot%202010-03-28%20at%2020.06.38.png
This happens both on the simulator and on the device.
Should I be keeping the variables around after I call glDrawArrays?
The reason you're seeing weird results is because you're not drawing what you think you are.
glDrawArrays(GL_TRIANGLES, 0, 9);
This means draw 9 vertices, hence 3 triangles. You only have 3 vertices declared in your array, so what the other 2 triangles will end up being is anybody's guess. You can see in the second picture that you indeed have more than 1 triangle... The data it ends up using is whatever else is on the stack at that time.
glDrawArrays does transfer on call, and I seriously doubt the iPhone would not be compliant on this. It's really basic GL, that (I believe) gets tested for conformance.
You are rendering uninitialized data in both cases. It just happens to look correct in the static case.
The third parameter to glDrawArrays is the number of vertices (which should be 3 in your case because you are trying to draw a single triangle).
You already told the GL that you are specifying 3 GLfloat per vertex (the first parameter of glVertexPointer). So the GL can figure out the total number of GLfloat to expect.
This should work:
GLfloat vertices[3][3] =
{
{0.0, 1.0, 0.0},
{1.0, 0.0, 0.0},
{-1.0, 0.0, 0.0}
};
glColor4ub(255, 0, 0, 255);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableClientState(GL_VERTEX_ARRAY);