简体   繁体   中英

How do I draw a Pixmap with GTK?

Using GTK3, I have been trying to draw a Pixmap from a memory buffer. I have just created a memory buffer, and filled it with alternating rows of colours in the 32-bit RGBA format. I have been trying the following function: gdk_pixbuf_new_from_data(const guchar *data, GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, int width, int height, int rowstride, GdkPixbufDestroyNotify destroy_fn, gpointer destroy_fn_data)

Using this, I have been able to wrap the memory buffer into a GdkPixbuf* , however when I attempt to draw the pixbuf to screen with Cairo, the image seems to be distorted.

Here is my test program that I have been experimenting with:

#include <gtk/gtk.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>

const int WIDTH = 1080;
const int HEIGHT = 720;

GtkWidget* mainWindow;

int currentCol = 0;

uint32_t* framebuffer = NULL;
GdkPixbuf* pixbuf = NULL;


typedef struct _rgbColor {
    uint8_t red;
    uint8_t green;
    uint8_t blue;
    uint8_t alpha;
}rgbColor;


void onWindowDestroy (GtkWidget* object, gpointer user_data) {
    gtk_main_quit();
}

gboolean onTimerTick(gpointer user_data) {
    rgbColor c = {0, 0, 0, 255};
    if (currentCol == 0) {
        c.red = 255;
    }
    if (currentCol == 1) {
        c.green = 255;
    }
    if (currentCol == 2) {
        c.blue = 255;
        currentCol = -1;
    }
    currentCol++;
    fillWithColour(framebuffer, c);

    rgbColor c1 = {0, 0, 255, 255};
    fillEveryInterval(framebuffer, c1, 20);
    gtk_widget_queue_draw(mainWindow);
    return 1;
}

gboolean onDraw(GtkWidget* widget, cairo_t *cr, gpointer user_data) {
    gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
    cairo_paint(cr);
    return 0;
}

void fillWithColour(uint32_t* fb, rgbColor c) {
    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            encodePixel(fb, c, x, y);
        }
    }
}

void fillEveryInterval(uint32_t* fb, rgbColor c, int interval) {
    for (int y = 1; y < HEIGHT; y += interval) {
        for (int x = 0; x < WIDTH; x++) {
            encodePixel(fb, c, x, y);
        }
    }
}


void encodePixel(uint32_t* fb, rgbColor c, int x, int y) {
    uint32_t r, g, b, a;

    r = c.red;
    g = c.green << 8;
    b = c.blue << 16;
    a = c.alpha << 24;
    
    *(fb + (sizeof(uint32_t)*y+x)) = b | g | r | a;
}

int main() {
    framebuffer = malloc(sizeof(uint32_t)*WIDTH*HEIGHT);
    rgbColor c = {255, 0, 0, 255};
    fillWithColour(framebuffer, c);


    gtk_init(NULL, NULL);
    mainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(mainWindow), WIDTH, HEIGHT);
    gtk_window_set_title(GTK_WINDOW(mainWindow), "Framebuffer test");

    GtkWidget* drawingArea = gtk_drawing_area_new();

    gtk_container_add(GTK_CONTAINER(mainWindow), drawingArea);

    g_signal_connect(GTK_WINDOW(mainWindow), "destroy", (GCallback)onWindowDestroy, NULL);
    g_signal_connect(GTK_DRAWING_AREA(drawingArea), "draw", (GCallback)onDraw, NULL);

    g_timeout_add(500, onTimerTick, NULL);

    gtk_widget_show_all(GTK_WINDOW(mainWindow));
    pixbuf = gdk_pixbuf_new_from_data(framebuffer, GDK_COLORSPACE_RGB, true, 8, WIDTH, HEIGHT, WIDTH*4, NULL, NULL);
    gtk_main();
}

I can't seem to figure out what is causing the issue, I have experimented with eliminating the alpha channel and packing the RGB values into 24-bits, however I was not successful with that method either. I think it may have something to do with the rowstride, however I have not been able to find a value which corrects the issue. Am I on the right track here, or is there a better way to draw a RGB buffer to screen using GTK?

You're just storing the pixels in the wrong location. In encodePixel , change this line:

*(fb + (sizeof(uint32_t)*y+x)) = b | g | r | a;`

to this

fb[WIDTH*y+x] = b | g | r | a;

And on a sidenote: You should do something with the many warnings from the compiler.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM