Why is my cairo_surface_t drawing semi-transparent? - c++

I am trying to draw a png image, the contents of which I have in memory in an ARGB32 format, using C++ Cairo and Gtk on Ubuntu.
First, I create a GtkDrawingArea, then on its expose-event I draw a solid blue background with a red line from top left to bottom right, then I create a surface and try to draw it onto the drawing area. Here's my expose-event callback:
unsigned char *pCairoBuf = ...
....
gboolean OnDrawingAreaExposeEvent(GtkWidget *pWidget, GdkEventExpose *pEvent, gpointer data)
{
cairo_t *cr = gdk_cairo_create(pWidget->window);
cairo_set_source_rgb(cr, 0.0, 0.0, 1.0);
cairo_rectangle(cr, 0.0, 0.0, pEvent->area.width, pEvent->area.height);
cairo_fill(cr);
cairo_set_source_rgb(cr, 1.0, 0.0, 0.0);
cairo_set_line_width(cr, 10.0);
cairo_move_to(cr, 0.0, 0.0);
cairo_line_to(cr, pEvent->area.width, pEvent->area.height);
cairo_stroke(cr);
// Use the existing buffer pCairoBuf that has (iRenderWidth * iRenderHeight * 4) bytes, 4 bytes per pixel for ARGB32 and zero row padding
cairo_surface_t *pSurface = cairo_image_surface_create_for_data(pCairoBuf, CAIRO_FORMAT_ARGB32, iRenderWidth, iRenderHeight, (iRenderWidth * 4));
cairo_set_source_surface(cr, pSurface, 0.0, 0.0);
cairo_paint(cr);
cairo_destroy(cr);
return TRUE;
}
The drawing area and the image are both 244x278 pixels. The image is an image of Smokey the Bear's head and is transparent around his head:
And I expect the final result to look like this:
But it ends up looking like this:
I did not add the code that shows how I got the data buffer pCairoBuf because I figured it would only cloud the issue, but perhaps I'm wrong? I figured that there's something else I'm doing wrong having to do with cairo surfaces, etc. that would explain the difference between what I'm expecting and what I'm getting.
Thanks in advance for any help!

As a guess, not having used any of those libraries, I'd say your alpha channel's uniform across your image and the rendering's applying this also to the parts of the image you'd like non-transparent. Try only applying the alpha channel to those pixels which you'd like to be transparent.

I figured it out. When I was filling in the ARGB32 data in the buffer that I pass to cairo_image_surface_create_for_data(), I was filling in the bytes in that order, A, R, G, B. As an experiment I reversed the order and filled in the bytes B, G, R, A, and it worked perfectly.

Related

Creating a texture on run time using data for OpenGL

