Drawing pixels with the GdkPixbuf



Hi,

I'm trying to write my own pixel values to a GdkPixbuf in a GtkImage
widget. I've attached the source file for my program, which doesn't
seem to do anything. The function for modifying the pixel values is a
slightly modified version of the one found on the GdkPixbuf
documentation page,

http://developer.gnome.org/gdk-pixbuf/unstable//gdk-pixbuf-The-GdkPixbuf-Structure.html

Can someone explain to me if there's anything I'm doing wrong with the
pixel information?

Paul Khermouch
pkhermouch gmail com

Attachment: box.jpg
Description: JPEG image

#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define WINDOW_WIDTH 600
#define WINDOW_HEIGHT 600

GtkWidget* window;
GtkWidget* image;
char changed;
char DEBUG;

static gboolean close_window(GtkWidget* widget, GdkEvent* event, gpointer data);
static void destroy(GtkWidget *widget, gpointer data);
static guint snooper(GtkWidget* widget, GdkEventKey* event, gpointer data);
static void configure_pixbuf();
static void draw_pixel(int x, int y, guchar red, guchar green, guchar blue);

int main(int argc, char* argv[]) {

    changed = 0;
    DEBUG = (argc > 1);

    // Initialize the gtk session.
    gtk_init(&argc, &argv);

    // Create a new window, set the title, size and icon,
    // and make the window non-resizeable.
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "Image Display");
    //gtk_widget_set_size_request(GTK_WIDGET(window), WINDOW_WIDTH, WINDOW_HEIGHT);
    gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
    
    // Link the "delete-event" signal, caused by clicking the X on the
    // title bar, to the close_window() function.
    g_signal_connect(window, "delete-event", G_CALLBACK(close_window), NULL);

    // Link the "destroy" signal, caused when we return FALSE in
    // close_window(), to the destroy() function.
    g_signal_connect(window, "destroy", G_CALLBACK(destroy), NULL);

    // Intercept key presses before the events occur. This will allow
    // us to move the images upon key presses while allowing the user to
    // enter text into the entry widget.
    gtk_key_snooper_install((GtkKeySnoopFunc) snooper, NULL);

    image = gtk_image_new_from_file("box.jpg");

    gtk_container_add(GTK_CONTAINER(window), image);

    // Display all of the widgets.
    gtk_widget_show(image);
    gtk_widget_show(window);
    g_print("Finished adding everything, calling gtk_main()\n");

    // Call gtk_main() to start up the GUI.
    gtk_main();

    return 0;

}

// Called when the user clicks the X button on the toolbar.
static gboolean close_window(GtkWidget* widget, GdkEvent* event, gpointer data) {
    
    // Return FALSE and the main window will emit the
    // "destroy" signal and call the destroy() function.
    // Return TRUE to indicate you don't want to destroy
    // the window after this function call, useful for
    // "Are you sure you want to quit?" dialogs.
    return FALSE;
    
}

// Called when the above function returns FALSE.
static void destroy(GtkWidget *widget, gpointer data) {
    
    gtk_main_quit();
    
}

// Keyboard snooper function.
static guint snooper(GtkWidget* widget, GdkEventKey* event, gpointer data) {

    if (event->keyval == 'q') {
        exit(0);
    }

    if (changed) {
        g_print("Image has already been modified\n");
        return 0;
    }
    
    GdkPixbuf *pixbuf;
    unsigned int width, height;
    guchar *pixelstream;
    int counter;

    pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(image));
    
    if (event->type == GDK_KEY_PRESS) {

        width = (unsigned int) gdk_pixbuf_get_width(pixbuf);
        height = (unsigned int) gdk_pixbuf_get_height(pixbuf);
        pixelstream = gdk_pixbuf_get_pixels(pixbuf);

        printf("width %u height %u\n", width, height);

        // Draw some pixels.
        for (counter = 0; counter < width; counter++) {
            draw_pixel(counter % width, height / 2, 255, 0, 0);
        }
        g_print("Changed the pixels?\n");
        changed = 1;

    }

    return 0;

}

static void configure_pixbuf() {

    GdkPixbuf *pixbuf;

    pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(image));

    // Already the default value.
    if (gdk_pixbuf_set_option(pixbuf, "bits-per-sample", 8) == FALSE) {
        printf("gdk_pixbuf_set_option() failed\n");
    }

}


static void draw_pixel(int x, int y, guchar red, guchar green, guchar blue) {
    
    int width, height, rowstride, n_channels;
    guchar *pixels, *p;
    GdkPixbuf *pixbuf;

    pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(image));
    
    n_channels = gdk_pixbuf_get_n_channels(pixbuf);

    // Check that the way of storing the pixel data
    // is the way we want.
    g_assert(gdk_pixbuf_get_colorspace(pixbuf) == GDK_COLORSPACE_RGB);
    g_assert(gdk_pixbuf_get_bits_per_sample(pixbuf) == 8);
    g_assert(gdk_pixbuf_get_has_alpha(pixbuf) == FALSE);
    g_assert(n_channels == 3);

    width = gdk_pixbuf_get_width (pixbuf);
    height = gdk_pixbuf_get_height (pixbuf);

    g_assert (x >= 0 && x < width);
    g_assert (y >= 0 && y < height);

    rowstride = gdk_pixbuf_get_rowstride (pixbuf);
    pixels = gdk_pixbuf_get_pixels (pixbuf);

    p = pixels + y * rowstride + x * n_channels;

    DEBUG && printf("draw_line: width %d height %d x %d y %d\n",
                    width, height, x, y);
    DEBUG && printf("array beginning: %lu, rowstride: %d, p: %lu\n",
                    (long unsigned) pixels, rowstride, (long unsigned) p);
    
    p[0] = red;
    p[1] = green;
    p[2] = blue;
    
}

Attachment: makefile
Description: Binary data



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]