Skip to content

Instantly share code, notes, and snippets.

@bellbind
Created July 2, 2009 13:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bellbind/139457 to your computer and use it in GitHub Desktop.
Save bellbind/139457 to your computer and use it in GitHub Desktop.
[C][gegl][webkitgtk][X][tool] get web site thumbnail
/*
* get screenshot PNG from web page
*
* build:
* FLAGS=`pkg-config --cflags --libs gtk+-x11-2.0 webkit-1.0 gegl`
* gcc -Wall $FLAGS getscreenshot_gegl.c -o getscreenshot_gegl
*
* usage:
* xvfb-run -s "-screen 0 1024x768x24" ./getscreenshot_gegl test.html
*
*/
#include <glib.h>
#include <glib/gprintf.h>
#include <gtk/gtk.h>
#include <webkit/webkit.h>
#include <gegl.h>
typedef struct _ThumbInfo ThumbInfo;
struct _ThumbInfo {
gint width;
gint height;
GString * filename;
};
typedef struct _FontInfo FontInfo;
struct _FontInfo {
gint point;
GString * name;
};
/* gegl info see:
* http://gegl.org/api.html
* http://gegl.org/operations.html
*/
static void
store_thumbnail(ThumbInfo * thumb, GdkPixbuf * pixbuf)
{
GeglNode * gegl;
GeglNode * input;
GeglNode * output;
GeglNode * scale;
GeglRectangle bb;
gegl = gegl_node_new();
input = gegl_node_new_child(gegl,
"operation", "gegl:pixbuf",
"pixbuf", pixbuf,
NULL);
bb = gegl_node_get_bounding_box(input);
output = gegl_node_new_child(gegl,
"operation", "gegl:png-save",
"path", thumb->filename->str,
"compression", 9,
NULL);
scale = gegl_node_new_child(gegl,
"operation", "gegl:scale",
"filter", "lanczos",
"x", (gdouble) thumb->width / bb.width,
"y", (gdouble) thumb->height / bb.height,
NULL);
gegl_node_link_many(input, scale, output, NULL);
{
gint dw = 0, dh = 0;
bb = gegl_node_get_bounding_box(scale);
while (bb.width > thumb->width) {
dw++;
gegl_node_set(scale,
"x", (gdouble) (thumb->width - dw) / bb.width,
NULL);
bb = gegl_node_get_bounding_box(scale);
}
while (bb.height > thumb->height) {
dh++;
gegl_node_set(scale,
"y", (gdouble) (thumb->height - dh) / bb.height,
NULL);
bb = gegl_node_get_bounding_box(scale);
}
}
gegl_node_process(output);
bb = gegl_node_get_bounding_box(scale);
g_object_unref(gegl);
g_printf("saved %dx%d PNG into %s\n",
bb.width, bb.height, thumb->filename->str);
}
/*
* see: http://webkitgtk.org/reference/webkitgtk-WebKitWebView.html signals
*/
static void
loaded(WebKitWebView * view, WebKitWebFrame * frame, gpointer data)
{
ThumbInfo * thumb;
GdkWindow * window;
GdkColormap * colormap;
gint width;
gint height;
GdkPixbuf * pixbuf;
thumb = data;
g_object_get(G_OBJECT(view), "window", &window, NULL);
gdk_window_get_size(GDK_WINDOW(window), &width, &height);
colormap = gdk_window_get_colormap(GDK_WINDOW(window));
/* gdk-pixbuf api: http://library.gnome.org/devel/gdk-pixbuf/stable/ */
pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
gdk_pixbuf_get_from_drawable(pixbuf, GDK_DRAWABLE(window), colormap,
0, 0, 0, 0, width, height);
store_thumbnail(thumb, pixbuf);
g_object_unref(G_OBJECT(pixbuf));
gtk_main_quit();
}
static GtkWidget *
init_window(GString * url, ThumbInfo * thumb, FontInfo * font)
{
GtkWidget * window;
GtkWidget * webview;
GdkScreen * screen;
WebKitWebSettings * settings;
screen = gdk_screen_get_default();
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_move(GTK_WINDOW(window), 0, 0);
gtk_window_resize(GTK_WINDOW(window),
gdk_screen_get_width(screen),
gdk_screen_get_height(screen));
webview = webkit_web_view_new();
/* webkit settings props:
* http://webkitgtk.org/reference/webkitgtk-WebKitWebSettings.html
*/
settings = webkit_web_settings_new();
g_object_set(G_OBJECT(settings),
"serif-font-family", font->name->str,
"sans-serif-font-family", font->name->str,
"monospace-font-family", font->name->str,
"default-font-family", font->name->str,
"default-font-size", font->point,
NULL);
webkit_web_view_set_settings(WEBKIT_WEB_VIEW(webview), settings);
gtk_container_add(GTK_CONTAINER(window), webview);
gtk_signal_connect(GTK_OBJECT(webview), "load-finished",
GTK_SIGNAL_FUNC(loaded), thumb);
webkit_web_view_open(WEBKIT_WEB_VIEW(webview), url->str);
gtk_widget_show_all(window);
return window;
}
static void
parse_option(gint * pargc, gchar ** pargv[],
ThumbInfo * thumb, FontInfo * font)
{
/* glib commandline option parser:
* http://library.gnome.org/devel/glib/stable/
*/
GOptionContext *context;
gchar * filename = NULL;
gchar * fontname = NULL;
GOptionEntry entries[] = {
{"width", 'w', 0, G_OPTION_ARG_INT,
&thumb->width,
"thumbnail width pixel", "WIDTH"},
{"height", 'h', 0, G_OPTION_ARG_INT,
&thumb->height,
"thumbnail height pixel", "HEIGHT"},
{"output", 'o', G_OPTION_FLAG_FILENAME, G_OPTION_ARG_FILENAME,
&filename,
"thumbnail PNG file name", "PNG_FILENAME"},
{"font", 'f', 0, G_OPTION_ARG_STRING,
&fontname,
"font name", "FONT_NAME"},
{"point", 'p', 0, G_OPTION_ARG_INT,
&font->point,
"default font point", "POINT"},
{NULL}
};
context = g_option_context_new("get web page thumbnail");
g_option_context_add_main_entries(context, entries, NULL);
/* gtk_get_option_group see:
* http://library.gnome.org/devel/gtk/stable/gtk-General.html */
g_option_context_add_group(context, gtk_get_option_group(TRUE));
g_option_context_add_group(context, gegl_get_option_group());
if (!g_option_context_parse(context, pargc, pargv, NULL)) {
gtk_exit(0);
}
if (filename) {
g_string_overwrite(thumb->filename, 0, filename);
}
if (fontname) {
g_string_overwrite(font->name, 0, fontname);
}
g_option_context_free(context);
}
int
main(int argc, char * argv[])
{
GString * url;
ThumbInfo thumb;
FontInfo font;
GtkWidget * window;
font.point = 14;
font.name = g_string_new("VLGothic");
thumb.width = 200;
thumb.height = 150;
thumb.filename = g_string_new("screenshot.png");
g_thread_init(NULL);
gdk_threads_init();
gdk_threads_enter();
parse_option(&argc, &argv, &thumb, &font);
url = g_string_new(argv[1]);
if (!g_str_has_prefix(url->str, "http")) {
url = g_string_prepend(url, "file://");
}
window = init_window(url, &thumb, &font);
gtk_main();
gegl_exit();
gdk_threads_leave();
g_string_free(url, TRUE);
g_string_free(font.name, TRUE);
g_string_free(thumb.filename, TRUE);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment