static void standard_output (const gchar *op_name) { GeglNode *composition, *input, *aux, *operation, *crop, *output; gchar *input_path = g_build_path (G_DIR_SEPARATOR_S, data_dir, "standard-input.png", NULL); gchar *aux_path = g_build_path (G_DIR_SEPARATOR_S, data_dir, "standard-aux.png", NULL); gchar *output_path = operation_to_path (op_name, FALSE); composition = gegl_node_new (); operation = gegl_node_create_child (composition, op_name); if (gegl_node_has_pad (operation, "output")) { input = gegl_node_new_child (composition, "operation", "gegl:load", "path", input_path, NULL); aux = gegl_node_new_child (composition, "operation", "gegl:load", "path", aux_path, NULL); crop = gegl_node_new_child (composition, "operation", "gegl:crop", "width", 200.0, "height", 200.0, NULL); output = gegl_node_new_child (composition, "operation", "gegl:png-save", "compression", 9, "path", output_path, NULL); gegl_node_link_many (operation, crop, output, NULL); if (gegl_node_has_pad (operation, "input")) gegl_node_link (input, operation); if (gegl_node_has_pad (operation, "aux")) gegl_node_connect_to (aux, "output", operation, "aux"); gegl_node_process (output); } g_free (input_path); g_free (aux_path); g_free (output_path); g_object_unref (composition); }
gint main (gint argc, gchar **argv) { GList *operations; GList *iter; gboolean first = TRUE; gegl_init (&argc, &argv); g_object_set (gegl_config (), "application-license", "GPL3", NULL); operations = gegl_operations (); g_print ("window.opdb=[\n"); for (iter=operations;iter;iter = g_list_next (iter)) { GeglOperationClass *klass = iter->data; const char *name = gegl_operation_class_get_key (klass, "name"); const char *categoris = gegl_operation_class_get_key (klass, "categories"); if (first) first = FALSE; else g_print (","); g_print ("{'op':'%s'\n", name); if (klass->compat_name) g_print (",'compat-op':'%s'\n", klass->compat_name); if (klass->opencl_support) g_print (",'opencl-support':'true'\n"); g_print (",'parent':'%s'\n", g_type_name (g_type_parent(G_OBJECT_CLASS_TYPE(klass)))); { char *image = operation_to_path (name); if (g_file_test (image, G_FILE_TEST_EXISTS)) g_print (",'image':'%s'\n", image); g_free (image); } { gchar *commandline = g_strdup_printf ( "sh -c \"(cd " TOP_SRCDIR ";grep -r '\\\"%s\\\"' operations) | grep operations | grep -v '~:' | grep '\\\"name\\\"' | cut -f 1 -d ':'\"", name); gchar *output = NULL; if (g_spawn_command_line_sync (commandline, &output, NULL, NULL, NULL)) { if (strlen(output)) { output[strlen(output)-1] = 0; g_print ( ",'source':'https://git.gnome.org/browse/gegl/tree/%s'\n", output); } g_free (output); } g_free (commandline); } if (categoris) { const gchar *ptr = categoris; gboolean first = TRUE; g_print (",'categories':["); while (ptr && *ptr) { gchar category[64]=""; gint i=0; while (*ptr && *ptr!=':' && i<63) { category[i++]=*(ptr++); category[i]='\0'; } if (*ptr==':') ptr++; { if (first) first = FALSE; else g_print (","); g_print ("'%s'", category); } } g_print ("]\n"); } json_list_properties (G_OBJECT_CLASS_TYPE (klass), name); json_list_pads (G_OBJECT_CLASS_TYPE (klass), name); { guint nkeys; gchar **keys = gegl_operation_list_keys (name, &nkeys); if (keys) { for (gint i = 0; keys[i]; i++) { const gchar *value = gegl_operation_get_key (name, keys[i]); if (g_str_equal (keys[i], "categories") || g_str_equal (keys[i], "cl-source") || g_str_equal (keys[i], "source") || g_str_equal (keys[i], "name") ) continue; g_print (",\"%s\":\"", keys[i]); json_escape_string (value); g_print ("\"\n"); } g_free (keys); } } g_print (" }\n"); } g_print ("]\n"); return 0; }
static gboolean test_operation (const gchar *op_name, const gchar *image, gchar *output_path) { gchar *ref_path; GeglNode *img, *ref_img, *gegl; GeglRectangle ref_bounds, comp_bounds; gint ref_pixels; gboolean result = TRUE; gegl = gegl_node_new (); ref_path = g_build_path (G_DIR_SEPARATOR_S, reference_dir, image, NULL); ref_img = gegl_node_new_child (gegl, "operation", "gegl:load", "path", ref_path, NULL); g_free (ref_path); img = gegl_node_new_child (gegl, "operation", "gegl:load", "path", output_path, NULL); ref_bounds = gegl_node_get_bounding_box (ref_img); comp_bounds = gegl_node_get_bounding_box (img); ref_pixels = ref_bounds.width * ref_bounds.height; if (ref_bounds.width != comp_bounds.width || ref_bounds.height != comp_bounds.height) { g_printf ("FAIL\n Reference and composition differ in size\n"); result = FALSE; } else { GeglNode *comparison; gdouble max_diff; comparison = gegl_node_create_child (gegl, "gegl:image-compare"); gegl_node_link (img, comparison); gegl_node_connect_to (ref_img, "output", comparison, "aux"); gegl_node_process (comparison); gegl_node_get (comparison, "max diff", &max_diff, NULL); if (max_diff < 1.0) { g_printf ("PASS\n"); result = TRUE; } else { GeglNode *output; gchar *diff_path; gdouble avg_diff_wrong, avg_diff_total; gint wrong_pixels; gegl_node_get (comparison, "avg_diff_wrong", &avg_diff_wrong, "avg_diff_total", &avg_diff_total, "wrong_pixels", &wrong_pixels, NULL); g_printf ("FAIL\n Reference image and composition differ\n" " wrong pixels : %i/%i (%2.2f%%)\n" " max Δe : %2.3f\n" " avg Δe : %2.3f (wrong) %2.3f (total)\n", wrong_pixels, ref_pixels, (wrong_pixels * 100.0 / ref_pixels), max_diff, avg_diff_wrong, avg_diff_total); diff_path = operation_to_path (op_name, TRUE); output = gegl_node_new_child (gegl, "operation", "gegl:png-save", "path", diff_path, NULL); gegl_node_link (comparison, output); gegl_node_process (output); g_free (diff_path); result = FALSE; } } g_object_unref (gegl); return result; }
static gboolean process_operations (GType type) { GType *operations; gboolean result = TRUE; guint count; gint i; operations = g_type_children (type, &count); if (!operations) { g_free (operations); return TRUE; } for (i = 0; i < count; i++) { GeglOperationClass *operation_class; const gchar *image, *xml, *name; gboolean matches; operation_class = g_type_class_ref (operations[i]); image = gegl_operation_class_get_key (operation_class, "reference-image"); xml = gegl_operation_class_get_key (operation_class, "reference-composition"); name = gegl_operation_class_get_key (operation_class, "name"); if (name == NULL) { result = result && process_operations (operations[i]); continue; } matches = g_regex_match (regex, name, 0, NULL) && !g_regex_match (exc_regex, name, 0, NULL); if (xml && matches) { GeglNode *composition; if (output_all) g_printf ("%s\n", name); else if (image) g_printf ("%s: ", name); /* more information will follow if we're testing */ composition = gegl_node_new_from_xml (xml, data_dir); if (!composition) { g_printf ("FAIL\n Composition graph is flawed\n"); result = FALSE; } else if (image || output_all) { gchar *output_path = operation_to_path (name, FALSE); GeglNode *output = gegl_node_new_child (composition, "operation", "gegl:png-save", "compression", 9, "path", output_path, NULL); gegl_node_link (composition, output); gegl_node_process (output); g_object_unref (composition); /* don't test if run with --all */ if (!output_all && image) result = test_operation (name, image, output_path) && result; g_free (output_path); } } /* if we are running with --all and the operation doesn't have a composition, use standard composition and images, don't test */ else if (output_all && matches && !(g_type_is_a (operations[i], GEGL_TYPE_OPERATION_SINK) || g_type_is_a (operations[i], GEGL_TYPE_OPERATION_TEMPORAL))) { g_printf ("%s\n", name); standard_output (name); } result = process_operations (operations[i]) && result; } g_free (operations); return result; }
static void standard_output (const gchar *op_name) { GeglNode *composition, *input, *aux, *operation, *crop, *output, *translate; GeglNode *background, *over; gchar *input_path = g_build_path (G_DIR_SEPARATOR_S, data_dir, "standard-input.png", NULL); gchar *aux_path = g_build_path (G_DIR_SEPARATOR_S, data_dir, "standard-aux.png", NULL); gchar *output_path = operation_to_path (op_name, FALSE); composition = gegl_node_new (); operation = gegl_node_create_child (composition, op_name); if (gegl_node_has_pad (operation, "output")) { input = gegl_node_new_child (composition, "operation", "gegl:load", "path", input_path, NULL); translate = gegl_node_new_child (composition, "operation", "gegl:translate", "x", 0.0, "y", 80.0, NULL); aux = gegl_node_new_child (composition, "operation", "gegl:load", "path", aux_path, NULL); crop = gegl_node_new_child (composition, "operation", "gegl:crop", "width", 200.0, "height", 200.0, NULL); output = gegl_node_new_child (composition, "operation", "gegl:png-save", "compression", 9, "path", output_path, NULL); background = gegl_node_new_child (composition, "operation", "gegl:checkerboard", "color1", gegl_color_new ("rgb(0.75,0.75,0.75)"), "color2", gegl_color_new ("rgb(0.25,0.25,0.25)"), NULL); over = gegl_node_new_child (composition, "operation", "gegl:over", NULL); if (gegl_node_has_pad (operation, "input")) gegl_node_link (input, operation); if (gegl_node_has_pad (operation, "aux")) { gegl_node_connect_to (aux, "output", translate, "input"); gegl_node_connect_to (translate, "output", operation, "aux"); } gegl_node_connect_to (background, "output", over, "input"); gegl_node_connect_to (operation, "output", over, "aux"); gegl_node_connect_to (over, "output", crop, "input"); gegl_node_connect_to (crop, "output", output, "input"); gegl_node_process (output); } g_free (input_path); g_free (aux_path); g_free (output_path); g_object_unref (composition); }
gint main (gint argc, gchar **argv) { GList *operations; GList *iter; GHashTable *categories = NULL; gegl_init (&argc, &argv); operations = gegl_operations (); /* Collect categories */ categories = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); for (iter=operations;iter;iter = g_list_next (iter)) { GeglOperationClass *klass = iter->data; const char *categoris = gegl_operation_class_get_key (klass, "categories"); const gchar *ptr = categoris; while (ptr && *ptr) { gchar category[64]=""; gint i=0; while (*ptr && *ptr!=':' && i<63) { category[i++]=*(ptr++); category[i]='\0'; } if (*ptr==':') ptr++; { GList *items = g_hash_table_lookup (categories, category); g_hash_table_insert (categories, g_strdup (category), g_list_append (items, klass)); } } } g_print ("%s", html_top); #if 0 g_print ("<div id='toc'>\n<ul>\n"); g_print ("<li><a href='index.html'>GEGL</a></li><li> </li>\n"); g_print ("<li><a href='index.html#Documentation'>Documentation</a></li>\n"); g_print ("<li><a href='index.html#Glossary'> Glossary</a></li>\n"); g_print ("<li><a href='operations.html#'> Operations</a></li>\n"); g_print ("<li><a href='api.html'> API reference</a></li>\n"); g_print ("<li><a href=''> </a></li>\n"); g_print ("<li><a href='#Categories'>Categories</a></li>\n"); g_print ("<li><a href=''> </a></li>\n"); /*category_menu_item ("All", NULL, NULL); g_hash_table_foreach (categories, category_menu_item, NULL);*/ /*border: 0.1em dashed rgb(210,210,210); */ //category_menu_index("All", operations, NULL); g_print ("</ul>\n</div>\n"); #endif g_print ("<h1>GEGL operation reference</h1>"); g_print ("<p>Image processing operations are shared objects (plug-ins) loaded when GEGL initializes. " "This page is generated from information registered by the plug-ins themselves.</p>" "<a name='Categories'><h2>Categories</h2></a><p>A plug-in can " "belong in multiple categories. Below is indexes broken down into the various available categories.</p>"); category_index ("All", operations, NULL); /* create menus for each of the categories */ g_hash_table_foreach (categories, category_index, NULL); /* list all operations */ g_print ("<table>\n"); for (iter=operations;iter;iter = g_list_next (iter)) { GeglOperationClass *klass = iter->data; const char *categoris = gegl_operation_class_get_key (klass, "categories"); const char *description = gegl_operation_class_get_key (klass, "description"); const char *name = gegl_operation_class_get_key (klass, "name"); if (categoris && strstr (categoris, "hidden")) continue; g_print ("<tr>\n <td colspan='1'> </td>\n <td class='op_name' colspan='4'><a name='op_%s'>%s</a></td>\n</tr>\n", klass->name, klass->name); if (name) { char *image = operation_to_path (name); if (g_file_test (image, G_FILE_TEST_EXISTS)) g_print ("<tr>\n <td colspan='1'> </td>\n <td colspan='4'><img style='float:right;padding-left:1.5em;' src='%s' />", image); else g_print ("<tr>\n <td colspan='1'> </td>\n"); if (description) g_print ("%s\n", description); g_print ("</td></tr>\n"); g_free (image); } else if (description) g_print ("<tr>\n <td colspan='1'> </td>\n <td class='op_description' colspan='4'>%s</td>\n</tr>\n", description); list_properties (G_OBJECT_CLASS_TYPE (klass), 2, TRUE); } g_print ("</table>\n"); g_print ("%s", html_bottom); g_list_free (operations); gegl_exit (); return 0; }