GdkPixbuf を使ってみた

ちょっと、画像処理(Pixel単位)が必要になり、いつもなら ImageMagick の convert コマンドを使うのだが、変化を見ながら数値を変える必要がありそうなので、画像を GdkPixbuf に読み込んで pixel 単位でデータを取得する方法を調べてみた。
Makefile とソースは以下のとおり。ただし、データ取得は理解したので、画像情報を取得するだけのソースです。

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

#define IMAGE_FILE "test.png"

int
main (int argc, char *argv[])
{
	GtkWidget *window, *image;
	GdkPixbuf *pixbuf;
	GError *error = NULL;

	gtk_init (&argc, &argv);
	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);

	pixbuf = gdk_pixbuf_new_from_file (IMAGE_FILE, &error);
	if (pixbuf == NULL)
	{
		g_print ("Error:\t%s\n", error->message);
		g_error_free (error);
		error = NULL;
		return EXIT_FAILURE;
	}

	g_print ("Number of channels:\t%d\n", gdk_pixbuf_get_n_channels (pixbuf));
	g_print ("Has Alpha channel:\t%d\n", gdk_pixbuf_get_has_alpha (pixbuf));
	g_print ("Bits per sample:\t%d\n", gdk_pixbuf_get_bits_per_sample (pixbuf));
	g_print ("Width:\t%d\n", gdk_pixbuf_get_width (pixbuf));
	g_print ("Height:\t%d\n", gdk_pixbuf_get_height (pixbuf));
	g_print ("Bytes of row:\t%d\n", gdk_pixbuf_get_rowstride (pixbuf));

	image = gtk_image_new_from_pixbuf (pixbuf);
	gtk_container_add (GTK_CONTAINER (window), image);
	gtk_widget_show_all (window);	
	gtk_main ();
	return EXIT_SUCCESS;
}
# $ pkg-config --cflags gtk+-3.0
CFLAGS = -pthread -I/usr/include/gtk-3.0 -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/pixman-1 -I/usr/include/libpng12 -I/usr/include/libdrm

# $ pkg-config --libs gtk+-3.0
LDFLAGS = -lgtk-3 -lgdk-3 -latk-1.0 -lgio-2.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lcairo-gobject -lpango-1.0 -lcairo -lgobject-2.0 -lglib-2.0

後は、gdk_pixbuf_get_pixels() でデータのポインタを取得して、(x, y) のポインタは、

pointer = gdk_pixbuf_get_pixels(pixbuf) + y * gdk_pixbuf_get_rowstride(pixbuf) + x * gdk_pixbuf_get_n_channels (pixbuf);

するだけです。データは RGBA の順番なので、分かりますよね。Alpha チャネルの有無に注意すれば失敗もないと思います。