diff --git a/kg/25-1/3/.clangd b/kg/25-1/3/.clangd new file mode 100644 index 0000000..863a4f8 --- /dev/null +++ b/kg/25-1/3/.clangd @@ -0,0 +1,4 @@ +CompileFlags: + Add: + - "-isystem" + - "/usr/include/gimp-3.0" diff --git a/kg/25-1/3/.gitignore b/kg/25-1/3/.gitignore new file mode 100644 index 0000000..f10d566 --- /dev/null +++ b/kg/25-1/3/.gitignore @@ -0,0 +1,4 @@ +build +dist +compile_commands.json +.cache diff --git a/kg/25-1/3/Makefile b/kg/25-1/3/Makefile new file mode 100644 index 0000000..849a91a --- /dev/null +++ b/kg/25-1/3/Makefile @@ -0,0 +1,23 @@ +DIRS=dist build $(PLUGIN_DIR) +CXX=clang++ -std=c++23 +NAME=seam_carving +PLUGIN_DIR=$(HOME)/.config/GIMP/3.0/plug-ins/$(NAME) + +all: $(DIRS) $(PLUGIN_DIR)/$(NAME) + +$(PLUGIN_DIR)/$(NAME): dist/plugin + cp $< $@ + +dist/plugin: build/plugin.o + $(CXX) $< -o $@ $(shell pkg-config --libs gimp-3.0 gimpui-3.0 gegl-0.4) + chmod +x $@ + +build/plugin.o: plugin.cpp + $(CXX) -c $< -o $@ $(shell pkg-config --cflags gimp-3.0 gimpui-3.0 gegl-0.4) + +clean: + rm -rf $(DIRS) + rm compile_commands.json + +$(DIRS): + mkdir -p $@ diff --git a/kg/25-1/3/README.docx b/kg/25-1/3/README.docx new file mode 100644 index 0000000..f517ac2 Binary files /dev/null and b/kg/25-1/3/README.docx differ diff --git a/kg/25-1/3/plugin.cpp b/kg/25-1/3/plugin.cpp new file mode 100644 index 0000000..e195126 --- /dev/null +++ b/kg/25-1/3/plugin.cpp @@ -0,0 +1,125 @@ +#include "gtk/gtk.h" +#include +#include +#include +#include +#include + +#define PLUG_IN_PROC "plug-in-seam-carving" +#define PLUG_IN_BINARY "seam_carving" + +struct _Plugin { + GimpPlugIn parent_instance; +}; + +#define PLUGIN_TYPE (plugin_get_type()) +G_DECLARE_FINAL_TYPE(Plugin, plugin, plugin, , GimpPlugIn) + +static GList *plugin_query_procedures(GimpPlugIn *plug_in); +static GimpProcedure *plugin_create_procedure(GimpPlugIn *plug_in, + const gchar *name); + +static GimpValueArray *plugin_run(GimpProcedure *procedure, + GimpRunMode run_mode, GimpImage *image, + GimpDrawable **drawables, + GimpProcedureConfig *config, + gpointer run_data); + +G_DEFINE_TYPE(Plugin, plugin, GIMP_TYPE_PLUG_IN) + +static void plugin_class_init(PluginClass *klass) { + GimpPlugInClass *plug_in_class = GIMP_PLUG_IN_CLASS(klass); + + plug_in_class->query_procedures = plugin_query_procedures; + plug_in_class->create_procedure = plugin_create_procedure; +} + +static void plugin_init(Plugin *plugin) {} + +static GList *plugin_query_procedures(GimpPlugIn *plug_in) { + return g_list_append(NULL, g_strdup(PLUG_IN_PROC)); +} + +static GimpProcedure *plugin_create_procedure(GimpPlugIn *plug_in, + const gchar *name) { + GimpProcedure *procedure = NULL; + + if (g_strcmp0(name, PLUG_IN_PROC) == 0) { + procedure = gimp_image_procedure_new( + plug_in, name, GIMP_PDB_PROC_TYPE_PLUGIN, plugin_run, NULL, NULL); + gimp_procedure_set_sensitivity_mask(procedure, + GIMP_PROCEDURE_SENSITIVE_DRAWABLE); + gimp_procedure_set_menu_label(procedure, "_Seam carving"); + gimp_procedure_add_menu_path(procedure, "/Filters/"); + gimp_procedure_set_documentation(procedure, "Intelligent image resizing", + NULL, NULL); + gimp_procedure_set_attribution(procedure, "Vlad Litvinov ", + "LGPL-3.0", "2025"); + gimp_procedure_add_int_argument(procedure, "blur-factor", "Blur factor", + NULL, 0, 100, 20, G_PARAM_READWRITE); + gimp_procedure_add_int_argument(procedure, "horizontal-resize", + "Horizontal resize", NULL, 0, 100, 50, + G_PARAM_READWRITE); + } + + return procedure; +} + +static GimpValueArray *plugin_run(GimpProcedure *procedure, + GimpRunMode run_mode, GimpImage *image, + GimpDrawable **drawables, + GimpProcedureConfig *config, + gpointer run_data) { + + gint blur_factor, horizontal_resize; + g_object_get(config, "blur-factor", &blur_factor, "horizontal-resize", + &horizontal_resize, NULL); + + if (run_mode == GIMP_RUN_INTERACTIVE) { + GtkWidget *dialog, *area, *label_bf, *label_hr, *scale_bf, *scale_hr; + + gimp_ui_init(PLUG_IN_BINARY); + + dialog = gtk_dialog_new_with_buttons("Seam carving", NULL, GTK_DIALOG_MODAL, + "_Ok", GTK_RESPONSE_OK, "_Cancel", + GTK_RESPONSE_CANCEL, NULL); + gtk_window_set_resizable(GTK_WINDOW(dialog), false); + + area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + gtk_widget_set_margin_start(area, 12); + gtk_widget_set_margin_end(area, 12); + gtk_widget_set_margin_top(area, 12); + + scale_bf = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 100, 1); + scale_hr = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 100, 1); + + gtk_range_set_value(GTK_RANGE(scale_bf), blur_factor); + gtk_range_set_value(GTK_RANGE(scale_hr), horizontal_resize); + + label_bf = gtk_label_new("Blur factor"); + label_hr = gtk_label_new("Horizontal resize"); + + gtk_box_pack_end(GTK_BOX(area), scale_hr, FALSE, FALSE, 0); + gtk_box_pack_end(GTK_BOX(area), label_hr, FALSE, FALSE, 0); + gtk_box_pack_end(GTK_BOX(area), scale_bf, FALSE, FALSE, 0); + gtk_box_pack_end(GTK_BOX(area), label_bf, FALSE, FALSE, 0); + + gtk_widget_show_all(dialog); + + gint response = gtk_dialog_run(GTK_DIALOG(dialog)); + + switch (response) { + case GTK_RESPONSE_OK: + blur_factor = gtk_range_get_value(GTK_RANGE(scale_bf)); + horizontal_resize = gtk_range_get_value(GTK_RANGE(scale_hr)); + break; + + default: + return gimp_procedure_new_return_values(procedure, GIMP_PDB_CANCEL, NULL); + } + } + + return gimp_procedure_new_return_values(procedure, GIMP_PDB_SUCCESS, NULL); +} + +GIMP_MAIN(PLUGIN_TYPE)