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 チャネルの有無に注意すれば失敗もないと思います。