I currently have some heat-map data in a database. I was successful in creating painting a heat-map using the same data [using some vertex shading] onto a plane. Example:
Heat-Map Image example for openGL
Name: Capture.jpg
Views: 0
Size: 8.5 KB
ID: 2667
Now, the problem is that I am currently using something like :
glBegin(GL_QUADS);
glColor4ub(point1.color.red(), point1.color.green(), point1.color.blue(), transparency);
glVertex3d(point1.xCood - 750, point1.yCood - 750, 0);
glColor4ub(point2.color.red(), point2.color.green(), point2.color.blue(), transparency);
glVertex3d(point2.xCood - 750, point2.yCood - 750, 0);
glColor4ub(point3.color.red(), point3.color.green(), point3.color.blue(), transparency);
glVertex3d(point3.xCood - 750, point3.yCood - 750, 0);
glColor4ub(point4.color.red(), point4.color.green(), point4.color.blue(), transparency);
glVertex3d(point4.xCood - 750, point4.yCood - 750, 0);
glEnd();
And what this does [at least in my theory] is that it creates another layer over the existing plane. This causes code on clicking the plane below to be rendered useless. Changing the existing code too much is not an option right now as I do not have access to edit it. I found that if I draw a texture (rather than color a plane) on the old plane, the code stays working.
Example(texture tile just defines number of repetitions required, value is 1 in this case):
glBegin(GL_QUADS);
glTexCoord2d(0.0, textureTile);
glVertex3d(gridRect.left(), gridRect.top(), 0.0);
glTexCoord2d(0.0, 0.0);
glVertex3d(gridRect.left(), gridRect.bottom(), 0.0);
glTexCoord2d(textureTile, 0.0);
glVertex3d(gridRect.right(), gridRect.bottom(), 0.0);
glTexCoord2d(textureTile, textureTile);
glVertex3d(gridRect.right(), gridRect.top(), 0.0);
glEnd();
That said, I was only successful in loading a texture from an image I made. Since the image is suppose to be calculated and painted during run time, I tried making an image from the data to load as a texture.
I used the Qt API functionality for achieving the same. I failed to recreate the same image. Might I be suggested a way to create a texture image from data owned.
Thanks
Sorry for the late answering(in case someone else wanted the answer).
I found the answer to be the use of QOpenGLFramebufferObject.
Final code looks something like:
glViewport(0, 0, VIEW_PORT_SIZE, VIEW_PORT_SIZE);
QOpenGLFramebufferObject fbObject(VIEW_PORT_SIZE, VIEW_PORT_SIZE);
fbObject.bind();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//Switch to Ortho Mode
glMatrixMode(GL_PROJECTION); // Select Projection
glPushMatrix(); // Push The Matrix
glLoadIdentity(); // Reset The Matrix
glOrtho(left, right, bottom, top, -100, 100); // Select Ortho Mode
glMatrixMode(GL_MODELVIEW); // Select Modelview Matrix
glPushMatrix(); // Push The Matrix
glLoadIdentity(); // Reset The Matrix
//Initialize variables
SPointData point1, point2, point3, point4;
//Paint on buffer
//.................<some painting task>................
//Switch to perspective mode
glMatrixMode(GL_PROJECTION); // Select Projection
glPopMatrix(); // Pop The Matrix
glMatrixMode(GL_MODELVIEW); // Select Modelview
glPopMatrix(); // Pop The Matrix
fbObject.release();
return fbObject.toImage();

VTK: How to color a platonic solid

While drawing an icosahedron (icosahedron->SetSolidTypeToIcosahedron();
) with VTK, I came to a point where I would like to draw it in various colours. I have tried:
icosahedronActor->GetProperty()->SetColor(1,0,0);
renderWindow->Render();
but no success, the icosahedron remains as blue as it was before :(
Any tips on how can I make this happen?
I assume you need to use a vtkLookupTable and apply it to your mapper.
vtkSmartPointer<vtkLookupTable> lut = vtkSmartPointer<vtkLookupTable>::New();
lut->SetNumberOfTableValues(n);
lut->SetTableRange(0.0, n-1);
lut->SetTableValue(0.0, 1.0, 0.0, 0.0);
//continue to set more values
lut->Build();
mapper->SetLookupTable(lut);
mapper->SetScalarRange(0.0, n);

cairomm draw single pixel

I've a simple boolean matrix I want to see it as an Image. I am using Cairomm. In documentations I see how to draw a line, curve, arc. But I just want to put black and white color to each pixels. Not getting any docs on pixel access. This is what I copied from examples. though I want a monochrome image. Not FORMAT_ARGB32
Cairo::RefPtr<Cairo::ImageSurface> surface = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, matrix.cols(), matrix.rows());
Cairo::RefPtr<Cairo::Context> context = Cairo::Context::create(surface);
right now I am drawing an 1 pixel line
context->set_antialias(Cairo::ANTIALIAS_NONE);
context->save(); // save the state of the context
context->set_source_rgb(1.0, 1.0, 1.0);
context->paint(); // fill image with the color
context->restore(); // color is back to black now
context->set_source_rgb(0.0, 0.0, 0.0);
context->set_line_width(1.0);
context->move_to(1.0, 1.0);
context->line_to(2.0, 2.0);
context->stroke();
Is this okay or there is something like context->draw(row, col, color) ?
An ImageSurface has a get_data() method. Together with flush() (before modifying data directly) and mark_dirty() (afterwards), you can use this to modify the pixel data directly and set individual pixels.
http://cairographics.org/documentation/cairomm/reference/classCairo_1_1ImageSurface.html#a94ba52fe4a201579c8a5541717822bdb

glColor not working, random color appearing

