/* * blur-mask 1.00 -- image filter plug-in for The GIMP. * * Copyright (C) 1995 Spencer Kimball and Peter Mattis * Copyright (C) 1996 Torsten Martinsen * Copyright (C) 1996 Marc Bless * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "gimp.h" #include /* * This filter is based on 'blur2' by Torsten Martinsen, * which is like the standard 'blur', except that it uses * a convolution kernel of variable size. * * Define areas with different blur depths by selecting a mask. * * TODO: * - minimum kernelsize (scale) * - invert mask * - auto apply */ static void blur_mask (Image, Image, Image); static int kernelsize = 3; static int dialog_ID; static void image_menu_callback (int, void *, void *); static void scale_callback (int, void *, void *); static void ok_callback (int, void *, void *); static void cancel_callback (int, void *, void *); int main (int argc, char **argv) { Image input = 0, output = 0, mask = 0; void *data; char msg[25]; int group_ID; int scaler_ID; int mask_menu_ID; int mask_ID; if (!gimp_init (argc, argv)) exit (0); if (!(input = gimp_get_input_image (0))) { gimp_quit (); exit (0); } if (!(output = gimp_get_output_image (0))) { gimp_free_image (input); gimp_quit (); exit (0); } if ((gimp_image_type (input) == RGB_IMAGE) || (gimp_image_type (input) == GRAY_IMAGE)) { data = gimp_get_params (); if (data) kernelsize = ((int *) data)[0]; dialog_ID = gimp_new_dialog ("Blur-Mask"); group_ID = gimp_new_row_group (dialog_ID, DEFAULT, NORMAL, ""); scaler_ID = gimp_new_scale (dialog_ID, group_ID, 3, 25, kernelsize, 0); mask_menu_ID = gimp_new_image_menu (dialog_ID, group_ID, IMAGE_CONSTRAIN_RGB || IMAGE_CONSTRAIN_GRAY, "Mask"); gimp_add_callback (dialog_ID, mask_menu_ID, image_menu_callback, &mask_ID); gimp_add_callback (dialog_ID, scaler_ID, scale_callback, &kernelsize); gimp_add_callback (dialog_ID, gimp_ok_item_id(dialog_ID), ok_callback, 0); gimp_add_callback (dialog_ID, gimp_cancel_item_id(dialog_ID), cancel_callback, 0); if (gimp_show_dialog (dialog_ID)) { gimp_set_params (sizeof (int), &kernelsize); sprintf (msg, "Blur-Mask (size %d)", kernelsize); mask = gimp_get_input_image (mask_ID); if (mask) { gimp_init_progress (msg); blur_mask (input, output, mask); gimp_update_image (output); } } } else gimp_message ("blur-mask: cannot operate on indexed color images"); gimp_free_image (input); gimp_free_image (output); gimp_quit (); return 0; } static void blur_mask (Image input, Image output, Image mask) { long width, height; long channels, rowstride, chmask; unsigned char *src; unsigned char *dest; unsigned char *dest_row; unsigned char *pmask; unsigned char *p; int x, y, r, g, b, sum, xx, yy, xv, yv, n; int x1, y1, x2, y2; gimp_image_area (input, &x1, &y1, &x2, &y2); width = gimp_image_width(input); height = gimp_image_height(input); channels = gimp_image_channels(input); rowstride = width * channels; pmask = gimp_image_data (mask); chmask = gimp_image_channels (mask); src = gimp_image_data(input); dest_row = gimp_image_data(output); dest_row += rowstride * y1 + x1 * channels; for (y = y1; y < y2; y++) { dest = dest_row; for (x = x1; x < x2; x++) { n = (kernelsize * *pmask / 255) / 2; /* if (!n) n++; */ pmask += chmask; r = g = b = 0; sum = 0; for (yy = -n; yy <= n; yy++) { for (xx = -n; xx <= n; xx++) { xv = x + xx; yv = y + yy; if (xv < x1 || yv < y1) continue; if (xv >= x2 || yv >= y2) continue; p = src + yv * rowstride + xv * channels; r += *p++; if (channels > 1) { g += *p++; b += *p; } ++sum; } } *dest++ = r/sum; if (channels > 1) { *dest++ = g/sum; *dest++ = b/sum; } } dest_row += rowstride; if ((y % 5) == 0) gimp_do_progress(y, y2 - y1); } } static void image_menu_callback (int item_ID, void *client_data, void *call_data) { *((long*) client_data) = *((long*) call_data); } static void scale_callback (int item_ID, void *client_data, void *call_data) { int n; n = *((long *) call_data); *((int *) client_data) = n | 1; } static void ok_callback (int item_ID, void *client_data, void *call_data) { gimp_close_dialog (dialog_ID, 1); } static void cancel_callback (int item_ID, void *client_data, void *call_data) { gimp_close_dialog (dialog_ID, 0); }