Last active
March 7, 2023 01:04
-
-
Save angstyloop/9e8d808570eab3329471e67b71e01f41 to your computer and use it in GitHub Desktop.
Threshold an image with VIPS and a GTK slider UI.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** threshold_scale.c | |
* | |
* Threshold an image with VIPS and a GTK slider UI. | |
* | |
* COMPILE | |
* | |
* gcc -Wall -o threshold_scale threshold_scale.c `pkg-config vips gtk+-3.0 --cflags --libs` | |
* | |
* EXAMPLE | |
* | |
* ./threshold_scale | |
* | |
*/ | |
#include <vips/vips.h> | |
#include <gtk/gtk.h> | |
// The label text will match the current value of the slider. | |
static gchar label_text[4] = "0"; | |
// Input and output image file paths | |
static gchar* input_image_path = "in.png"; | |
static gchar* output_image_path = "out.png"; | |
// The "value-change" signal handler | |
static void value_changed(GtkRange* range, gpointer window); | |
// The function called to update the image. | |
static void update_image(guint8 threshold); | |
// Define the image widget with a placeholder | |
static GtkWidget* image = NULL; | |
int main (int argc, char** argv) { | |
// Initialize VIPS. | |
if (VIPS_INIT(argv[0])) | |
vips_error_exit(NULL); | |
// Initialize GTK | |
gtk_init(&argc, &argv); | |
// Update the image for the first time, possibly creating it | |
update_image(0); | |
// Initialize the image | |
image = gtk_image_new_from_file("out.png"); | |
// Create the window | |
GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); | |
gtk_window_set_default_size(GTK_WINDOW(window), 250, 50); | |
gtk_window_set_resizable (GTK_WINDOW(window), FALSE); | |
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); | |
// Create the root widget, which contains all the other widgets | |
GtkWidget* root = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 20); | |
// Create the scale widget, a type of range widget. | |
GtkWidget* scale = | |
gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 100, 1); | |
gtk_scale_set_draw_value(GTK_SCALE(scale), FALSE); | |
gtk_widget_set_size_request(scale, 150, -1); | |
// Create label to show current value | |
GtkWidget* label = gtk_label_new("0"); | |
// Pack the image widget, scale widget, and label into the root widget | |
gtk_box_pack_start(GTK_BOX(root), image, FALSE, FALSE, 20); | |
gtk_box_pack_start(GTK_BOX(root), scale, FALSE, FALSE, 0); | |
gtk_box_pack_start(GTK_BOX(root), label, FALSE, FALSE, 20); | |
// Add the root widget to the window | |
gtk_container_add(GTK_CONTAINER(window), root); | |
// Connect signal handlers | |
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); | |
g_signal_connect(scale, "value-changed", G_CALLBACK(value_changed), label); | |
// Show the window | |
gtk_widget_show_all(window); | |
// Start the GTK main loop | |
gtk_main(); | |
return EXIT_SUCCESS; | |
} | |
static void value_changed(GtkRange* range, gpointer window) { | |
guint8 value = gtk_range_get_value(range); | |
value = value < 0 ? 0 : value > 100 ? 100 : value; | |
snprintf(label_text, 4, "%d", value); | |
gtk_label_set_text(GTK_LABEL(window), label_text); | |
update_image(value); | |
} | |
static void update_image(guint8 threshold) { | |
// Hang images off a dummy object, `context` | |
VipsObject* context = (VipsObject*) vips_image_new(); | |
VipsImage** t = (VipsImage**) vips_object_local_array(context, 4); | |
// Threshold the image, producing a binary image with only black (#000) or | |
// white (#FFF) pixels | |
if (!(t[0] = vips_image_new_from_file(input_image_path, | |
"access", VIPS_ACCESS_SEQUENTIAL, NULL)) || | |
vips_colourspace(t[0], &t[1], VIPS_INTERPRETATION_B_W, NULL) || | |
vips_extract_band(t[1], &t[2], 0, "n", 1, NULL) || | |
vips_moreeq_const1(t[2], &t[3], threshold, NULL) || | |
vips_image_write_to_file(t[3], output_image_path, NULL)) { | |
g_object_unref(context); | |
vips_error_exit(NULL); | |
} | |
// Clean up the dummy object and all images. | |
g_object_unref(context); | |
// Update the image widget | |
gtk_image_set_from_file((GtkImage*) image, output_image_path); | |
} |
Author
angstyloop
commented
Mar 7, 2023
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment