0
votes

In this question I'm mostly seeking for advice and guidance on overall understanding of some concepts of drawing wth GTK+ and Cairo in C language (IMO the information on topic is rather scarce, also my experience in really modest).

I'm coding some pet application which captures frames from webcam and displays them on a GTK window. My app is working, but there are some points which I don't feel like grasped.


Overall process:

I've got a webcam frame as an array of bytes mmaped from webcam device to my app's process memory. So when another frame is captured what I have is a 640*480*3 bytes long array which is denoted as being in a RGB24 format. After some searching it looks like for a purpose of displaying it in a GTK window I need to create an object called drawing area using gtk_drawing_area_new(), add a "draw" callback and do "drawing" there in a designated callback. So, according to Cairo "drawing" is a process of applying "source" to "destination". I assume that I already have a source - my webcam mmaped pixels, but it looks like I need to use some "source" that Cairo is able to understand. I found a candidate:

cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 640, 480);

As I see this call creates some Cairo acceptable object, which along the way allocates a buffer in my app's memory which I can get, using:

unsigned char* surface_data = cairo_image_surface_get_data(surface);

According to docs this is a 640x480x4 bytes long buffer, which, on a little endian archs, should be filled with BGRA formatted pixel data. Then I should rearrange my original webcam pixels for EVERY frame captured using this :

for (size_t idx_src=0, idx_dst=0; idx_src<640*480*3; idx_dst+=4, idx_src+=3) {
    surface_data[idx_dst] = image[idx_src+2]; //B [3rd pos -> 1st pos]
    surface_data[idx_dst+1] = image[idx_src+1]; //G [no change]
    surface_data[idx_dst+2] = image[idx_src]; //R [1st pos -> 3rd pos]
}

After this I should do "drawing" with:

cairo_set_source_surface(cr, surface, 0, 0);
cairo_paint(cr);

So questions:

  1. Is it what is supposed to be done for task at hand or I miss something completely here ?
  2. What confuses me is that I should rearrange my original webcam pixels for EVERY frame captured (this presumably consumes some cpu time, could be a limiting factor for capturing in HD res at high frame rates). Is there some other way ?
  3. Let's suppose I somehow acquire pixels from webcam in a Cairo conforming format, e.g. 640x480x4 BGRA formatted bytes. Is there a way to "wrap" this data in some Cairo acceptable object to exclude pixel rearranging part ?
  4. Any other thoughts I should've consider ?

Thanks for attention.

1
Could you do your mmap'ing via htons in order to swap the byte order?Paul Childs

1 Answers

1
votes

For most of your questions: Cairo only supports some image formats. Since your data comes in another format, you will have to convert it. All this copying around will likely be too slow. To make this work with an acceptable speed, you would need some other approach. No, I do not have any helpful suggestions here.

An unhelpful one would be: Is there some example for this webcam that you could look at?

Let's suppose I somehow acquire pixels from webcam in a Cairo conforming format, e.g. 640x480x4 BGRA formatted bytes. Is there a way to "wrap" this data in some Cairo acceptable object to exclude pixel rearranging part ?

Yup. cairo_image_surface_create_for_data.