1

This is my current code:

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

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

    p = pixels + y * rowstride + x * 8;
    p[0] = red;
    p[1] = green;
    p[2] = blue;
    p[3] = alpha;
}

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

    gtk_init(&argc, &argv);

    GtkWidget *window;
    GdkColorspace colorspace = GDK_COLORSPACE_RGB;
    GdkPixbuf *pixbuf;
    GtkWidget *image;

    window = gtk_dialog_new();
    gtk_widget_set_size_request(window, 512, 512);
    g_signal_connect(window, "destroy", G_CALLBACK (G_CALLBACK(gtk_main_quit)), NULL);

    pixbuf = gdk_pixbuf_new(colorspace, TRUE, 8, 512, 512);

    for(int i=0; i<512; i++) {
        put_pixel(pixbuf, i, i, 255, 0, 255, 255);
    }

    image = gtk_image_new_from_pixbuf(pixbuf);

    gtk_box_pack_start(GTK_BOX (GTK_DIALOG(window)->vbox), image, FALSE, FALSE, 0);

    gtk_widget_show_all(window);
    gtk_main();
}

and I was expected a purple line from (0, 0) to (512, 512). Instead, I have one purple line from (0, 0) to (256, 512) and one from (256, 0) to (512, 512).

Why is this and how can I fix it?

  • 2
    `pixels + y * rowstride + x * 8` associates as `pixels + (y * rowstride) + (x * 8)`, which is probably not what you want. – andlabs Jun 20 '17 at 17:49
  • @andlabs I got that from the docs, so I don't completely understand it, sorry! When trying to do (pixels + y) * rowstride, I get the error `invalid operands of types ‘guchar*’ and ‘int’ to binary ‘operator*’`? –  Jun 20 '17 at 18:03
  • That's still not correct. Think about what that expression wants to do. – andlabs Jun 20 '17 at 18:25
  • 1
    Actually never mind, I'm wrong. `gdk_pixbuf_get_rowstride()` returns a byte count, so the expression is still correct. Not sure what's wrong in your case... – andlabs Jun 20 '17 at 18:26

1 Answers1

2

You defined the variable but didn't use it (on put_pixel function)

Solution:

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

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

  p = pixels + y * rowstride + x * n_channels;
  p[0] = red;
  p[1] = green;
  p[2] = blue;
  p[3] = alpha;
}

You were offsetting X by 8 and should be 4 (RGBA). Rowstride is also correlated with the number of channels, in this case your image height is 512 so 512 * n_channels = 2048.

Conclusion:

On put_pixel function, add:

n_channels = gdk_pixbuf_get_n_channels (pixbuf);

and change :

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

to:

p = pixels + y * rowstride + x * n_channels;
José Fonte
  • 4,016
  • 2
  • 16
  • 28