[gegl] bin: implement a serial thumbnail generator
- From: Øyvind "pippin" Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] bin: implement a serial thumbnail generator
- Date: Sat, 26 Jan 2019 18:50:51 +0000 (UTC)
commit b75cfe6b72bab8e2b1103047c1b4b3387d1f059a
Author: Øyvind Kolås <pippin gimp org>
Date: Sat Jan 26 17:54:13 2019 +0100
bin: implement a serial thumbnail generator
When running $ gegl --thumbgen /file/path1 /file/path2 /file/path3
gegl will. for each file in succession load the specified file
and update its thumbnail - loading the buffer, doing full processing
and using GeglBuffers mipmap to scale down to a mock mrg with 256x256
size.
bin/gegl-options.c | 14 +++-
bin/gegl-options.h | 1 +
bin/ui.c | 197 ++++++++++++++++++++++++++++++++++++++++-------------
3 files changed, 161 insertions(+), 51 deletions(-)
---
diff --git a/bin/gegl-options.c b/bin/gegl-options.c
index 60f08277e..112c5d916 100644
--- a/bin/gegl-options.c
+++ b/bin/gegl-options.c
@@ -243,6 +243,14 @@ gegl_options_previous_file (GeglOptions *o)
return FALSE;
}
+#ifdef HAVE_MRG
+int thumbgen_main (int argc, char **argv);
+#else
+static int thumbgen_main (int argc, char **argv)
+{
+ return -222;
+}
+#endif
static GeglOptions *
parse_args (int argc,
@@ -264,8 +272,10 @@ parse_args (int argc,
o->mode = GEGL_RUN_MODE_HELP;
usage (argv[0]);
}
-
- else if (match ("--list-all")) {
+ else if (match ("--thumbgen")) {
+ thumbgen_main (argc, argv);
+ exit (0);
+ } else if (match ("--list-all")) {
guint n_operations;
gint i;
gchar **operations;
diff --git a/bin/gegl-options.h b/bin/gegl-options.h
index c318134aa..c7617772f 100644
--- a/bin/gegl-options.h
+++ b/bin/gegl-options.h
@@ -25,6 +25,7 @@ typedef enum
{
GEGL_RUN_MODE_HELP,
GEGL_RUN_MODE_DISPLAY,
+ GEGL_RUN_MODE_THUMBNAIl,
GEGL_RUN_MODE_OUTPUT,
GEGL_RUN_MODE_XML
} GeglRunMode;
diff --git a/bin/ui.c b/bin/ui.c
index 39f9e343e..0a2cb731f 100644
--- a/bin/ui.c
+++ b/bin/ui.c
@@ -391,6 +391,7 @@ gchar *get_thumb_path (const char *path)
gchar *ret;
gchar *uri = g_strdup_printf ("file://%s", path);
gchar *hex = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri, -1);
+ fprintf (stderr, "[%s]\n", path);
int i;
for (i = 0; hex[i]; i++)
hex[i] = tolower (hex[i]);
@@ -602,12 +603,14 @@ static void generate_thumb (ThumbQueueItem *item)
}
goto cleanup;
}
- /* spawning new gegl processes takes up a lot of time, perhaps passing multiple files
- in one go, or having a way of appending requests to existing processes would be good..
+ /* spawning new gegl processes takes up a lot of time, perhaps passing
+ * multiple files
+ in one go, or having a way of appending requests to existing processes
+would be good..
- perhaps doing simple downscales with no filters should be done with a faster tool?
- for thumbnail generation the mipmap downscale is already a very high quality result-
- that perhaps should be used instead of an actual scale op?
+ perhaps doing simple downscales with no filters should be done with a
+faster tool? for thumbnail generation the mipmap downscale is already a very
+high quality result- that perhaps should be used instead of an actual scale op?
*/
g_spawn_async (NULL, &argv[0], NULL, G_SPAWN_SEARCH_PATH|G_SPAWN_SEARCH_PATH_FROM_ENVP, NULL, NULL,
&child_pid, &error);
if (error)
@@ -692,7 +695,6 @@ static gboolean renderer_task (gpointer data)
if (thumb_queue)
{
-
{
int thumbnailers = o->concurrent_thumbnailers;
if (thumbnailers < 0) thumbnailers = -thumbnailers;
@@ -745,12 +747,19 @@ static gpointer renderer_thread (gpointer data)
return 0;
}
-int mrg_ui_main (int argc, char **argv, char **ops)
+static void init_state (State *o)
{
- Mrg *mrg = mrg_new (1024, 768, NULL);
const char *renderer_env = g_getenv ("GEGL_RENDERER");
-
- State o = {NULL,};
+ o->scale = 1.0;
+ o->graph_scale = 1.0;
+ o->render_quality = 1.0;
+ o->preview_quality = 1.0;
+ //o->preview_quality = 2.0;
+ o->slide_pause = 5.0;
+ o->slide_enabled = 0;
+ o->concurrent_thumbnailers = 2;
+ o->show_bindings = 0;
+ o->ui_consumer = g_hash_table_new (g_direct_hash, g_direct_equal);
if (renderer_env)
{
@@ -763,71 +772,147 @@ int mrg_ui_main (int argc, char **argv, char **ops)
} else
renderer = GEGL_RENDERER_IDLE;
- mrg_set_title (mrg, "GEGL");
+ o->gegl = gegl_node_new ();
+}
+
+static void cleanup_state (State *o)
+{
+ g_clear_object (&o->gegl);
+ g_clear_object (&o->processor);
+ g_clear_object (&o->processor_buffer);
+ g_clear_object (&o->buffer);
+}
+
+int mrg_ui_main (int argc, char **argv, char **ops)
+{
+ Mrg *mrg = mrg_new (1024, 768, NULL);
+ static State state = {NULL,};
+ State *o = &state;
+ global_state = o;
+
- o.ops = ops;
+ mrg_set_title (mrg, "GEGL");
gegl_init (&argc, &argv);
- o.gegl = gegl_node_new (); // so that we have an object to unref
- o.mrg = mrg;
- o.scale = 1.0;
- o.graph_scale = 1.0;
- o.render_quality = 1.0;
- o.preview_quality = 1.0;
- //o.preview_quality = 2.0;
- o.slide_pause = 5.0;
- o.slide_enabled = 0;
- o.concurrent_thumbnailers = 2;
- o.show_bindings = 0;
- o.ui_consumer = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ init_state (o);
+
+ o->ops = ops;
+ o->mrg = mrg;
if (access (argv[1], F_OK) != -1)
- o.path = realpath (argv[1], NULL);
+ o->path = realpath (argv[1], NULL);
else
{
printf ("usage: %s <full-path-to-image>\n", argv[0]);
return -1;
}
- load_path (&o);
- mrg_set_ui (mrg, gegl_ui, &o);
- global_state = &o;
- on_viewer_motion (NULL, &o, NULL);
+ load_path (o);
+ mrg_set_ui (mrg, gegl_ui, o);
+ on_viewer_motion (NULL, o, NULL);
switch (renderer)
{
case GEGL_RENDERER_THREAD:
- o.renderer_thread = g_thread_new ("renderer", renderer_thread, &o);
+ o->renderer_thread = g_thread_new ("renderer", renderer_thread, &o);
break;
case GEGL_RENDERER_IDLE:
- mrg_add_idle (mrg, renderer_idle, &o);
+ mrg_add_idle (mrg, renderer_idle, o);
break;
case GEGL_RENDERER_BLIT:
case GEGL_RENDERER_BLIT_MIPMAP:
break;
}
- if (o.ops)
+ if (o->ops)
{
- o.show_graph = 1;
+ o->show_graph = 1;
}
mrg_main (mrg);
has_quit = 1;
if (renderer == GEGL_RENDERER_THREAD)
- g_thread_join (o.renderer_thread);
+ g_thread_join (o->renderer_thread);
+ cleanup_state (o);
- g_clear_object (&o.gegl);
- g_clear_object (&o.processor);
- g_clear_object (&o.processor_buffer);
- g_clear_object (&o.buffer);
gegl_exit ();
end_audio ();
return 0;
}
+int cmd_thumb (COMMAND_ARGS); /* "thumb", 0, "<>", "generate thumbnail for active image"*/
+int
+cmd_thumb (COMMAND_ARGS)
+{
+ State *o = global_state;
+ gchar *thumbdata;
+ GeglBuffer *buffer;
+ GeglNode *gegl;
+ GeglNode *saver;
+ GeglNode *source;
+ gchar *thumbpath;
+
+ thumbpath = get_thumb_path (o->save_path);
+
+ gegl = gegl_node_new ();
+ thumbdata = g_malloc0 (256 * 256 * 4);
+ buffer = gegl_buffer_linear_new_from_data (thumbdata,
+ babl_format ("R'G'B' u8"),
+ GEGL_RECTANGLE(0,0,256,256),
+ 256 * 3, NULL, NULL);
+ saver = gegl_node_new_child (gegl,
+ "operation", "gegl:jpg-save",
+ "path", thumbpath,
+ NULL);
+ source = gegl_node_new_child (gegl,
+ "operation", "gegl:buffer-source",
+ "buffer", buffer,
+ NULL);
+ gegl_node_link_many (source, saver, NULL);
+
+ gegl_node_blit (o->sink, o->scale, GEGL_RECTANGLE(0,0,256,256),
+ babl_format("R'G'B' u8"),
+ thumbdata, 256*3, GEGL_BLIT_DEFAULT);
+ fprintf (stderr, "%s %s\n", o->path, thumbpath);
+ gegl_node_process (saver);
+ g_free (thumbpath);
+ g_object_unref (gegl);
+ g_object_unref (buffer);
+ g_free (thumbdata);
+ return 0;
+}
+
+int thumbgen_main (int argc, char **argv);
+
+int thumbgen_main (int argc, char **argv)
+{
+ static State state = {NULL,};
+ State *o = &state;
+ global_state = o;
+ gegl_init (&argc, &argv);
+
+ init_state (o);
+
+ for (char **arg = &argv[2]; *arg; arg++)
+ {
+ if (o->path)
+ g_free (o->path);
+ o->path = g_strdup (*arg);
+ load_path (o);
+ fprintf (stderr, "%s\n", *arg);
+ argvs_eval ("thumb");
+ }
+
+ cleanup_state (o);
+
+ gegl_exit ();
+
+ exit (0);
+}
+
static int hide_controls_cb (Mrg *mrg, void *data)
{
State *o = data;
@@ -857,7 +942,6 @@ static void on_viewer_motion (MrgEvent *e, void *data1, void *data2)
static int node_select_hack = 0;
-
static void on_pan_drag (MrgEvent *e, void *data1, void *data2)
{
static float zoom_pinch_coord[4][2] = {0,};
@@ -1168,9 +1252,11 @@ static void on_paint_drag (MrgEvent *e, void *data1, void *data2)
gegl_path_append (path, 'L', x, y);
gegl_node_set (o->active, "d", path, "color", gegl_color_new("blue"),
"width", 16.0 / o->scale, NULL);
+ rev_inc (o);
break;
case MRG_DRAG_MOTION:
gegl_path_append (path, 'L', x, y);
+ //rev_inc (o); XXX : maybe enable if it doesnt interfere with painting
break;
case MRG_DRAG_RELEASE:
o->active = gegl_node_get_ui_consumer (o->active, "output", NULL);
@@ -1668,7 +1754,6 @@ static GeglNode *add_aux (State *o, GeglNode *active, const char *optype)
gegl_node_link_many (producer, ret, NULL);
}
gegl_node_connect_to (ret, "output", ref, "aux");
- rev_inc (o);
return ret;
}
@@ -1686,7 +1771,6 @@ static GeglNode *add_input (State *o, GeglNode *active, const char *optype)
gegl_node_link_many (producer, ret, NULL);
}
gegl_node_connect_to (ret, "output", ref, "input");
- rev_inc (o);
return ret;
}
@@ -1705,7 +1789,6 @@ static GeglNode *add_output (State *o, GeglNode *active, const char *optype)
gegl_node_link_many (ref, ret, NULL);
gegl_node_connect_to (ret, "output", consumer, consumer_name);
}
- rev_inc (o);
return ret;
}
@@ -2848,19 +2931,28 @@ static void on_active_node_drag (MrgEvent *e, void *data1, void *data2, int is_a
if (angle < -120 || angle > 120) // upwards
{
if (dist > dist_add_node)
+ {
o->active = add_output (o, o->active, "gegl:nop");
+ rev_inc(o);
+ }
}
else if (angle < 60 && angle > -45) // down
{
if (is_aux)
{
if (dist > dist_add_node)
+ {
o->active = add_aux (o, o->active, "gegl:nop");
+ rev_inc(o);
+ }
}
else
{
if (dist > dist_add_node)
- o->active = add_input (o, o->active, "gegl:nop");
+ {
+ o->active = add_input (o, o->active, "gegl:nop");
+ }
+ rev_inc(o);
}
}
else if (angle < -45 && angle > -110) // left
@@ -5107,6 +5199,7 @@ static void zoom_to_fit (State *o)
Mrg *mrg = o->mrg;
GeglRectangle rect = gegl_node_get_bounding_box (o->sink);
float scale, scale2;
+ float width = 256, height = 256;
if (rect.width == 0 || rect.height == 0)
{
@@ -5116,15 +5209,21 @@ static void zoom_to_fit (State *o)
return;
}
- scale = 1.0 * mrg_width (mrg) / rect.width;
- scale2 = 1.0 * mrg_height (mrg) / rect.height;
+ if (mrg)
+ {
+ width = mrg_width (mrg);
+ height = mrg_height (mrg);
+ }
+
+ scale = 1.0 * width / rect.width;
+ scale2 = 1.0 * height / rect.height;
if (scale2 < scale) scale = scale2;
o->scale = scale;
- o->u = -(mrg_width (mrg) - rect.width * o->scale) / 2;
- o->v = -(mrg_height (mrg) - rect.height * o->scale) / 2;
+ o->u = -(width - rect.width * o->scale) / 2;
+ o->v = -(height - rect.height * o->scale) / 2;
o->u += rect.x * o->scale;
o->v += rect.y * o->scale;
@@ -6448,11 +6547,11 @@ cmd_node_add (COMMAND_ARGS)
gegl_node_link_many (ref, o->active, NULL);
gegl_node_connect_to (o->active, "output", consumer, consumer_name);
o->editing_op_name = 1;
- mrg_set_cursor_pos (o->mrg, 0);
+ if (o->mrg) mrg_set_cursor_pos (o->mrg, 0);
o->new_opname[0]=0;
}
}
- rev_inc (o);
+ if (o->mrg) rev_inc (o);
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]