There's something wrong in my code somewhere but for any number of primitives that I draw, despite calling glClearColor and then picking a color with glColor3f, the colors that appear are completely random...
So in my Rendering class I cycle through all the objects and call their drawing methods, for primitives they would look like:
inline void PrimitiveDrawer::drawWireframePrism(Vector3 pos, float radius, Vector3 col){
glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
glColor3f(col.x, col.y, col.z);
glLineWidth(3);
glBegin (GL_LINE_LOOP);
...
glEnd()
But no matter what color i select I always get different ones... The interesting think is that all primitive lines I draw with this method assume the color of the models that they bound (they are meant to be bounding volumes for meshes)... Could it have to do with the model loaders I am using?
This is affecting every shape (outside the ones around the models), where every GL_LINE assumes the same colour (green for some reason), including the glutBitMapCharacter that I am trying to draw... That's the main think that bothers me as I'd like to pick the colour for the text drawing, currently I am doing:
void renderBitmapString(float x, float y, void *font,char *string)
{
char *c;
glRasterPos2f(x, y);
for (c=string; *c != '\0'; c++) {
glutBitmapCharacter(font, *c);
}
}
void drawText(char text[20], float x, float y){
glPushMatrix();
setOrthographicProjection();
glLoadIdentity();
glClearColor( 0, 0, 0, 0 );
glColor4f(0, 0, 1, 1);
renderBitmapString(x, y,(void *)font, text);
resetPerspectiveProjection();
glPopMatrix();
}
But the text comes up green instead of blue?
glClearColor has nothing to do with glColor. glClearColor sets the color used with a call of glClear(GL_COLOR_BUFFER_BIT) to clear the framebuffer with.
Colors from other objects drawn sounds to me, that you forget to disable texturing. Add a glDiable(GL_TEXTURE_2D); after you're done drawing textured stuff.

How to draw a filled envelop like a cone on OpenGL (using GLUT)?

I am using freeglut for opengl rendering...
I need to draw an envelop looking like a cone (2D) that has to be filled with some color and some transparency applied.
Is the freeglut toolkit equipped with such an inbuilt functionality to draw filled geometries(or some trick)?
or is there some other api that has an inbuilt support for filled up geometries..
Edit1:
just to clarify the 2D cone thing... the envelop is the graphical interpretation of the coverage area of an aircraft during interception(of an enemy aircraft)...that resembles a sector of a circle..i should have mentioned sector instead..
and glutSolidCone doesnot help me as i want to draw a filled sector of a circle...which i have already done...what remains to do is to fill it with some color...
how to fill geometries with color in opengl?
Edit2:
All the answers posted to this questions can work for my problem in a way..
But i would definitely would want to know a way how to fill a geometry with some color.
Say if i want to draw an envelop which is a parabola...in that case there would be no default glut function to actually draw a filled parabola(or is there any?)..
So to generalise this question...how to draw a custom geometry in some solid color?
Edit3:
The answer that mstrobl posted works for GL_TRIANGLES but for such a code:
glBegin(GL_LINE_STRIP);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, 0.0);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(200.0, 0.0, 0.0);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(200.0, 200.0, 0.0);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 200.0, 0.0);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, 0.0);
glEnd();
which draws a square...only a wired square is drawn...i need to fill it with blue color.
anyway to do it?
if i put some drawing commands for a closed curve..like a pie..and i need to fill it with a color is there a way to make it possible...
i dont know how its possible for GL_TRIANGLES... but how to do it for any closed curve?
On Edit3: The way I understand your question is that you want to have OpenGL draw borders and anything between them should be filled with colors.
The idea you had was right, but a line strip is just that - a strip of lines, and it does not have any area.
You can, however, have the lines connect to each other to define a polygon. That will fill out the area of the polygon on a per-vertex basis. Adapting your code:
glBegin(GL_POLYGON);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, 0.0);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(200.0, 0.0, 0.0);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(200.0, 200.0, 0.0);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 200.0, 0.0);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, 0.0);
glEnd();
Please note however, that drawing a polygon this way has two limitations:
The polygon must be convex.
This is a slow operation.
But I assume you just want to get the job done, and this will do it. For the future you might consider just triangulating your polygon.
I'm not sure what you mean by "an envelop", but a cone is a primitive that glut has:
glutSolidCone(radius, height, number_of_slices, number_of_stacks)
The easiest way to fill it with color is to draw it with color. Since you want to make it somewhat transparent, you need an alpha value too:
glColor4f(float red, float green, float blue, float alpha)
// rgb and alpha run from 0.0f to 1.0f; in the example here alpha of 1.0 will
// mean no transparency, 0.0 total transparency. Call before drawing.
To render translucently, blending has to be enabled. And you must set the blending function to use. What you want to do will probably be achieved with the following. If you want to learn more, drop me a comment and I will look for some good pointers. But here goes your setup:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Call that before doing any drawing operations, possibly at program initialization. :)
Since you reclarified your question to ask for a pie: there's an easy way to draw that too using opengl primitives:
You'd draw a solid sphere using gluSolidSphere(). However, since you only want to draw part of it, you just clip the unwanted parts away:
void glClipPlane(GLenum plane, const GLdouble * equation);
With plane being GL_CLIPPLANE0 to GL_CLIPPLANEn and equation being a plane equation in normal form (ax + by + c*z + d = 0 would mean equation would hold the values { a, b, c, d }. Please note that those are doubles and not floats.
I remember there was a subroutine for that. But it's neither too hard to do by yourself.
But I don't understand the 2D -thing. Cone in 2D? Isn't it just a triangle?
Anyway, here's an algorithm to drawing a cone in opengl
First take a circle, subdivision it evenly so that you get a nice amount of edges.
Now pick the center of the circle, make triangles from the edges to the center of the circle. Then select a point over the circle and make triangles from the edges to that point.
The size shape and orientation depends about the values you use to generate the circle and two points. Every step is rather simple and shouldn't cause trouble for you.
First just subdivision a scalar value. Start from [0-2] -range. Take the midpoint ((start+end)/2) and split the range with it. Store the values as pairs. For instance, subdividing once should give you: [(0,1), (1,2)] Do this recursively couple of times, then calculate what those points are on the circle. Simple trigonometry, just remember to multiply the values with π before proceeding. After this you have a certain amount of edges. 2^n where n is the amount of subdivisions. Then you can simply turn them into triangles by giving them one vertex point more. Amount of triangles ends up being therefore: 2^(n+1). (The amounts are useful to know if you are doing it with fixed size arrays.
Edit: What you really want is a pie. (Sorry the pun)
It's equally simple to render. You can again use just triangles. Just select scalar range [-0.25 - 0.25], subdivide, project to circle, and generate one set of triangles.
The scalar - circle projection is simple as: x=cos(v*pi)r, y=sin(vpi)*r where (x,y) is the resulting vertex point, r is a radius, and trigonometric functions work on radiances, not degrees. (if they work with degrees, replace pi with 180)
Use vertex buffers or lists to render it yourself.
Edit: About the coloring question. glColor4f, if you want some parts of the geometry to be different by its color, you can assign a color for each vertex in vertex buffer itself. I don't right now know all the API calls to do it, but API reference in opengl is quite understandable.
On the edit on colors:
OpenGL is actually a state machine. This means that the current material and/or color position is used when drawing. Since you probably won't be using materials, ignore that for now. You want colors.
glColor3f(float r, float g, float b) // draw with r/g/b color and alpha of 1
glColor4f(float r, float g, float b, float alpha)
This will affect the colors of any vertices you draw, of any geometry you render - be it glu's or your own - after the glColorXX call has been executed. If you draw a face with vertices and change the color inbetween the glVertex3f/glVertex2f calls, the colors are interpolated.
Try this:
glBegin(GL_TRIANGLES);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(-3.0, 0.0, 0.0);
glColor3f(0.0, 1.0, 0.0);
glVertex3f(0.0, 3.0, 0.0);
glColor3f(1.0, 0.0, 0.0);
glVertex3f(3.0, 0.0, 0.0);
glEnd();
But I pointed at glColor4f already, so I assume you want to set the colors on a per-vertex basis. And you want to render using display lists.
Just like you can display lists of vertices, you can also make them have a list of colors: all you need to do is enable the color lists and tell opengl where the list resides. Of course, they need to have the same outfit as the vertex list (same order).
If you had
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices_);
glDisableClientState(GL_VERTEX_ARRAY);
you should add colors this way. They need not be float; in fact, you tell it what format it should be. For a color list with 1 byte per channel and 4 channels (R, G, B and A) use this:
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices_);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors_);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
EDIT: Forgot to add that you then have to tell OpenGL which elements to draw by calling glDrawElements.