-Yosh
This commit is contained in:
Manish Singh 1999-06-23 06:08:23 +00:00
parent 650aae34c6
commit 780b221fcc
340 changed files with 0 additions and 107626 deletions

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
CEL

View file

@ -1,517 +0,0 @@
/* cel.c -- KISS CEL file format plug-in for The GIMP
* (copyright) 1997,1998 Nick Lamb (njl195@zepler.org.uk)
*
* Skeleton cloned from Michael Sweet's PNG plug-in. KISS format courtesy
* of the KISS/GS documentation. Problem reports to the above address
*/
/* History:
* 0.1 Very limited functionality (modern 4bit only)
* 0.2 Default palette (nice yellows) is automatically used
* 0.3 Support for the older (pre KISS/GS) cell format
* 0.4 First support for saving images
* 0.5 Show copyright date, not version number, thanks to DbBrowser
* 0.6 File dialogs, palette handling, better magic behaviour
* 0.7 Handle interactivity settings, tidy up
* 1.0 Fixed for GIMP 0.99.27 running on GTK+ 1.0.0, and released
* 1.1 Oops, #include unistd.h, thanks Tamito Kajiyama
* 1.2 Changed email address, tidied up
* 1.3 Added g_message features, fixed Saving bugs...
* 1.4 Offsets work (needed them for a nice example set)
*
* Possible future additions:
* + Save (perhaps optionally?) the palette in a KCF
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
static void query(void);
static void run(char *name, int nparams, GParam *param,
int *nreturn_vals, GParam **return_vals);
static gint load_palette(FILE *fp, guchar palette[]);
static gint32 load_image(char *file, char *brief);
static gint save_image(char *file, char *brief,
gint32 image, gint32 layer);
static gint palette_dialog(char *title);
/* Globals... */
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
char *palette_file= NULL;
size_t data_length= 0;
/* Let GIMP library handle initialisation (and inquisitive users) */
MAIN()
/* GIMP queries plug-in for parameters etc. */
static void query(void) {
static GParamDef load_args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_STRING, "filename", "Filename to load image from" },
{ PARAM_STRING, "raw_filename", "Name entered" },
{ PARAM_STRING, "palette_filename", "Filename to load palette from" },
};
static GParamDef load_return_vals[] =
{
{ PARAM_IMAGE, "image", "Output image" },
};
static int nload_args = sizeof (load_args) / sizeof (load_args[0]);
static int nload_return_vals = sizeof (load_return_vals) / sizeof (load_return_vals[0]);
static GParamDef save_args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image" },
{ PARAM_DRAWABLE, "drawable", "Drawable to save" },
{ PARAM_STRING, "filename", "Filename to save image to" },
{ PARAM_STRING, "raw_filename", "Name entered" },
{ PARAM_STRING, "palette_filename", "Filename to save palette to" },
};
static int nsave_args = sizeof (save_args) / sizeof (save_args[0]);
gimp_install_procedure("file_cel_load",
"Loads files in KISS CEL file format",
"This plug-in loads individual KISS cell files.",
"Nick Lamb", "Nick Lamb <njl195@zepler.org.uk>", "May 1998",
"<Load>/CEL", NULL, PROC_PLUG_IN,
nload_args, nload_return_vals, load_args, load_return_vals);
gimp_register_magic_load_handler("file_cel_load", "cel",
"", "0,string,KiSS\040");
gimp_install_procedure("file_cel_save",
"Saves files in KISS CEL file format",
"This plug-in saves individual KISS cell files.",
"Nick Lamb", "Nick Lamb <njl195@zepler.org.uk>", "May 1998",
"<Save>/CEL", "INDEXEDA",
PROC_PLUG_IN, nsave_args, 0, save_args, NULL);
gimp_register_save_handler("file_cel_save", "cel", "");
}
static void run(char *name, int nparams, GParam *param,
int *nreturn_vals, GParam **return_vals) {
gint32 image; /* image ID after load */
gint status; /* status after save */
static GParam values[2]; /* Return values */
GRunModeType run_mode;
run_mode = param[0].data.d_int32;
/* Set up default return values */
*nreturn_vals = 1;
values[0].type = PARAM_STATUS;
values[0].data.d_status = STATUS_SUCCESS;
*return_vals = values;
if (strcmp(name, "file_cel_load") == 0) {
if (run_mode != RUN_NONINTERACTIVE) {
gimp_get_data ("file_cel_save:length", &data_length);
if (data_length > 0) {
palette_file= (char *) g_malloc(data_length);
gimp_get_data ("file_cel_save:data", palette_file);
} else {
palette_file= g_strdup("*.kcf");
data_length= strlen(palette_file) + 1;
}
}
if (run_mode == RUN_NONINTERACTIVE) {
palette_file= param[3].data.d_string;
data_length= strlen(palette_file) + 1;
} else if (run_mode == RUN_INTERACTIVE) {
/* Let user choose KCF palette (cancel ignores) */
palette_dialog("Load KISS Palette");
gimp_set_data ("file_cel_save:length", &data_length, sizeof (size_t));
gimp_set_data ("file_cel_save:data", palette_file, data_length);
}
image = load_image(param[1].data.d_string, param[2].data.d_string);
if (image != -1) {
*nreturn_vals = 2;
values[1].type = PARAM_IMAGE;
values[1].data.d_image = image;
} else {
values[0].data.d_status = STATUS_EXECUTION_ERROR;
}
} else if (strcmp (name, "file_cel_save") == 0) {
status = save_image(param[3].data.d_string, param[4].data.d_string,
param[1].data.d_int32, param[2].data.d_int32);
if (status != TRUE) {
values[0].data.d_status = STATUS_EXECUTION_ERROR;
} else {
gimp_set_data ("file_cel_save:length", &data_length, sizeof (size_t));
gimp_set_data ("file_cel_save:data", palette_file, data_length);
}
} else {
values[0].data.d_status = STATUS_EXECUTION_ERROR;
}
}
/* Load CEL image into The GIMP */
static gint32 load_image(char *file, char *brief) {
FILE* fp; /* Read file pointer */
char *progress; /* Title for progress display */
guchar header[32]; /* File header */
int height, width, /* Dimensions of image */
offx, offy, /* Layer offets */
colours; /* Number of colours */
gint32 image, /* Image */
layer; /* Layer */
guchar *palette, /* 24 bit palette */
*buffer, /* Temporary buffer */
*line; /* Pixel data */
GDrawable *drawable; /* Drawable for layer */
GPixelRgn pixel_rgn; /* Pixel region for layer */
int i, j, k; /* Counters */
/* Open the file for reading */
fp = fopen(file, "r");
if (fp == NULL) {
g_message("%s\nis not present or is unreadable", file);
gimp_quit();
}
progress= g_malloc(strlen(brief) + 10);
sprintf(progress, "Loading %s:", brief);
gimp_progress_init(progress);
/* Get the image dimensions and create the image... */
fread(header, 4, 1, fp);
if (strncmp(header, "KiSS", 4)) {
colours= 16;
width= header[0] + (256 * header[1]);
height= header[2] + (256 * header[3]);
offx= 0;
offy= 0;
} else { /* New-style image file, read full header */
fread(header, 28, 1, fp);
colours= (1 << header[1]);
width= header[4] + (256 * header[5]);
height= header[6] + (256 * header[7]);
offx= header[8] + (256 * header[9]);
offy= header[10] + (256 * header[11]);
}
image = gimp_image_new(width + offx, height + offy, INDEXED);
if (image == -1) {
g_message("CEL Can't create a new image");
gimp_quit();
}
gimp_image_set_filename(image, file);
/* Create an indexed-alpha layer to hold the image... */
layer = gimp_layer_new(image, "Background", width, height,
INDEXEDA_IMAGE, 100, NORMAL_MODE);
gimp_image_add_layer(image, layer, 0);
gimp_layer_set_offsets(layer, offx, offy);
/* Get the drawable and set the pixel region for our load... */
drawable = gimp_drawable_get(layer);
gimp_pixel_rgn_init(&pixel_rgn, drawable, 0, 0, drawable->width,
drawable->height, TRUE, FALSE);
/* Read the image in and give it to the GIMP a line at a time */
buffer = g_new(guchar, width);
line = g_new(guchar, (width+1) * 2);
for (i = 0; i < height && !feof(fp); ++i) {
switch (colours) {
case 16:
fread(buffer, (width+1)/2, 1, fp);
for (j = 0, k = 0; j < width*2; j+= 4, ++k) {
if (buffer[k] / 16 == 0) {
line[j]= 16;
line[j+1]= 0;
} else {
line[j]= (buffer[k] / 16) - 1;
line[j+1]= 255;
}
if (buffer[k] % 16 == 0) {
line[j+2]= 16;
line[j+3]= 0;
} else {
line[j+2]= (buffer[k] % 16) - 1;
line[j+3]= 255;
}
}
break;
case 256:
fread(buffer, width, 1, fp);
for (j = 0, k = 0; j < width*2; j+= 2, ++k) {
if (buffer[k] == 0) {
line[j]= 255;
line[j+1]= 0;
} else {
line[j]= buffer[k] - 1;
line[j+1]= 255;
}
}
break;
default:
g_message("Unsupported number of colours (%d)", colours);
gimp_quit();
}
gimp_pixel_rgn_set_rect(&pixel_rgn, line, 0, i, drawable->width, 1);
gimp_progress_update((float) i / (float) height);
}
/* Close image files, give back allocated memory */
fclose(fp);
g_free(buffer);
g_free(line);
/* Use palette from file or otherwise default grey palette */
palette = g_new(guchar, colours*3);
/* Open the file for reading if user picked one */
if (palette_file == NULL) {
fp= NULL;
} else {
fp = fopen(palette_file, "r");
}
if (fp != NULL) {
colours= load_palette(fp, palette);
} else {
for (i= 0; i < colours; ++i) {
palette[i*3]= palette[i*3+1]= palette[i*3+2]= i * 256 / colours;
}
}
gimp_image_set_cmap(image, palette + 3, colours - 1);
/* Close palette file, give back allocated memory */
fclose(fp);
g_free(palette);
/* Now get everything redrawn and hand back the finished image */
gimp_drawable_flush(drawable);
gimp_drawable_detach(drawable);
return (image);
}
static gint load_palette(FILE *fp, guchar palette[]) {
guchar header[32]; /* File header */
guchar buffer[2];
int i, bpp, colours= 0;
fread(header, 4, 1, fp);
if (!strncmp(header, "KiSS", 4)) {
fread(header+4, 28, 1, fp);
bpp= header[5];
colours= header[8] + header[9] * 256;
if (bpp == 12) {
for (i= 0; i < colours; ++i) {
fread(buffer, 1, 2, fp);
palette[i*3]= buffer[0] & 0xf0;
palette[i*3+1]= (buffer[1] & 0x0f) * 16;
palette[i*3+2]= (buffer[0] & 0x0f) * 16;
}
} else {
fread(palette, colours, 3, fp);
}
} else {
colours= 16; bpp= 12;
fseek(fp, 0, SEEK_SET);
for (i= 0; i < colours; ++i) {
fread(buffer, 1, 2, fp);
palette[i*3]= buffer[0] & 0xf0;
palette[i*3+1]= (buffer[1] & 0x0f) * 16;
palette[i*3+2]= (buffer[0] & 0x0f) * 16;
}
}
return colours;
}
static gint save_image(char *file, char *brief, gint32 image, gint32 layer) {
FILE* fp; /* Write file pointer */
char *progress; /* Title for progress display */
guchar header[32]; /* File header */
gint colours, type, /* Number of colours, type of layer */
offx, offy; /* Layer offsets */
guchar *buffer, /* Temporary buffer */
*line; /* Pixel data */
GDrawable *drawable; /* Drawable for layer */
GPixelRgn pixel_rgn; /* Pixel region for layer */
int i, j, k; /* Counters */
/* Check that this is an indexed image, fail otherwise */
type= gimp_drawable_type(layer);
if (type != INDEXEDA_IMAGE) {
g_message("Only an indexed-alpha image can be saved in CEL format");
gimp_quit();
}
/* Find out how offset this layer was */
gimp_drawable_offsets(layer, &offx, &offy);
drawable = gimp_drawable_get(layer);
/* Open the file for writing */
fp = fopen(file, "w");
if (fp == NULL) {
g_message("CEL Couldn't write image to\n%s", file);
gimp_quit();
}
progress= g_malloc(strlen(brief) + 9);
sprintf(progress, "Saving %s:", brief);
gimp_progress_init(progress);
/* Headers */
memset(header, 0, 32);
strcpy(header, "KiSS");
header[4]= 0x20;
/* Work out whether to save as 8bit or 4bit */
gimp_image_get_cmap(image, &colours);
if (colours > 15) {
header[5]= 8;
} else {
header[5]= 4;
}
/* Fill in the blanks ... */
header[8]= drawable->width % 256;
header[9]= drawable->width / 256;
header[10]= drawable->height % 256;
header[11]= drawable->height / 256;
header[12]= offx % 256;
header[13]= offx / 256;
header[14]= offy % 256;
header[15]= offy / 256;
fwrite(header, 32, 1, fp);
/* Arrange for memory etc. */
gimp_pixel_rgn_init(&pixel_rgn, drawable, 0, 0, drawable->width,
drawable->height, TRUE, FALSE);
buffer = g_new(guchar, drawable->width);
line = g_new(guchar, (drawable->width+1) * 2);
/* Get the image from the GIMP one line at a time and write it out */
for (i = 0; i < drawable->height; ++i) {
gimp_pixel_rgn_get_rect(&pixel_rgn, line, 0, i, drawable->width, 1);
memset(buffer, 0, drawable->width);
if (colours > 16) {
for (j = 0, k = 0; j < drawable->width*2; j+= 2, ++k) {
if (line[j+1] > 127) {
buffer[k]= line[j] + 1;
}
}
fwrite(buffer, drawable->width, 1, fp);
} else {
for (j = 0, k = 0; j < drawable->width*2; j+= 4, ++k) {
buffer[k]= 0;
if (line[j+1] > 127) {
buffer[k]+= (line[j] + 1)<< 4;
}
if (line[j+3] > 127) {
buffer[k]+= (line[j+2] + 1);
}
}
fwrite(buffer, (drawable->width+1)/2, 1, fp);
}
gimp_progress_update((float) i / (float) drawable->height);
}
/* Close files, give back allocated memory */
fclose(fp);
g_free(buffer);
g_free(line);
return TRUE;
}
static void palette_ok (GtkWidget *widget, GtkWidget **fs) {
g_free(palette_file);
palette_file= g_strdup(gtk_file_selection_get_filename
(GTK_FILE_SELECTION(fs)));
data_length= strlen(palette_file) + 1;
gtk_widget_destroy (GTK_WIDGET (fs));
}
static void palette_cancel (GtkWidget *widget, GtkWidget **window) {
gtk_main_quit ();
}
static gint palette_dialog(char *title) {
gchar **argv;
gint argc = 1;
GtkWidget *dialog;
argv= g_malloc(sizeof(gchar *));
argv[0]= g_strdup("CEL file-filter");
gtk_init (&argc, &argv);
gtk_rc_parse (gimp_gtkrc ());
dialog= gtk_file_selection_new(title);
gtk_window_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
gtk_file_selection_set_filename(GTK_FILE_SELECTION(dialog), palette_file);
gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (dialog)->ok_button),
"clicked", (GtkSignalFunc) palette_ok, dialog);
gtk_signal_connect (GTK_OBJECT (dialog),
"destroy", (GtkSignalFunc) palette_cancel, NULL);
gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (dialog)->cancel_button), "clicked", (GtkSignalFunc) palette_cancel, GTK_OBJECT (dialog));
gtk_widget_show(dialog);
gtk_main ();
gdk_flush ();
return 0;
}

View file

@ -1,39 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = CEL
CEL_SOURCES = \
CEL.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
CEL_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
CML_explorer

File diff suppressed because it is too large Load diff

View file

@ -1,39 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = CML_explorer
CML_explorer_SOURCES = \
CML_explorer.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
CML_explorer_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
aa

View file

@ -1,37 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = aa
aa_SOURCES = \
aa.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
@LIBAA_LIB@ \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
aa_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,367 +0,0 @@
/**
* aa.c version 1.0
* A plugin that uses libaa (ftp://ftp.ta.jcu.cz/pub/aa) to save images as
* ASCII.
* NOTE: This plugin *requires* aalib 1.2 or later. Earlier versions will
* not work.
* Code copied from all over the GIMP source.
* Tim Newsome <nuisance@cmu.edu>
*/
#include <aalib.h>
#include <string.h>
#include <libgimp/gimp.h>
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
/*
* Declare some local functions.
*/
static void query(void);
static void run(char *name, int nparams, GParam * param, int *nreturn_vals,
GParam ** return_vals);
static gint aa_savable(gint32 drawable_ID);
static gint save_aa(int output_type, char *filename, gint32 image,
gint32 drawable);
static gint gimp2aa(gint32 image, gint32 drawable_ID, aa_context * context);
static gint type_dialog(int selected);
static void type_dialog_close_callback(GtkWidget *widget, gpointer data);
static void type_dialog_ok_callback (GtkWidget *widget, gpointer data);
static void type_dialog_toggle_update (GtkWidget *widget, gpointer data);
static void type_dialog_cancel_callback (GtkWidget *widget, gpointer data);
/*
* Some global variables.
*/
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
/**
* Type the user selected. (Global for easier UI coding.
*/
static int selected_type = 0;
MAIN()
/**
* Called by the GIMP to figure out what this plugin does.
*/
static void query()
{
static GParamDef save_args[] =
{
{PARAM_INT32, "run_mode", "Interactive, non-interactive"},
{PARAM_IMAGE, "image", "Input image"},
{PARAM_DRAWABLE, "drawable", "Drawable to save"},
{PARAM_STRING, "filename", "The name of the file to save the image in"},
{PARAM_STRING, "raw_filename", "The name entered"},
{PARAM_STRING, "file_type", "File type to use"}
};
static int nsave_args = sizeof(save_args) / sizeof(save_args[0]);
gimp_install_procedure("file_aa_save",
"Saves files in various text formats",
"Saves files in various text formats",
"Tim Newsome <nuisance@cmu.edu>",
"Tim Newsome <nuisance@cmu.edu>",
"1997",
"<Save>/AA",
"GRAY*", /* support grayscales */
PROC_PLUG_IN,
nsave_args, 0,
save_args, NULL);
gimp_register_save_handler("file_aa_save", "ansi,txt,text,html", "");
}
/**
* Searches aa_formats defined by aalib to find the index of the type
* specified by string.
* -1 means it wasn't found.
*/
static int get_type_from_string(char *string)
{
int type = 0;
aa_format **p = aa_formats;
while (*p && strcmp((*p)->formatname, string)) {
p++;
type++;
}
if (*p == NULL)
return -1;
return type;
}
/**
* Called by the GIMP to run the actual plugin.
*/
static void run(char *name, int nparams, GParam * param, int *nreturn_vals,
GParam ** return_vals)
{
static GParam values[2];
GStatusType status = STATUS_SUCCESS;
GRunModeType run_mode;
int output_type = 0;
static int last_type = 0;
/* Set us up to return a status. */
*nreturn_vals = 1;
*return_vals = values;
values[0].type = PARAM_STATUS;
values[0].data.d_status = STATUS_CALLING_ERROR;
if (!aa_savable(param[2].data.d_int32)) {
values[0].data.d_status = STATUS_CALLING_ERROR;
return;
}
run_mode = param[0].data.d_int32;
switch (run_mode) {
case RUN_INTERACTIVE:
gimp_get_data("file_aa_save", &last_type);
output_type = type_dialog(last_type);
break;
case RUN_NONINTERACTIVE:
/* Make sure all the arguments are there! */
if (nparams != 6)
status = STATUS_CALLING_ERROR;
else
output_type = get_type_from_string(param[5].data.d_string);
break;
case RUN_WITH_LAST_VALS:
gimp_get_data("file_aa_save", &last_type);
output_type = last_type;
break;
default:
break;
}
if (output_type < 0) {
status = STATUS_CALLING_ERROR;
return;
}
if (save_aa(output_type, param[3].data.d_string, param[1].data.d_int32,
param[2].data.d_int32))
values[0].data.d_status = STATUS_EXECUTION_ERROR;
else
values[0].data.d_status = STATUS_SUCCESS;
last_type = output_type;
gimp_set_data("file_aa_save", &last_type, sizeof(last_type));
}
/**
* The actual save function. What it's all about.
* The image type has to be GRAY.
*/
static gint save_aa(int output_type, char *filename, gint32 image,
gint32 drawable_ID)
{
aa_savedata savedata =
{NULL, NULL};
aa_context *context = NULL;
aa_format format;
GDrawable *drawable = NULL;
/*fprintf(stderr, "save %s\n", filename); */
drawable = gimp_drawable_get(drawable_ID);
memcpy(&format, aa_formats[output_type], sizeof(format));
format.width = drawable->width / 2;
format.height = drawable->height / 2;
/*fprintf(stderr, "save_aa %i x %i\n", format.width, format.height); */
/* Get a libaa context which will save its output to filename. */
savedata.name = filename;
savedata.format = &format;
context = aa_init(&save_d, &aa_defparams, &savedata);
if (context == NULL)
return 1;
gimp2aa(image, drawable_ID, context);
aa_flush(context);
aa_close(context);
/*fprintf(stderr, "Success!\n"); */
return 0;
}
static gint gimp2aa(gint32 image, gint32 drawable_ID, aa_context * context)
{
int width, height, x, y;
guchar *buffer;
GDrawable *drawable = NULL;
GPixelRgn pixel_rgn;
aa_renderparams *renderparams = NULL;
int bpp;
width = aa_imgwidth(context);
height = aa_imgheight(context);
/*fprintf(stderr, "gimp2aa %i x %i\n", width, height); */
drawable = gimp_drawable_get(drawable_ID);
bpp = drawable->bpp;
buffer = g_new(guchar, width * bpp);
if (buffer == NULL)
return 1;
gimp_pixel_rgn_init(&pixel_rgn, drawable, 0, 0, drawable->width,
drawable->height, FALSE, FALSE);
for (y = 0; y < height; y++) {
gimp_pixel_rgn_get_row(&pixel_rgn, buffer, 0, y, width);
for (x = 0; x < width; x++) {
/* Just copy one byte. If it's indexed that's all we need. Otherwise
* it'll be the most significant one. */
aa_putpixel(context, x, y, buffer[x * bpp]);
}
}
renderparams = aa_getrenderparams();
renderparams->dither = AA_FLOYD_S;
aa_render(context, renderparams, 0, 0, aa_scrwidth(context),
aa_scrheight(context));
return 0;
}
static gint aa_savable(gint32 drawable_ID)
{
GDrawableType drawable_type;
drawable_type = gimp_drawable_type(drawable_ID);
if (drawable_type != GRAY_IMAGE && drawable_type != GRAYA_IMAGE)
return 0;
return 1;
}
/*
* User Interface dialog thingie.
*/
static gint type_dialog(int selected) {
GtkWidget *dlg;
GtkWidget *button;
GtkWidget *toggle;
GtkWidget *frame;
GtkWidget *toggle_vbox;
GSList *group;
gchar **argv;
gint argc;
argc = 1;
argv = g_new(gchar *, 1);
argv[0] = g_strdup("save");
gtk_init(&argc, &argv);
gtk_rc_parse(gimp_gtkrc());
/* Create the actual window. */
dlg = gtk_dialog_new();
gtk_window_set_title(GTK_WINDOW(dlg), "Save as text");
gtk_window_position(GTK_WINDOW(dlg), GTK_WIN_POS_MOUSE);
gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
(GtkSignalFunc) type_dialog_close_callback, NULL);
/* Action area */
button = gtk_button_new_with_label("OK");
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
(GtkSignalFunc) type_dialog_ok_callback, dlg);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area), button,
TRUE, TRUE, 0);
gtk_widget_grab_default(button);
gtk_widget_show(button);
button = gtk_button_new_with_label("Cancel");
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
(GtkSignalFunc) type_dialog_cancel_callback,
GTK_OBJECT(dlg));
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area), button,
TRUE, TRUE, 0);
gtk_widget_show(button);
/* file save type */
frame = gtk_frame_new("Data Formatting");
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width(GTK_CONTAINER(frame), 10);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), frame, FALSE, TRUE, 0);
toggle_vbox = gtk_vbox_new(FALSE, 5);
gtk_container_border_width(GTK_CONTAINER(toggle_vbox), 5);
gtk_container_add(GTK_CONTAINER(frame), toggle_vbox);
group = NULL;
{
aa_format **p = aa_formats;
int current = 0;
while (*p != NULL) {
toggle = gtk_radio_button_new_with_label(group, (*p)->formatname);
group = gtk_radio_button_group(GTK_RADIO_BUTTON(toggle));
gtk_box_pack_start (GTK_BOX (toggle_vbox), toggle, FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(toggle), "toggled",
(GtkSignalFunc) type_dialog_toggle_update,
(*p)->formatname);
if (current == selected)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), 1);
else
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), 0);
gtk_widget_show(toggle);
p++;
current++;
}
}
gtk_widget_show(toggle_vbox);
gtk_widget_show(frame);
gtk_widget_show(dlg);
gtk_main();
gdk_flush();
return selected_type;
}
/*
* Callbacks for the dialog.
*/
static void type_dialog_close_callback(GtkWidget *widget, gpointer data) {
gtk_main_quit();
}
static void type_dialog_ok_callback (GtkWidget *widget, gpointer data) {
gtk_widget_destroy (GTK_WIDGET (data));
}
static void type_dialog_cancel_callback (GtkWidget *widget, gpointer data) {
selected_type = -1;
gtk_widget_destroy (GTK_WIDGET (data));
}
static void type_dialog_toggle_update (GtkWidget *widget, gpointer data) {
selected_type = get_type_from_string((char *)data);
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
align_layers

View file

@ -1,36 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = align_layers
align_layers_SOURCES = \
align_layers.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
align_layers_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
animationplay

View file

@ -1,36 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = animationplay
animationplay_SOURCES = \
animationplay.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
animationplay_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
animoptimize

View file

@ -1,36 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = animoptimize
animoptimize_SOURCES = \
animoptimize.c
INCLUDES = \
-I$(top_srcdir) \
$(GLIB_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GLIB_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
animoptimize_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,860 +0,0 @@
/*
* Animation Optimizer plug-in version 1.0.0
*
* by Adam D. Moss, 1997-98
* adam@gimp.org
* adam@foxbox.org
*
* This is part of the GIMP package and falls under the GPL.
*/
/*
* REVISION HISTORY:
*
* 98.05.17 : version 1.0.0
* Finally preserves frame timings / layer names. Has
* a progress bar now. No longer beta, I suppose.
*
* 98.04.19 : version 0.70.0
* Plug-in doubles up as Animation UnOptimize too! (This
* is somewhat more useful than it sounds.)
*
* 98.03.16 : version 0.61.0
* Support more rare opaque/transparent combinations.
*
* 97.12.09 : version 0.60.0
* Added support for INDEXED* and GRAY* images.
*
* 97.12.09 : version 0.52.0
* Fixed some bugs.
*
* 97.12.08 : version 0.51.0
* Relaxed bounding box on optimized layers marked
* 'replace'.
*
* 97.12.07 : version 0.50.0
* Initial release.
*/
/*
* BUGS:
* ?
*/
/*
* TODO:
* User interface
* PDB interface
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "libgimp/gimp.h"
typedef enum
{
DISPOSE_UNDEFINED = 0x00,
DISPOSE_COMBINE = 0x01,
DISPOSE_REPLACE = 0x02
} DisposeType;
/* Declare local functions. */
static void query(void);
static void run(char *name,
int nparams,
GParam * param,
int *nreturn_vals,
GParam ** return_vals);
static void do_optimizations (void);
/*static int parse_ms_tag (char *str);*/
static DisposeType parse_disposal_tag (char *str);
static DisposeType get_frame_disposal (guint whichframe);
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
/* Global widgets'n'stuff */
guint width,height;
gint32 image_id;
gint32 new_image_id;
gint32 total_frames;
guint frame_number;
gint32* layers;
GDrawable* drawable;
gboolean playing = FALSE;
GImageType imagetype;
GDrawableType drawabletype_alpha;
guchar pixelstep;
guchar* palette;
gint ncolours;
gboolean optimize;
MAIN()
static void query()
{
static GParamDef args[] =
{
{PARAM_INT32, "run_mode", "Interactive, non-interactive"},
{PARAM_IMAGE, "image", "Input image"},
{PARAM_DRAWABLE, "drawable", "Input drawable (unused)"},
};
static GParamDef *return_vals = NULL;
static int nargs = sizeof(args) / sizeof(args[0]);
static int nreturn_vals = 0;
gimp_install_procedure("plug_in_animationoptimize",
"This plugin applies various optimizations to"
" a GIMP layer-based animation.",
"",
"Adam D. Moss <adam@gimp.org>",
"Adam D. Moss <adam@gimp.org>",
"1997-98",
"<Image>/Filters/Animation/Animation Optimize",
"RGB*, INDEXED*, GRAY*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
gimp_install_procedure("plug_in_animationunoptimize",
"This plugin 'simplifies' a GIMP layer-based"
" animation that has been AnimationOptimized. This"
" makes the animation much easier to work with if,"
" for example, the optimized version is all you"
" have.",
"",
"Adam D. Moss <adam@gimp.org>",
"Adam D. Moss <adam@gimp.org>",
"1997-98",
"<Image>/Filters/Animation/Animation UnOptimize",
"RGB*, INDEXED*, GRAY*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
static void run(char *name, int n_params, GParam * param, int *nreturn_vals,
GParam ** return_vals)
{
static GParam values[1];
GRunModeType run_mode;
GStatusType status = STATUS_SUCCESS;
*nreturn_vals = 1;
*return_vals = values;
run_mode = param[0].data.d_int32;
if (run_mode == RUN_NONINTERACTIVE)
{
if (n_params != 3)
{
status = STATUS_CALLING_ERROR;
}
}
/* Check the procedure name we were called with, to decide
what needs to be done. */
if (strcmp(name,"plug_in_animationoptimize")==0)
optimize = TRUE;
else
optimize = FALSE; /* UnOptimize */
if (status == STATUS_SUCCESS)
{
image_id = param[1].data.d_image;
do_optimizations();
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush();
}
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
}
static DisposeType
parse_disposal_tag (gchar *str)
{
gint offset = 0;
gint length;
length = strlen(str);
while ((offset+9)<=length)
{
if (strncmp(&str[offset],"(combine)",9)==0)
return(DISPOSE_COMBINE);
if (strncmp(&str[offset],"(replace)",9)==0)
return(DISPOSE_REPLACE);
offset++;
}
return (DISPOSE_UNDEFINED); /* FIXME */
}
static gchar*
remove_disposal_tag (gchar* str)
{
gchar* dest;
gint offset = 0;
gint destoffset = 0;
gint length;
length = strlen(str);
dest = g_malloc(length+11);
memset(dest, 0, length+11);
strcpy(dest, str);
while ((offset+9)<=length)
{
if (strncmp(&str[offset],"(combine)",9)==0)
{
offset+=9;
}
if (strncmp(&str[offset],"(replace)",9)==0)
{
offset+=9;
}
dest[destoffset] = str[offset];
destoffset++;
offset++;
}
return dest;
}
/* Rendering Functions */
static void
total_alpha(guchar* imdata, guint32 numpix, guchar bytespp)
{
/* Set image to total-transparency w/black
*/
memset(imdata, 0, numpix*bytespp);
}
static void
do_optimizations(void)
{
GPixelRgn pixel_rgn;
static guchar* rawframe = NULL;
static gint rawwidth=0, rawheight=0, rawbpp=0;
gint rawx=0, rawy=0;
guchar* srcptr;
guchar* destptr;
gint i,j,this_frame_num;
guint32 frame_sizebytes;
gint32 new_layer_id;
DisposeType dispose;
guchar* this_frame = NULL;
guchar* last_frame = NULL;
guchar* opti_frame = NULL;
gchar* oldlayer_name;
gchar* newlayer_name;
gboolean can_combine;
gint32 bbox_top, bbox_bottom, bbox_left, bbox_right;
gint32 rbox_top, rbox_bottom, rbox_left, rbox_right;
if (optimize)
gimp_progress_init ("Optimizing Animation...");
else
gimp_progress_init ("UnOptimizing Animation...");
width = gimp_image_width(image_id);
height = gimp_image_height(image_id);
layers = gimp_image_get_layers (image_id, &total_frames);
imagetype = gimp_image_base_type(image_id);
pixelstep = (imagetype == RGB) ? 4 : 2;
drawabletype_alpha = (imagetype == RGB) ? RGBA_IMAGE :
((imagetype == INDEXED) ? INDEXEDA_IMAGE : GRAYA_IMAGE);
frame_sizebytes = width * height * pixelstep;
this_frame = g_malloc(frame_sizebytes);
last_frame = g_malloc(frame_sizebytes);
opti_frame = g_malloc(frame_sizebytes);
total_alpha(this_frame, width*height, pixelstep);
total_alpha(last_frame, width*height, pixelstep);
new_image_id = gimp_image_new(width, height, imagetype);
if (imagetype == INDEXED)
{
palette = gimp_image_get_cmap(image_id, &ncolours);
gimp_image_set_cmap(new_image_id, palette, ncolours);
}
if ( (this_frame == NULL) || (last_frame == NULL) || (opti_frame == NULL) )
g_error("Not enough memory to allocate buffers for optimization.\n");
for (this_frame_num=0; this_frame_num<total_frames; this_frame_num++)
{
/*
* We actually unoptimize the animation before re-optimizing it,
* otherwise the logic can get a bit too hard... for me.
*/
/*
*
* BUILD THIS FRAME
*
*/
drawable = gimp_drawable_get (layers[total_frames-(this_frame_num+1)]);
/* Image has been closed/etc since we got the layer list? */
/* FIXME - How do we tell if a gimp_drawable_get() fails? */
if (gimp_drawable_width(drawable->id)==0)
{
gimp_quit();
}
dispose = get_frame_disposal(this_frame_num);
if (dispose==DISPOSE_REPLACE)
{
total_alpha(this_frame, width*height, pixelstep);
}
/* only get a new 'raw' drawable-data buffer if this and
the previous raw buffer were different sizes*/
if ((rawwidth*rawheight*rawbpp)
!=
((gimp_drawable_width(drawable->id)*
gimp_drawable_height(drawable->id)*
gimp_drawable_bpp(drawable->id))))
{
if (rawframe != NULL) g_free(rawframe);
rawframe = g_malloc((gimp_drawable_width(drawable->id)) *
(gimp_drawable_height(drawable->id)) *
(gimp_drawable_bpp(drawable->id)));
}
rawwidth = gimp_drawable_width(drawable->id);
rawheight = gimp_drawable_height(drawable->id);
rawbpp = gimp_drawable_bpp(drawable->id);
/* Initialise and fetch the whole raw new frame */
gimp_pixel_rgn_init (&pixel_rgn,
drawable,
0, 0,
drawable->width, drawable->height,
FALSE,
FALSE);
gimp_pixel_rgn_get_rect (&pixel_rgn,
rawframe,
0, 0,
drawable->width, drawable->height);
/* gimp_pixel_rgns_register (1, &pixel_rgn);*/
gimp_drawable_offsets (drawable->id,
&rawx,
&rawy);
/* render... */
switch (imagetype)
{
case RGB:
if ((rawwidth==width) &&
(rawheight==height) &&
(rawx==0) &&
(rawy==0))
{
/* --- These cases are for the best cases, in --- */
/* --- which this frame is the same size and position --- */
/* --- as the preview buffer itself --- */
if (gimp_drawable_has_alpha (drawable->id))
{ /* alpha RGB, same size */
destptr = this_frame;
srcptr = rawframe;
i = rawwidth*rawheight;
while (--i)
{
if (!((*(srcptr+3))&128))
{
srcptr += 4;
destptr += 4;
continue;
}
*(destptr++) = *(srcptr++);
*(destptr++) = *(srcptr++);
*(destptr++) = *(srcptr++);
*(destptr++) = 255;
srcptr++;
}
}
else /* RGB no alpha, same size */
{
destptr = this_frame;
srcptr = rawframe;
i = rawwidth*rawheight;
while (--i)
{
*(destptr++) = *(srcptr++);
*(destptr++) = *(srcptr++);
*(destptr++) = *(srcptr++);
*(destptr++) = 255;
}
}
}
else
{
/* --- These are suboptimal catch-all cases for when --- */
/* --- this frame is bigger/smaller than the preview --- */
/* --- buffer, and/or offset within it. --- */
/* FIXME: FINISH ME! */
if (gimp_drawable_has_alpha (drawable->id))
{ /* RGB alpha, diff size */
destptr = this_frame;
srcptr = rawframe;
for (j=rawy; j<rawheight+rawy; j++)
{
for (i=rawx; i<rawwidth+rawx; i++)
{
if ((i>=0 && i<width) &&
(j>=0 && j<height))
{
if ((*(srcptr+3))&128)
{
this_frame[(j*width+i)*4 ] = *(srcptr);
this_frame[(j*width+i)*4 +1] = *(srcptr+1);
this_frame[(j*width+i)*4 +2] = *(srcptr+2);
this_frame[(j*width+i)*4 +3] = 255;
}
}
srcptr += 4;
}
}
}
else
{
/* RGB no alpha, diff size */
destptr = this_frame;
srcptr = rawframe;
for (j=rawy; j<rawheight+rawy; j++)
{
for (i=rawx; i<rawwidth+rawx; i++)
{
if ((i>=0 && i<width) &&
(j>=0 && j<height))
{
this_frame[(j*width+i)*4 ] = *(srcptr);
this_frame[(j*width+i)*4 +1] = *(srcptr+1);
this_frame[(j*width+i)*4 +2] = *(srcptr+2);
this_frame[(j*width+i)*4 +3] = 255;
}
srcptr += 3;
}
}
}
}
break; /* case RGB */
case GRAY:
case INDEXED:
if ((rawwidth==width) &&
(rawheight==height) &&
(rawx==0) &&
(rawy==0))
{
/* --- These cases are for the best cases, in --- */
/* --- which this frame is the same size and position --- */
/* --- as the preview buffer itself --- */
if (gimp_drawable_has_alpha (drawable->id))
{ /* I alpha, same size */
destptr = this_frame;
srcptr = rawframe;
i = rawwidth*rawheight;
while (--i)
{
if (!(*(srcptr+1)))
{
srcptr += 2;
destptr += 2;
continue;
}
*(destptr++) = *(srcptr);
*(destptr++) = 255;
srcptr+=2;
}
}
else /* I, no alpha, same size */
{
destptr = this_frame;
srcptr = rawframe;
i = rawwidth*rawheight;
while (--i)
{
*(destptr++) = *(srcptr);
*(destptr++) = 255;
srcptr++;
}
}
}
else
{
/* --- These are suboptimal catch-all cases for when --- */
/* --- this frame is bigger/smaller than the preview --- */
/* --- buffer, and/or offset within it. --- */
/* FIXME: FINISH ME! */
if (gimp_drawable_has_alpha (drawable->id))
{ /* I alpha, diff size */
srcptr = rawframe;
for (j=rawy; j<rawheight+rawy; j++)
{
for (i=rawx; i<rawwidth+rawx; i++)
{
if ((i>=0 && i<width) &&
(j>=0 && j<height))
{
if (*(srcptr+1))
{
this_frame[(j*width+i)*pixelstep] =
*srcptr;
this_frame[(j*width+i)*pixelstep
+ pixelstep - 1] =
255;
}
}
srcptr += 2;
}
}
}
else
{
/* I, no alpha, diff size */
srcptr = rawframe;
for (j=rawy; j<rawheight+rawy; j++)
{
for (i=rawx; i<rawwidth+rawx; i++)
{
if ((i>=0 && i<width) &&
(j>=0 && j<height))
{
this_frame[(j*width+i)*pixelstep]
= *srcptr;
this_frame[(j*width+i)*pixelstep
+ pixelstep - 1] = 255;
}
srcptr ++;
}
}
}
}
break; /* case INDEXED/GRAY */
}
/* clean up */
gimp_drawable_detach(drawable);
can_combine = FALSE;
bbox_left = 0;
bbox_top = 0;
bbox_right = width;
bbox_bottom = height;
rbox_left = 0;
rbox_top = 0;
rbox_right = width;
rbox_bottom = height;
/* copy 'this' frame into a buffer which we can safely molest */
memcpy(opti_frame, this_frame, frame_sizebytes);
/*
*
* OPTIMIZE HERE!
*
*/
if (
(this_frame_num != 0) /* Can't delta bottom frame! */
&& (optimize)
)
{
int xit, yit, byteit;
can_combine = TRUE;
/*
* SEARCH FOR BOUNDING BOX
*/
bbox_left = width;
bbox_top = height;
bbox_right = 0;
bbox_bottom = 0;
rbox_left = width;
rbox_top = height;
rbox_right = 0;
rbox_bottom = 0;
for (yit=0; yit<height; yit++)
{
for (xit=0; xit<width; xit++)
{
gboolean keep_pix;
gboolean opaq_pix;
/* Check if 'this' and 'last' are transparent */
if (!(this_frame[yit*width*pixelstep + xit*pixelstep
+ pixelstep-1]&128)
&&
!(last_frame[yit*width*pixelstep + xit*pixelstep
+ pixelstep-1]&128))
{
keep_pix = FALSE;
opaq_pix = FALSE;
goto decided;
}
/* Check if just 'this' is transparent */
if ((last_frame[yit*width*pixelstep + xit*pixelstep
+ pixelstep-1]&128)
&&
!(this_frame[yit*width*pixelstep + xit*pixelstep
+ pixelstep-1]&128))
{
keep_pix = TRUE;
opaq_pix = FALSE;
can_combine = FALSE;
goto decided;
}
/* Check if just 'last' is transparent */
if (!(last_frame[yit*width*pixelstep + xit*pixelstep
+ pixelstep-1]&128)
&&
(this_frame[yit*width*pixelstep + xit*pixelstep
+ pixelstep-1]&128))
{
keep_pix = TRUE;
opaq_pix = TRUE;
goto decided;
}
/* If 'last' and 'this' are opaque, we have
* to check if they're the same colour - we
* only have to keep the pixel if 'last' or
* 'this' are opaque and different.
*/
keep_pix = FALSE;
opaq_pix = TRUE;
for (byteit=0; byteit<pixelstep-1; byteit++)
{
if (last_frame[yit*width*pixelstep + xit*pixelstep
+ byteit]
!=
this_frame[yit*width*pixelstep + xit*pixelstep
+ byteit])
{
keep_pix = TRUE;
goto decided;
}
}
decided:
if (opaq_pix)
{
if (xit<rbox_left) rbox_left=xit;
if (xit>rbox_right) rbox_right=xit;
if (yit<rbox_top) rbox_top=yit;
if (yit>rbox_bottom) rbox_bottom=yit;
}
if (keep_pix)
{
if (xit<bbox_left) bbox_left=xit;
if (xit>bbox_right) bbox_right=xit;
if (yit<bbox_top) bbox_top=yit;
if (yit>bbox_bottom) bbox_bottom=yit;
}
else
{
/* pixel didn't change this frame - make
* it transparent in our optimized buffer!
*/
opti_frame[yit*width*pixelstep + xit*pixelstep
+ pixelstep-1] = 0;
}
} /* xit */
} /* yit */
if (!can_combine)
{
bbox_left = rbox_left;
bbox_top = rbox_top;
bbox_right = rbox_right;
bbox_bottom = rbox_bottom;
}
bbox_right++;
bbox_bottom++;
/*
* Collapse opti_frame data down such that the data
* which occupies the bounding box sits at the start
* of the data (for convenience with ..set_rect()).
*/
destptr = opti_frame;
/*
* If can_combine, then it's safe to use our optimized
* alpha information. Otherwise, an opaque pixel became
* transparent this frame, and we'll have to use the
* actual true frame's alpha.
*/
if (can_combine)
srcptr = opti_frame;
else
srcptr = this_frame;
for (yit=bbox_top; yit<bbox_bottom; yit++)
{
for (xit=bbox_left; xit<bbox_right; xit++)
{
for (byteit=0; byteit<pixelstep; byteit++)
{
*(destptr++) = srcptr[yit*pixelstep*width +
pixelstep*xit + byteit];
}
}
}
} /* !bot frame? */
else
{
memcpy(opti_frame, this_frame, frame_sizebytes);
}
/*
*
* REMEMBER THE ANIMATION STATUS TO DELTA AGAINST NEXT TIME
*
*/
memcpy(last_frame, this_frame, frame_sizebytes);
/*
*
* PUT THIS FRAME INTO A NEW LAYER IN THE NEW IMAGE
*
*/
oldlayer_name =
gimp_layer_get_name(layers[total_frames-(this_frame_num+1)]);
newlayer_name = remove_disposal_tag(oldlayer_name);
g_free(oldlayer_name);
if (this_frame_num > 0)
strcat(newlayer_name, can_combine?"(combine)":"(replace)");
new_layer_id = gimp_layer_new(new_image_id,
newlayer_name,
bbox_right-bbox_left,
bbox_bottom-bbox_top,
drawabletype_alpha,
100.0,
NORMAL_MODE);
g_free(newlayer_name);
gimp_image_add_layer (new_image_id, new_layer_id, 0);
drawable = gimp_drawable_get (new_layer_id);
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
bbox_right-bbox_left,
bbox_bottom-bbox_top,
TRUE, FALSE);
gimp_pixel_rgn_set_rect (&pixel_rgn, opti_frame, 0, 0,
bbox_right-bbox_left,
bbox_bottom-bbox_top);
gimp_drawable_flush (drawable);
gimp_drawable_detach (drawable);
gimp_layer_translate (new_layer_id, (gint)bbox_left, (gint)bbox_top);
gimp_progress_update (((double)this_frame_num+1.0) /
((double)total_frames));
}
gimp_display_new (new_image_id);
g_free(rawframe);
rawframe = NULL;
g_free(last_frame);
last_frame = NULL;
g_free(this_frame);
this_frame = NULL;
g_free(opti_frame);
opti_frame = NULL;
}
/* Util. */
static DisposeType
get_frame_disposal (guint whichframe)
{
gchar* layer_name;
DisposeType disposal;
layer_name = gimp_layer_get_name(layers[total_frames-(whichframe+1)]);
disposal = parse_disposal_tag(layer_name);
g_free(layer_name);
return(disposal);
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
apply_lens

View file

@ -1,39 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = apply_lens
apply_lens_SOURCES = \
apply_lens.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
apply_lens_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,513 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* Apply lens plug-in --- makes your selected part of the image look like it
* is viewed under a solid lens.
* Copyright (C) 1997 Morten Eriksen
* mortene@pvv.ntnu.no
* (If you do anything cool with this plug-in, or have ideas for
* improvements (which aren't on my ToDo-list) - send me an email).
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* Compile with (on Linux):
* gcc -I/usr/local/include -I/usr/local/include/glib -o apply_lens apply_lens.c -L/usr/local/lib -L/usr/X11/lib -lgtk -lgdk -lgimp -lglib -lXext -lX11 -lm
*
*/
/* Version 0.1:
*
* First release. No known serious bugs, and basically does what you want.
* All fancy features postponed until the next release, though. :)
*
*/
/*
TO DO:
- antialiasing
- preview image
- adjustable (R, G, B and A) filter
- optimize for speed!
- refraction index warning dialog box when value < 1.0
- use "true" lens with specified thickness
- option to apply inverted lens
- adjustable "c" value in the ellipsoid formula
- radiobuttons for "ellipsoid" or "only horiz" and "only vert" (like in the
Ad*b* Ph*t*sh*p Spherify plug-in..)
- clean up source code
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "libgimp/gimp.h"
#include "gtk/gtk.h"
#include "config.h"
#include "libgimp/stdplugins-intl.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif /* M_PI */
#define ENTRY_WIDTH 100
/* Declare local functions.
*/
static void query(void);
static void run(char *name, int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals);
static void drawlens(GDrawable *drawable);
static gint lens_dialog(GDrawable *drawable);
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
typedef struct
{
gdouble refraction;
gint keep_surr, use_bkgr, set_transparent;
} LensValues;
static LensValues lvals =
{
/* Lens refraction value */
1.7,
/* Surroundings options */
TRUE, FALSE, FALSE
};
typedef struct
{
gint run;
} LensInterface;
static LensInterface bint =
{
FALSE /* run */
};
MAIN()
static void
query(void)
{
static GParamDef args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image (unused)" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_FLOAT, "refraction", "Lens refraction index" },
{ PARAM_INT32, "keep_surroundings", "Keep lens surroundings" },
{ PARAM_INT32, "set_background", "Set lens surroundings to bkgr value" },
{ PARAM_INT32, "set_transparent", "Set lens surroundings transparent" },
};
static GParamDef *return_vals = NULL;
static int nargs = sizeof(args)/ sizeof(args[0]);
static int nreturn_vals = 0;
INIT_I18N();
gimp_install_procedure("plug_in_applylens",
_("Apply a lens effect"),
_("This plug-in uses Snell's law to draw an ellipsoid lens over the image"),
"Morten Eriksen",
"Morten Eriksen",
"1997",
_("<Image>/Filters/Glass Effects/Apply Lens"),
"RGB*, GRAY*, INDEXED*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
static void
run(char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals)
{
static GParam values[1];
GDrawable *drawable;
GRunModeType run_mode;
GStatusType status = STATUS_SUCCESS;
INIT_I18N();
run_mode = param[0].data.d_int32;
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
*nreturn_vals = 1;
*return_vals = values;
drawable = gimp_drawable_get(param[2].data.d_drawable);
switch(run_mode) {
case RUN_INTERACTIVE:
gimp_get_data("plug_in_applylens", &lvals);
if(!lens_dialog(drawable)) return;
break;
case RUN_NONINTERACTIVE:
if(nparams != 7) status = STATUS_CALLING_ERROR;
if(status == STATUS_SUCCESS) {
lvals.refraction = param[3].data.d_float;
lvals.keep_surr = param[4].data.d_int32;
lvals.use_bkgr = param[5].data.d_int32;
lvals.set_transparent = param[6].data.d_int32;
}
if(status == STATUS_SUCCESS && (lvals.refraction < 1.0))
status = STATUS_CALLING_ERROR;
break;
case RUN_WITH_LAST_VALS:
gimp_get_data ("plug_in_applylens", &lvals);
break;
default:
break;
}
gimp_tile_cache_ntiles(2 *(drawable->width / gimp_tile_width() + 1));
gimp_progress_init(_("Applying lens..."));
drawlens(drawable);
if(run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush();
if(run_mode == RUN_INTERACTIVE)
gimp_set_data("plug_in_applylens", &lvals, sizeof(LensValues));
values[0].data.d_status = status;
gimp_drawable_detach(drawable);
}
/*
Ellipsoid formula: x^2/a^2 + y^2/b^2 + z^2/c^2 = 1
*/
static void
find_projected_pos(gfloat a, gfloat b,
gfloat x, gfloat y,
gfloat *projx, gfloat *projy)
{
gfloat c;
gfloat n[3];
gfloat nxangle, nyangle, theta1, theta2;
gfloat ri1 = 1.0, ri2 = lvals.refraction;
/* PARAM */
c = MIN(a, b);
n[0] = x;
n[1] = y;
n[2] = sqrt((1-x*x/(a*a)-y*y/(b*b))*(c*c));
nxangle = acos(n[0]/sqrt(n[0]*n[0]+n[2]*n[2]));
theta1 = M_PI/2 - nxangle;
theta2 = asin(sin(theta1)*ri1/ri2);
theta2 = M_PI/2 - nxangle - theta2;
*projx = x - tan(theta2)*n[2];
nyangle = acos(n[1]/sqrt(n[1]*n[1]+n[2]*n[2]));
theta1 = M_PI/2 - nyangle;
theta2 = asin(sin(theta1)*ri1/ri2);
theta2 = M_PI/2 - nyangle - theta2;
*projy = y - tan(theta2)*n[2];
}
static void
drawlens(GDrawable *drawable)
{
GPixelRgn srcPR, destPR;
gint width, height;
gint bytes;
gint row;
gint x1, y1, x2, y2;
guchar *src, *dest;
gint i, col;
gfloat regionwidth, regionheight, dx, dy, xsqr, ysqr;
gfloat a, b, asqr, bsqr, x, y;
glong pixelpos, pos;
guchar bgr_red, bgr_blue, bgr_green, alphaval;
GDrawableType drawtype = gimp_drawable_type(drawable->id);
gimp_palette_get_background(&bgr_red, &bgr_green, &bgr_blue);
gimp_drawable_mask_bounds(drawable->id, &x1, &y1, &x2, &y2);
regionwidth = x2-x1;
a = regionwidth/2;
regionheight = y2-y1;
b = regionheight/2;
asqr = a*a;
bsqr = b*b;
width = drawable->width;
height = drawable->height;
bytes = drawable->bpp;
gimp_pixel_rgn_init(&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
gimp_pixel_rgn_init(&destPR, drawable, 0, 0, width, height, TRUE, TRUE);
src = g_malloc((x2-x1)*(y2-y1)*bytes);
dest = g_malloc((x2-x1)*(y2-y1)*bytes);
gimp_pixel_rgn_get_rect(&srcPR, src, x1, y1, regionwidth, regionheight);
for(col = 0; col < regionwidth; col++) {
dx = (gfloat)col - a + 0.5;
xsqr = dx*dx;
for(row = 0; row < regionheight; row++) {
pixelpos = (col+row*regionwidth)*bytes;
dy = -((gfloat)row - b) - 0.5;
ysqr = dy*dy;
if(ysqr < (bsqr - (bsqr*xsqr)/asqr)) {
find_projected_pos(a, b, dx, dy, &x, &y);
y = -y;
pos = ((gint)(y+b)*regionwidth + (gint)(x+a)) * bytes;
for(i = 0; i < bytes; i++) {
dest[pixelpos+i] = src[pos+i];
}
}
else {
if(lvals.keep_surr) {
for(i = 0; i < bytes; i++) {
dest[pixelpos+i] = src[pixelpos+i];
}
}
else {
if(lvals.set_transparent) alphaval = 0;
else alphaval = 255;
switch(drawtype) {
case INDEXEDA_IMAGE:
dest[pixelpos+1] = alphaval;
case INDEXED_IMAGE:
dest[pixelpos+0] = 0;
break;
case RGBA_IMAGE:
dest[pixelpos+3] = alphaval;
case RGB_IMAGE:
dest[pixelpos+0] = bgr_red;
dest[pixelpos+1] = bgr_green;
dest[pixelpos+2] = bgr_blue;
break;
case GRAYA_IMAGE:
dest[pixelpos+1] = alphaval;
case GRAY_IMAGE:
dest[pixelpos+0] = bgr_red;
break;
}
}
}
}
if(((gint)(regionwidth-col) % 5) == 0)
gimp_progress_update((gdouble)col/(gdouble)regionwidth);
}
gimp_pixel_rgn_set_rect(&destPR, dest, x1, y1, regionwidth, regionheight);
g_free(src);
g_free(dest);
gimp_drawable_flush(drawable);
gimp_drawable_merge_shadow(drawable->id, TRUE);
gimp_drawable_update(drawable->id, x1, y1,(x2 - x1),(y2 - y1));
}
static void
lens_close_callback(GtkWidget *widget,
gpointer data)
{
gtk_main_quit();
}
static void
lens_ok_callback(GtkWidget *widget,
gpointer data)
{
bint.run = TRUE;
gtk_widget_destroy(GTK_WIDGET (data));
}
static void
lens_toggle_update(GtkWidget *widget,
gpointer data)
{
int *toggle_val;
toggle_val = (int *)data;
if(GTK_TOGGLE_BUTTON (widget)->active)
*toggle_val = TRUE;
else
*toggle_val = FALSE;
}
static void
lens_entry_callback(GtkWidget *widget,
gpointer data)
{
lvals.refraction = atof(gtk_entry_get_text(GTK_ENTRY(widget)));
if(lvals.refraction < 1.0) lvals.refraction = 1.0;
}
static gint
lens_dialog(GDrawable *drawable)
{
GtkWidget *dlg;
GtkWidget *label;
GtkWidget *entry;
GtkWidget *button;
GtkWidget *toggle;
GtkWidget *frame;
GtkWidget *vbox;
GtkWidget *hbox;
gchar buffer[12];
gchar **argv;
gint argc;
GSList *group = NULL;
GDrawableType drawtype;
drawtype = gimp_drawable_type(drawable->id);
argc = 1;
argv = g_new(gchar *, 1);
argv[0] = g_strdup("apply_lens");
gtk_init(&argc, &argv);
gtk_rc_parse(gimp_gtkrc());
dlg = gtk_dialog_new();
gtk_window_set_title(GTK_WINDOW(dlg), _("Lens effect"));
gtk_window_position(GTK_WINDOW(dlg), GTK_WIN_POS_MOUSE);
gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
(GtkSignalFunc)lens_close_callback,
NULL);
button = gtk_button_new_with_label(_("OK"));
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
(GtkSignalFunc)lens_ok_callback,
dlg);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area),
button, TRUE, TRUE, 0);
gtk_widget_grab_default(button);
gtk_widget_show(button);
button = gtk_button_new_with_label(_("Cancel"));
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
(GtkSignalFunc)gtk_widget_destroy,
GTK_OBJECT(dlg));
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area),
button, TRUE, TRUE, 0);
gtk_widget_show(button);
frame = gtk_frame_new(_("Parameter Settings"));
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width(GTK_CONTAINER(frame), 10);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), frame, TRUE, TRUE, 0);
vbox = gtk_vbox_new(FALSE, 5);
gtk_container_border_width(GTK_CONTAINER(vbox), 10);
gtk_container_add(GTK_CONTAINER(frame), vbox);
toggle = gtk_radio_button_new_with_label(group,
_("Keep original surroundings"));
group = gtk_radio_button_group(GTK_RADIO_BUTTON(toggle));
gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(toggle), "toggled",
(GtkSignalFunc) lens_toggle_update,
&lvals.keep_surr);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), lvals.keep_surr);
gtk_widget_show(toggle);
toggle =
gtk_radio_button_new_with_label(group,
drawtype == INDEXEDA_IMAGE ||
drawtype == INDEXED_IMAGE ?
_("Set surroundings to index 0") :
_("Set surroundings to background color"));
group = gtk_radio_button_group(GTK_RADIO_BUTTON(toggle));
gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(toggle), "toggled",
(GtkSignalFunc) lens_toggle_update,
&lvals.use_bkgr);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), lvals.use_bkgr);
gtk_widget_show(toggle);
if((drawtype == INDEXEDA_IMAGE) ||
(drawtype == GRAYA_IMAGE) ||
(drawtype == RGBA_IMAGE)) {
toggle = gtk_radio_button_new_with_label(group,
_("Make surroundings transparent"));
group = gtk_radio_button_group(GTK_RADIO_BUTTON(toggle));
gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(toggle), "toggled",
(GtkSignalFunc) lens_toggle_update,
&lvals.set_transparent);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle),
lvals.set_transparent);
gtk_widget_show(toggle);
}
hbox = gtk_hbox_new(FALSE, 5);
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
label = gtk_label_new(_("Lens refraction index: "));
gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, FALSE, 0);
gtk_widget_show(label);
entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
gtk_widget_set_usize(entry, ENTRY_WIDTH, 0);
sprintf(buffer, "%.2f", lvals.refraction);
gtk_entry_set_text(GTK_ENTRY(entry), buffer);
gtk_signal_connect(GTK_OBJECT(entry), "changed",
(GtkSignalFunc)lens_entry_callback,
NULL);
gtk_widget_show(entry);
gtk_widget_show(hbox);
gtk_widget_show(vbox);
gtk_widget_show(frame);
gtk_widget_show(dlg);
gtk_main();
gdk_flush();
return bint.run;
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
autocrop

View file

@ -1,36 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = autocrop
autocrop_SOURCES = \
autocrop.c
INCLUDES = \
-I$(top_srcdir) \
$(GLIB_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GLIB_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
autocrop_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,270 +0,0 @@
/*
* Autocrop plug-in version 1.00
* by Tim Newsome <drz@froody.bloke.com>
* thanks to quartic for finding a nasty bug for me
*/
/* 1999/04/09 -- Sven Neumann <sven@gimp.org>
* Fixed bad crash that occured when running on an entirely blank image.
* Cleaned up the code a bit, while I was at it.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "libgimp/gimp.h"
/* Declare local functions. */
static void query(void);
static void run(char *name,
int nparams,
GParam * param,
int *nreturn_vals,
GParam ** return_vals);
static int colors_equal(guchar *col1, guchar *col2, int bytes);
static int guess_bgcolor(GPixelRgn *pr, int width, int height, int bytes,
guchar *color);
static void doit(GDrawable *drawable, gint32);
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
gint bytes;
gint sx1, sy1, sx2, sy2;
int run_flag = 0;
MAIN()
static void query()
{
static GParamDef args[] =
{
{PARAM_INT32, "run_mode", "Interactive, non-interactive"},
{PARAM_IMAGE, "image", "Input image"},
{PARAM_DRAWABLE, "drawable", "Input drawable"},
};
static GParamDef *return_vals = NULL;
static int nargs = sizeof(args) / sizeof(args[0]);
static int nreturn_vals = 0;
gimp_install_procedure("plug_in_autocrop",
"Automagically crops a picture.",
"",
"Tim Newsome",
"Tim Newsome",
"1997",
"<Image>/Image/Transforms/Autocrop",
"RGB*, GRAY*, INDEXED*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
static void run(char *name, int n_params, GParam * param, int *nreturn_vals,
GParam ** return_vals)
{
static GParam values[1];
GDrawable *drawable;
GRunModeType run_mode;
GStatusType status = STATUS_SUCCESS;
gint32 image_id;
*nreturn_vals = 1;
*return_vals = values;
run_mode = param[0].data.d_int32;
if (run_mode == RUN_NONINTERACTIVE) {
if (n_params != 3)
status = STATUS_CALLING_ERROR;
}
if (status == STATUS_SUCCESS) {
/* Get the specified drawable */
drawable = gimp_drawable_get(param[2].data.d_drawable);
image_id = param[1].data.d_image;
/* Make sure that the drawable is gray or RGB color */
if (gimp_drawable_color(drawable->id) ||
gimp_drawable_gray(drawable->id) ||
gimp_drawable_indexed(drawable->id))
{
gimp_progress_init("Cropping...");
gimp_tile_cache_ntiles(2 * (drawable->width / gimp_tile_width() + 1));
doit(drawable, image_id);
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush();
}
else
{
status = STATUS_EXECUTION_ERROR;
}
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
}
}
static void doit(GDrawable *drawable, gint32 image_id)
{
GPixelRgn srcPR;
gint width, height;
int x, y, abort;
gint32 nx, ny, nw, nh;
guchar *buffer;
guchar color[4] = {0, 0, 0, 0};
int nreturn_vals;
width = drawable->width;
height = drawable->height;
bytes = drawable->bpp;
nx = 0;
ny = 0;
nw = width;
nh = height;
/* initialize the pixel regions */
gimp_pixel_rgn_init(&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
/* First, let's figure out what exactly to crop. */
buffer = g_malloc((width > height ? width : height) * bytes);
guess_bgcolor(&srcPR, width, height, bytes, color);
/* Check how many of the top lines are uniform. */
abort = 0;
for (y = 0; y < height && !abort; y++) {
gimp_pixel_rgn_get_row(&srcPR, buffer, 0, y, width);
for (x = 0; x < width && !abort; x++) {
abort = !colors_equal(color, buffer + x * bytes, bytes);
}
}
if (y == height && !abort) {
g_free(buffer);
gimp_drawable_detach(drawable);
return;
}
y--;
ny = y;
nh = height - y;
gimp_progress_update(.25);
/* Check how many of the bottom lines are uniform. */
abort = 0;
for (y = height - 1; y >= 0 && !abort; y--) {
gimp_pixel_rgn_get_row(&srcPR, buffer, 0, y, width);
for (x = 0; x < width && !abort; x++) {
abort = !colors_equal(color, buffer + x * bytes, bytes);
}
}
nh = y - ny + 2;
gimp_progress_update(.5);
/* Check how many of the left lines are uniform. */
abort = 0;
for (x = 0; x < width && !abort; x++) {
gimp_pixel_rgn_get_col(&srcPR, buffer, x, ny, nh);
for (y = 0; y < nh && !abort; y++) {
abort = !colors_equal(color, buffer + y * bytes, bytes);
}
}
x--;
nx = x;
nw = width - x;
gimp_progress_update(.75);
/* Check how many of the right lines are uniform. */
abort = 0;
for (x = width - 1; x >= 0 && !abort; x--) {
gimp_pixel_rgn_get_col(&srcPR, buffer, x, ny, nh);
for (y = 0; y < nh && !abort; y++) {
abort = !colors_equal(color, buffer + y * bytes, bytes);
}
}
nw = x - nx + 2;
g_free(buffer);
gimp_drawable_detach(drawable);
if (nw != width || nh != height) {
gimp_run_procedure("gimp_crop", &nreturn_vals,
PARAM_IMAGE, image_id,
PARAM_INT32, nw,
PARAM_INT32, nh,
PARAM_INT32, nx,
PARAM_INT32, ny,
PARAM_END);
}
}
static int guess_bgcolor(GPixelRgn *pr, int width, int height, int bytes,
guchar *color) {
guchar tl[4], tr[4], bl[4], br[4];
gimp_pixel_rgn_get_pixel(pr, tl, 0, 0);
gimp_pixel_rgn_get_pixel(pr, tr, width - 1, 0);
gimp_pixel_rgn_get_pixel(pr, bl, 0, height - 1);
gimp_pixel_rgn_get_pixel(pr, br, width - 1, height - 1);
/* Algorithm pinched from pnmcrop.
* To guess the background, first see if 3 corners are equal.
* Then if two are equal.
* Otherwise average the colors.
*/
if (colors_equal(tr, bl, bytes) && colors_equal(tr, br, bytes)) {
memcpy(color, tr, bytes);
return 3;
} else if (colors_equal(tl, bl, bytes) && colors_equal(tl, br, bytes)) {
memcpy(color, tl, bytes);
return 3;
} else if (colors_equal(tl, tr, bytes) && colors_equal(tl, br, bytes)) {
memcpy(color, tl, bytes);
return 3;
} else if (colors_equal(tl, tr, bytes) && colors_equal(tl, bl, bytes)) {
memcpy(color, tl, bytes);
return 3;
} else if (colors_equal(tl, tr, bytes) || colors_equal(tl, bl, bytes) ||
colors_equal(tl, br, bytes)) {
memcpy(color, tl, bytes);
return 2;
} else if (colors_equal(tr, bl, bytes) || colors_equal(tr, bl, bytes)) {
memcpy(color, tr, bytes);
return 2;
} else if (colors_equal(br, bl, bytes)) {
memcpy(color, br, bytes);
return 2;
} else {
while (bytes--) {
color[bytes] = (tl[bytes] + tr[bytes] + bl[bytes] + br[bytes]) / 4;
}
return 0;
}
}
static int colors_equal(guchar *col1, guchar *col2, int bytes) {
int equal = 1;
int b;
for (b = 0; b < bytes; b++) {
if (col1[b] != col2[b]) {
equal = 0;
break;
}
}
return equal;
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
autostretch_hsv

View file

@ -1,39 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = autostretch_hsv
autostretch_hsv_SOURCES = \
autostretch_hsv.c
INCLUDES = \
-I$(top_srcdir) \
$(GLIB_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GLIB_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
autostretch_hsv_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,436 +0,0 @@
/* Autostretch HSV 0.10 --- image filter plug-in for The Gimp image
* manipulation program
*
* Copyright (C) 1997 Scott Goehring
* Copyright (C) 1996 Federico Mena Quintero
*
* You can contact me at scott@poverty.bloomington.in.us
* You can contact the original The Gimp authors at gimp@xcf.berkeley.edu
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* This simple plug-in does an automatic contrast stretch. For each
channel in the image, it finds the minimum and maximum values... it
uses those values to stretch the individual histograms to the full
contrast range. For some images it may do just what you want; for
others it may be total crap :) This version operates in HSV space
and preserves hue, unlike the original Contrast Autostretch. */
#include <stdlib.h>
#include <stdio.h>
#include "libgimp/gimp.h"
#include "config.h"
#include "libgimp/stdplugins-intl.h"
/* Declare local functions.
*/
static void query (void);
static void run (char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals);
static void autostretch_hsv (GDrawable * drawable);
static void indexed_autostretch_hsv (gint32 image_ID);
static void calc_rgb_to_hsv(guchar *rgb, double *h, double *s, double *v);
static void calc_hsv_to_rgb(guchar *rgb, double h, double s, double v);
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
MAIN ()
static void
query ()
{
static GParamDef args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
};
static GParamDef *return_vals = NULL;
static int nargs = sizeof (args) / sizeof (args[0]);
static int nreturn_vals = 0;
INIT_I18N();
gimp_install_procedure ("plug_in_autostretch_hsv",
_("Automatically stretch the contrast of the specified drawable to cover all possible ranges."),
_("This simple plug-in does an automatic contrast stretch. For each channel in the image, it finds the minimum and maximum values... it uses those values to stretch the individual histograms to the full contrast range. For some images it may do just what you want; for others it may be total crap :). This version differs from Contrast Autostretch in that it works in HSV space, and preserves hue."),
"Scott Goehring and Federico Mena Quintero",
"Scott Goehring and Federico Mena Quintero",
"1997",
_("<Image>/Image/Colors/Auto-Stretch HSV"),
"RGB*, INDEXED*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
static void
run (char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals)
{
static GParam values[1];
GDrawable *drawable;
GRunModeType run_mode;
GStatusType status = STATUS_SUCCESS;
gint32 image_ID;
INIT_I18N();
run_mode = param[0].data.d_int32;
/* Get the specified drawable */
drawable = gimp_drawable_get (param[2].data.d_drawable);
image_ID = param[1].data.d_image;
/* Make sure that the drawable is gray or RGB color */
if (gimp_drawable_color (drawable->id) || gimp_drawable_gray (drawable->id))
{
gimp_progress_init (_("Auto-Stretching HSV..."));
gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width () + 1));
autostretch_hsv (drawable);
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush ();
}
else if (gimp_drawable_indexed (drawable->id))
{
indexed_autostretch_hsv (image_ID);
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush ();
}
else
{
/* gimp_message ("autostretch_hsv: cannot operate on indexed color images"); */
status = STATUS_EXECUTION_ERROR;
}
*nreturn_vals = 1;
*return_vals = values;
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
gimp_drawable_detach (drawable);
}
static void
indexed_autostretch_hsv(gint32 image_ID) /* a.d.m. */
{
guchar *cmap;
gint ncols,i;
double shi = 0.0, vhi = 0.0, slo = 1.0, vlo = 1.0;
cmap = gimp_image_get_cmap (image_ID, &ncols);
if (cmap==NULL)
{
fprintf(stderr, "autostretch_hsv: cmap was NULL! Quitting...\n");
gimp_quit();
}
for (i=0;i<ncols;i++)
{
double h, s, v;
calc_rgb_to_hsv(&cmap[i*3], &h, &s, &v);
if (s > shi) shi = s;
if (s < slo) slo = s;
if (v > vhi) vhi = v;
if (v < vlo) vlo = v;
}
for (i=0;i<ncols;i++)
{
double h, s, v;
calc_rgb_to_hsv(&cmap[i*3], &h, &s, &v);
if (shi!=slo)
s = (s-slo) / (shi-slo);
if (vhi!=vlo)
v = (v-vlo) / (vhi-vlo);
calc_hsv_to_rgb(&cmap[i*3], h, s, v);
}
gimp_image_set_cmap (image_ID, cmap, ncols);
}
static void
autostretch_hsv (GDrawable *drawable)
{
GPixelRgn src_rgn, dest_rgn;
guchar *src, *s;
guchar *dest, *d;
double shi = 0.0, slo = 1.0, vhi = 0.0, vlo = 1.0;
gint progress, max_progress;
gint has_alpha, alpha;
gint x1, y1, x2, y2;
gint x, y;
gpointer pr;
/* Get selection area */
gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
has_alpha = gimp_drawable_has_alpha (drawable->id);
alpha = (has_alpha) ? drawable->bpp - 1 : drawable->bpp;
/* Initialize progress */
progress = 0;
max_progress = (x2 - x1) * (y2 - y1) * 2;
gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, (x2 - x1), (y2 - y1), FALSE, FALSE);
for (pr = gimp_pixel_rgns_register (1, &src_rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr))
{
src = src_rgn.data;
for (y = 0; y < src_rgn.h; y++)
{
s = src;
for (x = 0; x < src_rgn.w; x++)
{
if (!has_alpha || (has_alpha && s[alpha]))
{
double h, z, v;
calc_rgb_to_hsv(s, &h, &z, &v);
if (z > shi) shi = z;
if (z < slo) slo = z;
if (v > vhi) vhi = v;
if (v < vlo) vlo = v;
}
s += src_rgn.bpp;
}
src += src_rgn.rowstride;
}
/* Update progress */
progress += src_rgn.w * src_rgn.h;
gimp_progress_update ((double) progress / (double) max_progress);
}
/* Now substitute pixel vales */
gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, (x2 - x1), (y2 - y1), FALSE, FALSE);
gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, (x2 - x1), (y2 - y1), TRUE, TRUE);
for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr))
{
src = src_rgn.data;
dest = dest_rgn.data;
for (y = 0; y < src_rgn.h; y++)
{
s = src;
d = dest;
for (x = 0; x < src_rgn.w; x++)
{
double h, z, v;
calc_rgb_to_hsv(s, &h, &z, &v);
if (shi!=slo)
z = (z-slo) / (shi-slo);
if (vhi!=vlo)
v = (v-vlo) / (vhi-vlo);
calc_hsv_to_rgb(d, h, z, v);
if (has_alpha)
d[alpha] = s[alpha];
s += src_rgn.bpp;
d += dest_rgn.bpp;
}
src += src_rgn.rowstride;
dest += dest_rgn.rowstride;
}
/* Update progress */
progress += src_rgn.w * src_rgn.h;
gimp_progress_update ((double) progress / (double) max_progress);
}
/* update the region */
gimp_drawable_flush (drawable);
gimp_drawable_merge_shadow (drawable->id, TRUE);
gimp_drawable_update (drawable->id, x1, y1, (x2 - x1), (y2 - y1));
}
static void
calc_rgb_to_hsv(guchar *rgb, double *hue, double *sat, double *val)
{
double red, green, blue;
double h, s, v;
double min, max;
double delta;
red = rgb[0] / 255.0;
green = rgb[1] / 255.0;
blue = rgb[2] / 255.0;
h = 0.0; /* Shut up -Wall */
if (red > green)
{
if (red > blue)
max = red;
else
max = blue;
if (green < blue)
min = green;
else
min = blue;
}
else
{
if (green > blue)
max = green;
else
max = blue;
if (red < blue)
min = red;
else
min = blue;
}
v = max;
if (max != 0.0)
s = (max - min) / max;
else
s = 0.0;
if (s == 0.0)
h = 0.0;
else
{
delta = max - min;
if (red == max)
h = (green - blue) / delta;
else if (green == max)
h = 2 + (blue - red) / delta;
else if (blue == max)
h = 4 + (red - green) / delta;
h /= 6.0;
if (h < 0.0)
h += 1.0;
else if (h > 1.0)
h -= 1.0;
}
*hue = h;
*sat = s;
*val = v;
}
static void
calc_hsv_to_rgb(guchar *rgb, double h, double s, double v)
{
double hue, saturation, value;
double f, p, q, t;
if (s == 0.0)
{
h = v;
s = v;
v = v; /* heh */
}
else
{
hue = h * 6.0;
saturation = s;
value = v;
if (hue == 6.0)
hue = 0.0;
f = hue - (int) hue;
p = value * (1.0 - saturation);
q = value * (1.0 - saturation * f);
t = value * (1.0 - saturation * (1.0 - f));
switch ((int) hue)
{
case 0:
h = value;
s = t;
v = p;
break;
case 1:
h = q;
s = value;
v = p;
break;
case 2:
h = p;
s = value;
v = t;
break;
case 3:
h = p;
s = q;
v = value;
break;
case 4:
h = t;
s = p;
v = value;
break;
case 5:
h = value;
s = p;
v = q;
break;
}
}
rgb[0] = h*255;
rgb[1] = s*255;
rgb[2] = v*255;
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
blinds

View file

@ -1,36 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = blinds
blinds_SOURCES = \
blinds.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
blinds_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
blur

View file

@ -1,41 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = blur
blur_SOURCES = \
blur.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/plug-ins/gpc/libgpc.a \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/plug-ins/gpc/libgpc.a \
$(top_builddir)/libgimp/libgimp.la
blur_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,704 +0,0 @@
/****************************************************************************
* This is a plugin for the GIMP v 0.99.8 or later. Documentation is
* available at http://www.rru.com/~meo/gimp/ .
*
* Copyright (C) 1997-98 Miles O'Neal <meo@rru.com> http://www.rru.com/~meo/
* Blur code Copyright (C) 1995 Spencer Kimball and Peter Mattis
* GUI based on GTK code from:
* alienmap (Copyright (C) 1996, 1997 Daniel Cotting)
* plasma (Copyright (C) 1996 Stephen Norris),
* oilify (Copyright (C) 1996 Torsten Martinsen),
* ripple (Copyright (C) 1997 Brian Degenhardt) and
* whirl (Copyright (C) 1997 Federico Mena Quintero).
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
****************************************************************************/
/****************************************************************************
* Blur:
*
* blur version 2.0 (1 May 1998, MEO)
* history
* 2.0 - 1 May 1998 MEO
* based on randomize 1.7
*
* Please send any patches or suggestions to the author: meo@rru.com .
*
* Blur applies a 3x3 blurring convolution kernel to the specified drawable.
*
* For each pixel in the selection or image,
* whether to change the pixel is decided by picking a
* random number, weighted by the user's "randomization" percentage.
* If the random number is in range, the pixel is modified. For
* blurring, an average is determined from the current and adjacent
* pixels. *(Except for the random factor, the blur code came
* straight from the original S&P blur plug-in.)*
*
* This works only with RGB and grayscale images.
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "libgimp/gimp.h"
#include "gtk/gtk.h"
#include <plug-ins/gpc/gpc.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "libgimp/stdplugins-intl.h"
/*********************************
*
* PLUGIN-SPECIFIC CONSTANTS
*
********************************/
/*
* progress meter update frequency
*/
#define PROG_UPDATE_TIME ((row % 10) == 0)
#define PLUG_IN_NAME "plug_in_blur"
#define BLUR_VERSION "Blur 2.0"
#define SEED_TIME 10
#define SEED_USER 11
#define ENTRY_WIDTH 75
#define SCALE_WIDTH 100
/*********************************
*
* PLUGIN-SPECIFIC STRUCTURES AND DATA
*
********************************/
typedef struct {
gdouble blur_pct; /* likelihood of randomization (as %age) */
gdouble blur_rcount; /* repeat count */
gint seed_type; /* seed init. type - current time or user value */
gint blur_seed; /* seed value for rand() function */
} BlurVals;
static BlurVals pivals = {
50.0,
1.0,
SEED_TIME,
0,
};
typedef struct {
gint run;
} BlurInterface;
static BlurInterface blur_int = {
FALSE /* have we run? */
};
/*********************************
*
* LOCAL FUNCTIONS
*
********************************/
static void query(void);
static void run(
char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals
);
GPlugInInfo PLUG_IN_INFO = {
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
static void blur(GDrawable *drawable);
static inline void blur_prepare_row(
GPixelRgn *pixel_rgn,
guchar *data,
int x,
int y,
int w
);
static gint blur_dialog();
static void blur_ok_callback(
GtkWidget *widget,
gpointer data
);
/************************************ Guts ***********************************/
MAIN()
/*********************************
*
* query() - query_proc
*
* called by the GIMP to learn about this plug-in
*
********************************/
static void
query()
{
static GParamDef args_ni[] = {
{ PARAM_INT32, "run_mode", "non-interactive" },
{ PARAM_IMAGE, "image", "Input image (unused)" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
};
static int nargs_ni = sizeof(args_ni) / sizeof (args_ni[0]);
static GParamDef args[] = {
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image (unused)" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_FLOAT, "blur_pct", "Randomization percentage (1 - 100)" },
{ PARAM_FLOAT, "blur_rcount", "Repeat count(1 - 100)" },
{ PARAM_INT32, "seed_type", "Seed type (10 = current time, 11 = seed value)" },
{ PARAM_INT32, "blur_seed", "Seed value (used only if seed type is 11)" },
};
static int nargs = sizeof(args) / sizeof (args[0]);
static GParamDef *return_vals = NULL;
static int nreturn_vals = 0;
const char *blurb = _("Apply a 3x3 blurring convolution kernel to the specified drawable.");
const char *help = _("This plug-in randomly blurs the specified drawable, using a 3x3 blur. You control the percentage of the pixels that are blurred and the number of times blurring is applied. Indexed images are not supported.");
const char *author = "Miles O'Neal <meo@rru.com> http://www.rru.com/~meo/";
const char *copyrights = "Miles O'Neal, Spencer Kimball, Peter Mattis, Torsten Martinsen, Brian Degenhardt, Federico Mena Quintero, Stephen Norris, Daniel Cotting";
const char *copyright_date = "1995-1998";
INIT_I18N();
gimp_install_procedure("plug_in_blur_randomize",
(char *) blurb,
(char *) help,
(char *) author,
(char *) copyrights,
(char *) copyright_date,
_("<Image>/Filters/Blur/Blur"),
"RGB*, GRAY*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
gimp_install_procedure(PLUG_IN_NAME,
(char *) blurb,
(char *) help,
(char *) author,
(char *) copyrights,
(char *) copyright_date,
NULL,
"RGB*, GRAY*",
PROC_PLUG_IN,
nargs_ni, nreturn_vals,
args_ni, return_vals);
}
/*********************************
*
* run() - main routine
*
* This handles the main interaction with the GIMP itself,
* and invokes the routine that actually does the work.
*
********************************/
static void
run(char *name, int nparams, GParam *param, int *nreturn_vals,
GParam **return_vals)
{
GDrawable *drawable;
GRunModeType run_mode;
GStatusType status = STATUS_SUCCESS; /* assume the best! */
char prog_label[32];
static GParam values[1];
INIT_I18N();
/*
* Get the specified drawable, do standard initialization.
*/
run_mode = param[0].data.d_int32;
drawable = gimp_drawable_get(param[2].data.d_drawable);
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
*nreturn_vals = 1;
*return_vals = values;
/*
* Make sure the drawable type is appropriate.
*/
if (gimp_drawable_color(drawable->id) ||
gimp_drawable_gray(drawable->id)) {
switch (run_mode) {
/*
* If we're running interactively, pop up the dialog box.
*/
case RUN_INTERACTIVE:
gimp_get_data(PLUG_IN_NAME, &pivals);
if (!blur_dialog()) /* return on Cancel */
return;
break;
/*
* If we're not interactive (probably scripting), we
* get the parameters from the param[] array, since
* we don't use the dialog box. Make sure all
* parameters have legitimate values.
*/
case RUN_NONINTERACTIVE:
if ((strcmp(name, "plug_in_blur_randomize") == 0) &&
(nparams == 7)) {
pivals.blur_pct = (gdouble)param[3].data.d_float;
pivals.blur_pct = (gdouble)MIN(100.0, pivals.blur_pct);
pivals.blur_pct = (gdouble)MAX(1.0, pivals.blur_pct);
pivals.blur_rcount = (gdouble)param[4].data.d_float;
pivals.blur_rcount = (gdouble)MIN(100.0,pivals.blur_rcount);
pivals.blur_rcount = (gdouble)MAX(1.0, pivals.blur_rcount);
pivals.seed_type = (gint) param[5].data.d_int32;
pivals.seed_type = (gint) MIN(SEED_USER, param[5].data.d_int32);
pivals.seed_type = (gint) MAX(SEED_TIME, param[5].data.d_int32);
pivals.blur_seed = (gint) param[6].data.d_int32;
status = STATUS_SUCCESS;
} else if ((strcmp(name, PLUG_IN_NAME) == 0) &&
(nparams == 3)) {
pivals.blur_pct = (gdouble) 100.0;
pivals.blur_rcount = (gdouble) 1.0;
pivals.seed_type = SEED_TIME;
pivals.blur_seed = 0;
status = STATUS_SUCCESS;
} else {
status = STATUS_CALLING_ERROR;
}
break;
/*
* If we're running with the last set of values, get those values.
*/
case RUN_WITH_LAST_VALS:
gimp_get_data(PLUG_IN_NAME, &pivals);
break;
/*
* Hopefully we never get here!
*/
default:
break;
}
if (status == STATUS_SUCCESS) {
/*
* JUST DO IT!
*/
strcpy(prog_label, BLUR_VERSION);
gimp_progress_init(prog_label);
gimp_tile_cache_ntiles(2 * (drawable->width / gimp_tile_width() + 1));
/*
* Initialize the rand() function seed
*/
if (pivals.seed_type == SEED_TIME)
srand(time(NULL));
else
srand(pivals.blur_seed);
blur(drawable);
/*
* If we ran interactively (even repeating) update the display.
*/
if (run_mode != RUN_NONINTERACTIVE) {
gimp_displays_flush();
}
/*
* If we use the dialog popup, set the data for future use.
*/
if (run_mode == RUN_INTERACTIVE) {
gimp_set_data(PLUG_IN_NAME, &pivals, sizeof(BlurVals));
}
}
} else {
/*
* If we got the wrong drawable type, we need to complain.
*/
status = STATUS_EXECUTION_ERROR;
}
/*
* DONE!
* Set the status where the GIMP can see it, and let go
* of the drawable.
*/
values[0].data.d_status = status;
gimp_drawable_detach(drawable);
}
/*********************************
*
* blur_prepare_row()
*
* Get a row of pixels. If the requested row
* is off the edge, clone the edge row.
*
********************************/
static inline void
blur_prepare_row(GPixelRgn *pixel_rgn, guchar *data, int x, int y, int w)
{
int b;
if (y == 0) {
gimp_pixel_rgn_get_row(pixel_rgn, data, x, (y + 1), w);
} else if (y == pixel_rgn->h) {
gimp_pixel_rgn_get_row(pixel_rgn, data, x, (y - 1), w);
} else {
gimp_pixel_rgn_get_row(pixel_rgn, data, x, y, w);
}
/*
* Fill in edge pixels
*/
for (b = 0; b < pixel_rgn->bpp; b++) {
data[-(gint)pixel_rgn->bpp + b] = data[b];
data[w * pixel_rgn->bpp + b] = data[(w - 1) * pixel_rgn->bpp + b];
}
}
/*********************************
*
* blur()
*
* Actually mess with the image.
*
********************************/
static void
blur(GDrawable *drawable)
{
GPixelRgn srcPR, destPR, destPR2, *sp, *dp, *tp;
gint width, height;
gint bytes;
guchar *dest, *d;
guchar *prev_row, *pr;
guchar *cur_row, *cr;
guchar *next_row, *nr;
guchar *tmp;
gint row, col;
gint x1, y1, x2, y2;
gint cnt;
gint has_alpha, ind;
/*
* Get the input area. This is the bounding box of the selection in
* the image (or the entire image if there is no selection). Only
* operating on the input area is simply an optimization. It doesn't
* need to be done for correct operation. (It simply makes it go
* faster, since fewer pixels need to be operated on).
*/
gimp_drawable_mask_bounds(drawable->id, &x1, &y1, &x2, &y2);
/*
* Get the size of the input image. (This will/must be the same
* as the size of the output image. Also get alpha info.
*/
width = drawable->width;
height = drawable->height;
bytes = drawable->bpp;
has_alpha = gimp_drawable_has_alpha(drawable->id);
/*
* allocate row buffers
*/
prev_row = (guchar *) malloc((x2 - x1 + 2) * bytes);
cur_row = (guchar *) malloc((x2 - x1 + 2) * bytes);
next_row = (guchar *) malloc((x2 - x1 + 2) * bytes);
dest = (guchar *) malloc((x2 - x1) * bytes);
/*
* initialize the pixel regions
*/
gimp_pixel_rgn_init(&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
gimp_pixel_rgn_init(&destPR, drawable, 0, 0, width, height, TRUE, TRUE);
gimp_pixel_rgn_init(&destPR2, drawable, 0, 0, width, height, TRUE, TRUE);
sp = &srcPR;
dp = &destPR;
tp = NULL;
pr = prev_row + bytes;
cr = cur_row + bytes;
nr = next_row + bytes;
for (cnt = 1; cnt <= pivals.blur_rcount; cnt++) {
/*
* prepare the first row and previous row
*/
blur_prepare_row(sp, pr, x1, y1 - 1, (x2 - x1));
blur_prepare_row(dp, cr, x1, y1, (x2 - x1));
/*
* loop through the rows, applying the selected convolution
*/
for (row = y1; row < y2; row++) {
/* prepare the next row */
blur_prepare_row(sp, nr, x1, row + 1, (x2 - x1));
d = dest;
ind = 0;
for (col = 0; col < (x2 - x1) * bytes; col++) {
if (((rand() % 100)) <= (gint) pivals.blur_pct) {
ind++;
if (ind==bytes || !(has_alpha)) {
/*
* If no alpha channel, or if there is one and this is it...
*/
*d++ = ((gint) pr[col - bytes] + (gint) pr[col] +
(gint) pr[col + bytes] +
(gint) cr[col - bytes] + (gint) cr[col] +
(gint) cr[col + bytes] +
(gint) nr[col - bytes] + (gint) nr[col] +
(gint) nr[col + bytes]) / 9;
ind = 0;
} else {
/*
* otherwise we have an alpha channel, but this is a color channel
*/
*d++ = ((gint) (((gdouble) (pr[col - bytes] * pr[col - ind])
+ (gdouble) (pr[col] * pr[col + bytes - ind])
+ (gdouble) (pr[col + bytes] * pr[col + 2*bytes - ind])
+ (gdouble) (cr[col - bytes] * cr[col - ind])
+ (gdouble) (cr[col] * cr[col + bytes - ind])
+ (gdouble) (cr[col + bytes] * cr[col + 2*bytes - ind])
+ (gdouble) (nr[col - bytes] * nr[col - ind])
+ (gdouble) (nr[col] * nr[col + bytes - ind])
+ (gdouble) (nr[col + bytes] * nr[col + 2*bytes - ind]))
/ ((gdouble) pr[col - ind]
+ (gdouble) pr[col + bytes - ind]
+ (gdouble) pr[col + 2*bytes - ind]
+ (gdouble) cr[col - ind]
+ (gdouble) cr[col + bytes - ind]
+ (gdouble) cr[col + 2*bytes - ind]
+ (gdouble) nr[col - ind]
+ (gdouble) nr[col + bytes - ind]
+ (gdouble) nr[col + 2*bytes - ind])));
}
/*
* Otherwise, this pixel was not selected for randomization,
* so use the current value.
*/
} else {
*d++ = (gint) cr[col];
}
}
/*
* Save the modified row, shuffle the row pointers, and every
* so often, update the progress meter.
*/
gimp_pixel_rgn_set_row(dp, dest, x1, row, (x2 - x1));
tmp = pr;
pr = cr;
cr = nr;
nr = tmp;
if (PROG_UPDATE_TIME)
gimp_progress_update((double) row / (double) (y2 - y1));
}
/*
* if we have more cycles to perform, swap the src and dest Pixel Regions
*/
if (cnt < pivals.blur_rcount) {
if (tp != NULL) {
tp = dp;
dp = sp;
sp = tp;
} else {
tp = &srcPR;
sp = &destPR;
dp = &destPR2;
}
}
}
gimp_progress_update((double) 100);
/*
* update the blurred region
*/
gimp_drawable_flush(drawable);
gimp_drawable_merge_shadow(drawable->id, TRUE);
gimp_drawable_update(drawable->id, x1, y1, (x2 - x1), (y2 - y1));
/*
* clean up after ourselves.
*/
free(prev_row);
free(cur_row);
free(next_row);
free(dest);
}
/*********************************
*
* GUI ROUTINES
*
********************************/
/*********************************
*
* blur_dialog() - set up the plug-in's dialog box
*
********************************/
static gint
blur_dialog()
{
GtkWidget *dlg, *entry, *frame,
*seed_hbox, *seed_vbox, *table;
GSList *seed_group = NULL;
gchar **argv;
gint argc;
gchar buffer[10];
/*
* various initializations
*/
gint do_time = (pivals.seed_type == SEED_TIME);
gint do_user = (pivals.seed_type == SEED_USER);
argc = 1;
argv = g_new(gchar *, 1);
argv[0] = g_strdup("blur");
gtk_init(&argc, &argv);
gtk_rc_parse(gimp_gtkrc());
/*
* Open a new dialog, label it and set up its
* destroy callback.
*/
dlg = gtk_dialog_new();
gtk_window_set_title(GTK_WINDOW(dlg), BLUR_VERSION);
gtk_window_position(GTK_WINDOW(dlg), GTK_WIN_POS_MOUSE);
gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
(GtkSignalFunc) gpc_close_callback, NULL);
/*
* Parameter settings
*
* First set up the basic containers, label them, etc.
*/
frame = gtk_frame_new(_("Parameter Settings"));
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width(GTK_CONTAINER(frame), 10);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), frame, TRUE, TRUE, 0);
table = gtk_table_new(4, 2, FALSE);
gtk_container_border_width(GTK_CONTAINER(table), 10);
gtk_container_add(GTK_CONTAINER(frame), table);
gtk_widget_show(table);
gpc_setup_tooltips(table);
/*
* Action area OK & Cancel buttons
*/
gpc_add_action_button(_("OK"), (GtkSignalFunc) blur_ok_callback, dlg,
_("Accept settings and apply filter to image"));
gpc_add_action_button(_("Cancel"), (GtkSignalFunc) gpc_cancel_callback, dlg,
_("Close plug-in without making any changes"));
/*
* Randomization seed initialization controls
*/
gpc_add_label(_("Randomization Seed:"), table, 0, 1, 1, 2);
/*
* Box to hold seed initialization radio buttons
*/
seed_vbox = gtk_vbox_new(FALSE, 2);
gtk_container_border_width(GTK_CONTAINER(seed_vbox), 5);
gtk_table_attach(GTK_TABLE(table), seed_vbox, 1, 2, 1, 2,
GTK_FILL | GTK_EXPAND, GTK_FILL, 5, 0);
/*
* Time button
*/
gpc_add_radio_button(&seed_group, _("Current Time"), seed_vbox, &do_time,
_("Seed random number generator from the current time - this guarantees a reasonable randomization"));
/*
* Box to hold seed user initialization controls
*/
seed_hbox = gtk_hbox_new(FALSE, 3);
gtk_container_border_width(GTK_CONTAINER(seed_hbox), 0);
gtk_box_pack_start(GTK_BOX(seed_vbox), seed_hbox, FALSE, FALSE, 0);
/*
* User button
*/
gpc_add_radio_button(&seed_group, _("Other Value"), seed_hbox, &do_user,
_("Enable user-entered value for random number generator seed - this allows you to repeat a given \"random\" operation"));
/*
* Randomization seed number (text)
*/
entry = gtk_entry_new();
gtk_widget_set_usize(entry, ENTRY_WIDTH, 0);
gtk_box_pack_start(GTK_BOX(seed_hbox), entry, FALSE, FALSE, 0);
sprintf(buffer, "%d", pivals.blur_seed);
gtk_entry_set_text(GTK_ENTRY(entry), buffer);
gtk_signal_connect(GTK_OBJECT(entry), "changed",
(GtkSignalFunc) gpc_text_update, &pivals.blur_seed);
gtk_widget_show(entry);
gpc_set_tooltip(entry, _("Value for seeding the random number generator"));
gtk_widget_show(seed_hbox);
/*
* Randomization percentage label & scale (1 to 100)
*/
gpc_add_label(_("Randomization %:"), table, 0, 1, 2, 3);
gpc_add_hscale(table, SCALE_WIDTH,
1.0, 100.0, &pivals.blur_pct, 1, 2, 2, 3,
_("Percentage of pixels to be filtered"));
/*
* Repeat count label & scale (1 to 100)
*/
gpc_add_label(_("Repeat:"), table, 0, 1, 3, 4);
gpc_add_hscale(table, SCALE_WIDTH,
1.0, 100.0, &pivals.blur_rcount, 1, 2, 3, 4,
_("Number of times to apply filter"));
/*
* Display everything.
*/
gtk_widget_show(frame);
gtk_widget_show(dlg);
gtk_main();
gdk_flush();
/*
* Figure out which type of seed initialization to apply.
*/
if (do_time) {
pivals.seed_type = SEED_TIME;
} else {
pivals.seed_type = SEED_USER;
}
return blur_int.run;
}
static void
blur_ok_callback(GtkWidget *widget, gpointer data) {
blur_int.run = TRUE;
gtk_widget_destroy(GTK_WIDGET(data));
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
bumpmap

View file

@ -1,41 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = bumpmap
bumpmap_SOURCES = \
bumpmap.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/libgimp/libgimpui.la \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimpui.la \
$(top_builddir)/libgimp/libgimp.la
bumpmap_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
bz2

View file

@ -1,39 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = bz2
bz2_SOURCES = \
bz2.c
INCLUDES = \
-I$(top_srcdir) \
$(GLIB_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GLIB_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
bz2_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,457 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
* Copyright (C) 1997 Daniel Risacher
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* bzip2 plug-in for the gimp */
/* this is almost exactly the same as the gz(ip) plugin by */
/* Dan Risacher & Josh, so feel free to go look there. */
/* GZ plugin adapted to BZ2 by Adam. I've left all other */
/* Error checking added by srn. */
/* credits intact since it was only a super-wussy mod. */
/* This is reads and writes bzip2ed image files for the Gimp
*
* You need to have bzip2 installed for it to work.
*
* It should work with file names of the form
* filename.foo.bz2 where foo is some already-recognized extension
*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#ifdef __EMX__
#include <fcntl.h>
#include <process.h>
#endif
#include "libgimp/gimp.h"
#include "config.h"
#include "libgimp/stdplugins-intl.h"
static void query (void);
static void run (char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals);
static gint32 load_image (char *filename, gint32 run_mode);
static gint save_image (char *filename,
gint32 image_ID,
gint32 drawable_ID,
gint32 run_mode);
static int valid_file (char* filename) ;
static char* find_extension (char* filename) ;
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
MAIN ()
static void
query ()
{
static GParamDef load_args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_STRING, "filename", "The name of the file to load" },
{ PARAM_STRING, "raw_filename", "The name entered" },
};
static GParamDef load_return_vals[] =
{
{ PARAM_IMAGE, "image", "Output image" },
};
static int nload_args = sizeof (load_args) / sizeof (load_args[0]);
static int nload_return_vals = sizeof (load_return_vals) / sizeof (load_return_vals[0]);
static GParamDef save_args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image" },
{ PARAM_DRAWABLE, "drawable", "Drawable to save" },
{ PARAM_STRING, "filename", "The name of the file to save the image in" },
{ PARAM_STRING, "raw_filename", "The name of the file to save the image in" }
};
static int nsave_args = sizeof (save_args) / sizeof (save_args[0]);
gimp_install_procedure ("file_bz2_load",
"loads files compressed with bzip2",
"You need to have bzip2 installed.",
"Daniel Risacher",
"Daniel Risacher, Spencer Kimball and Peter Mattis",
"1995-1997",
"<Load>/bzip2",
NULL,
PROC_PLUG_IN,
nload_args, nload_return_vals,
load_args, load_return_vals);
gimp_install_procedure ("file_bz2_save",
"saves files compressed with bzip2",
"You need to have bzip2 installed",
"Daniel Risacher",
"Daniel Risacher, Spencer Kimball and Peter Mattis",
"1995-1997",
"<Save>/bzip2",
"RGB*, GRAY*, INDEXED*",
PROC_PLUG_IN,
nsave_args, 0,
save_args, NULL);
gimp_register_load_handler ("file_bz2_load", "xcf.bz2,bz2,xcfbz2", "");
gimp_register_save_handler ("file_bz2_save", "xcf.bz2,bz2,xcfbz2", "");
}
static void
run (char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals)
{
static GParam values[2];
GRunModeType run_mode;
GStatusType status = STATUS_SUCCESS;
gint32 image_ID;
INIT_I18N();
run_mode = param[0].data.d_int32;
*nreturn_vals = 1;
*return_vals = values;
values[0].type = PARAM_STATUS;
values[0].data.d_status = STATUS_CALLING_ERROR;
if (strcmp (name, "file_bz2_load") == 0)
{
image_ID = load_image (param[1].data.d_string,
param[0].data.d_int32);
if (image_ID != -1)
{
*nreturn_vals = 2;
values[0].data.d_status = STATUS_SUCCESS;
values[1].type = PARAM_IMAGE;
values[1].data.d_image = image_ID;
}
else
{
values[0].data.d_status = STATUS_EXECUTION_ERROR;
g_assert (FALSE);
}
}
else if (strcmp (name, "file_bz2_save") == 0)
{
switch (run_mode)
{
case RUN_INTERACTIVE:
break;
case RUN_NONINTERACTIVE:
/* Make sure all the arguments are there! */
if (nparams != 4)
status = STATUS_CALLING_ERROR;
case RUN_WITH_LAST_VALS:
break;
default:
break;
}
*nreturn_vals = 1;
if (save_image (param[3].data.d_string,
param[1].data.d_int32,
param[2].data.d_int32,
param[0].data.d_int32 ))
{
values[0].data.d_status = STATUS_SUCCESS;
}
else
values[0].data.d_status = STATUS_EXECUTION_ERROR;
}
else
g_assert (FALSE);
}
#ifdef __EMX__
static int spawn_bz(char *filename, char* tmpname, char *parms, int *pid)
{
FILE *f;
int tfd;
if (!(f = fopen(filename,"wb"))){
g_message("bz: fopen failed: %s\n", g_strerror(errno));
return -1;
}
/* save fileno(stdout) */
tfd = dup(fileno(stdout));
/* make stdout for this process be the output file */
if (dup2(fileno(f),fileno(stdout)) == -1)
{
g_message ("bz: dup2 failed: %s\n", g_strerror(errno));
close(tfd);
return -1;
}
fcntl(tfd, F_SETFD, FD_CLOEXEC);
*pid = spawnlp (P_NOWAIT, "bzip2", "bzip2", parms, tmpname, NULL);
fclose(f);
/* restore fileno(stdout) */
dup2(tfd,fileno(stdout));
close(tfd);
if (*pid == -1)
{
g_message ("bz: spawn failed: %s\n", g_strerror(errno));
return -1;
}
return 0;
}
#endif
static gint
save_image (char *filename,
gint32 image_ID,
gint32 drawable_ID,
gint32 run_mode)
{
FILE* f;
GParam* params;
gint retvals;
char* ext;
char* tmpname;
int pid;
int status;
if (NULL == (ext = find_extension(filename))) return -1;
/* get a temp name with the right extension and save into it. */
params = gimp_run_procedure ("gimp_temp_name",
&retvals,
PARAM_STRING, ext + 1,
PARAM_END);
tmpname = params[1].data.d_string;
params = gimp_run_procedure ("gimp_file_save",
&retvals,
PARAM_INT32, run_mode,
PARAM_IMAGE, image_ID,
PARAM_DRAWABLE, drawable_ID,
PARAM_STRING, tmpname,
PARAM_STRING, tmpname,
PARAM_END);
if (params[0].data.d_status == FALSE || !valid_file(tmpname)) {
unlink (tmpname);
return -1;
}
/* if (! file_save(image_ID, tmpname, tmpname)) { */
/* unlink (tmpname); */
/* return -1; */
/* } */
#ifndef __EMX__
/* fork off a bzip2 process */
if ((pid = fork()) < 0)
{
g_message (_("bz2: fork failed: %s\n"), g_strerror(errno));
return -1;
}
else if (pid == 0)
{
if (!(f = fopen(filename,"w"))){
g_message(_("bz2: fopen failed: %s\n"), g_strerror(errno));
_exit(127);
}
/* make stdout for this process be the output file */
if (-1 == dup2(fileno(f),fileno(stdout)))
g_message (_("bz2: dup2 failed: %s\n"), g_strerror(errno));
/* and bzip2 into it */
execlp ("bzip2", "bzip2", "-cf", tmpname, NULL);
g_message (_("bz2: exec failed: bzip2: %s\n"), g_strerror(errno));
_exit(127);
}
else
#else /* __EMX__ */
if (spawn_bz(filename, tmpname, "-cf", &pid) == -1)
return -1;
#endif
{
waitpid (pid, &status, 0);
if (!WIFEXITED(status) ||
WEXITSTATUS(status) != 0)
{
g_message (_("bz2: bzip2 exited abnormally on file %s\n"), tmpname);
return 0;
}
}
unlink (tmpname);
return TRUE;
}
static gint32
load_image (char *filename, gint32 run_mode)
{
GParam* params;
gint retvals;
char* ext;
char* tmpname;
int pid;
int status;
if (NULL == (ext = find_extension(filename))) return -1;
/* find a temp name */
params = gimp_run_procedure ("gimp_temp_name",
&retvals,
PARAM_STRING, ext + 1,
PARAM_END);
tmpname = params[1].data.d_string;
#ifndef __EMX__
/* fork off a g(un)zip and wait for it */
if ((pid = fork()) < 0)
{
g_message (_("bz2: fork failed: %s\n"), g_strerror(errno));
return -1;
}
else if (pid == 0) /* child process */
{
FILE* f;
if (!(f = fopen(tmpname,"w"))){
g_message(_("bz2: fopen failed: %s\n"), g_strerror(errno));
_exit(127);
}
/* make stdout for this child process be the temp file */
if (-1 == dup2(fileno(f),fileno(stdout)))
g_message (_("bz2: dup2 failed: %s\n"), g_strerror(errno));
/* and unzip into it */
execlp ("bzip2", "bzip2", "-cfd", filename, NULL);
g_message (_("bz2: exec failed: bunzip2: %s\n"), g_strerror(errno));
_exit(127);
}
else /* parent process */
#else /* __EMX__ */
if (spawn_bz(filename, tmpname, "-cfd", &pid) == -1)
return -1;
#endif
{
waitpid (pid, &status, 0);
if (!WIFEXITED(status) ||
WEXITSTATUS(status) != 0)
{
g_message (_("bz2: bzip2 exited abnormally on file %s\n"), filename);
return -1;
}
}
/* now that we un-bzip2ed it, load the temp file */
params = gimp_run_procedure ("gimp_file_load",
&retvals,
PARAM_INT32, run_mode,
PARAM_STRING, tmpname,
PARAM_STRING, tmpname,
PARAM_END);
unlink (tmpname);
if (params[0].data.d_status == FALSE)
return -1;
else
{
gimp_image_set_filename (params[1].data.d_int32, filename);
return params[1].data.d_int32;
}
}
static int valid_file (char* filename)
{
int stat_res;
struct stat buf;
stat_res = stat(filename, &buf);
if ((0 == stat_res) && (buf.st_size > 0))
return 1;
else
return 0;
}
static char* find_extension (char* filename)
{
char* filename_copy;
char* ext;
/* we never free this copy - aren't we evil! */
filename_copy = malloc(strlen(filename)+1);
strcpy(filename_copy, filename);
/* find the extension, boy! */
ext = strrchr (filename_copy, '.');
while (1) {
if (!ext || ext[1] == 0 || strchr(ext, '/'))
{
g_message (_("bz2: can't open bzip2ed file without a sensible extension\n"));
return NULL;
}
if (0 == strcmp(ext, ".xcfbz2")) {
return ".xcf"; /* we've found it */
}
if (0 != strcmp(ext,".bz2")) {
return ext;
} else {
/* we found ".bz2" so strip it, loop back, and look again */
*ext = 0;
ext = strrchr (filename_copy, '.');
}
}
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
c_astretch

View file

@ -1,36 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = c_astretch
c_astretch_SOURCES = \
c_astretch.c
INCLUDES = \
-I$(top_srcdir) \
$(GLIB_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GLIB_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
c_astretch_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,292 +0,0 @@
/* Contrast Autostretch 1.06 --- image filter plug-in for The Gimp image
* manipulation program
*
* Copyright (C) 1996 Federico Mena Quintero
*
* You can contact me at quartic@polloux.fciencias.unam.mx
* You can contact the original The Gimp authors at gimp@xcf.berkeley.edu
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* This simple plug-in does an automatic contrast stretch. For each
channel in the image, it finds the minimum and maximum values... it
uses those values to stretch the individual histograms to the full
contrast range. For some images it may do just what you want; for
others it may be total crap :) */
#include <stdlib.h>
#include <stdio.h>
#include "libgimp/gimp.h"
/* Declare local functions.
*/
static void query (void);
static void run (char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals);
static void c_astretch (GDrawable * drawable);
static void indexed_c_astretch (gint32 image_ID);
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
MAIN ()
static void
query ()
{
static GParamDef args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
};
static GParamDef *return_vals = NULL;
static int nargs = sizeof (args) / sizeof (args[0]);
static int nreturn_vals = 0;
gimp_install_procedure ("plug_in_c_astretch",
"Automatically stretch the contrast of the specified drawable to cover all possible ranges.",
"This simple plug-in does an automatic contrast stretch. For each channel in the image, it finds the minimum and maximum values... it uses those values to stretch the individual histograms to the full contrast range. For some images it may do just what you want; for others it may be total crap :)",
"Federico Mena Quintero",
"Federico Mena Quintero",
"1996",
"<Image>/Image/Colors/Auto-Stretch Contrast",
"RGB*, GRAY*, INDEXED*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
static void
run (char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals)
{
static GParam values[1];
GDrawable *drawable;
GRunModeType run_mode;
GStatusType status = STATUS_SUCCESS;
gint32 image_ID;
run_mode = param[0].data.d_int32;
/* Get the specified drawable */
drawable = gimp_drawable_get (param[2].data.d_drawable);
image_ID = param[1].data.d_image;
/* Make sure that the drawable is gray or RGB color */
if (gimp_drawable_color (drawable->id) || gimp_drawable_gray (drawable->id))
{
gimp_progress_init ("Auto-Stretching Contrast...");
gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width () + 1));
c_astretch (drawable);
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush ();
}
else if (gimp_drawable_indexed (drawable->id))
{
indexed_c_astretch (image_ID);
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush ();
}
else
{
/* gimp_message ("c_astretch: cannot operate on indexed color images"); */
status = STATUS_EXECUTION_ERROR;
}
*nreturn_vals = 1;
*return_vals = values;
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
gimp_drawable_detach (drawable);
}
static void
indexed_c_astretch(gint32 image_ID) /* a.d.m. */
{
guchar *cmap;
gint ncols,i;
gint rhi=0,ghi=0,bhi=0,rlo=255,glo=255,blo=255;
cmap = gimp_image_get_cmap (image_ID, &ncols);
if (cmap==NULL)
{
printf("c_astretch: cmap was NULL! Quitting...\n");
gimp_quit();
}
for (i=0;i<ncols;i++)
{
if (cmap[i*3 +0] > rhi) rhi=cmap[i*3 +0];
if (cmap[i*3 +1] > ghi) ghi=cmap[i*3 +1];
if (cmap[i*3 +2] > bhi) bhi=cmap[i*3 +2];
if (cmap[i*3 +0] < rlo) rlo=cmap[i*3 +0];
if (cmap[i*3 +1] < glo) glo=cmap[i*3 +1];
if (cmap[i*3 +2] < blo) blo=cmap[i*3 +2];
}
for (i=0;i<ncols;i++)
{
if (rhi!=rlo)
cmap[i*3 +0] = (255 * (cmap[i*3 +0] - rlo)) / (rhi-rlo);
if (ghi!=glo)
cmap[i*3 +1] = (255 * (cmap[i*3 +1] - glo)) / (ghi-glo);
if (rhi!=rlo)
cmap[i*3 +2] = (255 * (cmap[i*3 +2] - blo)) / (bhi-blo);
}
gimp_image_set_cmap (image_ID, cmap, ncols);
}
static void
c_astretch (GDrawable *drawable)
{
GPixelRgn src_rgn, dest_rgn;
guchar *src, *s;
guchar *dest, *d;
guchar min[3], max[3];
guchar range;
guchar lut[256][3];
gint progress, max_progress;
gint has_alpha, alpha;
gint x1, y1, x2, y2;
gint x, y, b;
gpointer pr;
/* Get selection area */
gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
has_alpha = gimp_drawable_has_alpha (drawable->id);
alpha = (has_alpha) ? drawable->bpp - 1 : drawable->bpp;
/* Initialize progress */
progress = 0;
max_progress = (x2 - x1) * (y2 - y1) * 2;
/* Get minimum and maximum values for each channel */
min[0] = min[1] = min[2] = 255;
max[0] = max[1] = max[2] = 0;
gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, (x2 - x1), (y2 - y1), FALSE, FALSE);
for (pr = gimp_pixel_rgns_register (1, &src_rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr))
{
src = src_rgn.data;
for (y = 0; y < src_rgn.h; y++)
{
s = src;
for (x = 0; x < src_rgn.w; x++)
{
for (b = 0; b < alpha; b++)
{
if (!has_alpha || (has_alpha && s[alpha]))
{
if (s[b] < min[b])
min[b] = s[b];
if (s[b] > max[b])
max[b] = s[b];
}
}
s += src_rgn.bpp;
}
src += src_rgn.rowstride;
}
/* Update progress */
progress += src_rgn.w * src_rgn.h;
gimp_progress_update ((double) progress / (double) max_progress);
}
/* Calculate LUTs with stretched contrast */
for (b = 0; b < alpha; b++)
{
range = max[b] - min[b];
if (range != 0)
for (x = min[b]; x <= max[b]; x++)
lut[x][b] = 255 * (x - min[b]) / range;
else
lut[min[b]][b] = min[b];
}
/* Now substitute pixel vales */
gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, (x2 - x1), (y2 - y1), FALSE, FALSE);
gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, (x2 - x1), (y2 - y1), TRUE, TRUE);
for (pr = gimp_pixel_rgns_register (2, &src_rgn, &dest_rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr))
{
src = src_rgn.data;
dest = dest_rgn.data;
for (y = 0; y < src_rgn.h; y++)
{
s = src;
d = dest;
for (x = 0; x < src_rgn.w; x++)
{
for (b = 0; b < alpha; b++)
d[b] = lut[s[b]][b];
if (has_alpha)
d[alpha] = s[alpha];
s += src_rgn.bpp;
d += dest_rgn.bpp;
}
src += src_rgn.rowstride;
dest += dest_rgn.rowstride;
}
/* Update progress */
progress += src_rgn.w * src_rgn.h;
gimp_progress_update ((double) progress / (double) max_progress);
}
/* update the region */
gimp_drawable_flush (drawable);
gimp_drawable_merge_shadow (drawable->id, TRUE);
gimp_drawable_update (drawable->id, x1, y1, (x2 - x1), (y2 - y1));
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
checkerboard

View file

@ -1,39 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = checkerboard
checkerboard_SOURCES = \
checkerboard.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
checkerboard_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,477 +0,0 @@
/*
* This is a plug-in for the GIMP.
*
* Copyright (C) 1997 Brent Burton & the Edward Blevins
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include "gtk/gtk.h"
#include "libgimp/gimp.h"
#include "config.h"
#include "libgimp/stdplugins-intl.h"
/* Variables set in dialog box */
typedef struct data {
gint mode;
gint size;
} CheckVals;
typedef struct {
gint run;
} CheckInterface;
static CheckInterface cint =
{
FALSE
};
static void query (void);
static void run (gchar *name,
gint nparams,
GParam *param,
gint *nreturn_vals,
GParam **return_vals);
static void check (GDrawable * drawable);
static gint check_dialog (void);
static void check_close_callback (GtkWidget *widget, gpointer data);
static void check_ok_callback (GtkWidget *widget, gpointer data);
static void check_toggle_update (GtkWidget *widget, gpointer data);
static void check_slider_update (GtkAdjustment *adjustment, gint *size_val);
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
static CheckVals cvals =
{
0,
10
};
static int inblock(int pos, int size);
MAIN ()
static void
query ()
{
static GParamDef args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image (unused)" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_INT32, "check_mode", "Regular or Physcobilly" },
{ PARAM_INT32, "check_size", "Size of the checks" }
};
static GParamDef *return_vals = NULL;
static int nargs = sizeof (args) / sizeof (args[0]);
static int nreturn_vals = 0;
INIT_I18N();
gimp_install_procedure ("plug_in_checkerboard",
_("Adds a checkerboard pattern to an image"),
"More here later",
"Brent Burton & the Edward Blevins",
"Brent Burton & the Edward Blevins",
"1997",
_("<Image>/Filters/Render/Checkerboard"),
"RGB*, GRAY*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
static void
run (gchar *name,
gint nparams,
GParam *param,
gint *nreturn_vals,
GParam **return_vals)
{
static GParam values[1];
GDrawable *drawable;
GRunModeType run_mode;
GStatusType status = STATUS_SUCCESS;
INIT_I18N();
run_mode = param[0].data.d_int32;
*nreturn_vals = 1;
*return_vals = values;
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
drawable = gimp_drawable_get (param[2].data.d_drawable);
switch (run_mode)
{
case RUN_INTERACTIVE:
gimp_get_data ("plug_in_checkerboard", &cvals);
if (! check_dialog())
{
gimp_drawable_detach (drawable);
return;
}
break;
case RUN_NONINTERACTIVE:
if (nparams != 5)
status = STATUS_CALLING_ERROR;
if (status == STATUS_SUCCESS)
{
cvals.mode = param[3].data.d_int32;
cvals.size = param[4].data.d_int32;
}
break;
case RUN_WITH_LAST_VALS:
gimp_get_data ("plug_in_checkerboard", &cvals);
break;
default:
break;
}
if (gimp_drawable_color (drawable->id) || gimp_drawable_gray (drawable->id))
{
gimp_progress_init (_("Adding Checkerboard..."));
check (drawable);
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush ();
if (run_mode == RUN_INTERACTIVE)
gimp_set_data ("plug_in_checkerboard", &cvals, sizeof (CheckVals));
}
else
{
status = STATUS_EXECUTION_ERROR;
}
values[0].data.d_status = status;
gimp_drawable_detach (drawable);
}
static void
check( GDrawable * drawable)
{
GPixelRgn dest_rgn;
GParam *return_vals;
gint nreturn_vals;
guchar *dest_row;
guchar *dest;
gint row, col;
gint progress, max_progress;
gint x1, y1, x2, y2, x, y;
guint8 fg[4],bg[4];
gint bp;
gpointer pr;
gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, (x2 - x1), (y2 - y1), TRUE, TRUE);
progress = 0;
max_progress = (x2 - x1) * (y2 - y1);
/* Get the foreground and background colors */
switch ( gimp_drawable_type (drawable->id) )
{
case RGBA_IMAGE:
fg[3] = 255;
bg[3] = 255;
case RGB_IMAGE :
return_vals = gimp_run_procedure ("gimp_palette_get_foreground",
&nreturn_vals,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
fg[0] = return_vals[1].data.d_color.red;
fg[1] = return_vals[1].data.d_color.green;
fg[2] = return_vals[1].data.d_color.blue;
}
else
{
fg[0] = 255;
fg[1] = 255;
fg[2] = 255;
}
return_vals = gimp_run_procedure ("gimp_palette_get_background",
&nreturn_vals,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
{
bg[0] = return_vals[1].data.d_color.red;
bg[1] = return_vals[1].data.d_color.green;
bg[2] = return_vals[1].data.d_color.blue;
}
else
{
bg[0] = 0;
bg[1] = 0;
bg[2] = 0;
}
break;
case GRAYA_IMAGE:
fg[1] = 255;
bg[1] = 255;
case GRAY_IMAGE :
fg[0] = 255;
bg[0] = 0;
break;
default:
break;
}
for (pr = gimp_pixel_rgns_register (1, &dest_rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr))
{
y = dest_rgn.y;
dest_row = dest_rgn.data;
for ( row = 0; row < dest_rgn.h; row++)
{
dest = dest_row;
x = dest_rgn.x;
for (col = 0; col < dest_rgn.w; col++)
{
gint val, xp, yp;
if (cvals.mode) {
/* Psychobilly Mode */
val = (inblock(x,cvals.size) == inblock(y,cvals.size)) ? 0 : 1;
}
else {
/* Normal, regular checkerboard mode.
* Determine base factor (even or odd) of block
* this x/y position is in.
*/
xp = x/cvals.size;
yp = y/cvals.size;
/* if both even or odd, color sqr */
val = ( (xp&1) == (yp&1) ) ? 0 : 1;
}
for (bp = 0; bp < dest_rgn.bpp; bp++)
dest[bp] = val ? fg[bp] : bg[bp];
dest += dest_rgn.bpp;
x++;
}
dest_row += dest_rgn.rowstride;
y++;
}
progress += dest_rgn.w * dest_rgn.h;
gimp_progress_update ((double) progress / (double) max_progress);
}
gimp_drawable_flush (drawable);
gimp_drawable_merge_shadow (drawable->id, TRUE);
gimp_drawable_update (drawable->id, x1, y1, (x2 - x1), (y2 - y1));
}
static int
inblock( gint pos, gint size)
{
static gint *in = NULL; /* initialized first time */
gint i,j,k, len;
/* avoid a FP exception */
if (size == 1)
size = 2;
len = size*size;
/*
* Initialize the array; since we'll be called thousands of
* times with the same size value, precompute the array.
*/
if (in == NULL) {
in = (int*)malloc(sizeof(int)* len);
if (in == NULL) {
return 0;
} else {
int cell = 1; /* cell value */
/*
* i is absolute index into in[]
* j is current number of blocks to fill in with a 1 or 0.
* k is just counter for the j cells.
*/
i=0;
for (j=1; j<=size; j++ ) { /* first half */
for (k=0; k<j; k++ ) {
in[i++] = cell;
}
cell = !cell;
}
for ( j=size-1; j>=1; j--) { /* second half */
for (k=0; k<j; k++ ) {
in[i++] = cell;
}
cell = !cell;
}
}
} /* if n NULL */
/* place pos within 0..(len-1) grid and return the value. */
return in[ pos % (len-1) ];
}
static gint
check_dialog ()
{
GtkWidget *dlg;
GtkWidget *button;
GtkWidget *frame;
GtkWidget *table;
GtkWidget *label;
GtkWidget *toggle;
GtkWidget *slider;
GtkObject *size_data;
gchar **argv;
gint argc;
argc = 1;
argv = g_new (gchar *, 1);
argv[0] = g_strdup ("whirl");
gtk_init (&argc, &argv);
gtk_rc_parse (gimp_gtkrc ());
dlg = gtk_dialog_new ();
gtk_window_set_title (GTK_WINDOW (dlg), _("Checkerboard"));
gtk_window_position (GTK_WINDOW (dlg), GTK_WIN_POS_MOUSE);
gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
(GtkSignalFunc) check_close_callback,
NULL);
/* Action area */
button = gtk_button_new_with_label (_("OK"));
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
(GtkSignalFunc) check_ok_callback,
dlg);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button, TRUE, TRUE, 0);
gtk_widget_grab_default (button);
gtk_widget_show (button);
button = gtk_button_new_with_label (_("Cancel"));
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
(GtkSignalFunc) gtk_widget_destroy,
GTK_OBJECT (dlg));
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button, TRUE, TRUE, 0);
gtk_widget_show (button);
/* parameter settings */
frame = gtk_frame_new (_("Parameter Settings"));
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width (GTK_CONTAINER (frame), 10);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, TRUE, TRUE, 0);
table = gtk_table_new (5, 5, FALSE);
gtk_container_border_width (GTK_CONTAINER (table), 10);
gtk_container_add (GTK_CONTAINER (frame), table);
toggle = gtk_check_button_new_with_label (_("Psychobilly"));
gtk_table_attach (GTK_TABLE (table), toggle, 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 5, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
(GtkSignalFunc) check_toggle_update,
&cvals.mode);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cvals.mode);
gtk_widget_show (toggle);
label = gtk_label_new (_("Check Size"));
gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
gtk_widget_show (label);
size_data = gtk_adjustment_new (cvals.size, 1, 400, 1, 1, 0);
slider = gtk_hscale_new (GTK_ADJUSTMENT (size_data));
gtk_widget_set_usize (slider, 300, 0);
gtk_table_attach (GTK_TABLE (table), slider, 0, 1, 4, 5, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
gtk_scale_set_value_pos (GTK_SCALE (slider), GTK_POS_TOP);
gtk_scale_set_digits (GTK_SCALE (slider), 0);
gtk_range_set_update_policy (GTK_RANGE (slider), GTK_UPDATE_DELAYED);
gtk_signal_connect (GTK_OBJECT (size_data), "value_changed",
(GtkSignalFunc) check_slider_update,
&cvals.size);
gtk_widget_show (slider);
gtk_widget_show (frame);
gtk_widget_show (table);
gtk_widget_show (dlg);
gtk_main ();
gdk_flush ();
return cint.run;
}
static void
check_slider_update (GtkAdjustment *adjustment,
gint *size_val)
{
*size_val = adjustment->value;
}
static void
check_toggle_update (GtkWidget *widget,
gpointer data)
{
gint *toggle_val;
toggle_val = (gint *) data;
if (GTK_TOGGLE_BUTTON (widget)->active)
*toggle_val = TRUE;
else
*toggle_val = FALSE;
}
static void
check_close_callback (GtkWidget *widget,
gpointer data)
{
gtk_main_quit ();
}
static void
check_ok_callback (GtkWidget *widget,
gpointer data)
{
cint.run = TRUE;
gtk_widget_destroy (GTK_WIDGET (data));
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
colorify

View file

@ -1,39 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = colorify
colorify_SOURCES = \
colorify.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
colorify_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,481 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* Colorify. Changes the pixel's luminosity to a specified color
* Copyright (C) 1997 Francisco Bustamante
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Changes:
1.1
-Corrected small bug when calling color selection dialog
-Added LUTs to speed things a little bit up
1.0
-First release */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gtk/gtk.h"
#include "libgimp/gimp.h"
#include "config.h"
#include "libgimp/stdplugins-intl.h"
#define PLUG_IN_NAME "Colorify"
#define PLUG_IN_VERSION "1.1"
static void query (void);
static void run (char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals);
typedef struct {
guchar color[3];
} ColorifyVals;
typedef struct {
gint run;
} ColorifyInterface;
typedef struct {
guchar red;
guchar green;
guchar blue;
GtkWidget *preview;
gint button_num;
} ButtonInformation;
static ColorifyInterface cint =
{
FALSE
};
static ColorifyVals cvals =
{
{255, 255, 255}
};
static ButtonInformation button_info[] =
{
{255, 0, 0, NULL, 0},
{255, 255, 0, NULL, 0},
{0, 255, 0, NULL, 0},
{0, 255, 255, NULL, 0},
{0, 0, 255, NULL, 0},
{255, 0, 255, NULL, 0},
{255, 255, 255, NULL, 0},
};
GPlugInInfo PLUG_IN_INFO =
{
NULL,
NULL,
query,
run,
};
gint lum_red_lookup[256], lum_green_lookup[256], lum_blue_lookup[256];
gint final_red_lookup[256], final_green_lookup[256], final_blue_lookup[256];
MAIN ()
static int colorify_dialog (guchar red, guchar green, guchar blue);
static void colorify (GDrawable *drawable);
static void set_preview_color (GtkWidget *preview, guchar red, guchar green, guchar blue);
static void
query ()
{
static GParamDef args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_COLOR, "color", "Color to apply"},
};
static GParamDef *return_vals = NULL;
static int nargs = sizeof(args) / sizeof(args[0]),
nreturn_vals = 0;
INIT_I18N();
gimp_install_procedure ("plug_in_colorify",
_("Similar to the \"Color\" mode for layers."),
_("Makes an average of the RGB channels and uses it to set the color"),
"Francisco Bustamante", "Francisco Bustamante",
"0.0.1",
_("<Image>/Filters/Colors/Colorify"), "RGB",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
gint sel_x1, sel_x2, sel_y1, sel_y2, sel_width, sel_height;
GtkWidget *preview;
GtkWidget *c_dialog;
static void
run (char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals)
{
GRunModeType run_mode;
GStatusType status;
static GParam values[1];
GDrawable *drawable;
INIT_I18N();
status = STATUS_SUCCESS;
run_mode = param[0].data.d_int32;
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
*nreturn_vals = 1;
*return_vals = values;
drawable = gimp_drawable_get (param[2].data.d_drawable);
gimp_drawable_mask_bounds (drawable->id, &sel_x1, &sel_y1, &sel_x2, &sel_y2);
sel_width = sel_x2 - sel_x1;
sel_height = sel_y2 - sel_y1;
switch (run_mode) {
case RUN_INTERACTIVE :
gimp_get_data(PLUG_IN_NAME, &cvals);
if (!colorify_dialog (cvals.color[0], cvals.color[1], cvals.color[2]))
return;
break;
case RUN_NONINTERACTIVE :
if (nparams != 4)
status = STATUS_CALLING_ERROR;
if (status == STATUS_SUCCESS) {
cvals.color[0] = param[3].data.d_color.red;
cvals.color[1] = param[3].data.d_color.green;
cvals.color[2] = param[3].data.d_color.blue;
}
break;
case RUN_WITH_LAST_VALS :
/* Possibly retrieve data */
gimp_get_data (PLUG_IN_NAME, &cvals);
break;
default :
break;
}
if (status == STATUS_SUCCESS) {
gimp_progress_init(_("Colorifying..."));
colorify (drawable);
if (run_mode == RUN_INTERACTIVE)
gimp_set_data (PLUG_IN_NAME, &cvals, sizeof (ColorifyVals));
if (run_mode != RUN_NONINTERACTIVE) {
gimp_displays_flush ();
}
}
values[0].data.d_status = status;
}
static void colorify_row (guchar *row,
gint width);
static void close_callback (GtkWidget *widget,
gpointer data);
static void colorify_ok_callback (GtkWidget *widget,
gpointer data);
static void custom_color_callback (GtkWidget *widget,
gpointer data);
static void predefined_color_callback (GtkWidget *widget,
gpointer data);
static void color_changed (GtkWidget *widget,
gpointer data);
static void
colorify (GDrawable *drawable)
{
GPixelRgn source_region, dest_region;
guchar *row;
gint y = 0;
gint progress = 0;
gint i = 0;
for (i = 0; i < 256; i ++) {
lum_red_lookup[i] = i * 0.30;
lum_green_lookup[i] = i * 0.59;
lum_blue_lookup[i] = i * 0.11;
final_red_lookup[i] = i * cvals.color[0] / 255;
final_green_lookup[i] = i * cvals.color[1] / 255;
final_blue_lookup[i] = i * cvals.color[2] / 255;
}
row = g_malloc (sel_width * 3 * sizeof(guchar));
gimp_pixel_rgn_init (&source_region, drawable, sel_x1, sel_y1, sel_width, sel_height, FALSE, FALSE);
gimp_pixel_rgn_init (&dest_region, drawable, sel_x1, sel_y1, sel_width, sel_height, TRUE, TRUE);
for (y = sel_y1; y < sel_y2; y++) {
gimp_pixel_rgn_get_row (&source_region, row, sel_x1, y, sel_width);
colorify_row (row, sel_width);
gimp_pixel_rgn_set_row (&dest_region, row, sel_x1, y, sel_width);
gimp_progress_update ((double) ++progress / sel_height);
}
g_free (row);
gimp_drawable_flush (drawable);
gimp_drawable_merge_shadow (drawable->id, TRUE);
gimp_drawable_update (drawable->id, sel_x1, sel_y1, sel_width, sel_height);
}
static void
colorify_row (guchar *row,
gint width)
{
gint cur_x;
gint lum; /* luminosity */
guchar *current = row;
for (cur_x = 0; cur_x < width; cur_x++) {
lum = lum_red_lookup[current[0]] + lum_green_lookup[current[1]] + lum_blue_lookup[current[2]];
current[0] = final_red_lookup[lum];
current[1] = final_green_lookup[lum];
current[2] = final_blue_lookup[lum];
current += 3;
}
}
static int
colorify_dialog (guchar red,
guchar green,
guchar blue)
{
GtkWidget *dialog;
GtkWidget *label;
GtkWidget *button;
GtkWidget *frame;
GtkWidget *table;
gchar **argv;
gint argc;
gint i;
GSList *group = NULL;
argc = 1;
argv = g_new (gchar *, 1);
argv[0] = g_strdup ("colorify");
gtk_init (&argc, &argv);
gtk_rc_parse (gimp_gtkrc());
dialog = gtk_dialog_new ();
gtk_window_set_title (GTK_WINDOW (dialog), _("Colorify"));
gtk_window_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
(GtkSignalFunc) close_callback,
NULL);
button = gtk_button_new_with_label (_("Ok"));
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
(GtkSignalFunc) colorify_ok_callback,
dialog);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, TRUE, TRUE, 0);
gtk_widget_grab_default (button);
gtk_widget_show (button);
button = gtk_button_new_with_label (_("Cancel"));
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
(GtkSignalFunc) gtk_widget_destroy,
GTK_OBJECT (dialog));
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, TRUE, TRUE, 0);
gtk_widget_show (button);
frame = gtk_frame_new (_("Color"));
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width (GTK_CONTAINER (frame), 10);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), frame, TRUE, TRUE, 0);
gtk_widget_show (frame);
table = gtk_table_new (2, 7, TRUE);
gtk_container_border_width (GTK_CONTAINER (table), 10);
gtk_container_add (GTK_CONTAINER (frame), table);
gtk_table_set_row_spacings (GTK_TABLE (table), 5);
gtk_table_set_col_spacings (GTK_TABLE (table), 5);
gtk_widget_show (table);
label = gtk_label_new (_("Custom Color: "));
gtk_table_attach (GTK_TABLE (table), label, 4, 6, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
gtk_widget_show (label);
button = gtk_radio_button_new (group);
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
gtk_widget_set_usize (button, 35, 35);
gtk_signal_connect (GTK_OBJECT (button), "button_press_event",
(GtkSignalFunc) custom_color_callback,
NULL);
gtk_table_attach (GTK_TABLE (table), button, 6, 7, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
gtk_widget_show (button);
preview = gtk_preview_new (GTK_PREVIEW_COLOR);
gtk_preview_size (GTK_PREVIEW (preview), 30, 30);
set_preview_color (preview, cvals.color[0], cvals.color[1], cvals.color[2]);
gtk_container_add (GTK_CONTAINER (button), preview);
gtk_widget_show (preview);
for(i = 0; i < 7; i++) {
group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
button = gtk_radio_button_new (group);
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
button_info[i].preview = gtk_preview_new (GTK_PREVIEW_COLOR);
gtk_preview_size (GTK_PREVIEW (button_info[i].preview),
30, 30);
gtk_container_add (GTK_CONTAINER (button), button_info[i].preview);
set_preview_color (button_info[i].preview,
button_info[i].red,
button_info[i].green,
button_info[i].blue);
button_info[i].button_num = i;
gtk_signal_connect (GTK_OBJECT (button), "clicked",
(GtkSignalFunc) predefined_color_callback,
&button_info[i].button_num);
gtk_widget_show (button_info[i].preview);
gtk_table_attach (GTK_TABLE (table), button, i, i + 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
gtk_widget_show (button);
}
gtk_widget_show (dialog);
gtk_main();
return cint.run;
}
static void
close_callback (GtkWidget *widget,
gpointer data)
{
gtk_main_quit();
}
static void
colorify_ok_callback (GtkWidget *widget,
gpointer data)
{
gtk_widget_destroy (GTK_WIDGET (data));
cint.run = TRUE;
}
static void
set_preview_color (GtkWidget *preview,
guchar red,
guchar green,
guchar blue)
{
gint i;
guchar buf[3 * 30];
for (i = 0; i < 30; i ++) {
buf [3 * i] = red;
buf [3 * i + 1] = green;
buf [3 * i + 2] = blue;
}
for (i = 0; i < 30; i ++)
gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 30);
gtk_widget_draw (preview, NULL);
}
static void
custom_color_callback (GtkWidget *widget,
gpointer data)
{
GtkColorSelectionDialog *csd;
gdouble colour[3];
c_dialog = gtk_color_selection_dialog_new (_("Colorify Custom Color"));
csd = GTK_COLOR_SELECTION_DIALOG (c_dialog);
gtk_color_selection_set_update_policy (GTK_COLOR_SELECTION(csd->colorsel),
GTK_UPDATE_DISCONTINUOUS);
gtk_widget_destroy (csd->help_button);
gtk_widget_destroy (csd->cancel_button);
gtk_signal_connect (GTK_OBJECT (csd->ok_button), "clicked",
(GtkSignalFunc) color_changed,
NULL);
colour[0] = cvals.color[0] / 255.0;
colour[1] = cvals.color[1] / 255.0;
colour[2] = cvals.color[2] / 255.0;
gtk_color_selection_set_color (GTK_COLOR_SELECTION (csd->colorsel),
colour);
gtk_window_position (GTK_WINDOW(c_dialog), GTK_WIN_POS_MOUSE);
gtk_widget_show (c_dialog);
}
static void
predefined_color_callback (GtkWidget *widget,
gpointer data)
{
gint *num;
num = (gint *) data;
cvals.color[0] = button_info[*num].red;
cvals.color[1] = button_info[*num].green;
cvals.color[2] = button_info[*num].blue;
}
static void
color_changed (GtkWidget *widget,
gpointer data)
{
gdouble colour[3];
gtk_color_selection_get_color (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (c_dialog)->colorsel),
colour);
cvals.color[0] = (guchar) (colour[0] * 255.0);
cvals.color[1] = (guchar) (colour[1] * 255.0);
cvals.color[2] = (guchar) (colour[2] * 255.0);
set_preview_color (preview, cvals.color[0], cvals.color[1], cvals.color[2]);
gtk_widget_destroy (c_dialog);
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
compose

View file

@ -1,41 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = compose
compose_SOURCES = \
compose.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/libgimp/libgimpui.la \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimpui.la \
$(top_builddir)/libgimp/libgimp.la
compose_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
convmatrix

View file

@ -1,39 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = convmatrix
convmatrix_SOURCES = \
convmatrix.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
convmatrix_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,908 +0,0 @@
/* Convolution Matrix plug-in for the GIMP -- Version 0.1
* Copyright (C) 1997 Lauri Alanko <la@iki.fi>
*
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The GNU General Public License is also available from
* http://www.fsf.org/copyleft/gpl.html
*
*
* CHANGELOG:
* v0.12 15.9.1997
* Got rid of the unportable snprintf. Also made some _tiny_ GUI fixes.
*
* v0.11 20.7.1997
* Negative values in the matrix are now abs'ed when used to weight
* alpha. Embossing effects should work properly now. Also fixed a
* totally idiotic bug with embossing.
*
* v0.1 2.7.1997
* Initial release. Works... kinda.
*
*
* TODO:
*
* - remove channels selector (that's what the channels dialog is for)
* - remove idiotic slowdowns
* - clean up code
* - preview
* - optimize properly
* - save & load matrices
* - spiffy frontend for designing matrices
*
* What else?
*
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "libgimp/gimp.h"
#include "gtk/gtk.h"
#include "libgimp/stdplugins-intl.h"
typedef enum {
EXTEND,
WRAP,
CLEAR,
MIRROR
}BorderMode;
GDrawable *drawable;
char * const channel_labels[]={
N_("Grey"), N_("Red"), N_("Green"), N_("Blue"), N_("Alpha")
};
char * const bmode_labels[]={
N_("Extend"), N_("Wrap"), N_("Crop")
};
/* Declare local functions. */
static void query(void);
static void run(char *name,
int nparams,
GParam * param,
int *nreturn_vals,
GParam ** return_vals);
static gint dialog();
static void doit(void);
static void check_config(void);
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
gint bytes;
gint sx1, sy1, sx2, sy2;
int run_flag = 0;
typedef struct {
gfloat matrix[5][5];
gfloat divisor;
gfloat offset;
gint alpha_alg;
BorderMode bmode;
gint channels[5];
gint autoset;
} config;
const config default_config =
{
{
{0.0,0.0,0.0,0.0,0.0},
{0.0,0.0,0.0,0.0,0.0},
{0.0,0.0,1.0,0.0,0.0},
{0.0,0.0,0.0,0.0,0.0},
{0.0,0.0,0.0,0.0,0.0}
}, /* matrix */
1, /* divisor */
0, /* offset */
1, /* Alpha-handling algorithm */
CLEAR, /* border-mode */
{1,1,1,1,1}, /* Channels mask */
0 /* autoset */
};
config my_config;
struct{
GtkWidget *matrix[5][5];
GtkWidget *divisor;
GtkWidget *offset;
GtkWidget *alpha_alg;
GtkWidget *bmode[3];
GtkWidget *channels[5];
GtkWidget *autoset;
GtkWidget *ok;
}my_widgets;
MAIN()
static void query()
{
static GParamDef args[] =
{
{PARAM_INT32, "run_mode", "Interactive, non-interactive"},
{PARAM_IMAGE, "image", "Input image (unused)"},
{PARAM_DRAWABLE, "drawable", "Input drawable"},
/* {PARAM_FLOATARRAY, "matrix", "The 5x5 convolution matrix"},
{PARAM_INT32, "alpha_alg", "Enable weighting by alpha channel"},
{PARAM_FLOAT, "divisor", "Divisor"},
{PARAM_FLOAT, "offset", "Offset"},
{PARAM_INT32ARRAY, "channels", "Mask of the channels to be filtered"},
{PARAM_INT32, "bmode", "Mode for treating image borders"}
*/
};
static GParamDef *return_vals = NULL;
static int nargs = (int)(sizeof(args) / sizeof(args[0]));
static int nreturn_vals = 0;
INIT_I18N();
gimp_install_procedure("plug_in_convmatrix",
_("A generic 5x5 convolution matrix"),
"",
"Lauri Alanko",
"Lauri Alanko",
"1997",
_("<Image>/Filters/Generic/Convolution Matrix"),
"RGB*, GRAY*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
static void run(char *name, int n_params, GParam * param,
int *nreturn_vals, GParam ** return_vals){
static GParam values[1];
GRunModeType run_mode;
GStatusType status = STATUS_SUCCESS;
int x,y;
INIT_I18N();
(void)name; /* Shut up warnings about unused parameters. */
*nreturn_vals = 1;
*return_vals = values;
run_mode = param[0].data.d_int32;
/* Get the specified drawable */
drawable = gimp_drawable_get(param[2].data.d_drawable);
my_config=default_config;
if (run_mode == RUN_NONINTERACTIVE) {
if(n_params!=9)
status=STATUS_CALLING_ERROR;
else{
for(y=0;y<5;y++)
for(x=0;x<5;x++)
my_config.matrix[x][y]=param[3].data.d_floatarray[y*5+x];
my_config.divisor=param[4].data.d_float;
my_config.offset=param[5].data.d_float;
my_config.alpha_alg=param[6].data.d_int32;
my_config.bmode=param[6].data.d_int32;
for(y=0;y<5;y++)
my_config.channels[y]=param[7].data.d_int32array[y];
check_config();
}
} else {
gimp_get_data("plug_in_convmatrix", &my_config);
if (run_mode == RUN_INTERACTIVE) {
/* Oh boy. We get to do a dialog box, because we can't really expect the
* user to set us up with the right values using gdb.
*/
check_config();
if (!dialog()) {
/* The dialog was closed, or something similarly evil happened. */
status = STATUS_EXECUTION_ERROR;
}
}
}
if (status == STATUS_SUCCESS) {
/* Make sure that the drawable is gray or RGB color */
if (gimp_drawable_color(drawable->id) ||
gimp_drawable_gray(drawable->id)) {
gimp_progress_init(_("Applying convolution"));
gimp_tile_cache_ntiles(2 * (drawable->width /
gimp_tile_width() + 1));
doit();
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush();
if (run_mode == RUN_INTERACTIVE)
gimp_set_data("plug_in_convmatrix", &my_config,
sizeof(my_config));
} else {
status = STATUS_EXECUTION_ERROR;
}
gimp_drawable_detach(drawable);
}
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
}
/* A generic wrapper to gimp_pixel_rgn_get_row which handles unlimited
* wrapping or gives you transparent regions outside the image */
static void my_get_row(GPixelRgn *PR, guchar *dest, int x, int y, int w){
int width, height, bytes;
int i;
width=PR->drawable->width;
height=PR->drawable->height;
bytes=PR->drawable->bpp;
/* Y-wrappings */
switch(my_config.bmode){
case WRAP:
/* Wrapped, so we get the proper row from the other side */
while(y<0) /* This is the _sure_ way to wrap. :) */
y+=height;
while(y>=height)
y-=height;
break;
case CLEAR:
/* Beyond borders, so set full transparent. */
if(y<0 || y>=height){
memset(dest,0,w*bytes);
return; /* Done, so back. */
}
case MIRROR:
/* The border lines are _not_ duplicated in the mirror image */
/* is this right? */
while(y<0 || y>=height){
if(y<0)
y=-y; /* y=-y-1 */
if(y>=height)
y=2*height-y-2; /* y=2*height-y-1 */
}
break;
case EXTEND:
y=CLAMP(y,0,height-1);
break;
}
switch(my_config.bmode){
case CLEAR:
if(x<0){
i=MIN(w,-x);
memset(dest,0,i*bytes);
dest+=i*bytes;
w-=i;
x+=i;
}
if(w){
i=MIN(w,width);
gimp_pixel_rgn_get_row(PR, dest, x, y, i);
dest+=i*bytes;
w-=i;
x+=i;
}
if(w)
memset(dest,0,w*bytes);
break;
case WRAP:
while(x<0)
x+=width;
i=MIN(w, width-x);
gimp_pixel_rgn_get_row(PR, dest, x, y, i);
w-=i;
dest+=i*bytes;
x=0;
while(w){
i=MIN(w, width);
gimp_pixel_rgn_get_row(PR, dest, x, y, i);
w-=i;
dest+=i*bytes;
}
break;
case EXTEND:
if(x<0){
gimp_pixel_rgn_get_pixel(PR, dest, 0, y);
x++;
w--;
dest+=bytes;
while(x<0 && w){
for(i=0;i<bytes;i++){
*dest=*(dest-bytes);
dest++;
}
x++;
w--;
}
}
if(w){
i=MIN(w,width);
gimp_pixel_rgn_get_row(PR, dest, x, y, i);
w-=i;
dest+=i*bytes;
}
while(w){
for(i=0;i<bytes;i++){
*dest=*(dest-bytes);
dest++;
}
x++;
w--;
}
break;
case MIRROR: /* Not yet handled */
break;
}
}
gfloat calcmatrix(guchar **srcrow, gint xoff, int i){
gfloat sum=0, alphasum=0;
static gfloat matrixsum=0;
static gint bytes=0;
gfloat temp;
gint x,y;
if(!bytes){
bytes=drawable->bpp;
for(y=0;y<5;y++)
for(x=0;x<5;x++){
temp=my_config.matrix[x][y];
matrixsum+=ABS(temp);
}
}
for(y=0;y<5;y++)
for(x=0;x<5;x++){
temp=my_config.matrix[x][y];
if(i!=(bytes-1) && my_config.alpha_alg==1){
temp*=srcrow[y][xoff+x*bytes+bytes-1-i];
alphasum+=ABS(temp);
}
temp*=srcrow[y][xoff+x*bytes];
sum+=temp;
}
sum/=my_config.divisor;
if(i!=(bytes-1) && my_config.alpha_alg==1){
if(alphasum!=0)
sum=sum*matrixsum/alphasum;
else
sum=0;
/* sum=srcrow[2][xoff+2*bytes]*my_config.matrix[2][2];*/
}
sum+=my_config.offset;
return sum;
}
static void doit(void)
{
GPixelRgn srcPR, destPR;
gint width, height, row, col;
int w, h, i;
guchar *destrow[3], *srcrow[5], *temprow;
gfloat sum;
gint xoff;
gint chanmask[4];
/* Get the input area. This is the bounding box of the selection in
* the image (or the entire image if there is no selection). Only
* operating on the input area is simply an optimization. It doesn't
* need to be done for correct operation. (It simply makes it go
* faster, since fewer pixels need to be operated on).
*/
gimp_drawable_mask_bounds(drawable->id, &sx1, &sy1, &sx2, &sy2);
w=sx2-sx1;
h=sy2-sy1;
/* Get the size of the input image. (This will/must be the same
* as the size of the output image.
*/
width = drawable->width;
height = drawable->height;
bytes = drawable->bpp;
if(gimp_drawable_color(drawable->id))
for(i=0;i<3;i++)
chanmask[i]=my_config.channels[i+1];
else /* Grayscale */
chanmask[0]=my_config.channels[0];
if(gimp_drawable_has_alpha(drawable->id))
chanmask[bytes-1]=my_config.channels[4];
for(i=0;i<5;i++)
srcrow[i]=(guchar *) malloc ((w + 4) * bytes);
for(i=0;i<3;i++)
destrow[i]=(guchar *) malloc ((w) * bytes);
/* initialize the pixel regions */
gimp_pixel_rgn_init(&srcPR, drawable, sx1-2, sy1-2, w+4, h+4, FALSE, FALSE);
gimp_pixel_rgn_init(&destPR, drawable, sx1, sy1, w, h, TRUE, TRUE);
/* initialize source arrays */
for(i=0;i<5;i++)
my_get_row(&srcPR, srcrow[i], sx1-2, sy1+i-2,w+4);
for (row=sy1;row<sy2;row++){
xoff=0;
for(col=sx1;col<sx2;col++)
for(i=0;i<bytes;i++){
if(chanmask[i]<=0)
sum=srcrow[2][xoff+2*bytes];
else
sum=calcmatrix(srcrow,xoff,i);
destrow[2][xoff]=(guchar)CLAMP(sum,0,255);
xoff++;
}
if(row>sy1+1)
gimp_pixel_rgn_set_row(&destPR,destrow[0], sx1,row-2,w);
temprow=destrow[0];
destrow[0]=destrow[1];
destrow[1]=destrow[2];
destrow[2]=temprow;
temprow=srcrow[0];
for(i=0;i<4;i++)
srcrow[i]=srcrow[i+1];
srcrow[4]=temprow;
my_get_row(&srcPR,srcrow[4],sx1-2,row+3,w+4);
gimp_progress_update((double)(row-sy1)/h);
}
/* put the final rows in the buffer in place */
if(h<3)
gimp_pixel_rgn_set_row(&destPR,destrow[2], sx1,row-3,w);
if(h>1)
gimp_pixel_rgn_set_row(&destPR,destrow[0], sx1,row-2,w);
if(h>2)
gimp_pixel_rgn_set_row(&destPR,destrow[1], sx1,row-1,w);
/* update the timred region */
gimp_drawable_flush(drawable);
gimp_drawable_merge_shadow(drawable->id, TRUE);
gimp_drawable_update(drawable->id, sx1, sy1, sx2 - sx1, sy2 - sy1);
}
/***************************************************
* GUI stuff
*/
void fprint(gfloat f, gchar *buffer){
int i,t;
sprintf(buffer, "%.7f", f);
for(t=0;buffer[t]!='.';t++);
i=t+1;
while(buffer[i]!='\0'){
if(buffer[i]!='0')
t=i+1;
i++;
}
buffer[t]='\0';
}
static void redraw_matrix(void){
int x,y;
gchar buffer[12];
for(y=0;y<5;y++)
for(x=0;x<5;x++){
fprint(my_config.matrix[x][y],buffer);
gtk_entry_set_text(GTK_ENTRY(my_widgets.matrix[x][y]),buffer);
}
}
static void redraw_channels(void){
int i;
for(i=0;i<5;i++)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(my_widgets.channels[i]),
my_config.channels[i]>0);
}
static void redraw_autoset(void){
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(my_widgets.autoset),my_config.autoset);
}
static void redraw_alpha_alg(void){
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(my_widgets.alpha_alg),my_config.alpha_alg>0);
}
static void redraw_off_and_div(void){
gchar buffer[12];
fprint(my_config.divisor,buffer);
gtk_entry_set_text(GTK_ENTRY(my_widgets.divisor),buffer);
fprint(my_config.offset,buffer);
gtk_entry_set_text(GTK_ENTRY(my_widgets.offset),buffer);
}
static void redraw_bmode(void){
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(my_widgets.bmode[my_config.bmode]),TRUE);
}
static void redraw_all(void){
redraw_matrix();
redraw_off_and_div();
redraw_autoset();
redraw_alpha_alg();
redraw_bmode();
redraw_channels();
}
static void check_matrix(void){
int x,y;
int valid=0;
gfloat sum=0.0;
for(y=0;y<5;y++)
for(x=0;x<5;x++){
sum+=my_config.matrix[x][y];
if(my_config.matrix[x][y]!=0.0)
valid=1;
}
if(my_config.autoset){
if(sum>0){
my_config.offset=0;
my_config.divisor=sum;
}else if(sum<0){
my_config.offset=255;
my_config.divisor=-sum;
}else{
my_config.offset=128;
/* The sum is 0, so this is probably some sort of
* embossing filter. Should divisor be autoset to 1
* or left undefined, ie. for the user to define? */
my_config.divisor=1;
}
redraw_off_and_div();
}
/* gtk_widget_set_sensitive(my_widgets.ok,valid); */
}
static void close_callback(GtkWidget *widget, gpointer data){
(void)widget; /* Shut up warnings about unused parameters. */
(void)data;
gtk_main_quit();
}
static void ok_callback(GtkWidget * widget, gpointer data){
(void)widget; /* Shut up warnings about unused parameters. */
run_flag = 1;
gtk_widget_destroy(GTK_WIDGET(data));
}
/* Checks that the configuration is valid for the image type */
static void check_config(void){
int i;
for(i=0;i<5;i++)
if(my_config.channels[i]<0)
my_config.channels[i]=0;
if(gimp_drawable_color(drawable->id))
my_config.channels[0]=-1;
else if(gimp_drawable_gray(drawable->id))
for(i=1;i<4;i++)
my_config.channels[i]=-1;
if(!gimp_drawable_has_alpha(drawable->id)){
my_config.channels[4]=-1;
my_config.alpha_alg=-1;
my_config.bmode=EXTEND;
}
}
static void defaults_callback(GtkWidget * widget, gpointer data){
(void)widget; /* Shut up warnings about unused parameters. */
(void)data;
my_config=default_config;
check_config();
redraw_all();
}
static void entry_callback(GtkWidget * widget, gpointer data)
{
gfloat *value=(gfloat *)data;
*value=atof(gtk_entry_get_text(GTK_ENTRY(widget)));
#if 0
check_matrix();
#else
if(widget==my_widgets.divisor)
gtk_widget_set_sensitive(GTK_WIDGET(my_widgets.ok),(*value!=0.0));
else if(widget!=my_widgets.offset)
check_matrix();
#endif
}
static void my_toggle_callback(GtkWidget * widget, gpointer data)
{
int val=GTK_TOGGLE_BUTTON(widget)->active;
if(val)
*(int *)data=TRUE;
else
*(int *)data=FALSE;
if(widget==my_widgets.alpha_alg){
gtk_widget_set_sensitive(my_widgets.bmode[CLEAR],val);
if(val==0 && my_config.bmode==CLEAR){
my_config.bmode=EXTEND;
redraw_bmode();
}
}else if(widget==my_widgets.autoset){
gtk_widget_set_sensitive(my_widgets.divisor,!val);
gtk_widget_set_sensitive(my_widgets.offset,!val);
check_matrix();
}
}
static void my_bmode_callback(GtkWidget * widget, gpointer data){
(void)widget; /* Shut up warnings about unused parameters. */
(void)data;
my_config.bmode=(int)data-1;
}
static gint dialog()
{
GtkWidget *dlg;
GtkWidget *button;
GtkWidget *label;
GtkWidget *entry;
GtkWidget *table;
GtkWidget *outbox;
GtkWidget *box;
GtkWidget *inbox;
GtkWidget *yetanotherbox;
GtkWidget *frame;
gchar buffer[32];
gchar **argv;
gint argc;
gint x,y,i;
GSList *group;
argc = 1;
argv = g_new(gchar *, 1);
argv[0] = g_strdup("convmatrix");
gtk_init(&argc, &argv);
gtk_rc_parse (gimp_gtkrc ());
dlg = gtk_dialog_new();
gtk_window_set_title(GTK_WINDOW(dlg), _("Convolution Matrix"));
gtk_window_position(GTK_WINDOW(dlg), GTK_WIN_POS_MOUSE);
gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
(GtkSignalFunc) close_callback, NULL);
/* Action area */
my_widgets.ok = button = gtk_button_new_with_label(_("OK"));
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
(GtkSignalFunc) ok_callback,
GTK_OBJECT(dlg));
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area), button, TRUE, TRUE, 0);
gtk_widget_grab_default(button);
gtk_widget_show(button);
button = gtk_button_new_with_label(_("Defaults"));
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
(GtkSignalFunc) defaults_callback,
GTK_OBJECT(dlg));
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area), button, TRUE, TRUE, 0);
gtk_widget_show(button);
button = gtk_button_new_with_label(_("Cancel"));
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
(GtkSignalFunc) close_callback,
GTK_OBJECT(dlg));
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area), button, TRUE, TRUE, 0);
gtk_widget_show(button);
/* Outbox */
outbox=gtk_hbox_new(FALSE,0);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dlg)->vbox), outbox, TRUE, TRUE, 0);
/* Outbox:YABox */
yetanotherbox=gtk_vbox_new(FALSE,0);
gtk_box_pack_start (GTK_BOX (outbox), yetanotherbox, TRUE, TRUE, 0);
/* Outbox:YABox:Frame */
frame = gtk_frame_new (_("Matrix"));
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width (GTK_CONTAINER (frame), 10);
gtk_box_pack_start (GTK_BOX (yetanotherbox), frame, TRUE, TRUE, 0);
/* Outbox:YABox:Frame:Inbox */
inbox=gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(frame),inbox);
/* The main table */
/* Set its size (y, x) */
/* Outbox:YABox:Frame:Inbox:Table */
table = gtk_table_new(5, 5, TRUE);
gtk_container_border_width(GTK_CONTAINER(table), 10);
gtk_container_add (GTK_CONTAINER (inbox), table);
gtk_widget_show(table);
gtk_table_set_row_spacings(GTK_TABLE(table), 5);
gtk_table_set_col_spacings(GTK_TABLE(table), 5);
/* The 5x5 matrix entry fields */
for(y=0;y<5;y++)
for(x=0;x<5;x++){
my_widgets.matrix[x][y]= entry = gtk_entry_new();
gtk_table_attach(GTK_TABLE(table), entry, x, x+1, y, y+1, GTK_EXPAND | GTK_FILL,
GTK_EXPAND | GTK_FILL, 0, 0);
gtk_widget_set_usize(entry, 40, 0);
gtk_entry_set_text(GTK_ENTRY(entry), buffer);
gtk_signal_connect(GTK_OBJECT(entry), "changed",
(GtkSignalFunc) entry_callback, &my_config.matrix[x][y]);
gtk_widget_show(entry);
}
gtk_widget_show(table);
/* The remaining two parameters */
/* Outbox:YABox:Frame:Inbox:Box */
box=gtk_hbox_new(TRUE,0);
gtk_container_border_width(GTK_CONTAINER(box),10);
gtk_box_pack_start(GTK_BOX(inbox), box, TRUE, TRUE, 0);
/* divisor */
label=gtk_label_new(_("Divisor"));
gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 0);
gtk_widget_show(label);
my_widgets.divisor=entry=gtk_entry_new();
gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
gtk_widget_set_usize(entry, 40, 0);
gtk_signal_connect(GTK_OBJECT(entry), "changed",
(GtkSignalFunc) entry_callback, &my_config.divisor);
gtk_widget_show(entry);
/* Offset */
label=gtk_label_new(_("Offset"));
gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 0);
gtk_widget_show(label);
my_widgets.offset=entry=gtk_entry_new();
gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
gtk_widget_set_usize(entry, 40, 0);
gtk_signal_connect(GTK_OBJECT(entry), "changed",
(GtkSignalFunc) entry_callback, &my_config.offset);
gtk_widget_show(entry);
gtk_widget_show(box);
gtk_widget_show(inbox);
gtk_widget_show(frame);
/* Outbox:YABox:Box */
box=gtk_hbox_new(TRUE,0);
gtk_box_pack_start(GTK_BOX(yetanotherbox),box, TRUE, TRUE, 0);
my_widgets.autoset=button=gtk_check_button_new_with_label(_("Automatic"));
gtk_box_pack_start(GTK_BOX(box), button, TRUE, FALSE,0);
gtk_signal_connect(GTK_OBJECT(button), "toggled",
(GtkSignalFunc) my_toggle_callback, &my_config.autoset);
gtk_widget_show(button);
/* Alpha-weighting */
my_widgets.alpha_alg=button=gtk_check_button_new_with_label(_("Alpha-weighting"));
if(my_config.alpha_alg==-1)
gtk_widget_set_sensitive(button,0);
gtk_box_pack_start(GTK_BOX(box),button,TRUE,TRUE,0);
gtk_signal_connect(GTK_OBJECT(button), "toggled",(GtkSignalFunc)my_toggle_callback,&my_config.alpha_alg);
gtk_widget_show(button);
gtk_widget_show(box);
gtk_widget_show(yetanotherbox);
/* Outbox:Inbox */
inbox=gtk_vbox_new(FALSE,0);
gtk_box_pack_start(GTK_BOX(outbox),inbox, FALSE, FALSE,0);
/* Wrap-modes */
/* OutBox:Inbox:Frame */
frame=gtk_frame_new(_("Border"));
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width (GTK_CONTAINER (frame), 10);
gtk_box_pack_start(GTK_BOX(inbox), frame, TRUE, TRUE,0);
/* OutBox:Inbox:Frame:Box */
box=gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(frame),box);
group=NULL;
for(i=0;i<3;i++){
my_widgets.bmode[i]=button=gtk_radio_button_new_with_label(group,gettext(bmode_labels[i]));
group=gtk_radio_button_group(GTK_RADIO_BUTTON(button));
gtk_box_pack_start(GTK_BOX(box),button,TRUE,TRUE,0);
gtk_widget_show(button);
gtk_signal_connect(GTK_OBJECT(button),"toggled",
(GtkSignalFunc)my_bmode_callback,(gpointer)(i+1));
/* Gaahh! We cast an int to a gpointer! So sue me.
* The +1 should protect against some null pointers */
}
gtk_widget_show(box);
gtk_widget_show(frame);
/* OutBox:Inbox:Frame */
frame=gtk_frame_new(_("Channels"));
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width (GTK_CONTAINER (frame), 10);
gtk_box_pack_start(GTK_BOX(inbox), frame, TRUE, TRUE,0);
/* OutBox:Inbox:Frame:Box */
box=gtk_vbox_new(TRUE, 0);
gtk_container_add(GTK_CONTAINER(frame),box);
for(i=0;i<5;i++){
my_widgets.channels[i]=button=gtk_check_button_new_with_label(gettext(channel_labels[i]));
if(my_config.channels[i]<0)
gtk_widget_set_sensitive(button,0);
gtk_signal_connect(GTK_OBJECT(button), "toggled",(GtkSignalFunc)my_toggle_callback,&my_config.channels[i]);
gtk_box_pack_start(GTK_BOX(box),button,TRUE,TRUE,0);
gtk_widget_show(button);
}
gtk_widget_show(box);
gtk_widget_show(frame);
gtk_widget_show(inbox);
gtk_widget_show(outbox);
gtk_widget_show(dlg);
redraw_all();
gtk_widget_set_sensitive(my_widgets.bmode[CLEAR],(my_config.alpha_alg>0));
gtk_main();
gdk_flush();
return run_flag;
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
cubism

View file

@ -1,39 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = cubism
cubism_SOURCES = \
cubism.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
cubism_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,898 +0,0 @@
/* Cubism --- image filter plug-in for The Gimp image manipulation program
* Copyright (C) 1996 Spencer Kimball, Tracy Scott
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* You can contact me at quartic@polloux.fciencias.unam.mx
* You can contact the original The Gimp authors at gimp@xcf.berkeley.edu
* Speedups by Elliot Lee
*/
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "gtk/gtk.h"
#include "libgimp/gimp.h"
#include "config.h"
#include "libgimp/stdplugins-intl.h"
/* Some useful macros */
#define SQR(a) ((a) * (a))
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif /* M_PI */
#ifndef RAND_MAX
#define RAND_MAX 2147483647
#endif /* RAND_MAX */
#define SCALE_WIDTH 125
#define BLACK 0
#define BG 1
#define SUPERSAMPLE 3
#define MAX_POINTS 4
#define MIN_ANGLE -36000
#define MAX_ANGLE 36000
#define RANDOMNESS 5
typedef struct
{
gdouble x, y;
} Vertex;
typedef struct
{
gint npts;
Vertex pts[MAX_POINTS];
} Polygon;
typedef struct
{
gdouble tile_size;
gdouble tile_saturation;
gint bg_color;
} CubismVals;
typedef struct
{
gint run;
} CubismInterface;
/* Declare local functions.
*/
static void query (void);
static void run (char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals);
static void cubism (GDrawable *drawable);
static gint cubism_dialog (void);
static void render_cubism (GDrawable * drawable);
static void fill_poly_color (Polygon * poly,
GDrawable * drawable,
guchar * col);
static void convert_segment (gint x1,
gint y1,
gint x2,
gint y2,
gint offset,
gint * min,
gint * max);
static void randomize_indices (gint count,
gint * indices);
static gdouble fp_rand (gdouble val);
static gint int_rand (gint val);
static gdouble calc_alpha_blend (gdouble * vec,
gdouble one_over_dist,
gdouble x,
gdouble y);
static void polygon_add_point (Polygon * poly,
gdouble x,
gdouble y);
static void polygon_translate (Polygon * poly,
gdouble tx,
gdouble ty);
static void polygon_rotate (Polygon * poly,
gdouble theta);
static gint polygon_extents (Polygon * poly,
gdouble * min_x,
gdouble * min_y,
gdouble * max_x,
gdouble * max_y);
static void polygon_reset (Polygon * poly);
static void cubism_close_callback (GtkWidget *widget,
gpointer data);
static void cubism_ok_callback (GtkWidget *widget,
gpointer data);
static void cubism_toggle_update (GtkWidget *widget,
gpointer data);
static void cubism_scale_update (GtkAdjustment *adjustment,
double *scale_val);
/*
* Local variables
*/
static guchar bg_col[4];
static CubismVals cvals =
{
10.0, /* tile_size */
2.5, /* tile_saturation */
BLACK /* bg_color */
};
static CubismInterface cint =
{
FALSE /* run */
};
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
/*
* Functions
*/
MAIN ()
static void
query ()
{
static GParamDef args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_FLOAT, "tile_size", "Average diameter of each tile (in pixels)" },
{ PARAM_FLOAT, "tile_saturation", "Expand tiles by this amount" },
{ PARAM_INT32, "bg_color", "Background color: { BLACK (0), BG (1) }" }
};
static GParamDef *return_vals = NULL;
static int nargs = sizeof (args) / sizeof (args[0]);
static int nreturn_vals = 0;
INIT_I18N();
gimp_install_procedure ("plug_in_cubism",
_("Convert the input drawable into a collection of rotated squares"),
"Help not yet written for this plug-in",
"Spencer Kimball & Tracy Scott",
"Spencer Kimball & Tracy Scott",
"1996",
_("<Image>/Filters/Artistic/Cubism"),
"RGB*, GRAY*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
static void
run (char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals)
{
static GParam values[1];
GDrawable *active_drawable;
GRunModeType run_mode;
GStatusType status = STATUS_SUCCESS;
INIT_I18N();
run_mode = param[0].data.d_int32;
*nreturn_vals = 1;
*return_vals = values;
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
switch (run_mode)
{
case RUN_INTERACTIVE:
/* Possibly retrieve data */
gimp_get_data ("plug_in_cubism", &cvals);
/* First acquire information with a dialog */
if (! cubism_dialog ())
return;
break;
case RUN_NONINTERACTIVE:
/* Make sure all the arguments are there! */
if (nparams != 6)
status = STATUS_CALLING_ERROR;
if (status == STATUS_SUCCESS)
{
cvals.tile_size = param[3].data.d_float;
cvals.tile_saturation = param[4].data.d_float;
cvals.bg_color = param[5].data.d_int32;
}
if (status == STATUS_SUCCESS &&
(cvals.bg_color < BLACK || cvals.bg_color > BG))
status = STATUS_CALLING_ERROR;
break;
case RUN_WITH_LAST_VALS:
/* Possibly retrieve data */
gimp_get_data ("plug_in_cubism", &cvals);
break;
default:
break;
}
/* get the active drawable */
active_drawable = gimp_drawable_get (param[2].data.d_drawable);
/* Render the cubism effect */
if ((status == STATUS_SUCCESS) &&
(gimp_drawable_color (active_drawable->id) || gimp_drawable_gray (active_drawable->id)))
{
/* set cache size */
gimp_tile_cache_ntiles (SQR (4 * cvals.tile_size * cvals.tile_saturation) / SQR (gimp_tile_width ()));
cubism (active_drawable);
/* If the run mode is interactive, flush the displays */
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush ();
/* Store mvals data */
if (run_mode == RUN_INTERACTIVE)
gimp_set_data ("plug_in_cubism", &cvals, sizeof (CubismVals));
}
else if (status == STATUS_SUCCESS)
{
/* gimp_message ("cubism: cannot operate on indexed color images"); */
status = STATUS_EXECUTION_ERROR;
}
values[0].data.d_status = status;
gimp_drawable_detach (active_drawable);
}
static void
cubism (GDrawable *drawable)
{
gint x1, y1, x2, y2;
/* find the drawable mask bounds */
gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
/* determine the background color */
if (cvals.bg_color == BLACK)
bg_col[0] = bg_col[1] = bg_col[2] = 0;
else
gimp_palette_get_background (&bg_col[0], &bg_col[1], &bg_col[2]);
if (gimp_drawable_has_alpha (drawable->id))
bg_col[drawable->bpp - 1] = 0;
gimp_progress_init (_("Cubistic Transformation"));
/* render the cubism */
render_cubism (drawable);
/* merge the shadow, update the drawable */
gimp_drawable_flush (drawable);
gimp_drawable_merge_shadow (drawable->id, TRUE);
gimp_drawable_update (drawable->id, x1, y1, (x2 - x1), (y2 - y1));
}
static gint
cubism_dialog ()
{
GtkWidget *dlg;
GtkWidget *label;
GtkWidget *button;
GtkWidget *toggle;
GtkWidget *scale;
GtkWidget *frame;
GtkWidget *table;
GtkObject *scale_data;
gchar **argv;
gint argc;
argc = 1;
argv = g_new (gchar *, 1);
argv[0] = g_strdup ("cubism");
gtk_init (&argc, &argv);
gtk_rc_parse (gimp_gtkrc ());
dlg = gtk_dialog_new ();
gtk_window_set_title (GTK_WINDOW (dlg), _("Cubism"));
gtk_window_position (GTK_WINDOW (dlg), GTK_WIN_POS_MOUSE);
gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
(GtkSignalFunc) cubism_close_callback,
NULL);
/* Action area */
button = gtk_button_new_with_label (_("OK"));
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
(GtkSignalFunc) cubism_ok_callback,
dlg);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button, TRUE, TRUE, 0);
gtk_widget_grab_default (button);
gtk_widget_show (button);
button = gtk_button_new_with_label (_("Cancel"));
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
(GtkSignalFunc) gtk_widget_destroy,
GTK_OBJECT (dlg));
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button, TRUE, TRUE, 0);
gtk_widget_show (button);
/* parameter settings */
frame = gtk_frame_new (_("Parameter Settings"));
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width (GTK_CONTAINER (frame), 10);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, TRUE, TRUE, 0);
table = gtk_table_new (3, 2, FALSE);
gtk_container_border_width (GTK_CONTAINER (table), 10);
gtk_container_add (GTK_CONTAINER (frame), table);
toggle = gtk_check_button_new_with_label (_("Use Background Color"));
gtk_table_attach (GTK_TABLE (table), toggle, 0, 2, 0, 1, GTK_FILL, 0, 0, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
(GtkSignalFunc) cubism_toggle_update,
&cvals.bg_color);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), (cvals.bg_color == BG));
gtk_widget_show (toggle);
label = gtk_label_new (_("Tile Size"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, GTK_FILL, 0, 5, 0);
scale_data = gtk_adjustment_new (cvals.tile_size, 0.0, 100.0, 1.0, 1.0, 0.0);
scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data));
gtk_widget_set_usize (scale, SCALE_WIDTH, 0);
gtk_table_attach (GTK_TABLE (table), scale, 1, 2, 1, 2, GTK_FILL, 0, 0, 0);
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
gtk_scale_set_digits (GTK_SCALE (scale), 1);
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
gtk_signal_connect (GTK_OBJECT (scale_data), "value_changed",
(GtkSignalFunc) cubism_scale_update,
&cvals.tile_size);
gtk_widget_show (label);
gtk_widget_show (scale);
label = gtk_label_new (_("Tile Saturation"));
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, GTK_FILL, 0, 5, 0);
scale_data = gtk_adjustment_new (cvals.tile_saturation, 0.0, 10.0, 0.1, 0.1, 0.0);
scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data));
gtk_widget_set_usize (scale, SCALE_WIDTH, 0);
gtk_table_attach (GTK_TABLE (table), scale, 1, 2, 2, 3, GTK_FILL, 0, 0, 0);
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
gtk_scale_set_digits (GTK_SCALE (scale), 1);
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
gtk_signal_connect (GTK_OBJECT (scale_data), "value_changed",
(GtkSignalFunc) cubism_scale_update,
&cvals.tile_saturation);
gtk_widget_show (label);
gtk_widget_show (scale);
gtk_widget_show (frame);
gtk_widget_show (table);
gtk_widget_show (dlg);
gtk_main ();
gdk_flush ();
return cint.run;
}
static void
render_cubism (GDrawable *drawable)
{
GPixelRgn src_rgn;
gdouble img_area, tile_area;
gdouble x, y;
gdouble width, height;
gdouble theta;
gint ix, iy;
gint rows, cols;
gint i, j, count;
gint num_tiles;
gint x1, y1, x2, y2;
Polygon poly;
guchar col[4];
guchar *dest;
gint bytes;
gint has_alpha;
gint *random_indices;
gpointer pr;
has_alpha = gimp_drawable_has_alpha (drawable->id);
bytes = drawable->bpp;
gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
img_area = (x2 - x1) * (y2 - y1);
tile_area = SQR (cvals.tile_size);
cols = ((x2 - x1) + cvals.tile_size - 1) / cvals.tile_size;
rows = ((y2 - y1) + cvals.tile_size - 1) / cvals.tile_size;
/* Fill the image with the background color */
gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, (x2 - x1), (y2 - y1), TRUE, TRUE);
for (pr = gimp_pixel_rgns_register (1, &src_rgn); pr != NULL; pr = gimp_pixel_rgns_process (pr))
{
count = src_rgn.w * src_rgn.h;
dest = src_rgn.data;
while (count--)
for (i = 0; i < bytes; i++)
*dest++ = bg_col[i];
}
num_tiles = (rows + 1) * (cols + 1);
random_indices = (gint *) malloc (sizeof (gint) * num_tiles);
for (i = 0; i < num_tiles; i++)
random_indices[i] = i;
randomize_indices (num_tiles, random_indices);
count = 0;
gimp_pixel_rgn_init (&src_rgn, drawable, x1, y1, (x2 - x1), (y2 - y1), FALSE, FALSE);
while (count < num_tiles)
{
i = random_indices[count] / (cols + 1);
j = random_indices[count] % (cols + 1);
x = j * cvals.tile_size + (cvals.tile_size / 4.0) - fp_rand (cvals.tile_size/2.0) + x1;
y = i * cvals.tile_size + (cvals.tile_size / 4.0) - fp_rand (cvals.tile_size/2.0) + y1;
width = (cvals.tile_size + fp_rand (cvals.tile_size / 4.0) - cvals.tile_size / 8.0) *
cvals.tile_saturation;
height = (cvals.tile_size + fp_rand (cvals.tile_size / 4.0) - cvals.tile_size / 8.0) *
cvals.tile_saturation;
theta = fp_rand (2 * M_PI);
polygon_reset (&poly);
polygon_add_point (&poly, -width / 2.0, -height / 2.0);
polygon_add_point (&poly, width / 2.0, -height / 2.0);
polygon_add_point (&poly, width / 2.0, height / 2.0);
polygon_add_point (&poly, -width / 2.0, height / 2.0);
polygon_rotate (&poly, theta);
polygon_translate (&poly, x, y);
/* bounds check on x, y */
ix = (int) x;
iy = (int) y;
if (ix < x1)
ix = x1;
if (ix >= x2)
ix = x2 - 1;
if (iy < y1)
iy = y1;
if (iy >= y2)
iy = y2 - 1;
gimp_pixel_rgn_get_pixel (&src_rgn, col, ix, iy);
if (! has_alpha || (has_alpha && col[bytes - 1] != 0))
fill_poly_color (&poly, drawable, col);
count++;
if ((count % 5) == 0)
gimp_progress_update ((double) count / (double) num_tiles);
}
gimp_progress_update (1.0);
free (random_indices);
}
static inline gdouble
calc_alpha_blend (gdouble *vec,
gdouble one_over_dist,
gdouble x,
gdouble y)
{
gdouble r;
if (!one_over_dist)
return 1.0;
else
{
r = (vec[0] * x + vec[1] * y) * one_over_dist;
if (r < 0.2)
r = 0.2;
else if (r > 1.0)
r = 1.0;
}
return r;
}
static void
fill_poly_color (Polygon *poly,
GDrawable *drawable,
guchar *col)
{
GPixelRgn src_rgn;
gdouble dmin_x, dmin_y;
gdouble dmax_x, dmax_y;
gint xs, ys;
gint xe, ye;
gint min_x, min_y;
gint max_x, max_y;
gint size_x, size_y;
gint * max_scanlines, *max_scanlines_iter;
gint * min_scanlines, *min_scanlines_iter;
gint val;
gint alpha;
gint bytes;
guchar buf[4];
gint i, j, x, y;
gdouble sx, sy;
gdouble ex, ey;
gdouble xx, yy;
gdouble vec[2];
gdouble dist, one_over_dist;
gint supersample;
gint supersample2;
gint x1, y1, x2, y2;
gint *vals, *vals_iter, *vals_end;
sx = poly->pts[0].x;
sy = poly->pts[0].y;
ex = poly->pts[1].x;
ey = poly->pts[1].y;
dist = sqrt (SQR (ex - sx) + SQR (ey - sy));
if (dist > 0.0)
{
one_over_dist = 1/dist;
vec[0] = (ex - sx) * one_over_dist;
vec[1] = (ey - sy) * one_over_dist;
} else
one_over_dist = 0.0;
supersample = SUPERSAMPLE;
supersample2 = SQR (supersample);
gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
bytes = drawable->bpp;
polygon_extents (poly, &dmin_x, &dmin_y, &dmax_x, &dmax_y);
min_x = (gint) dmin_x;
min_y = (gint) dmin_y;
max_x = (gint) dmax_x;
max_y = (gint) dmax_y;
size_y = (max_y - min_y) * supersample;
size_x = (max_x - min_x) * supersample;
min_scanlines = min_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y);
max_scanlines = max_scanlines_iter = (gint *) malloc (sizeof (gint) * size_y);
for (i = 0; i < size_y; i++)
{
min_scanlines[i] = max_x * supersample;
max_scanlines[i] = min_x * supersample;
}
if(poly->npts) {
gint poly_npts = poly->npts;
Vertex *curptr;
xs = (gint) (poly->pts[poly_npts-1].x);
ys = (gint) (poly->pts[poly_npts-1].y);
xe = (gint) poly->pts[0].x;
ye = (gint) poly->pts[0].y;
xs *= supersample;
ys *= supersample;
xe *= supersample;
ye *= supersample;
convert_segment (xs, ys, xe, ye, min_y * supersample,
min_scanlines, max_scanlines);
for(i = 1, curptr = &poly->pts[0]; i < poly_npts; i++) {
xs = (gint) curptr->x;
ys = (gint) curptr->y;
curptr++;
xe = (gint) curptr->x;
ye = (gint) curptr->y;
xs *= supersample;
ys *= supersample;
xe *= supersample;
ye *= supersample;
convert_segment (xs, ys, xe, ye, min_y * supersample,
min_scanlines, max_scanlines);
}
}
gimp_pixel_rgn_init (&src_rgn, drawable, 0, 0,
drawable->width, drawable->height,
TRUE, TRUE);
vals = (gint *) malloc (sizeof (gint) * size_x);
for (i = 0; i < size_y; i++, min_scanlines_iter++, max_scanlines_iter++)
{
if (! (i % supersample)) {
memset (vals, 0, sizeof (gint) * size_x);
}
yy = (gdouble)i / (gdouble)supersample + min_y;
for (j = *min_scanlines_iter; j < *max_scanlines_iter; j++)
{
x = j - min_x * supersample;
vals[x] += 255;
}
if (! ((i + 1) % supersample))
{
y = (i / supersample) + min_y;
if (y >= y1 && y < y2)
{
for (j = 0; j < size_x; j += supersample)
{
x = (j / supersample) + min_x;
if (x >= x1 && x < x2)
{
for (val = 0, vals_iter = &vals[j],
vals_end = &vals_iter[supersample];
vals_iter < vals_end;
vals_iter++)
val += *vals_iter;
val /= supersample2;
if (val > 0)
{
xx = (gdouble) j / (gdouble) supersample + min_x;
alpha = (gint) (val * calc_alpha_blend (vec, one_over_dist, xx - sx, yy - sy));
gimp_pixel_rgn_get_pixel (&src_rgn, buf, x, y);
#ifndef USE_READABLE_BUT_SLOW_CODE
{
guchar *buf_iter = buf,
*col_iter = col,
*buf_end = buf+bytes;
for(; buf_iter < buf_end; buf_iter++, col_iter++)
*buf_iter = ((guint)(*col_iter * alpha)
+ (((guint)*buf_iter)
* (256 - alpha))) >> 8;
}
#else /* original, pre-ECL code */
for (b = 0; b < bytes; b++)
buf[b] = ((col[b] * alpha) + (buf[b] * (255 - alpha))) / 255;
#endif
gimp_pixel_rgn_set_pixel (&src_rgn, buf, x, y);
}
}
}
}
}
}
free (vals);
free (min_scanlines);
free (max_scanlines);
}
static void
convert_segment (gint x1,
gint y1,
gint x2,
gint y2,
gint offset,
gint *min,
gint *max)
{
gint ydiff, y, tmp;
gdouble xinc, xstart;
if (y1 > y2)
{ tmp = y2; y2 = y1; y1 = tmp;
tmp = x2; x2 = x1; x1 = tmp; }
ydiff = (y2 - y1);
if ( ydiff )
{
xinc = (gdouble) (x2 - x1) / (gdouble) ydiff;
xstart = x1 + 0.5 * xinc;
for (y = y1 ; y < y2; y++)
{
if (xstart < min[y - offset])
min[y-offset] = xstart;
if (xstart > max[y - offset])
max[y-offset] = xstart;
xstart += xinc;
}
}
}
static void
randomize_indices (gint count,
gint *indices)
{
gint i;
gint index1, index2;
gint tmp;
for (i = 0; i < count * RANDOMNESS; i++)
{
index1 = int_rand (count);
index2 = int_rand (count);
tmp = indices[index1];
indices[index1] = indices[index2];
indices[index2] = tmp;
}
}
static gdouble
fp_rand (gdouble val)
{
gdouble rand_val;
rand_val = (gdouble) rand () / (gdouble) (RAND_MAX - 1);
return rand_val * val;
}
static gint
int_rand (gint val)
{
gint rand_val;
rand_val = rand () % val;
return rand_val;
}
static void
polygon_add_point (Polygon *poly,
gdouble x,
gdouble y)
{
if (poly->npts < 12)
{
poly->pts[poly->npts].x = x;
poly->pts[poly->npts].y = y;
poly->npts++;
}
else
g_print ("Unable to add additional point.\n");
}
static void
polygon_rotate (Polygon *poly,
gdouble theta)
{
gint i;
gdouble ct, st;
gdouble ox, oy;
ct = cos (theta);
st = sin (theta);
for (i = 0; i < poly->npts; i++)
{
ox = poly->pts[i].x;
oy = poly->pts[i].y;
poly->pts[i].x = ct * ox - st * oy;
poly->pts[i].y = st * ox + ct * oy;
}
}
static void
polygon_translate (Polygon *poly,
gdouble tx,
gdouble ty)
{
gint i;
for (i = 0; i < poly->npts; i++)
{
poly->pts[i].x += tx;
poly->pts[i].y += ty;
}
}
static gint
polygon_extents (Polygon *poly,
gdouble *x1,
gdouble *y1,
gdouble *x2,
gdouble *y2)
{
gint i;
if (!poly->npts)
return 0;
*x1 = *x2 = poly->pts[0].x;
*y1 = *y2 = poly->pts[0].y;
for (i = 1; i < poly->npts; i++)
{
if (poly->pts[i].x < *x1)
*x1 = poly->pts[i].x;
if (poly->pts[i].x > *x2)
*x2 = poly->pts[i].x;
if (poly->pts[i].y < *y1)
*y1 = poly->pts[i].y;
if (poly->pts[i].y > *y2)
*y2 = poly->pts[i].y;
}
return 1;
}
static void
polygon_reset (Polygon *poly)
{
poly->npts = 0;
}
/* Cubism interface functions */
static void
cubism_close_callback (GtkWidget *widget,
gpointer data)
{
gtk_main_quit ();
}
static void
cubism_ok_callback (GtkWidget *widget,
gpointer data)
{
cint.run = TRUE;
gtk_widget_destroy (GTK_WIDGET (data));
}
static void
cubism_toggle_update (GtkWidget *widget,
gpointer data)
{
int *toggle_val;
toggle_val = (int *) data;
if (GTK_TOGGLE_BUTTON (widget)->active)
*toggle_val = TRUE;
else
*toggle_val = FALSE;
}
static void
cubism_scale_update (GtkAdjustment *adjustment,
double *scale_val)
{
*scale_val = adjustment->value;
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
decompose

View file

@ -1,39 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = decompose
decompose_SOURCES = \
decompose.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
decompose_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
deinterlace

View file

@ -1,38 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = deinterlace
deinterlace_SOURCES = \
deinterlace.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/plug-ins/megawidget/libmegawidget.a \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/plug-ins/megawidget/libmegawidget.a \
$(top_builddir)/libgimp/libgimp.la
deinterlace_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,263 +0,0 @@
/* Deinterlace 1.00 - image processing plug-in for the Gimp 1.0 API
*
* Copyright (C) 1997 Andrew Kieschnick (andrewk@mail.utexas.edu)
*
* Original deinterlace for the Gimp 0.54 API by Federico Mena Quintero
*
* Copyright (C) 1996 Federico Mena Quintero
*
* Any bugs in this code are probably my (Andrew Kieschnick's) fault, as I
* pretty much rewrote it from scratch.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <libgimp/gimp.h>
#include <gtk/gtk.h>
#include <plug-ins/megawidget/megawidget.h>
/* Declare local functions.
*/
static void query (void);
static void run (char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals);
static void deinterlace (GDrawable *drawable);
static gint deinterlace_dialog(void);
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
static gint DeinterlaceValue = 1;
MAIN ()
static void
query ()
{
static GParamDef args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image (unused)" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_INT32, "evenodd", "0 = keep odd, 1 = keep even" },
};
static GParamDef *return_vals = NULL;
static int nargs = sizeof (args) / sizeof (args[0]);
static int nreturn_vals = 0;
gimp_install_procedure ("plug_in_deinterlace",
"Deinterlace",
"Deinterlace is useful for processing images from video capture cards. When only the odd or even fields get captured, deinterlace can be used to interpolate between the existing fields to correct this.",
"Andrew Kieschnick",
"Andrew Kieschnick",
"1997",
"<Image>/Filters/Enhance/Deinterlace",
"RGB*, GRAY*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
static void
run (char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals)
{
static GParam values[1];
GDrawable *drawable;
GRunModeType run_mode;
GStatusType status = STATUS_SUCCESS;
run_mode = param[0].data.d_int32;
/* Get the specified drawable */
drawable = gimp_drawable_get (param[2].data.d_drawable);
switch (run_mode)
{
case RUN_INTERACTIVE:
gimp_get_data("plug_in_deinterlace", &DeinterlaceValue);
if (! deinterlace_dialog())
status = STATUS_EXECUTION_ERROR;
break;
case RUN_NONINTERACTIVE:
if (nparams != 4)
status = STATUS_CALLING_ERROR;
if (status == STATUS_SUCCESS)
DeinterlaceValue = param[3].data.d_int32;
break;
case RUN_WITH_LAST_VALS:
gimp_get_data("plug_in_deinterlace", &DeinterlaceValue);
break;
default:
break;
}
if (status == STATUS_SUCCESS)
{
/* Make sure that the drawable is gray or RGB color */
if (gimp_drawable_color (drawable->id) || gimp_drawable_gray (drawable->id))
{
gimp_progress_init ("deinterlace");
gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width () + 1));
deinterlace (drawable);
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush ();
if (run_mode == RUN_INTERACTIVE)
gimp_set_data("plug_in_deinterlace", &DeinterlaceValue, sizeof(DeinterlaceValue));
}
else
{
/* gimp_message ("deinterlace: cannot operate on indexed color images"); */
status = STATUS_EXECUTION_ERROR;
}
}
*nreturn_vals = 1;
*return_vals = values;
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
gimp_drawable_detach (drawable);
}
static void
deinterlace (GDrawable *drawable)
{
GPixelRgn srcPR, destPR;
gint width, height;
gint bytes;
guchar *dest;
guchar *upper;
guchar *lower;
gint row, col;
gint x1, y1, x2, y2;
/* Get the input area. This is the bounding box of the selection in
* the image (or the entire image if there is no selection). Only
* operating on the input area is simply an optimization. It doesn't
* need to be done for correct operation. (It simply makes it go
* faster, since fewer pixels need to be operated on).
*/
gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
/* Get the size of the input image. (This will/must be the same
* as the size of the output image.
*/
width = drawable->width;
height = drawable->height;
bytes = drawable->bpp;
/* allocate row buffers */
dest = (guchar *) malloc ((x2 - x1) * bytes);
upper = (guchar *) malloc ((x2 - x1) * bytes);
lower = (guchar *) malloc ((x2 - x1) * bytes);
/* initialize the pixel regions */
gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height, TRUE, TRUE);
/* loop through the rows, performing our magic*/
for (row = y1; row < y2; row++)
{
gimp_pixel_rgn_get_row (&srcPR, dest, x1, row, (x2-x1));
/* Only do interpolation if the row:
(1) Isn't one we want to keep
(2) Has both an upper and a lower row
Otherwise, just duplicate the source row
*/
if (!((row % 2 == DeinterlaceValue) || (row - 1 < 0) || (row + 1 >= height))) {
gimp_pixel_rgn_get_row (&srcPR, upper, x1, row-1, (x2-x1));
gimp_pixel_rgn_get_row (&srcPR, lower, x1, row+1, (x2-x1));
for (col=0; col < ((x2-x1)*bytes); col++)
dest[col]=(upper[col]+lower[col])>>1;
}
gimp_pixel_rgn_set_row (&destPR, dest, x1, row, (x2-x1));
if ((row % 5) == 0)
gimp_progress_update ((double) row / (double) (y2 - y1));
}
/* update the deinterlaced region */
gimp_drawable_flush (drawable);
gimp_drawable_merge_shadow (drawable->id, TRUE);
gimp_drawable_update (drawable->id, x1, y1, (x2 - x1), (y2 - y1));
free (dest);
}
static gint deinterlace_dialog()
{
GtkWidget *dlg;
GtkWidget *vbox;
gint runp;
struct mwRadioGroup modes[] = {
{ "Keep Odd Fields", 0},
{ "Keep Even Fields", 0},
{ NULL, 0}};
gchar **argv;
gint argc;
/* Set args */
argc = 1;
argv = g_new(gchar *, 1);
argv[0] = g_strdup("deinterlace");
gtk_init(&argc, &argv);
gtk_rc_parse(gimp_gtkrc());
modes[DeinterlaceValue].var = 1;
dlg = mw_app_new("plug_in_deinterlace", "Deinterlace", &runp);
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_border_width(GTK_CONTAINER(vbox), 5);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), vbox, TRUE, TRUE, 0);
gtk_widget_show(vbox);
mw_radio_group_new(vbox, "Mode", modes);
gtk_widget_show(dlg);
gtk_main();
gdk_flush();
DeinterlaceValue = mw_radio_result(modes);
if (runp)
return 1;
else
return 0;
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
depthmerge

View file

@ -1,41 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = depthmerge
depthmerge_SOURCES = \
depthmerge.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/libgimp/libgimpui.la \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimpui.la \
$(top_builddir)/libgimp/libgimp.la
depthmerge_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
despeckle

View file

@ -1,36 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = despeckle
despeckle_SOURCES = \
despeckle.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
despeckle_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
destripe

View file

@ -1,39 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = destripe
destripe_SOURCES = \
destripe.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
AM_CPPFLAGS = \
-DLOCALEDIR=\""$(localedir)"\"
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
destripe_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,955 +0,0 @@
/*
* Destripe filter for The GIMP -- an image manipulation
* program
*
* Copyright 1997 Marc Lehmann, heavily modified from a filter by
* Michael Sweet.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Contents:
*
* main() - Main entry - just call gimp_main()...
* query() - Respond to a plug-in query...
* run() - Run the filter...
* destripe() - Destripe an image.
* destripe_dialog() - Popup a dialog window...
* preview_init() - Initialize the preview window...
* preview_scroll_callback() - Update the preview when a scrollbar is moved.
* preview_update() - Update the preview window.
* preview_exit() - Free all memory used by the preview window...
* dialog_create_ivalue() - Create an integer value control...
* dialog_iscale_update() - Update the value field using the scale.
* dialog_ientry_update() - Update the value field using the text entry.
* dialog_histogram_callback()
* dialog_ok_callback() - Start the filter...
* dialog_cancel_callback() - Cancel the filter...
* dialog_close_callback() - Exit the filter dialog application.
*
* 1997/08/16 * Initial Revision.
* 1998/02/06 * Minor changes.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include <string.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "libgimp/stdplugins-intl.h"
/*
* Constants...
*/
#define PLUG_IN_NAME "plug_in_destripe"
#define PLUG_IN_VERSION "0.2"
#define PREVIEW_SIZE 200
#define SCALE_WIDTH 140
#define ENTRY_WIDTH 40
#define MAX_AVG 100
/*
* Local functions...
*/
static void query(void);
static void run(char *, int, GParam *, int *, GParam **);
static void destripe(void);
static gint destripe_dialog(void);
static void dialog_create_ivalue(char *, GtkTable *, int, gint *, int, int);
static void dialog_iscale_update(GtkAdjustment *, gint *);
static void dialog_ientry_update(GtkWidget *, gint *);
static void dialog_ok_callback(GtkWidget *, gpointer);
static void dialog_cancel_callback(GtkWidget *, gpointer);
static void dialog_close_callback(GtkWidget *, gpointer);
static void preview_init(void);
static void preview_exit(void);
static void preview_update(void);
static void preview_scroll_callback(void);
/*
* Globals...
*/
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run /* run_proc */
};
GtkWidget *preview; /* Preview widget */
int preview_width, /* Width of preview widget */
preview_height, /* Height of preview widget */
preview_x1, /* Upper-left X of preview */
preview_y1, /* Upper-left Y of preview */
preview_x2, /* Lower-right X of preview */
preview_y2; /* Lower-right Y of preview */
GtkObject *hscroll_data, /* Horizontal scrollbar data */
*vscroll_data; /* Vertical scrollbar data */
GDrawable *drawable = NULL; /* Current image */
int sel_x1, /* Selection bounds */
sel_y1,
sel_x2,
sel_y2;
int histogram = FALSE;
int img_bpp; /* Bytes-per-pixel in image */
gint run_filter = FALSE; /* True if we should run the filter */
int avg_width = 36;
/*
* 'main()' - Main entry - just call gimp_main()...
*/
MAIN()
/*
* 'query()' - Respond to a plug-in query...
*/
static void
query(void)
{
static GParamDef args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_INT32, "avg_width", "Averaging filter width (default = 36)" }
};
static GParamDef *return_vals = NULL;
static int nargs = sizeof(args) / sizeof(args[0]),
nreturn_vals = 0;
INIT_I18N();
gimp_install_procedure(PLUG_IN_NAME,
_("Destripe filter, used to remove vertical stripes caused by cheap scanners."),
_("This plug-in tries to remove vertical stripes from an image."),
"Marc Lehmann <pcg@goof.com>", "Marc Lehmann <pcg@goof.com>",
PLUG_IN_VERSION,
_("<Image>/Filters/Enhance/Destripe"),
"RGB*, GRAY*",
PROC_PLUG_IN, nargs, nreturn_vals, args, return_vals);
}
/*
* 'run()' - Run the filter...
*/
static void
run(char *name, /* I - Name of filter program. */
int nparams, /* I - Number of parameters passed in */
GParam *param, /* I - Parameter values */
int *nreturn_vals, /* O - Number of return values */
GParam **return_vals) /* O - Return values */
{
GRunModeType run_mode; /* Current run mode */
GStatusType status; /* Return status */
static GParam values[1]; /* Return values */
INIT_I18N();
/*
* Initialize parameter data...
*/
status = STATUS_SUCCESS;
run_mode = param[0].data.d_int32;
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
*nreturn_vals = 1;
*return_vals = values;
/*
* Get drawable information...
*/
drawable = gimp_drawable_get(param[2].data.d_drawable);
gimp_drawable_mask_bounds(drawable->id, &sel_x1, &sel_y1, &sel_x2, &sel_y2);
img_bpp = gimp_drawable_bpp(drawable->id);
/*
* See how we will run
*/
switch (run_mode)
{
case RUN_INTERACTIVE :
/*
* Possibly retrieve data...
*/
gimp_get_data(PLUG_IN_NAME, &avg_width);
/*
* Get information from the dialog...
*/
if (!destripe_dialog())
return;
break;
case RUN_NONINTERACTIVE :
/*
* Make sure all the arguments are present...
*/
if (nparams != 4)
status = STATUS_CALLING_ERROR;
else
avg_width = param[3].data.d_int32;
break;
case RUN_WITH_LAST_VALS :
/*
* Possibly retrieve data...
*/
gimp_get_data(PLUG_IN_NAME, &avg_width);
break;
default :
status = STATUS_CALLING_ERROR;
break;
};
/*
* Destripe the image...
*/
if (status == STATUS_SUCCESS)
{
if ((gimp_drawable_color(drawable->id) ||
gimp_drawable_gray(drawable->id)))
{
/*
* Set the tile cache size...
*/
gimp_tile_cache_ntiles((drawable->width + gimp_tile_width() - 1) /
gimp_tile_width());
/*
* Run!
*/
destripe();
/*
* If run mode is interactive, flush displays...
*/
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush();
/*
* Store data...
*/
if (run_mode == RUN_INTERACTIVE)
gimp_set_data(PLUG_IN_NAME, &avg_width, sizeof(avg_width));
}
else
status = STATUS_EXECUTION_ERROR;
};
/*
* Reset the current run status...
*/
values[0].data.d_status = status;
/*
* Detach from the drawable...
*/
gimp_drawable_detach(drawable);
}
static inline void
preview_draw_row (int x, int y, int w, guchar *row)
{
guchar *rgb = g_new(guchar, w * 3);
guchar *rgb_ptr;
int i;
switch (img_bpp)
{
case 1:
case 2:
for (i = 0, rgb_ptr = rgb; i < w; i++, row += img_bpp, rgb_ptr += 3)
rgb_ptr[0] = rgb_ptr[1] = rgb_ptr[2] = *row;
gtk_preview_draw_row(GTK_PREVIEW(preview), rgb, x, y, w);
break;
case 3:
gtk_preview_draw_row(GTK_PREVIEW(preview), row, x, y, w);
break;
case 4:
for (i = 0, rgb_ptr = rgb; i < w; i++, row += 4, rgb_ptr += 3)
rgb_ptr[0] = row[0],
rgb_ptr[1] = row[1],
rgb_ptr[2] = row[2];
gtk_preview_draw_row(GTK_PREVIEW(preview), rgb, x, y, w);
break;
}
g_free(rgb);
}
static void
destripe_rect (int sel_x1, int sel_y1, int sel_x2, int sel_y2, int do_preview)
{
GPixelRgn src_rgn; /* source image region */
GPixelRgn dst_rgn; /* destination image region */
guchar *src_rows; /* image data */
double progress, progress_inc;
int sel_width = sel_x2 - sel_x1;
int sel_height = sel_y2 - sel_y1;
long *hist, *corr; /* "histogram" data */
int tile_width = gimp_tile_width ();
int i, x, y, ox, cols;
/* initialize */
progress = 0.0;
progress_inc = 0.0;
/*
* Let the user know what we're doing...
*/
if (!do_preview)
{
gimp_progress_init (_("Destriping..."));
progress = 0;
progress_inc = 0.5 * tile_width / sel_width;
}
/*
* Setup for filter...
*/
gimp_pixel_rgn_init(&src_rgn, drawable, sel_x1, sel_y1, sel_width, sel_height, FALSE, FALSE);
gimp_pixel_rgn_init(&dst_rgn, drawable, sel_x1, sel_y1, sel_width, sel_height, TRUE, TRUE);
hist = g_new (long, sel_width * img_bpp);
corr = g_new (long, sel_width * img_bpp);
src_rows = g_malloc (tile_width * sel_height * img_bpp * sizeof (guchar));
memset (hist, 0, sel_width * img_bpp * sizeof (long));
/*
* collect "histogram" data.
*/
for (ox = sel_x1; ox < sel_x2; ox += tile_width)
{
guchar *rows = src_rows;
cols = sel_x2 - ox;
if (cols > tile_width)
cols = tile_width;
gimp_pixel_rgn_get_rect (&src_rgn, rows, ox, sel_y1, cols, sel_height);
for (y = 0; y < sel_height; y++)
{
long *h = hist + (ox - sel_x1) * img_bpp;
guchar *row_end = rows + cols * img_bpp;
while (rows < row_end)
*h++ += *rows++;
}
if (!do_preview)
gimp_progress_update (progress += progress_inc);
}
/*
* average out histogram
*/
if (1)
{
int extend = (avg_width >> 1) * img_bpp;
for (i = 0; i < MIN (3, img_bpp); i++)
{
long *h = hist - extend + i;
long *c = corr - extend + i;
long sum = 0;
int cnt = 0;
for (x = -extend; x < sel_width * img_bpp; x += img_bpp)
{
if (x + extend < sel_width * img_bpp) { sum += h[ extend]; cnt++; };
if (x - extend >= 0) { sum -= h[-extend]; cnt--; };
if (x >= 0) { *c = ((sum/cnt - *h) << 10) / *h; };
h += img_bpp;
c += img_bpp;
}
}
}
else
{
for (i = 0; i < MIN (3, img_bpp); i++)
{
long *h = hist + i + sel_width * img_bpp - img_bpp;
long *c = corr + i + sel_width * img_bpp - img_bpp;
long i = *h;
*c = 0;
do
{
h -= img_bpp;
c -= img_bpp;
if (*h - i > avg_width && i - *h > avg_width)
i = *h;
*c = (i-128) << 10 / *h;
}
while (h > hist);
}
}
/*
* remove stripes.
*/
for (ox = sel_x1; ox < sel_x2; ox += tile_width)
{
guchar *rows = src_rows;
cols = sel_x2 - ox;
if (cols > tile_width)
cols = tile_width;
gimp_pixel_rgn_get_rect (&src_rgn, rows, ox, sel_y1, cols, sel_height);
if (!do_preview)
gimp_progress_update (progress += progress_inc);
for (y = 0; y < sel_height; y++)
{
long *c = corr + (ox - sel_x1) * img_bpp;
guchar *row_end = rows + cols * img_bpp;
if (histogram)
while (rows < row_end)
{
*rows = MIN (255, MAX (0, 128 + (*rows * *c >> 10)));
c++; rows++;
}
else
while (rows < row_end)
{
*rows = MIN (255, MAX (0, *rows + (*rows * *c >> 10) ));
c++; rows++;
}
if (do_preview)
preview_draw_row (ox - sel_x1, y, cols, rows - cols * img_bpp);
}
if (!do_preview)
{
gimp_pixel_rgn_set_rect (&dst_rgn, src_rows, ox, sel_y1, cols, sel_height);
gimp_progress_update (progress += progress_inc);
}
}
g_free(src_rows);
/*
* Update the screen...
*/
if (do_preview)
{
gtk_widget_draw (preview, NULL);
gdk_flush ();
}
else
{
gimp_drawable_flush (drawable);
gimp_drawable_merge_shadow (drawable->id, TRUE);
gimp_drawable_update (drawable->id, sel_x1, sel_y1, sel_width, sel_height);
}
g_free (hist);
g_free (corr);
}
/*
* 'destripe()' - Destripe an image.
*
*/
static void
destripe (void)
{
destripe_rect (sel_x1, sel_y1, sel_x2, sel_y2, 0);
}
static void
dialog_histogram_callback(GtkWidget *widget, /* I - Toggle button */
gpointer data) /* I - Data */
{
histogram = !histogram;
preview_update ();
}
/*
* 'destripe_dialog()' - Popup a dialog window for the filter box size...
*/
static gint
destripe_dialog(void)
{
GtkWidget *dialog, /* Dialog window */
*table, /* Table "container" for controls */
*ptable, /* Preview table */
*ftable, /* Filter table */
*frame, /* Frame for preview */
*scrollbar, /* Horizontal + vertical scroller */
*button;
gint argc; /* Fake argc for GUI */
gchar **argv; /* Fake argv for GUI */
guchar *color_cube; /* Preview color cube... */
/*
* Initialize the program's display...
*/
argc = 1;
argv = g_new(gchar *, 1);
argv[0] = g_strdup("destripe");
gtk_init(&argc, &argv);
gtk_rc_parse(gimp_gtkrc());
gdk_set_use_xshm(gimp_use_xshm());
#ifdef SIGBUS
signal(SIGBUS, SIG_DFL);
#endif
signal(SIGSEGV, SIG_DFL);
gtk_preview_set_gamma(gimp_gamma());
gtk_preview_set_install_cmap(gimp_install_cmap());
color_cube = gimp_color_cube();
gtk_preview_set_color_cube(color_cube[0], color_cube[1], color_cube[2], color_cube[3]);
gtk_widget_set_default_visual(gtk_preview_get_visual());
gtk_widget_set_default_colormap(gtk_preview_get_cmap());
/*
* Dialog window...
*/
dialog = gtk_dialog_new();
gtk_window_set_title(GTK_WINDOW(dialog), _("Destripe"));
gtk_window_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
gtk_container_border_width(GTK_CONTAINER(dialog), 0);
gtk_signal_connect(GTK_OBJECT(dialog), "destroy",
(GtkSignalFunc) dialog_close_callback,
NULL);
/*
* Top-level table for dialog...
*/
table = gtk_table_new(3, 3, FALSE);
gtk_container_border_width(GTK_CONTAINER(table), 6);
gtk_table_set_row_spacings(GTK_TABLE(table), 4);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table, FALSE, FALSE, 0);
gtk_widget_show(table);
/*
* Preview window...
*/
ptable = gtk_table_new(2, 2, FALSE);
gtk_container_border_width(GTK_CONTAINER(ptable), 0);
gtk_table_attach(GTK_TABLE(table), ptable, 0, 2, 0, 1, 0, 0, 0, 0);
gtk_widget_show(ptable);
frame = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
gtk_table_attach(GTK_TABLE(ptable), frame, 0, 1, 0, 1, 0, 0, 0, 0);
gtk_widget_show(frame);
preview_width = MIN(sel_x2 - sel_x1, PREVIEW_SIZE);
preview_height = MIN(sel_y2 - sel_y1, PREVIEW_SIZE);
preview = gtk_preview_new(GTK_PREVIEW_COLOR);
gtk_preview_size(GTK_PREVIEW(preview), preview_width, preview_height);
gtk_container_add(GTK_CONTAINER(frame), preview);
gtk_widget_show(preview);
hscroll_data = gtk_adjustment_new(0, 0, sel_x2 - sel_x1 - 1, 1.0,
MIN(preview_width, sel_x2 - sel_x1),
MIN(preview_width, sel_x2 - sel_x1));
gtk_signal_connect(hscroll_data, "value_changed",
(GtkSignalFunc)preview_scroll_callback, NULL);
scrollbar = gtk_hscrollbar_new(GTK_ADJUSTMENT(hscroll_data));
gtk_range_set_update_policy(GTK_RANGE(scrollbar), GTK_UPDATE_CONTINUOUS);
gtk_table_attach(GTK_TABLE(ptable), scrollbar, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
gtk_widget_show(scrollbar);
vscroll_data = gtk_adjustment_new(0, 0, sel_y2 - sel_y1 - 1, 1.0,
MIN(preview_height, sel_y2 - sel_y1),
MIN(preview_height, sel_y2 - sel_y1));
gtk_signal_connect(vscroll_data, "value_changed",
(GtkSignalFunc)preview_scroll_callback, NULL);
scrollbar = gtk_vscrollbar_new(GTK_ADJUSTMENT(vscroll_data));
gtk_range_set_update_policy(GTK_RANGE(scrollbar), GTK_UPDATE_CONTINUOUS);
gtk_table_attach(GTK_TABLE(ptable), scrollbar, 1, 2, 0, 1, 0, GTK_FILL, 0, 0);
gtk_widget_show(scrollbar);
preview_init();
/*
* Filter type controls...
*/
ftable = gtk_table_new(4, 1, FALSE);
gtk_container_border_width(GTK_CONTAINER(ftable), 4);
gtk_table_attach(GTK_TABLE(table), ftable, 2, 3, 0, 1, 0, 0, 0, 0);
gtk_widget_show(ftable);
button = gtk_check_button_new_with_label(_("Histogram"));
gtk_table_attach(GTK_TABLE(ftable), button, 0, 1, 0, 1,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
histogram ? TRUE : FALSE);
gtk_signal_connect(GTK_OBJECT(button), "toggled",
(GtkSignalFunc)dialog_histogram_callback,
NULL);
gtk_widget_show(button);
/* button = gtk_check_button_new_with_label("Recursive");
gtk_table_attach(GTK_TABLE(ftable), button, 0, 1, 1, 2,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
(filter_type & FILTER_RECURSIVE) ? TRUE : FALSE);
gtk_signal_connect(GTK_OBJECT(button), "toggled",
(GtkSignalFunc)dialog_recursive_callback,
NULL);
gtk_widget_show(button);*/
/*
* Box size (radius) control...
*/
dialog_create_ivalue(_("Width"), GTK_TABLE(table), 2, &avg_width, 2, MAX_AVG);
/*
* OK, cancel buttons...
*/
gtk_container_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), 6);
button = gtk_button_new_with_label(_("OK"));
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
(GtkSignalFunc) dialog_ok_callback,
dialog);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, TRUE, TRUE, 0);
gtk_widget_grab_default(button);
gtk_widget_show(button);
button = gtk_button_new_with_label(_("Cancel"));
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
(GtkSignalFunc) dialog_cancel_callback,
dialog);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, TRUE, TRUE, 0);
gtk_widget_show(button);
/*
* Show it and wait for the user to do something...
*/
gtk_widget_show(dialog);
preview_update();
gtk_main();
gdk_flush();
/*
* Free the preview data...
*/
preview_exit();
/*
* Return ok/cancel...
*/
return (run_filter);
}
/*
* 'preview_init()' - Initialize the preview window...
*/
static void
preview_init(void)
{
int width; /* Byte width of the image */
/*
* Setup for preview filter...
*/
width = preview_width * img_bpp;
preview_x1 = sel_x1;
preview_y1 = sel_y1;
preview_x2 = preview_x1 + MIN(preview_width, sel_x2 - sel_x1);
preview_y2 = preview_y1 + MIN(preview_height, sel_y2 -sel_y1);
}
/*
* 'preview_scroll_callback()' - Update the preview when a scrollbar is moved.
*/
static void
preview_scroll_callback(void)
{
preview_x1 = sel_x1 + GTK_ADJUSTMENT(hscroll_data)->value;
preview_y1 = sel_y1 + GTK_ADJUSTMENT(vscroll_data)->value;
preview_x2 = preview_x1 + MIN(preview_width, sel_x2 - sel_x1);
preview_y2 = preview_y1 + MIN(preview_height, sel_y2 - sel_y1);
preview_update();
}
/*
* 'preview_update()' - Update the preview window.
*/
static void
preview_update(void)
{
destripe_rect (preview_x1, preview_y1, preview_x2, preview_y2, 1);
}
/*
* 'preview_exit()' - Free all memory used by the preview window...
*/
static void
preview_exit(void)
{
}
/*
* 'dialog_create_ivalue()' - Create an integer value control...
*/
static void
dialog_create_ivalue(char *title, /* I - Label for control */
GtkTable *table, /* I - Table container to use */
int row, /* I - Row # for container */
gint *value, /* I - Value holder */
int left, /* I - Minimum value for slider */
int right) /* I - Maximum value for slider */
{
GtkWidget *label, /* Control label */
*scale, /* Scale widget */
*entry; /* Text widget */
GtkObject *scale_data; /* Scale data */
char buf[256]; /* String buffer */
/*
* Label...
*/
label = gtk_label_new(title);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 1.0);
gtk_table_attach(table, label, 0, 1, row, row + 1, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(label);
/*
* Scale...
*/
scale_data = gtk_adjustment_new(*value, left, right, 1.0, 1.0, 1.0);
gtk_signal_connect(GTK_OBJECT(scale_data), "value_changed",
(GtkSignalFunc) dialog_iscale_update,
value);
scale = gtk_hscale_new(GTK_ADJUSTMENT(scale_data));
gtk_widget_set_usize(scale, SCALE_WIDTH, 0);
gtk_table_attach(table, scale, 1, 2, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
gtk_scale_set_draw_value(GTK_SCALE(scale), FALSE);
gtk_range_set_update_policy(GTK_RANGE(scale), GTK_UPDATE_CONTINUOUS);
gtk_widget_show(scale);
/*
* Text entry...
*/
entry = gtk_entry_new();
gtk_object_set_user_data(GTK_OBJECT(entry), scale_data);
gtk_object_set_user_data(scale_data, entry);
gtk_widget_set_usize(entry, ENTRY_WIDTH, 0);
sprintf(buf, "%d", *value);
gtk_entry_set_text(GTK_ENTRY(entry), buf);
gtk_signal_connect(GTK_OBJECT(entry), "changed",
(GtkSignalFunc) dialog_ientry_update,
value);
gtk_table_attach(GTK_TABLE(table), entry, 2, 3, row, row + 1, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(entry);
}
/*
* 'dialog_iscale_update()' - Update the value field using the scale.
*/
static void
dialog_iscale_update(GtkAdjustment *adjustment, /* I - New value */
gint *value) /* I - Current value */
{
GtkWidget *entry; /* Text entry widget */
char buf[256]; /* Text buffer */
if (*value != adjustment->value)
{
*value = adjustment->value;
entry = gtk_object_get_user_data(GTK_OBJECT(adjustment));
sprintf(buf, "%d", *value);
gtk_signal_handler_block_by_data(GTK_OBJECT(entry), value);
gtk_entry_set_text(GTK_ENTRY(entry), buf);
gtk_signal_handler_unblock_by_data(GTK_OBJECT(entry), value);
preview_update();
};
}
/*
* 'dialog_ientry_update()' - Update the value field using the text entry.
*/
static void
dialog_ientry_update(GtkWidget *widget, /* I - Entry widget */
gint *value) /* I - Current value */
{
GtkAdjustment *adjustment;
gint new_value;
new_value = atoi(gtk_entry_get_text(GTK_ENTRY(widget)));
if (*value != new_value)
{
adjustment = gtk_object_get_user_data(GTK_OBJECT(widget));
if ((new_value >= adjustment->lower) &&
(new_value <= adjustment->upper))
{
*value = new_value;
adjustment->value = new_value;
gtk_signal_emit_by_name(GTK_OBJECT(adjustment), "value_changed");
preview_update();
};
};
}
/*
* 'dialog_ok_callback()' - Start the filter...
*/
static void
dialog_ok_callback(GtkWidget *widget, /* I - OK button widget */
gpointer data) /* I - Dialog window */
{
run_filter = TRUE;
gtk_widget_destroy(GTK_WIDGET(data));
}
/*
* 'dialog_cancel_callback()' - Cancel the filter...
*/
static void
dialog_cancel_callback(GtkWidget *widget, /* I - Cancel button widget */
gpointer data) /* I - Dialog window */
{
gtk_widget_destroy(GTK_WIDGET(data));
}
/*
* 'dialog_close_callback()' - Exit the filter dialog application.
*/
static void
dialog_close_callback(GtkWidget *widget, /* I - Dialog window */
gpointer data) /* I - Dialog window */
{
gtk_main_quit();
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
diffraction

View file

@ -1,36 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = diffraction
diffraction_SOURCES = \
diffraction.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
diffraction_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,836 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* Diffraction plug-in --- Generate diffraction patterns
* Copyright (C) 1997 Federico Mena Quintero and David Bleecker
* federico@nuclecu.unam.mx
* bleecker@math.hawaii.edu
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/types.h>
#include "gtk/gtk.h"
#include "libgimp/gimp.h"
/***** Magic numbers *****/
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif /* M_PI */
#define ITERATIONS 100 /* 100 */
#define WEIRD_FACTOR 0.04 /* 0.04 */
#define PREVIEW_WIDTH 64
#define PREVIEW_HEIGHT 64
#define PROGRESS_WIDTH 32
#define PROGRESS_HEIGHT 16
#define SCALE_WIDTH 150
/***** Types *****/
typedef struct {
gdouble lam_r;
gdouble lam_g;
gdouble lam_b;
gdouble contour_r;
gdouble contour_g;
gdouble contour_b;
gdouble edges_r;
gdouble edges_g;
gdouble edges_b;
gdouble brightness;
gdouble scattering;
gdouble polarization;
} diffraction_vals_t;
typedef struct {
GtkWidget *preview;
GtkWidget *progress;
guchar preview_row[PREVIEW_WIDTH * 3];
gint run;
} diffraction_interface_t;
/***** Prototypes *****/
static void query(void);
static void run(char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals);
static void diffraction(GDrawable *drawable);
static void diff_init_luts(void);
static void diff_diffract(double x, double y, double *r, double *g, double *b);
static double diff_point(double x, double y, double edges, double contours, double lam);
static double diff_intensity(double x, double y, double lam);
static gint diffraction_dialog(void);
static void dialog_update_preview(void);
static void dialog_create_value(char *title, GtkTable *table, int row, gdouble *value, double left, double right);
static void dialog_update_callback(GtkWidget *widget, gpointer data);
static void dialog_scale_update(GtkAdjustment *adjustment, gdouble *value);
static void dialog_close_callback(GtkWidget *widget, gpointer data);
static void dialog_ok_callback(GtkWidget *widget, gpointer data);
static void dialog_cancel_callback(GtkWidget *widget, gpointer data);
/***** Variables *****/
GPlugInInfo PLUG_IN_INFO = {
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run /* run_proc */
}; /* PLUG_IN_INFO */
static diffraction_vals_t dvals = {
0.815, /* lam_r */
1.221, /* lam_g */
1.123, /* lam_b */
0.821, /* contour_r */
0.821, /* contour_g */
0.974, /* contour_b */
0.610, /* edges_r */
0.677, /* edges_g */
0.636, /* edges_b */
0.066, /* brightness */
37.126, /* scattering */
-0.473 /* polarization */
}; /* dvals */
static diffraction_interface_t dint = {
NULL, /* preview */
NULL, /* progress */
{ 0 }, /* preview_row */
FALSE /* run */
}; /* dint */
static double cos_lut[ITERATIONS + 1];
static double param_lut1[ITERATIONS + 1];
static double param_lut2[ITERATIONS + 1];
/***** Functions *****/
/*****/
MAIN()
/*****/
static void
query(void)
{
static GParamDef args[] = {
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_FLOAT, "lam_r", "Light frequency (red)" },
{ PARAM_FLOAT, "lam_g", "Light frequency (green)" },
{ PARAM_FLOAT, "lam_b", "Light frequency (blue)" },
{ PARAM_FLOAT, "contour_r", "Number of contours (red)" },
{ PARAM_FLOAT, "contour_g", "Number of contours (green)" },
{ PARAM_FLOAT, "contour_b", "Number of contours (blue)" },
{ PARAM_FLOAT, "edges_r", "Number of sharp edges (red)" },
{ PARAM_FLOAT, "edges_g", "Number of sharp edges (green)" },
{ PARAM_FLOAT, "edges_b", "Number of sharp edges (blue)" },
{ PARAM_FLOAT, "brightness", "Brightness and shifting/fattening of contours" },
{ PARAM_FLOAT, "scattering", "Scattering (Speed vs. quality)" },
{ PARAM_FLOAT, "polarization", "Polarization" }
}; /* args */
static GParamDef *return_vals = NULL;
static int nargs = sizeof(args) / sizeof(args[0]);
static int nreturn_vals = 0;
gimp_install_procedure("plug_in_diffraction",
"Generate diffraction patterns",
"Help? What help? Real men do not need help :-)", /* FIXME */
"Federico Mena Quintero",
"Federico Mena Quintero & David Bleecker",
"April 1997, 0.5",
"<Image>/Filters/Render/Diffraction Patterns",
"RGB*",
PROC_PLUG_IN,
nargs,
nreturn_vals,
args,
return_vals);
} /* query */
/*****/
static void
run(char *name,
int nparams,
GParam *param,
int *nreturn_vals,
GParam **return_vals)
{
static GParam values[1];
GDrawable *active_drawable;
GRunModeType run_mode;
GStatusType status;
/* Initialize */
diff_init_luts();
status = STATUS_SUCCESS;
run_mode = param[0].data.d_int32;
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
*nreturn_vals = 1;
*return_vals = values;
switch (run_mode) {
case RUN_INTERACTIVE:
/* Possibly retrieve data */
gimp_get_data("plug_in_diffraction", &dvals);
/* Get information from the dialog */
if (!diffraction_dialog())
return;
break;
case RUN_NONINTERACTIVE:
/* Make sure all the arguments are present */
if (nparams != 15)
status = STATUS_CALLING_ERROR;
if (status == STATUS_SUCCESS) {
dvals.lam_r = param[3].data.d_float;
dvals.lam_g = param[4].data.d_float;
dvals.lam_b = param[5].data.d_float;
dvals.contour_r = param[6].data.d_float;
dvals.contour_g = param[7].data.d_float;
dvals.contour_b = param[8].data.d_float;
dvals.edges_r = param[9].data.d_float;
dvals.edges_g = param[10].data.d_float;
dvals.edges_b = param[11].data.d_float;
dvals.brightness = param[12].data.d_float;
dvals.scattering = param[13].data.d_float;
dvals.polarization = param[14].data.d_float;
} /* if */
break;
case RUN_WITH_LAST_VALS:
/* Possibly retrieve data */
gimp_get_data("plug_in_diffraction", &dvals);
break;
default:
break;
} /* switch */
/* Get the active drawable */
active_drawable = gimp_drawable_get(param[2].data.d_drawable);
/* Create the diffraction pattern */
if ((status == STATUS_SUCCESS) && gimp_drawable_color(active_drawable->id)) {
/* Set the tile cache size */
gimp_tile_cache_ntiles((active_drawable->width + gimp_tile_width() - 1) / gimp_tile_width());
/* Run! */
diffraction(active_drawable);
/* If run mode is interactive, flush displays */
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush();
/* Store data */
if (run_mode == RUN_INTERACTIVE)
gimp_set_data("plug_in_diffraction", &dvals, sizeof(diffraction_vals_t));
} else if (status == STATUS_SUCCESS)
status = STATUS_EXECUTION_ERROR;
values[0].data.d_status = status;
gimp_drawable_detach(active_drawable);
} /* run */
/*****/
static void
diffraction(GDrawable *drawable)
{
GPixelRgn dest_rgn;
gpointer pr;
gint x1, y1, x2, y2;
gint width, height;
gint has_alpha;
gint row, col;
guchar *dest_row;
guchar *dest;
gint progress, max_progress;
double left, right, bottom, top;
double dhoriz, dvert;
double px, py;
double r, g, b;
/* Get the mask bounds and image size */
gimp_drawable_mask_bounds(drawable->id, &x1, &y1, &x2, &y2);
width = x2 - x1;
height = y2 - y1;
has_alpha = gimp_drawable_has_alpha(drawable->id);
/* Initialize pixel regions */
gimp_pixel_rgn_init(&dest_rgn, drawable, x1, y1, width, height, TRUE, TRUE);
progress = 0;
max_progress = width * height;
gimp_progress_init("Creating diffraction pattern...");
/* Create diffraction pattern */
left = -5.0;
right = 5.0;
bottom = -5.0;
top = 5.0;
dhoriz = (right - left) / (width - 1);
dvert = (bottom - top) / (height - 1);
for (pr = gimp_pixel_rgns_register(1, &dest_rgn);
pr != NULL; pr = gimp_pixel_rgns_process(pr)) {
dest_row = dest_rgn.data;
py = top + dvert * (dest_rgn.y - y1);
for (row = 0; row < dest_rgn.h; row++) {
dest = dest_row;
px = left + dhoriz * (dest_rgn.x - x1);
for (col = 0; col < dest_rgn.w; col++) {
diff_diffract(px, py, &r, &g, &b);
*dest++ = 255.0 * r;
*dest++ = 255.0 * g;
*dest++ = 255.0 * b;
if (has_alpha)
*dest++ = 255;
px += dhoriz;
} /* for */
/* Update progress */
progress += dest_rgn.w;
gimp_progress_update((double) progress / max_progress);
py += dvert;
dest_row += dest_rgn.rowstride;
} /* for */
} /* for */
gimp_drawable_flush(drawable);
gimp_drawable_merge_shadow(drawable->id, TRUE);
gimp_drawable_update(drawable->id, x1, y1, width, height);
} /* diffraction */
static void
diff_init_luts(void)
{
int i;
double a;
double sina;
a = -M_PI;
for (i = 0; i <= ITERATIONS; i++) {
sina = sin(a);
cos_lut[i] = cos(a);
param_lut1[i] = 0.75 * sina;
param_lut2[i] = 0.5 * (4.0 * cos_lut[i] * cos_lut[i] + sina * sina);
a += (2.0 * M_PI / ITERATIONS);
} /* for */
} /* diff_init_luts */
/*****/
static void
diff_diffract(double x, double y, double *r, double *g, double *b)
{
*r = diff_point(x, y, dvals.edges_r, dvals.contour_r, dvals.lam_r);
*g = diff_point(x, y, dvals.edges_g, dvals.contour_g, dvals.lam_g);
*b = diff_point(x, y, dvals.edges_b, dvals.contour_b, dvals.lam_b);
} /* diff_diffract */
/*****/
static double
diff_point(double x, double y, double edges, double contours, double lam)
{
return fabs(edges * sin(contours * atan(dvals.brightness * diff_intensity(x, y, lam))));
} /* diff_point */
/*****/
static double
diff_intensity(double x, double y, double lam)
{
int i;
double cxy, sxy;
double param;
double polpi2;
double cospolpi2, sinpolpi2;
cxy = 0.0;
sxy = 0.0;
lam *= 4.0;
for (i = 0; i <= ITERATIONS; i++) {
param = lam *
(cos_lut[i] * x +
param_lut1[i] * y -
param_lut2[i]);
cxy += cos(param);
sxy += sin(param);
} /* for */
cxy *= WEIRD_FACTOR;
sxy *= WEIRD_FACTOR;
polpi2 = dvals.polarization * (M_PI / 2.0);
cospolpi2 = cos(polpi2);
sinpolpi2 = sin(polpi2);
return dvals.scattering * ((cospolpi2 + sinpolpi2) * cxy * cxy +
(cospolpi2 - sinpolpi2) * sxy * sxy);
} /* diff_intensity */
#if 0
/*****/
static double
diff_intensity(double x, double y, double lam)
{
int i;
double cxy, sxy;
double s;
double cosa, sina;
double twocosa, param;
double polpi2;
double cospolpi2, sinpolpi2;
s = dvals.scattering;
cxy = 0.0;
sxy = 0.0;
for (i = 0; i <= ITERATIONS; i++) {
cosa = cos_lut[i];
sina = sin_lut[i];
twocosa = 2.0 * cosa;
param = 4.0 * lam *
(cosa * x +
0.75 * sina * y -
0.5 * (twocosa * twocosa + sina * sina));
cxy += 0.04 * cos(param);
sxy += 0.04 * sin(param);
} /* for */
polpi2 = dvals.polarization * (M_PI / 2.0);
cospolpi2 = cos(polpi2);
sinpolpi2 = sin(polpi2);
return s * ((cospolpi2 + sinpolpi2) * cxy * cxy +
(cospolpi2 - sinpolpi2) * sxy * sxy);
} /* diff_intensity */
#endif
/*****/
static gint
diffraction_dialog(void)
{
GtkWidget *dialog;
GtkWidget *top_table;
GtkWidget *notebook;
GtkWidget *frame;
GtkWidget *vbox;
GtkWidget *table;
GtkWidget *label;
GtkWidget *button;
gint argc;
gchar **argv;
guchar *color_cube;
#if 0
printf("Waiting... (pid %d)\n", getpid());
kill(getpid(), SIGSTOP);
#endif
argc = 1;
argv = g_new(gchar *, 1);
argv[0] = g_strdup("diffraction");
gtk_init(&argc, &argv);
gtk_rc_parse (gimp_gtkrc ());
gdk_set_use_xshm (gimp_use_xshm ());
gtk_preview_set_gamma(gimp_gamma());
gtk_preview_set_install_cmap(gimp_install_cmap());
color_cube = gimp_color_cube();
gtk_preview_set_color_cube(color_cube[0], color_cube[1], color_cube[2], color_cube[3]);
gtk_widget_set_default_visual(gtk_preview_get_visual());
gtk_widget_set_default_colormap(gtk_preview_get_cmap());
dialog = gtk_dialog_new();
gtk_window_set_title(GTK_WINDOW(dialog), "Diffraction patterns");
gtk_window_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
gtk_container_border_width(GTK_CONTAINER(dialog), 0);
gtk_signal_connect(GTK_OBJECT(dialog), "destroy",
(GtkSignalFunc) dialog_close_callback,
NULL);
top_table = gtk_table_new(2, 2, FALSE);
gtk_container_border_width(GTK_CONTAINER(top_table), 6);
gtk_table_set_row_spacings(GTK_TABLE(top_table), 4);
gtk_table_set_col_spacings(GTK_TABLE(top_table), 4);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), top_table, FALSE, FALSE, 0);
gtk_widget_show(top_table);
/* Preview */
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_border_width(GTK_CONTAINER(vbox), 0);
gtk_table_attach(GTK_TABLE(top_table), vbox, 0, 1, 0, 1,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
gtk_widget_show(vbox);
frame = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 0);
gtk_widget_show(frame);
dint.preview = gtk_preview_new(GTK_PREVIEW_COLOR);
gtk_preview_size(GTK_PREVIEW(dint.preview), PREVIEW_WIDTH, PREVIEW_HEIGHT);
gtk_container_add(GTK_CONTAINER(frame), dint.preview);
gtk_widget_show(dint.preview);
dint.progress = gtk_progress_bar_new();
gtk_widget_set_usize(dint.progress, PROGRESS_WIDTH, PROGRESS_HEIGHT);
gtk_box_pack_start(GTK_BOX(vbox), dint.progress, TRUE, FALSE, 0);
gtk_widget_show(dint.progress);
button = gtk_button_new_with_label("Preview!");
gtk_signal_connect(GTK_OBJECT(button), "clicked",
(GtkSignalFunc) dialog_update_callback,
NULL);
gtk_table_attach(GTK_TABLE(top_table), button, 0, 1, 1, 2,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
gtk_widget_show(button);
/* Notebook */
notebook = gtk_notebook_new();
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP);
gtk_table_attach(GTK_TABLE(top_table), notebook, 1, 2, 0, 2, GTK_EXPAND | GTK_FILL, 0, 0, 0);
gtk_widget_show(notebook);
/* Frequencies tab */
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_border_width(GTK_CONTAINER(vbox), 4);
table = gtk_table_new(3, 2, FALSE);
gtk_container_border_width(GTK_CONTAINER(table), 0);
gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
gtk_widget_show(table);
dialog_create_value("Red", GTK_TABLE(table), 0, &dvals.lam_r, 0.0, 20.0);
dialog_create_value("Green", GTK_TABLE(table), 1, &dvals.lam_g, 0.0, 20.0);
dialog_create_value("Blue", GTK_TABLE(table), 2, &dvals.lam_b, 0.0, 20.0);
label = gtk_label_new("Frequencies");
gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
gtk_widget_show(vbox);
/* Contours tab */
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_border_width(GTK_CONTAINER(vbox), 4);
table = gtk_table_new(3, 2, FALSE);
gtk_container_border_width(GTK_CONTAINER(table), 0);
gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
gtk_widget_show(table);
dialog_create_value("Red", GTK_TABLE(table), 0, &dvals.contour_r, 0.0, 10.0);
dialog_create_value("Green", GTK_TABLE(table), 1, &dvals.contour_g, 0.0, 10.0);
dialog_create_value("Blue", GTK_TABLE(table), 2, &dvals.contour_b, 0.0, 10.0);
label = gtk_label_new("Contours");
gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
gtk_widget_show(vbox);
/* Sharp edges tab */
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_border_width(GTK_CONTAINER(vbox), 4);
table = gtk_table_new(3, 2, FALSE);
gtk_container_border_width(GTK_CONTAINER(table), 0);
gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
gtk_widget_show(table);
dialog_create_value("Red", GTK_TABLE(table), 0, &dvals.edges_r, 0.0, 1.0);
dialog_create_value("Green", GTK_TABLE(table), 1, &dvals.edges_g, 0.0, 1.0);
dialog_create_value("Blue", GTK_TABLE(table), 2, &dvals.edges_b, 0.0, 1.0);
label = gtk_label_new("Sharp edges");
gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
gtk_widget_show(vbox);
/* Other options tab */
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_border_width(GTK_CONTAINER(vbox), 4);
table = gtk_table_new(3, 2, FALSE);
gtk_container_border_width(GTK_CONTAINER(table), 0);
gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 0);
gtk_widget_show(table);
dialog_create_value("Brightness", GTK_TABLE(table), 0, &dvals.brightness, 0.0, 1.0);
dialog_create_value("Scattering", GTK_TABLE(table), 1, &dvals.scattering, 0.0, 100.0);
dialog_create_value("Polarization", GTK_TABLE(table), 2, &dvals.polarization, -1.0, 1.0);
label = gtk_label_new("Other options");
gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), vbox, label);
gtk_widget_show(vbox);
/* Buttons */
gtk_container_border_width(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), 6);
button = gtk_button_new_with_label("OK");
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
(GtkSignalFunc) dialog_ok_callback,
dialog);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, TRUE, TRUE, 0);
gtk_widget_grab_default(button);
gtk_widget_show(button);
button = gtk_button_new_with_label("Cancel");
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
(GtkSignalFunc) dialog_cancel_callback,
dialog);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button, TRUE, TRUE, 0);
gtk_widget_show(button);
/* Done */
gtk_widget_show(dialog);
dialog_update_preview();
gtk_main();
gdk_flush();
return dint.run;
} /* diffraction_dialog */
/*****/
static void
dialog_update_preview(void)
{
double left, right, bottom, top;
double px, py;
double dx, dy;
double r, g, b;
int x, y;
guchar *p;
left = -5.0;
right = 5.0;
bottom = -5.0;
top = 5.0;
dx = (right - left) / (PREVIEW_WIDTH - 1);
dy = (bottom - top) / (PREVIEW_HEIGHT - 1);
py = top;
for (y = 0; y < PREVIEW_HEIGHT; y++) {
px = left;
p = dint.preview_row;
for (x = 0; x < PREVIEW_WIDTH; x++) {
diff_diffract(px, py, &r, &g, &b);
*p++ = 255.0 * r;
*p++ = 255.0 * g;
*p++ = 255.0 * b;
px += dx;
} /* for */
gtk_preview_draw_row(GTK_PREVIEW(dint.preview), dint.preview_row, 0, y, PREVIEW_WIDTH);
gtk_progress_bar_update(GTK_PROGRESS_BAR(dint.progress), (double) y / (PREVIEW_HEIGHT - 1));
py += dy;
} /* for */
gtk_widget_draw(dint.preview, NULL);
gtk_progress_bar_update(GTK_PROGRESS_BAR(dint.progress), 0.0);
gdk_flush();
} /* dialog_update_preview */
/*****/
static void
dialog_create_value(char *title, GtkTable *table, int row, gdouble *value, double left, double right)
{
GtkWidget *label;
GtkWidget *scale;
GtkObject *scale_data;
label = gtk_label_new(title);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 1.0);
gtk_table_attach(table, label, 0, 1, row, row + 1, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(label);
scale_data = gtk_adjustment_new(*value, left, right,
(right - left) / 50.0,
(right - left) / 100.0,
0.0);
scale = gtk_hscale_new(GTK_ADJUSTMENT(scale_data));
gtk_widget_set_usize(scale, SCALE_WIDTH, 0);
gtk_table_attach(table, scale, 1, 2, row, row + 1, GTK_EXPAND | GTK_FILL, 0, 0, 0);
gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_TOP);
gtk_scale_set_digits(GTK_SCALE(scale), 3);
gtk_range_set_update_policy(GTK_RANGE(scale), GTK_UPDATE_CONTINUOUS);
gtk_signal_connect(GTK_OBJECT(scale_data), "value_changed",
(GtkSignalFunc) dialog_scale_update,
value);
gtk_widget_show(scale);
} /* dialog_create_value */
/*****/
static void
dialog_update_callback(GtkWidget *widget, gpointer data)
{
dialog_update_preview();
} /* dialog_update_callback */
/*****/
static void
dialog_scale_update(GtkAdjustment *adjustment, gdouble *value)
{
*value = adjustment->value;
} /* dialog_scale_update */
/*****/
static void
dialog_close_callback(GtkWidget *widget, gpointer data)
{
gtk_main_quit();
} /* dialog_close_callback */
/*****/
static void
dialog_ok_callback(GtkWidget *widget, gpointer data)
{
dint.run = TRUE;
gtk_widget_destroy(GTK_WIDGET(data));
} /* dialog_ok_callback */
/*****/
static void
dialog_cancel_callback(GtkWidget *widget, gpointer data)
{
gtk_widget_destroy(GTK_WIDGET(data));
} /* dialog_cancel_callback */

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
displace

View file

@ -1,38 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = displace
displace_SOURCES = \
displace.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimpui.la \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimpui.la \
$(top_builddir)/libgimp/libgimp.la
displace_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,886 +0,0 @@
/* Displace --- image filter plug-in for The Gimp image manipulation program
* Copyright (C) 1996 Stephen Robert Norris
* Much of the code taken from the pinch plug-in by 1996 Federico Mena Quintero
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* You can contact me at srn@flibble.cs.su.oz.au.
* Please send me any patches or enhancements to this code.
* You can contact the original The Gimp authors at gimp@xcf.berkeley.edu
*
* Extensive modifications to the dialog box, parameters, and some
* legibility stuff in displace() by Federico Mena Quintero ---
* federico@nuclecu.unam.mx. If there are any bugs in these
* changes, they are my fault and not Stephen's.
*
* JTL: May 29th 1997
* Added (part of) the patch from Eiichi Takamori -- the part which removes the border artefacts
* (http://ha1.seikyou.ne.jp/home/taka/gimp/displace/displace.html)
* Added ability to use transparency as the identity transformation
* (Full transparency is treated as if it was grey 0.5)
* and the possibility to use RGB/RGBA pictures where the intensity of the pixel is taken into account
*
*/
/* Version 1.12. */
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <signal.h>
#include "gtk/gtk.h"
#include "libgimp/gimp.h"
#include "libgimp/gimpui.h"
/* Some useful macros */
#define ENTRY_WIDTH 75
#define TILE_CACHE_SIZE 48
#define WRAP 0
#define SMEAR 1
#define BLACK 2
typedef struct {
gdouble amount_x;
gdouble amount_y;
gint do_x;
gint do_y;
gint displace_map_x;
gint displace_map_y;
gint displace_type;
} DisplaceVals;
typedef struct {
GtkWidget *amount_x;
GtkWidget *amount_y;
GtkWidget *menu_x;
GtkWidget *menu_y;
gint run;
} DisplaceInterface;
/*
* Function prototypes.
*/
static void query (void);
static void run (gchar *name,
gint nparams,
GParam *param,
gint *nreturn_vals,
GParam **return_vals);
static void displace (GDrawable *drawable);
static gint displace_dialog (GDrawable *drawable);
static GTile * displace_pixel (GDrawable * drawable,
GTile * tile,
gint width,
gint height,
gint x1,
gint y1,
gint x2,
gint y2,
gint x,
gint y,
gint * row,
gint * col,
guchar * pixel);
static guchar bilinear (gdouble x,
gdouble y,
guchar * v);
static gint displace_map_constrain (gint32 image_id,
gint32 drawable_id,
gpointer data);
static void displace_map_x_callback (gint32 id,
gpointer data);
static void displace_map_y_callback (gint32 id,
gpointer data);
static void displace_close_callback (GtkWidget *widget,
gpointer data);
static void displace_ok_callback (GtkWidget *widget,
gpointer data);
static void displace_toggle_update (GtkWidget *widget,
gpointer data);
static void displace_x_toggle_update (GtkWidget *widget,
gpointer data);
static void displace_y_toggle_update (GtkWidget *widget,
gpointer data);
static void displace_entry_callback (GtkWidget *widget,
gpointer data);
static gdouble displace_map_give_value (guchar* ptr,
gint alpha,
gint bytes);
/***** Local vars *****/
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
static DisplaceVals dvals =
{
20.0, /* amount_x */
20.0, /* amount_y */
TRUE, /* do_x */
TRUE, /* do_y */
-1, /* displace_map_x */
-1, /* displace_map_y */
WRAP /* displace_type */
};
static DisplaceInterface dint =
{
NULL, /* amount_x */
NULL, /* amount_y */
NULL, /* menu_x */
NULL, /* menu_y */
FALSE /* run */
};
/***** Functions *****/
MAIN ()
static void
query ()
{
static GParamDef args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image (unused)" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_FLOAT, "amount_x", "Displace multiplier for X direction" },
{ PARAM_FLOAT, "amount_y", "Displace multiplier for Y direction" },
{ PARAM_INT32, "do_x", "Displace in X direction?" },
{ PARAM_INT32, "do_y", "Displace in Y direction?" },
{ PARAM_DRAWABLE, "displace_map_x", "Displacement map for X direction" },
{ PARAM_DRAWABLE, "displace_map_y", "Displacement map for Y direction" },
{ PARAM_INT32, "displace_type", "Edge behavior: { WRAP (0), SMEAR (1), BLACK (2) }" }
};
static GParamDef *return_vals = NULL;
static gint nargs = sizeof (args) / sizeof (args[0]);
static gint nreturn_vals = 0;
gimp_install_procedure ("plug_in_displace",
"Displace the contents of the specified drawable",
"Displaces the contents of the specified drawable by the amounts specified by 'amount_x' and 'amount_y' multiplied by the intensity of corresponding pixels in the 'displace_map' drawables. Both 'displace_map' drawables must be of type GRAY_IMAGE for this operation to succeed.",
"Stephen Robert Norris & (ported to 1.0 by) Spencer Kimball",
"Stephen Robert Norris",
"1996",
"<Image>/Filters/Map/Displace",
"RGB*, GRAY*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
static void
run (gchar *name,
gint nparams,
GParam *param,
gint *nreturn_vals,
GParam **return_vals)
{
static GParam values[1];
GDrawable *drawable;
GRunModeType run_mode;
GStatusType status = STATUS_SUCCESS;
run_mode = param[0].data.d_int32;
/* Get the specified drawable */
drawable = gimp_drawable_get (param[2].data.d_drawable);
*nreturn_vals = 1;
*return_vals = values;
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
switch (run_mode)
{
case RUN_INTERACTIVE:
/* Possibly retrieve data */
gimp_get_data ("plug_in_displace", &dvals);
/* First acquire information with a dialog */
if (! displace_dialog (drawable))
return;
break;
case RUN_NONINTERACTIVE:
/* Make sure all the arguments are there! */
if (nparams != 10)
status = STATUS_CALLING_ERROR;
if (status == STATUS_SUCCESS)
{
dvals.amount_x = param[3].data.d_float;
dvals.amount_y = param[4].data.d_float;
dvals.do_x = param[5].data.d_int32;
dvals.do_y = param[6].data.d_int32;
dvals.displace_map_x = param[7].data.d_int32;
dvals.displace_map_y = param[8].data.d_int32;
dvals.displace_type = param[9].data.d_int32;
}
break;
case RUN_WITH_LAST_VALS:
/* Possibly retrieve data */
gimp_get_data ("plug_in_displace", &dvals);
break;
default:
break;
}
if (status == STATUS_SUCCESS && (dvals.do_x || dvals.do_y))
{
gimp_progress_init ("Displacing...");
/* set the tile cache size */
gimp_tile_cache_ntiles (TILE_CACHE_SIZE);
/* run the displace effect */
displace (drawable);
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush ();
/* Store data */
if (run_mode == RUN_INTERACTIVE)
gimp_set_data ("plug_in_displace", &dvals, sizeof (DisplaceVals));
}
values[0].data.d_status = status;
gimp_drawable_detach (drawable);
}
static int
displace_dialog (GDrawable *drawable)
{
GtkWidget *dlg;
GtkWidget *label;
GtkWidget *button;
GtkWidget *toggle;
GtkWidget *toggle_hbox;
GtkWidget *frame;
GtkWidget *table;
GtkWidget *entry;
GtkWidget *option_menu;
GtkWidget *menu;
GSList *group = NULL;
gchar **argv;
gchar buffer[32];
gint argc;
gint use_wrap = (dvals.displace_type == WRAP);
gint use_smear = (dvals.displace_type == SMEAR);
gint use_black = (dvals.displace_type == BLACK);
argc = 1;
argv = g_new (gchar *, 1);
argv[0] = g_strdup ("displace");
#if 0
printf("displace: pid = %d\n", (int)getpid());
kill(getpid(), SIGSTOP);
#endif
gtk_init (&argc, &argv);
gtk_rc_parse(gimp_gtkrc());
dlg = gtk_dialog_new ();
gtk_window_set_title (GTK_WINDOW (dlg), "Displace");
gtk_window_position (GTK_WINDOW (dlg), GTK_WIN_POS_MOUSE);
gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
(GtkSignalFunc) displace_close_callback,
NULL);
/* Action area */
button = gtk_button_new_with_label ("OK");
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
(GtkSignalFunc) displace_ok_callback,
dlg);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button, TRUE, TRUE, 0);
gtk_widget_grab_default (button);
gtk_widget_show (button);
button = gtk_button_new_with_label ("Cancel");
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
(GtkSignalFunc) gtk_widget_destroy,
GTK_OBJECT (dlg));
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button, TRUE, TRUE, 0);
gtk_widget_show (button);
/* The main table */
frame = gtk_frame_new ("Displace Options");
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width (GTK_CONTAINER (frame), 10);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, TRUE, TRUE, 0);
table = gtk_table_new (3, 3, FALSE);
gtk_container_border_width (GTK_CONTAINER (table), 5);
gtk_container_add (GTK_CONTAINER (frame), table);
gtk_table_set_row_spacing (GTK_TABLE (table), 0, 10);
gtk_table_set_row_spacing (GTK_TABLE (table), 1, 10);
gtk_table_set_col_spacing (GTK_TABLE (table), 0, 10);
gtk_table_set_col_spacing (GTK_TABLE (table), 1, 10);
/* on_x, on_y */
toggle = gtk_check_button_new_with_label ("X Displacement: ");
gtk_table_attach (GTK_TABLE (table), toggle, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
(GtkSignalFunc) displace_x_toggle_update,
&dvals.do_x);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), dvals.do_x);
gtk_widget_show (toggle);
toggle = gtk_check_button_new_with_label ("Y Displacement: ");
gtk_table_attach (GTK_TABLE (table), toggle, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
(GtkSignalFunc) displace_y_toggle_update,
&dvals.do_y);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), dvals.do_y);
gtk_widget_show (toggle);
/* amount_x, amount_y */
dint.amount_x = entry = gtk_entry_new ();
gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
gtk_widget_set_usize (entry, ENTRY_WIDTH, 0);
sprintf (buffer, "%f", dvals.amount_x);
gtk_entry_set_text (GTK_ENTRY (entry), buffer);
gtk_signal_connect (GTK_OBJECT (entry), "changed",
(GtkSignalFunc) displace_entry_callback,
&dvals.amount_x);
gtk_widget_set_sensitive (dint.amount_x, dvals.do_x);
gtk_widget_show (entry);
dint.amount_y = entry = gtk_entry_new ();
gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
gtk_widget_set_usize (entry, ENTRY_WIDTH, 0);
sprintf (buffer, "%f", dvals.amount_y);
gtk_entry_set_text (GTK_ENTRY (entry), buffer);
gtk_signal_connect (GTK_OBJECT (entry), "changed",
(GtkSignalFunc) displace_entry_callback,
&dvals.amount_y);
gtk_widget_set_sensitive (dint.amount_y, dvals.do_y);
gtk_widget_show (entry);
/* menu_x, menu_y */
dint.menu_x = option_menu = gtk_option_menu_new ();
gtk_table_attach (GTK_TABLE (table), option_menu, 2, 3, 0, 1,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
menu = gimp_drawable_menu_new (displace_map_constrain, displace_map_x_callback,
drawable, dvals.displace_map_x);
gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
gtk_widget_set_sensitive (dint.menu_x, dvals.do_x);
gtk_widget_show (option_menu);
dint.menu_y = option_menu = gtk_option_menu_new ();
gtk_table_attach (GTK_TABLE (table), option_menu, 2, 3, 1, 2,
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
menu = gimp_drawable_menu_new (displace_map_constrain, displace_map_y_callback,
drawable, dvals.displace_map_y);
gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu);
gtk_widget_set_sensitive (dint.menu_y, dvals.do_y);
gtk_widget_show (option_menu);
/* Displacement Type */
toggle_hbox = gtk_hbox_new (FALSE, 10);
gtk_container_border_width (GTK_CONTAINER (toggle_hbox), 5);
gtk_table_attach (GTK_TABLE (table), toggle_hbox, 0, 3, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
label = gtk_label_new ("On Edges: ");
gtk_box_pack_start (GTK_BOX (toggle_hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
toggle = gtk_radio_button_new_with_label (group, "Wrap");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
gtk_box_pack_start (GTK_BOX (toggle_hbox), toggle, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
(GtkSignalFunc) displace_toggle_update,
&use_wrap);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), use_wrap);
gtk_widget_show (toggle);
toggle = gtk_radio_button_new_with_label (group, "Smear");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
gtk_box_pack_start (GTK_BOX (toggle_hbox), toggle, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
(GtkSignalFunc) displace_toggle_update,
&use_smear);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), use_smear);
gtk_widget_show (toggle);
toggle = gtk_radio_button_new_with_label (group, "Black");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
gtk_box_pack_start (GTK_BOX (toggle_hbox), toggle, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
(GtkSignalFunc) displace_toggle_update,
&use_black);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), use_black);
gtk_widget_show (toggle);
gtk_widget_show (toggle_hbox);
gtk_widget_show (table);
gtk_widget_show (frame);
gtk_widget_show (dlg);
gtk_main ();
gdk_flush ();
/* determine displace type */
if (use_wrap)
dvals.displace_type = WRAP;
else if (use_smear)
dvals.displace_type = SMEAR;
else if (use_black)
dvals.displace_type = BLACK;
return dint.run;
}
/* The displacement is done here. */
static void
displace (GDrawable *drawable)
{
GDrawable *map_x;
GDrawable *map_y;
GPixelRgn dest_rgn;
GPixelRgn map_x_rgn;
GPixelRgn map_y_rgn;
GTile * tile = NULL;
gint row = -1;
gint col = -1;
gpointer pr;
gint width;
gint height;
gint bytes;
guchar *destrow, *dest;
guchar *mxrow, *mx;
guchar *myrow, *my;
guchar pixel[4][4];
gint x1, y1, x2, y2;
gint x, y;
gint progress, max_progress;
gdouble amnt;
gdouble needx, needy;
gint xi, yi;
guchar values[4];
guchar val;
gint k;
gdouble xm_val, ym_val;
gint xm_alpha = 0;
gint ym_alpha = 0;
gint xm_bytes = 1;
gint ym_bytes = 1;
/* initialize */
mxrow = NULL;
myrow = NULL;
/* Get selection area */
gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
width = drawable->width;
height = drawable->height;
bytes = drawable->bpp;
progress = 0;
max_progress = (x2 - x1) * (y2 - y1);
/*
* The algorithm used here is simple - see
* http://the-tech.mit.edu/KPT/Tips/KPT7/KPT7.html for a description.
*/
/* Get the drawables */
if (dvals.displace_map_x != -1 && dvals.do_x)
{
map_x = gimp_drawable_get (dvals.displace_map_x);
gimp_pixel_rgn_init (&map_x_rgn, map_x, x1, y1, (x2 - x1), (y2 - y1), FALSE, FALSE);
if (gimp_drawable_has_alpha(map_x->id))
xm_alpha = 1;
xm_bytes = gimp_drawable_bpp(map_x->id);
}
else
map_x = NULL;
if (dvals.displace_map_y != -1 && dvals.do_y)
{
map_y = gimp_drawable_get (dvals.displace_map_y);
gimp_pixel_rgn_init (&map_y_rgn, map_y, x1, y1, (x2 - x1), (y2 - y1), FALSE, FALSE);
if (gimp_drawable_has_alpha(map_y->id))
ym_alpha = 1;
ym_bytes = gimp_drawable_bpp(map_y->id);
}
else
map_y = NULL;
gimp_pixel_rgn_init (&dest_rgn, drawable, x1, y1, (x2 - x1), (y2 - y1), TRUE, TRUE);
/* Register the pixel regions */
if (dvals.do_x && dvals.do_y)
pr = gimp_pixel_rgns_register (3, &dest_rgn, &map_x_rgn, &map_y_rgn);
else if (dvals.do_x)
pr = gimp_pixel_rgns_register (2, &dest_rgn, &map_x_rgn);
else if (dvals.do_y)
pr = gimp_pixel_rgns_register (2, &dest_rgn, &map_y_rgn);
else
pr = NULL;
for (pr = pr; pr != NULL; pr = gimp_pixel_rgns_process (pr))
{
destrow = dest_rgn.data;
if (dvals.do_x)
mxrow = map_x_rgn.data;
if (dvals.do_y)
myrow = map_y_rgn.data;
for (y = dest_rgn.y; y < (dest_rgn.y + dest_rgn.h); y++)
{
dest = destrow;
mx = mxrow;
my = myrow;
/*
* We could move the displacement image address calculation out of here,
* but when we can have different sized displacement and destination
* images we'd have to move it back anyway.
*/
for (x = dest_rgn.x; x < (dest_rgn.x + dest_rgn.w); x++)
{
if (dvals.do_x)
{
xm_val = displace_map_give_value(mx, xm_alpha, xm_bytes);
amnt = dvals.amount_x * (xm_val - 127.5) / 127.5;
needx = x + amnt;
mx += xm_bytes;
}
else
needx = x;
if (dvals.do_y)
{
ym_val = displace_map_give_value(my, ym_alpha, ym_bytes);
amnt = dvals.amount_y * (ym_val - 127.5) / 127.5;
needy = y + amnt;
my += ym_bytes;
}
else
needy = y;
/* Calculations complete; now copy the proper pixel */
if (needx >= 0.0)
xi = (int) needx;
else
xi = -((int) -needx + 1);
if (needy >= 0.0)
yi = (int) needy;
else
yi = -((int) -needy + 1);
tile = displace_pixel (drawable, tile, width, height, x1, y1, x2, y2, xi, yi, &row, &col, pixel[0]);
tile = displace_pixel (drawable, tile, width, height, x1, y1, x2, y2, xi + 1, yi, &row, &col, pixel[1]);
tile = displace_pixel (drawable, tile, width, height, x1, y1, x2, y2, xi, yi + 1, &row, &col, pixel[2]);
tile = displace_pixel (drawable, tile, width, height, x1, y1, x2, y2, xi + 1, yi + 1, &row, &col, pixel[3]);
for (k = 0; k < bytes; k++)
{
values[0] = pixel[0][k];
values[1] = pixel[1][k];
values[2] = pixel[2][k];
values[3] = pixel[3][k];
val = bilinear(needx, needy, values);
*dest++ = val;
} /* for */
}
destrow += dest_rgn.rowstride;
if (dvals.do_x)
mxrow += map_x_rgn.rowstride;
if (dvals.do_y)
myrow += map_y_rgn.rowstride;
}
progress += dest_rgn.w * dest_rgn.h;
gimp_progress_update ((double) progress / (double) max_progress);
} /* for */
if (tile)
gimp_tile_unref (tile, FALSE);
/* detach from the map drawables */
if (dvals.do_x)
gimp_drawable_detach (map_x);
if (dvals.do_y)
gimp_drawable_detach (map_y);
/* update the region */
gimp_drawable_flush (drawable);
gimp_drawable_merge_shadow (drawable->id, TRUE);
gimp_drawable_update (drawable->id, x1, y1, (x2 - x1), (y2 - y1));
} /* displace */
static gdouble
displace_map_give_value(guchar *pt, gint alpha, gint bytes)
{
gdouble ret, val_alpha;
if (bytes >= 3)
ret = 0.30 * pt[0] + 0.59 * pt[1] + 0.11 * pt[2];
else
ret = (gdouble) *pt;
if (alpha)
{
val_alpha = pt[bytes - 1];
ret = ((ret - 127.5) * val_alpha / 255.0) + 127.5;
};
return (ret);
}
static GTile *
displace_pixel (GDrawable * drawable,
GTile * tile,
gint width,
gint height,
gint x1,
gint y1,
gint x2,
gint y2,
gint x,
gint y,
gint * row,
gint * col,
guchar * pixel)
{
static guchar empty_pixel[4] = {0, 0, 0, 0};
guchar *data;
gint b;
/* Tile the image. */
if (dvals.displace_type == WRAP)
{
if (x < 0)
x = width - (-x % width);
else
x %= width;
if (y < 0)
y = height - (-y % height);
else
y %= height;
}
/* Smear out the edges of the image by repeating pixels. */
else if (dvals.displace_type == SMEAR)
{
if (x < 0)
x = 0;
else if (x > width - 1)
x = width - 1;
if (y < 0)
y = 0;
else if (y > height - 1)
y = height - 1;
}
if (x >= x1 && y >= y1 && x < x2 && y < y2)
{
if ((x >> 6 != *col) || (y >> 6 != *row))
{
*col = x / 64;
*row = y / 64;
if (tile)
gimp_tile_unref (tile, FALSE);
tile = gimp_drawable_get_tile (drawable, FALSE, *row, *col);
gimp_tile_ref (tile);
}
data = tile->data + tile->bpp * (tile->ewidth * (y % 64) + (x % 64));
}
else
data = empty_pixel;
for (b = 0; b < drawable->bpp; b++)
pixel[b] = data[b];
return tile;
}
static guchar
bilinear (gdouble x, gdouble y, guchar *v)
{
gdouble m0, m1;
x = fmod(x, 1.0);
y = fmod(y, 1.0);
if (x < 0)
x += 1.0;
if (y < 0)
y += 1.0;
m0 = (gdouble) v[0] + x * ((gdouble) v[1] - v[0]);
m1 = (gdouble) v[2] + x * ((gdouble) v[3] - v[2]);
return (guchar) (m0 + y * (m1 - m0));
} /* bilinear */
/* Displace interface functions */
static gint
displace_map_constrain (gint32 image_id,
gint32 drawable_id,
gpointer data)
{
GDrawable *drawable;
drawable = (GDrawable *) data;
if (drawable_id == -1)
return TRUE;
if (gimp_drawable_width (drawable_id) == drawable->width &&
gimp_drawable_height (drawable_id) == drawable->height)
return TRUE;
else
return FALSE;
}
static void
displace_map_x_callback (gint32 id,
gpointer data)
{
dvals.displace_map_x = id;
}
static void
displace_map_y_callback (gint32 id,
gpointer data)
{
dvals.displace_map_y = id;
}
static void
displace_close_callback (GtkWidget *widget,
gpointer data)
{
gtk_main_quit ();
}
static void
displace_ok_callback (GtkWidget *widget,
gpointer data)
{
dint.run = TRUE;
gtk_widget_destroy (GTK_WIDGET (data));
}
static void
displace_toggle_update (GtkWidget *widget,
gpointer data)
{
int *toggle_val;
toggle_val = (int *) data;
if (GTK_TOGGLE_BUTTON (widget)->active)
*toggle_val = TRUE;
else
*toggle_val = FALSE;
}
static void
displace_x_toggle_update (GtkWidget *widget,
gpointer data)
{
int *toggle_val;
toggle_val = (int *) data;
if (GTK_TOGGLE_BUTTON (widget)->active)
*toggle_val = TRUE;
else
*toggle_val = FALSE;
if (dint.amount_x)
gtk_widget_set_sensitive (dint.amount_x, *toggle_val);
if (dint.menu_x)
gtk_widget_set_sensitive (dint.menu_x, *toggle_val);
}
static void
displace_y_toggle_update (GtkWidget *widget,
gpointer data)
{
int *toggle_val;
toggle_val = (int *) data;
if (GTK_TOGGLE_BUTTON (widget)->active)
*toggle_val = TRUE;
else
*toggle_val = FALSE;
if (dint.amount_y)
gtk_widget_set_sensitive (dint.amount_y, *toggle_val);
if (dint.menu_y)
gtk_widget_set_sensitive (dint.menu_y, *toggle_val);
}
static void
displace_entry_callback (GtkWidget *widget,
gpointer data)
{
double *text_val;
text_val = (double *) data;
*text_val = atof (gtk_entry_get_text (GTK_ENTRY (widget)));
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
edge

View file

@ -1,36 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = edge
edge_SOURCES = \
edge.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
edge_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,853 +0,0 @@
/* edge filter for the GIMP
* -Peter Mattis
*
* This filter performs edge detection on the input image.
* The code for this filter is based on "pgmedge", a program
* that is part of the netpbm package.
*/
/* pgmedge.c - edge-detect a portable graymap
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/
/*
* Ported to GIMP Plug-in API 1.0
* version 1.07
* This version requires GIMP v0.99.10 or above.
*
* This plug-in performs edge detection. The code is based on edge.c
* for GIMP 0.54 by Peter Mattis.
*
* Eiichi Takamori <taka@ma1.seikyou.ne.jp>
* http://ha1.seikyou.ne.jp/home/taka/gimp/
*
* Tips: you can enter arbitrary value into entry.
* (not bounded between 1.0 and 10.0)
*
* Changes from version 1.06 to version 1.07:
* - Added entry
* - Cleaned up code a bit
*
* Differences from Peter Mattis's original `edge' plug-in:
* - Added Wrapmode. (useful for tilable images)
* - Enhanced speed in this version.
* - It works with the alpha channel.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "gtk/gtk.h"
#include "libgimp/gimp.h"
#include "libgimp/gimpui.h"
#ifdef RCSID
static char rcsid[] = "$Id$";
#endif
/* Some useful macros */
#define TILE_CACHE_SIZE 48
#define SCALE_WIDTH 92
#define ENTRY_WIDTH 40
#define WRAP 0
#define SMEAR 1
#define BLACK 2
typedef struct {
gdouble amount;
gint wrapmode;
} EdgeVals;
typedef struct {
gint run;
} EdgeInterface;
typedef struct {
GTile *tile;
gint row, col; /* tile's row, col */
gint bpp;
gint tile_width, tile_height;
GDrawable *drawable;
gint drawable_width, drawable_height;
} TileBuf;
/*
* Function prototypes.
*/
static void query (void);
static void run (gchar *name,
gint nparams,
GParam *param,
gint *nreturn_vals,
GParam **return_vals);
static void edge (GDrawable *drawable);
static gint edge_dialog (GDrawable *drawable);
static void edge_close_callback (GtkWidget *widget,
gpointer data);
static void edge_ok_callback (GtkWidget *widget,
gpointer data);
static void edge_toggle_update (GtkWidget *widget,
gpointer data);
static void edge_scale_update (GtkAdjustment *ajustment,
gpointer data);
static void edge_entry_update (GtkWidget *entry,
gpointer data);
static long long_sqrt (long n);
static void init_tile_buf ( TileBuf *buf, GDrawable *drawable );
static void get_tile_pixel ( TileBuf *buf, gint x, gint y,
guchar *pixel, gint wrapmode );
static void end_tile_buf ( TileBuf *buf );
/***** Local vars *****/
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
static EdgeVals evals =
{
2.0, /* amount */
SMEAR /* wrapmode */
};
static EdgeInterface eint =
{
FALSE /* run */
};
/***** Functions *****/
MAIN ()
static void
query ()
{
static GParamDef args[] =
{
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "image", "Input image (unused)" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_FLOAT, "amount", "Edge detection amount" },
{ PARAM_INT32, "wrapmode", "Edge detection behavior: { WRAP (0), SMEAR (1), BLACK (2) }" }
};
static GParamDef *return_vals = NULL;
static gint nargs = sizeof (args) / sizeof (args[0]);
static gint nreturn_vals = 0;
gchar *help_string =
" Perform edge detection on the contents of the specified"
" drawable. It applies, I think, convolusion with 3x3 kernel. AMOUNT"
" is an arbitrary constant, WRAPMODE is like displace plug-in"
" (useful for tilable image).";
gimp_install_procedure ("plug_in_edge",
"Perform edge detection on the contents of the specified drawable",
help_string,
"Peter Mattis & (ported to 1.0 by) Eiichi Takamori",
"Peter Mattis",
"1996",
"<Image>/Filters/Edge-Detect/Edge",
"RGB*, GRAY*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
static void
run (gchar *name,
gint nparams,
GParam *param,
gint *nreturn_vals,
GParam **return_vals)
{
static GParam values[1];
GDrawable *drawable;
GRunModeType run_mode;
GStatusType status = STATUS_SUCCESS;
run_mode = param[0].data.d_int32;
/* Get the specified drawable */
drawable = gimp_drawable_get (param[2].data.d_drawable);
*nreturn_vals = 1;
*return_vals = values;
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
switch (run_mode)
{
case RUN_INTERACTIVE:
/* Possibly retrieve data */
gimp_get_data ("plug_in_edge", &evals);
/* First acquire information with a dialog */
if (! edge_dialog (drawable))
return;
break;
case RUN_NONINTERACTIVE:
/* Make sure all the arguments are there! */
if (nparams != 5)
status = STATUS_CALLING_ERROR;
if (status == STATUS_SUCCESS)
{
evals.amount = param[3].data.d_float;
evals.wrapmode = param[4].data.d_int32;
}
break;
case RUN_WITH_LAST_VALS:
/* Possibly retrieve data */
gimp_get_data ("plug_in_edge", &evals);
break;
default:
break;
}
/* make sure the drawable exist and is not indexed */
if (gimp_drawable_color (drawable->id) || gimp_drawable_gray (drawable->id))
{
gimp_progress_init ("Edge detection...");
/* set the tile cache size */
gimp_tile_cache_ntiles (TILE_CACHE_SIZE);
/* run the edge effect */
edge (drawable);
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush ();
/* Store data */
if (run_mode == RUN_INTERACTIVE)
gimp_set_data ("plug_in_edge", &evals, sizeof (EdgeVals));
}
else
{
/* gimp_message ("edge: cannot operate on indexed color images"); */
status = STATUS_EXECUTION_ERROR;
}
values[0].data.d_status = status;
gimp_drawable_detach (drawable);
}
/*********************************************************************
TileBuf Util Routines: Util routines for getting arbitrary pixel
CAUTION -- the tile is read only !!
**********************************************************************/
static void
init_tile_buf( TileBuf *buf, GDrawable *drawable )
{
buf->tile = NULL;
buf->col = 0;
buf->row = 0;
if ( gimp_drawable_color( drawable->id ) )
buf->bpp = 3;
else
buf->bpp = 1;
buf->tile_width = gimp_tile_width();
buf->tile_height = gimp_tile_height();
buf->drawable = drawable;
buf->drawable_width = gimp_drawable_width( drawable->id );
buf->drawable_height = gimp_drawable_height( drawable->id );
}
static void
get_tile_pixel( TileBuf *buf, gint x, gint y, guchar *pixel, gint wrapmode )
{
gint b;
gint offx, offy;
gint row, col;
guchar *ptr;
if ( x < 0 || x >= buf->drawable_width ||
y < 0 || y >= buf->drawable_height )
switch( wrapmode )
{
case WRAP:
if ( x < 0 || x >= buf->drawable_width )
{
x %= buf->drawable_width;
if ( x < 0 )
x += buf->drawable_width;
}
if ( y < 0 || y >= buf->drawable_height )
{
y %= buf->drawable_height;
if ( y < 0 )
y += buf->drawable_height;
}
break;
case SMEAR:
if ( x < 0 )
x = 0;
if ( x >= buf->drawable_width )
x = buf->drawable_width - 1;
if ( y < 0 )
y = 0;
if ( y >= buf->drawable_height )
y = buf->drawable_height - 1;
break;
case BLACK:
if ( x < 0 || x >= buf->drawable_width ||
y < 0 || y >= buf->drawable_height )
{
for ( b = 0; b < buf->bpp; b++ )
pixel[b]=0;
return;
}
break;
default:
return;
}
col = x / buf->tile_width;
offx = x % buf->tile_width;
row = y / buf->tile_height;
offy = y % buf->tile_height;
/* retrieve tile */
if ( !buf->tile || col != buf->col || row != buf->row )
{
if( buf->tile )
gimp_tile_unref( buf->tile, FALSE );
buf->col = col;
buf->row = row;
buf->tile = gimp_drawable_get_tile( buf->drawable, FALSE, row, col );
gimp_tile_ref( buf->tile );
}
/* retrieve target pixel */
ptr = buf->tile->data + ( offy * buf->tile->ewidth + offx ) * buf->tile->bpp;
for( b = 0; b < buf->bpp; b++ )
pixel[b] = ptr[b];
}
static void
end_tile_buf( TileBuf *buf )
{
if( buf->tile )
gimp_tile_unref( buf->tile, FALSE );
}
/**********************************************************************
TileBuf Util Routines End
**********************************************************************/
static long
long_sqrt (n)
long n;
{
#define lsqrt_max4pow (1UL << 30)
/* lsqrt_max4pow is the (machine-specific) largest power of 4 that can
* be represented in an unsigned long.
*
* Compute the integer square root of the integer argument n
* Method is to divide n by x computing the quotient x and remainder r
* Notice that the divisor x is changing as the quotient x changes
*
* Instead of shifting the dividend/remainder left, we shift the
* quotient/divisor right. The binary point starts at the extreme
* left, and shifts two bits at a time to the extreme right.
*
* The residue contains n-x^2. (Within these comments, the ^ operator
* signifies exponentiation rather than exclusive or. Also, the /
* operator returns fractions, rather than truncating, so 1/4 means
* one fourth, not zero.)
*
* Since (x + 1/2)^2 == x^2 + x + 1/4,
* n - (x + 1/2)^2 == (n - x^2) - (x + 1/4)
* Thus, we can increase x by 1/2 if we decrease (n-x^2) by (x+1/4)
*/
unsigned long residue; /* n - x^2 */
unsigned long root; /* x + 1/4 */
unsigned long half; /* 1/2 */
residue = n; /* n - (x = 0)^2, with suitable alignment */
/*
* if the correct answer fits in two bits, pull it out of a magic hat
*/
if (residue <= 12)
return (0x03FFEA94 >> (residue *= 2)) & 3;
root = lsqrt_max4pow; /* x + 1/4, shifted all the way left */
/* half = root + root; 1/2, shifted likewise */
/*
* Unwind iterations corresponding to leading zero bits
*/
while (root > residue)
root >>= 2;
/*
* Unwind the iteration corresponding to the first one bit
* Operations have been rearranged and combined for efficiency
* Initialization of half is folded into this iteration
*/
residue -= root; /* Decrease (n-x^2) by (0+1/4) */
half = root >> 2; /* 1/4, with binary point shifted right 2 */
root += half; /* x=1. (root is now (x=1)+1/4.) */
half += half; /* 1/2, properly aligned */
/*
* Normal loop (there is at least one iteration remaining)
*/
do
{
if (root <= residue) /* Whenever we can, */
{
residue -= root; /* decrease (n-x^2) by (x+1/4) */
root += half; /* increase x by 1/2 */
}
half >>= 2; /* Shift binary point 2 places right */
root -= half; /* x{ +1/2 } +1/4 - 1/8 == x { +1/2 } 1/8 */
root >>= 1; /* 2x{ +1 } +1/4, shifted right 2 places */
}
while (half); /* When 1/2 == 0, bin. point is at far right */
/*
* round up if (x+1/2)^2 < n
*/
if (root < residue)
++root;
/*
* Guaranteed to be correctly rounded (or truncated)
*/
return root;
}
/********************************************************/
/* */
/* Edge Detection main */
/* */
/********************************************************/
static void
edge( GDrawable *drawable )
{
/*
* this function is too long, so I must split this into a few
* functions later ... -- taka
*/
GPixelRgn src_rgn, dest_rgn;
gpointer pr;
TileBuf buf;
guchar *srcrow, *src;
guchar *destrow, *dest;
guchar pix00[3], pix01[3], pix02[3];
guchar pix10[3],/*pix11[3],*/ pix12[3];
guchar pix20[3], pix21[3], pix22[3];
glong width, height;
gint alpha, has_alpha, chan;
gint x, y;
gint x1, y1, x2, y2;
glong sum1, sum2;
glong sum, scale;
gint maxval;
gint cur_progress;
gint max_progress;
gint wrapmode;
if (evals.amount < 1.0 ) evals.amount = 1.0;
init_tile_buf( &buf, drawable );
gimp_drawable_mask_bounds ( drawable->id, &x1, &y1, &x2, &y2);
width = gimp_drawable_width ( drawable->id );
height = gimp_drawable_height ( drawable->id );
alpha = gimp_drawable_bpp ( drawable->id );
has_alpha = gimp_drawable_has_alpha ( drawable->id );
if( has_alpha ) alpha--;
maxval = 255;
scale = (10 << 16) / evals.amount;
wrapmode = evals.wrapmode;
cur_progress = 0;
max_progress = (x2 - x1) * (y2 - y1);
gimp_pixel_rgn_init( &src_rgn, drawable, x1, y1, x2-x1, y2-y1, FALSE, FALSE );
gimp_pixel_rgn_init( &dest_rgn, drawable, x1, y1, x2-x1, y2-y1, TRUE, TRUE );
for( pr = gimp_pixel_rgns_register( 2, &src_rgn, &dest_rgn );
pr != NULL;
pr = gimp_pixel_rgns_process(pr) )
{
srcrow = src_rgn.data;
destrow = dest_rgn.data;
for ( y = dest_rgn.y;
y < (dest_rgn.y + dest_rgn.h);
y++, srcrow += src_rgn.rowstride, destrow += dest_rgn.rowstride )
{
src = srcrow;
dest = destrow;
for( x = dest_rgn.x;
x < (dest_rgn.x + dest_rgn.w);
x++, src += src_rgn.bpp, dest += dest_rgn.bpp )
{
if( dest_rgn.x < x && x < dest_rgn.x + dest_rgn.w - 1 &&
dest_rgn.y < y && y < dest_rgn.y + dest_rgn.h - 1 )
{
/*
** 3x3 kernel is inside of the tile -- do fast
** version
*/
for( chan = 0; chan < alpha; chan++ )
{
/*
* PIX(1,1) is the current pixel, so
* e.g. PIX(0,0) means 1 above and 1 left pixel.
*
* There were casting to `long' in GIMP 0.54
* edge code, but I think `guchar' should be
* extended to `int' with minus operators, so
* there's no need to cast to `long'. Both sum1
* and sum2 will be between -4*255 to 4*255
*
* -- taka
*/
#define PIX(X,Y) src[ (Y-1)*(int)src_rgn.rowstride + (X-1)*(int)src_rgn.bpp + chan ]
/* make convolusion */
sum1 = ( PIX(2,0) - PIX(0,0) ) +
2 * ( PIX(2,1) - PIX(0,1) ) +
( PIX(2,2) - PIX(2,0) );
sum2 = ( PIX(0,2) - PIX(0,0) ) +
2 * ( PIX(1,2) - PIX(1,0) ) +
( PIX(2,2) - PIX(2,0) );
#undef PIX
/* common job ... */
sum = long_sqrt ( (long) sum1 * sum1 + (long) sum2 * sum2);
sum = (sum * scale) >> 16; /* arbitrary scaling factor */
if (sum > maxval) sum = maxval;
dest[chan] = sum;
}
} else {
/*
** The kernel is not inside of the tile -- do slow
** version
*/
/*
* When the kernel intersects the boundary of the
* image, get_tile_pixel() will (should) do the
* right work with `wrapmode'.
*/
get_tile_pixel( &buf, x-1, y-1, pix00, wrapmode );
get_tile_pixel( &buf, x , y-1, pix10, wrapmode );
get_tile_pixel( &buf, x+1, y-1, pix20, wrapmode );
get_tile_pixel( &buf, x-1, y , pix01, wrapmode );
get_tile_pixel( &buf, x+1, y , pix21, wrapmode );
get_tile_pixel( &buf, x-1, y+1, pix02, wrapmode );
get_tile_pixel( &buf, x , y+1, pix12, wrapmode );
get_tile_pixel( &buf, x+1, y+1, pix22, wrapmode );
for( chan = 0; chan < alpha; chan++ )
{
/* make convolusion */
sum1 = (pix20[chan] - pix00[chan] ) +
2 * (pix21[chan] - pix01[chan] ) +
(pix22[chan] - pix20[chan] );
sum2 = (pix02[chan] - pix00[chan] ) +
2 * (pix12[chan] - pix10[chan] ) +
(pix22[chan] - pix20[chan] );
/* common job ... */
sum = long_sqrt ( (long) sum1 * sum1 + (long) sum2 * sum2);
sum = (sum * scale) >> 16; /* arbitrary scaling factor */
if (sum > maxval) sum = maxval;
dest[chan] = sum;
}
}
if(has_alpha)
dest[alpha]=src[alpha];
}
}
cur_progress += dest_rgn.w * dest_rgn.h;
gimp_progress_update ( (double) cur_progress / (double) max_progress);
}
end_tile_buf( &buf );
gimp_drawable_flush (drawable);
gimp_drawable_merge_shadow (drawable->id, TRUE);
gimp_drawable_update (drawable->id, x1, y1, (x2 - x1), (y2 - y1));
}
/*******************************************************/
/* */
/* Dialog */
/* */
/*******************************************************/
static gint
edge_dialog(GDrawable *drawable)
{
GtkWidget *dlg;
GtkWidget *frame;
GtkWidget *table;
GtkWidget *hbox;
GtkWidget *button;
GtkWidget *toggle;
GtkWidget *label;
GtkWidget *scale;
GtkObject *scale_data;
GtkWidget *entry;
gchar buffer[256];
GSList *group = NULL;
gchar **argv;
gint argc;
gint use_wrap = (evals.wrapmode == WRAP);
gint use_smear = (evals.wrapmode == SMEAR);
gint use_black = (evals.wrapmode == BLACK);
gdouble init_val;
argc = 1;
argv = g_new (gchar *, 1);
argv[0] = g_strdup ("edge");
gtk_init (&argc, &argv);
gtk_rc_parse (gimp_gtkrc ());
dlg = gtk_dialog_new ();
gtk_window_set_title (GTK_WINDOW (dlg), "Edge Detection");
gtk_window_position (GTK_WINDOW (dlg), GTK_WIN_POS_MOUSE);
gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
(GtkSignalFunc) edge_close_callback,
NULL);
/* Action area */
button = gtk_button_new_with_label ("OK");
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
(GtkSignalFunc) edge_ok_callback,
dlg);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button, TRUE, TRUE, 0);
gtk_widget_grab_default (button);
gtk_widget_show (button);
button = gtk_button_new_with_label ("Cancel");
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
(GtkSignalFunc) gtk_widget_destroy,
GTK_OBJECT (dlg));
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->action_area), button, TRUE, TRUE, 0);
gtk_widget_show (button);
/* parameter settings */
frame = gtk_frame_new ("Edge Detection Options");
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width (GTK_CONTAINER (frame), 10);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, TRUE, TRUE, 0);
table = gtk_table_new (2, 3, FALSE);
gtk_container_border_width (GTK_CONTAINER (table), 5);
gtk_container_add (GTK_CONTAINER (frame), table);
/*
Label, scale, entry for evals.amount
*/
label = gtk_label_new ("Amount:");
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
gtk_widget_show (label);
/* This prevents annoying change of adjustment */
init_val = evals.amount < 1.0 ? 1.0 :
evals.amount > 10.0 ? 10.0 : evals.amount;
scale_data = gtk_adjustment_new (init_val, 1.0, 10.0, 0.1, 0.1, 0.0);
scale = gtk_hscale_new (GTK_ADJUSTMENT (scale_data));
gtk_widget_set_usize (scale, SCALE_WIDTH, 0);
gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE);
#if 0
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
gtk_scale_set_digits (GTK_SCALE (scale), 1);
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
#endif
entry = gtk_entry_new ();
gtk_widget_set_usize (entry, ENTRY_WIDTH, 0);
gtk_widget_show (scale);
gtk_widget_show (entry);
gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
GTK_FILL, 0, 5, 0);
gtk_table_attach (GTK_TABLE (table), scale, 2, 3, 0, 1,
GTK_EXPAND | GTK_FILL, 0, 5, 0);
gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
GTK_FILL, 0, 0, 0);
gtk_signal_connect (GTK_OBJECT (scale_data), "value_changed",
(GtkSignalFunc) edge_scale_update,
&evals.amount);
sprintf (buffer, "%0.1f", evals.amount);
gtk_entry_set_text (GTK_ENTRY (entry), buffer);
gtk_signal_connect (GTK_OBJECT (entry), "changed",
(GtkSignalFunc) edge_entry_update,
&evals.amount);
gtk_object_set_user_data (GTK_OBJECT (entry), scale_data);
gtk_object_set_user_data (scale_data, entry);
/*
Radio buttons WRAP, SMEAR, BLACK ...
*/
hbox = gtk_hbox_new (FALSE, 5);
gtk_container_border_width (GTK_CONTAINER (hbox), 5);
gtk_table_attach (GTK_TABLE (table), hbox, 0, 3, 1, 2,
GTK_FILL, GTK_FILL, 0, 0);
toggle = gtk_radio_button_new_with_label (group, "Wrap");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
(GtkSignalFunc) edge_toggle_update,
&use_wrap);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), use_wrap);
gtk_widget_show (toggle);
toggle = gtk_radio_button_new_with_label (group, "Smear");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
(GtkSignalFunc) edge_toggle_update,
&use_smear);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), use_smear);
gtk_widget_show (toggle);
toggle = gtk_radio_button_new_with_label (group, "Black");
group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
gtk_box_pack_start (GTK_BOX (hbox), toggle, TRUE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
(GtkSignalFunc) edge_toggle_update,
&use_black);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), use_black);
gtk_widget_show (toggle);
gtk_widget_show (hbox);
gtk_widget_show (table);
gtk_widget_show (frame);
gtk_widget_show (dlg);
gtk_main ();
gdk_flush ();
if (use_wrap)
evals.wrapmode = WRAP;
else if (use_smear)
evals.wrapmode = SMEAR;
else if (use_black)
evals.wrapmode = BLACK;
return eint.run;
}
/* Edge detection interface functions */
static void
edge_close_callback (GtkWidget *widget,
gpointer data)
{
gtk_main_quit ();
}
static void
edge_ok_callback (GtkWidget *widget,
gpointer data)
{
eint.run = TRUE;
gtk_widget_destroy (GTK_WIDGET (data));
}
static void
edge_toggle_update (GtkWidget *widget,
gpointer data)
{
int *toggle_val;
toggle_val = (int *) data;
if (GTK_TOGGLE_BUTTON (widget)->active)
*toggle_val = TRUE;
else
*toggle_val = FALSE;
}
static void
edge_scale_update (GtkAdjustment *adjustment,
gpointer data)
{
GtkWidget *entry;
gdouble *ptr = (gdouble *) data;
*ptr = adjustment->value;
entry = gtk_object_get_user_data (GTK_OBJECT (adjustment));
if (entry)
{
gchar buffer[256];
sprintf (buffer, "%0.1f", *ptr);
gtk_signal_handler_block_by_data (GTK_OBJECT (entry), data);
gtk_entry_set_text (GTK_ENTRY (entry), buffer);
gtk_signal_handler_unblock_by_data (GTK_OBJECT (entry), data);
}
}
static void
edge_entry_update (GtkWidget *entry,
gpointer data)
{
GtkAdjustment *adjustment;
gdouble *ptr = (gdouble *) data;
gdouble new_val;
*ptr = atof (gtk_entry_get_text (GTK_ENTRY (entry)));
adjustment = gtk_object_get_user_data (GTK_OBJECT (entry));
if (adjustment)
{
new_val = *ptr < adjustment->lower ? adjustment->lower :
*ptr > adjustment->upper ? adjustment->upper : *ptr;
adjustment->value = new_val;
gtk_signal_handler_block_by_data (GTK_OBJECT (adjustment), data);
gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "value_changed");
gtk_signal_handler_unblock_by_data (GTK_OBJECT (adjustment), data);
}
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
emboss

View file

@ -1,38 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = emboss
emboss_SOURCES = \
emboss.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/plug-ins/megawidget/libmegawidget.a \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/plug-ins/megawidget/libmegawidget.a \
$(top_builddir)/libgimp/libgimp.la
emboss_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,516 +0,0 @@
/**************************************************
* file: emboss/emboss.c
*
* Copyright (c) 1997 Eric L. Hernes (erich@rrnet.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software withough specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id$
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <sys/types.h>
#include <libgimp/gimp.h>
#include <gtk/gtk.h>
#include <plug-ins/megawidget/megawidget.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif /* M_PI */
static mw_preview_t emboss_do_preview;
struct Grgb {
guint8 red;
guint8 green;
guint8 blue;
};
struct GRegion {
gint32 x;
gint32 y;
gint32 width;
gint32 height;
};
struct piArgs {
gint32 img;
gint32 drw;
gdouble azimuth;
gdouble elevation;
gint32 depth;
gint32 embossp;
};
struct embossFilter {
gdouble Lx;
gdouble Ly;
gdouble Lz;
gdouble Nz;
gdouble Nz2;
gdouble NzLz;
gdouble bg;
} Filter;
static void query(void);
static void run(gchar *name, gint nparam, GParam *param,
gint *nretvals, GParam **retvals);
int pluginCore(struct piArgs *argp);
int pluginCoreIA(struct piArgs *argp);
static inline void EmbossInit(gdouble azimuth, gdouble elevation,
gushort width45);
static inline void EmbossRow(guchar *src, guchar *texture, guchar *dst,
guint xSize, guint bypp, gint alpha);
#define DtoR(d) ((d)*(M_PI/(gdouble)180))
GPlugInInfo PLUG_IN_INFO = {
NULL, /* init */
NULL, /* quit */
query, /* query */
run, /* run */
};
static struct mwPreview *thePreview;
MAIN()
static void
query(void){
static GParamDef args[] = {
{ PARAM_INT32, "run_mode", "Interactive, non-interactive" },
{ PARAM_IMAGE, "img", "The Image" },
{ PARAM_DRAWABLE, "drw", "The Drawable" },
{ PARAM_FLOAT, "azimuth", "The Light Angle (degrees)" },
{ PARAM_FLOAT, "elevation", "The Elevation Angle (degrees)" },
{ PARAM_INT32, "depth", "The Filter Width" },
{ PARAM_INT32, "embossp", "Emboss or Bumpmap" },
};
static gint nargs = sizeof (args) / sizeof (args[0]);
static GParamDef *rets = NULL;
static gint nrets = 0;
gimp_install_procedure("plug_in_emboss",
"Emboss filter",
"Emboss or Bumpmap the given drawable, specifying the angle and elevation for the light source.",
"Eric L. Hernes, John Schlag",
"Eric L. Hernes",
"1997",
"<Image>/Filters/Distorts/Emboss",
"RGB",
PROC_PLUG_IN,
nargs, nrets,
args, rets);
}
static void
run(gchar *name, gint nparam, GParam *param,
gint *nretvals, GParam **retvals)
{
static GParam rvals[1];
struct piArgs args;
GDrawable *drw;
*nretvals = 1;
*retvals = rvals;
memset(&args,(int)0,sizeof(struct piArgs));
rvals[0].type = PARAM_STATUS;
rvals[0].data.d_status = STATUS_SUCCESS;
switch (param[0].data.d_int32)
{
case RUN_INTERACTIVE:
gimp_get_data("plug_in_emboss", &args);
if (args.img == 0 && args.drw == 0)
{
/* initial conditions */
args.azimuth = 30.0;
args.elevation = 45.0;
args.depth = 20;
args.embossp = 1;
}
args.img = param[1].data.d_image;
args.drw = param[2].data.d_drawable;
drw = gimp_drawable_get(args.drw);
thePreview = mw_preview_build(drw);
if (pluginCoreIA(&args)==-1)
{
rvals[0].data.d_status = STATUS_EXECUTION_ERROR;
}
else
{
gimp_set_data("plug_in_emboss", &args, sizeof(struct piArgs));
}
break;
case RUN_NONINTERACTIVE:
if (nparam != 7)
{
rvals[0].data.d_status = STATUS_CALLING_ERROR;
break;
}
args.img = param[1].data.d_image;
args.drw = param[2].data.d_drawable;
args.azimuth = param[3].data.d_float;
args.elevation = param[4].data.d_float;
args.depth = param[5].data.d_int32;
args.embossp = param[6].data.d_int32;
if (pluginCore(&args)==-1)
{
rvals[0].data.d_status = STATUS_EXECUTION_ERROR;
break;
}
break;
case RUN_WITH_LAST_VALS:
gimp_get_data("plug_in_emboss", &args);
/* use this image and drawable, even with last args */
args.img = param[1].data.d_image;
args.drw = param[2].data.d_drawable;
if (pluginCore(&args)==-1) {
rvals[0].data.d_status = STATUS_EXECUTION_ERROR;
}
break;
}
}
#define pixelScale 255.9
static void
EmbossInit(gdouble azimuth, gdouble elevation, gushort width45) {
/*
* compute the light vector from the input parameters.
* normalize the length to pixelScale for fast shading calculation.
*/
Filter.Lx = cos(azimuth) * cos(elevation) * pixelScale;
Filter.Ly = sin(azimuth) * cos(elevation) * pixelScale;
Filter.Lz = sin(elevation) * pixelScale;
/*
* constant z component of image surface normal - this depends on the
* image slope we wish to associate with an angle of 45 degrees, which
* depends on the width of the filter used to produce the source image.
*/
Filter.Nz = (6 * 255) / width45;
Filter.Nz2 = Filter.Nz * Filter.Nz;
Filter.NzLz = Filter.Nz * Filter.Lz;
/* optimization for vertical normals: L.[0 0 1] */
Filter.bg = Filter.Lz;
}
/*
* ANSI C code from the article
* "Fast Embossing Effects on Raster Image Data"
* by John Schlag, jfs@kerner.com
* in "Graphics Gems IV", Academic Press, 1994
*
*
* Emboss - shade 24-bit pixels using a single distant light source.
* Normals are obtained by differentiating a monochrome 'bump' image.
* The unary case ('texture' == NULL) uses the shading result as output.
* The binary case multiples the optional 'texture' image by the shade.
* Images are in row major order with interleaved color components (rgbrgb...).
* E.g., component c of pixel x,y of 'dst' is dst[3*(y*xSize + x) + c].
*
*/
static inline void
EmbossRow(guchar *src, guchar *texture, guchar *dst,
guint xSize, guint bypp, gint alpha) {
glong Nx, Ny, NdotL;
guchar *s1, *s2, *s3;
gint x, shade, b;
gint bytes;
/* mung pixels, avoiding edge pixels */
s1 = src + bypp;
s2 = s1 + (xSize*bypp);
s3 = s2 + (xSize*bypp);
dst += bypp;
bytes = (alpha) ? bypp - 1 : bypp;
if (texture) texture += bypp;
for (x = 1; x < xSize-1; x++, s1+=bypp, s2+=bypp, s3+=bypp) {
/*
* compute the normal from the src map. the type of the
* expression before the cast is compiler dependent. in
* some cases the sum is unsigned, in others it is
* signed. ergo, cast to signed.
*/
Nx = (int)(s1[-(int)bypp] + s2[-(int)bypp] + s3[-(int)bypp]
- s1[bypp] - s2[bypp] - s3[bypp]);
Ny = (int)(s3[-(int)bypp] + s3[0] + s3[bypp] - s1[-(int)bypp]
- s1[0] - s1[bypp]);
/* shade with distant light source */
if ( Nx == 0 && Ny == 0 )
shade = Filter.bg;
else if ( (NdotL = Nx*Filter.Lx + Ny*Filter.Ly + Filter.NzLz) < 0 )
shade = 0;
else
shade = NdotL / sqrt(Nx*Nx + Ny*Ny + Filter.Nz2);
/* do something with the shading result */
if ( texture ) {
for(b=0;b<bytes;b++) {
*dst++ = (*texture++ * shade) >> 8;
}
if (alpha) {
*dst++=s2[bytes]; /* preserve the alpha */
texture++;
}
}
else {
for(b=0;b<bytes;b++) {
*dst++ = shade;
}
if (alpha) *dst++=s2[bytes]; /* preserve the alpha */
}
}
if (texture) texture += bypp;
}
int pluginCore(struct piArgs *argp) {
GDrawable *drw;
GPixelRgn src, dst;
gint p_update;
gint y;
gint x1, y1, x2, y2;
guint width, height;
gint bypp, rowsize, has_alpha;
guchar *srcbuf, *dstbuf;
drw=gimp_drawable_get(argp->drw);
gimp_drawable_mask_bounds(argp->drw, &x1, &y1, &x2, &y2);
/* expand the bounds a little */
x1 = MAX(0, x1 - 5);
y1 = MAX(0, y1 - 5);
x2 = MIN(drw->width, x2+5);
y2 = MIN(drw->height, y2+5);
width = x2 - x1;
height = y2 - y1;
bypp=drw->bpp;
p_update = height/20;
rowsize = width * bypp;
has_alpha = gimp_drawable_has_alpha (argp->drw);
gimp_pixel_rgn_init (&src, drw, x1, y1, width, height, FALSE, FALSE);
gimp_pixel_rgn_init (&dst, drw, x1, y1, width, height, TRUE, TRUE);
srcbuf=(guchar*)g_malloc(rowsize*3);
dstbuf=(guchar*)g_malloc(rowsize);
memset(srcbuf,(int)0,(size_t)(rowsize*3));
memset(dstbuf,(int)0,(size_t)rowsize);
EmbossInit(DtoR(argp->azimuth), DtoR(argp->elevation), argp->depth);
gimp_progress_init("Emboss");
gimp_tile_cache_ntiles((width + gimp_tile_width() - 1) / gimp_tile_width());
/* first row */
gimp_pixel_rgn_get_rect(&src, srcbuf, x1, y1, width, 3);
memcpy(srcbuf, srcbuf+rowsize, rowsize);
EmbossRow(srcbuf, argp->embossp ? (guchar *)0 : srcbuf,
dstbuf, width, bypp, has_alpha);
gimp_pixel_rgn_set_row(&dst, dstbuf, 0, 0, width);
/* last row */
gimp_pixel_rgn_get_rect(&src, srcbuf, x1, y2-3, width, 3);
memcpy(srcbuf+rowsize*2, srcbuf+rowsize, rowsize);
EmbossRow(srcbuf, argp->embossp ? (guchar *)0 : srcbuf,
dstbuf, width, bypp, has_alpha);
gimp_pixel_rgn_set_row(&dst, dstbuf, x1, y2-1, width);
for(y=0 ;y<height-2; y++){
if (y%p_update==0) gimp_progress_update((gdouble)y/(gdouble)height);
gimp_pixel_rgn_get_rect(&src, srcbuf, x1, y1+y, width, 3);
EmbossRow(srcbuf, argp->embossp ? (guchar *)0 : srcbuf,
dstbuf, width, bypp, has_alpha);
gimp_pixel_rgn_set_row(&dst, dstbuf, x1, y1+y+1, width);
}
g_free(srcbuf);
g_free(dstbuf);
gimp_drawable_flush(drw);
gimp_drawable_merge_shadow (drw->id, TRUE);
gimp_drawable_update(drw->id, x1, y1, width, height);
gimp_displays_flush();
return 0;
}
int pluginCoreIA(struct piArgs *argp) {
GtkWidget *dlg;
GtkWidget *hbox;
GtkWidget *table;
GtkWidget *preview;
GtkWidget *frame;
gint runp;
struct mwRadioGroup functions[] = {
{ "Emboss", 0 },
{ "Bumpmap", 0 },
{ NULL, 0 },
};
gchar **argv;
gint argc;
/* Set args */
argc = 1;
argv = g_new(gchar *, 1);
argv[0] = g_strdup("emboss");
gtk_init(&argc, &argv);
gtk_rc_parse(gimp_gtkrc ());
functions[!argp->embossp].var = 1;
dlg = mw_app_new("plug_in_emboss", "Emboss", &runp);
hbox = gtk_hbox_new(FALSE, 5);
gtk_container_border_width(GTK_CONTAINER(hbox), 5);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), hbox, TRUE, TRUE, 0);
gtk_widget_show(hbox);
preview = mw_preview_new(hbox, thePreview, &emboss_do_preview);
gtk_object_set_data(GTK_OBJECT(preview), "piArgs", argp);
gtk_object_set_data(GTK_OBJECT(preview), "mwRadioGroup", &functions);
emboss_do_preview(preview);
mw_radio_group_new(hbox, "Function", functions);
frame = gtk_frame_new("Parameters");
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width(GTK_CONTAINER(frame), 5);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), frame, TRUE, TRUE, 0);
gtk_widget_show(frame);
table = gtk_table_new(4, 2, FALSE);
gtk_container_border_width(GTK_CONTAINER (table), 5);
gtk_container_add(GTK_CONTAINER(frame), table);
mw_fscale_entry_new(table, "Azimuth", 0.0, 360.0, 1.0, 10.0, 0.0,
0, 1, 1, 2, &argp->azimuth);
mw_fscale_entry_new(table, "Elevation", 0.0, 180.0, 1.0, 10.0, 0.0,
0, 1, 2, 3, &argp->elevation);
mw_iscale_entry_new(table, "Depth", 1, 100, 1, 5, 0,
0, 1, 3, 4, &argp->depth);
gtk_widget_show(table);
gtk_widget_show(table);
gtk_widget_show(dlg);
gtk_main();
gdk_flush();
argp->embossp = !mw_radio_result(functions);
if(runp){
return pluginCore(argp);
} else {
return -1;
}
}
static void
emboss_do_preview(GtkWidget *w) {
static GtkWidget *theWidget = NULL;
struct piArgs *ap;
struct mwRadioGroup *rgp;
guchar *dst, *c;
gint y, rowsize;
if(theWidget==NULL){
theWidget=w;
}
ap = gtk_object_get_data(GTK_OBJECT(theWidget), "piArgs");
rgp = gtk_object_get_data(GTK_OBJECT(theWidget), "mwRadioGroup");
ap->embossp = !mw_radio_result(rgp);
rowsize=thePreview->width*thePreview->bpp;
dst = g_malloc(rowsize);
c = g_malloc(rowsize*3);
memcpy(c, thePreview->bits, rowsize);
memcpy(c+rowsize, thePreview->bits, rowsize*2);
EmbossInit(DtoR(ap->azimuth), DtoR(ap->elevation), ap->depth);
EmbossRow(c, ap->embossp ? (guchar *)0 : c,
dst, thePreview->width, thePreview->bpp, FALSE);
gtk_preview_draw_row(GTK_PREVIEW(theWidget),
dst, 0, 0, thePreview->width);
memcpy(c, thePreview->bits+((thePreview->height-2)*rowsize), rowsize*2);
memcpy(c+(rowsize*2), thePreview->bits+((thePreview->height-1)*rowsize),
rowsize);
EmbossRow(c, ap->embossp ? (guchar *)0 : c,
dst, thePreview->width, thePreview->bpp, FALSE);
gtk_preview_draw_row(GTK_PREVIEW(theWidget),
dst, 0, thePreview->height-1, thePreview->width);
g_free(c);
for(y=0, c=thePreview->bits;y<thePreview->height-2; y++, c+=rowsize){
EmbossRow(c, ap->embossp ? (guchar *)0 : c,
dst, thePreview->width, thePreview->bpp, FALSE);
gtk_preview_draw_row(GTK_PREVIEW(theWidget),
dst, 0, y, thePreview->width);
}
gtk_widget_draw(theWidget, NULL);
gdk_flush();
g_free(dst);
}
/*
* Local Variables:
* mode: C
* c-indent-level: 2
*
* End:
*/
/* end of file: emboss/emboss.c */

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
engrave

View file

@ -1,36 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = engrave
engrave_SOURCES = \
engrave.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
engrave_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,643 +0,0 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
* Copyright (C) 1997 Eiichi Takamori
* Copyright (C) 1996, 1997 Torsten Martinsen
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* This plug-in creates a black-and-white 'engraved' version of an image.
* Much of the code is stolen from the Pixelize plug-in.
*/
#include <stdio.h>
#include <stdlib.h>
#include "gtk/gtk.h"
#include "libgimp/gimp.h"
/* Some useful macros */
#define ENTRY_WIDTH 60
#define SCALE_WIDTH 125
#define TILE_CACHE_SIZE 16
#define INTENSITY(r,g,b) (r * 0.30 + g * 0.59 + b * 0.11)
typedef struct {
gint height;
gint limit;
} EngraveValues;
typedef struct {
gint run;
} EngraveInterface;
static void query(void);
static void run(gchar * name,
gint nparams,
GParam * param,
gint * nreturn_vals,
GParam ** return_vals);
static gint engrave_dialog(void);
static void engrave_close_callback(GtkWidget * widget,
gpointer data);
static void engrave_ok_callback(GtkWidget * widget,
gpointer data);
static void engrave(GDrawable * drawable);
static void engrave_large(GDrawable * drawable, gint height, gint limit);
static void engrave_small(GDrawable * drawable, gint height, gint limit, gint tile_width);
static void engrave_sub(gint height, gint limit, gint bpp, gint color_n);
static void engrave_toggle_update (GtkWidget *widget,
gpointer data);
static void engrave_scale_update (GtkAdjustment *adjustment,
int *scale_val);
static void engrave_entry_update (GtkWidget *widget,
gint *value);
static void dialog_create_value (char *title,
GtkTable *table,
int row,
gint *value,
int left,
int right);
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
static EngraveValues pvals =
{
10
};
static EngraveInterface pint =
{
FALSE /* run */
};
MAIN()
static void
query()
{
static GParamDef args[] =
{
{PARAM_INT32, "run_mode", "Interactive, non-interactive"},
{PARAM_IMAGE, "image", "Input image (unused)"},
{PARAM_DRAWABLE, "drawable", "Input drawable"},
{PARAM_INT32, "height", "Resolution in pixels"},
{PARAM_INT32, "limit", "If true, limit line width"}
};
static GParamDef *return_vals = NULL;
static gint nargs = sizeof(args) / sizeof(args[0]);
static gint nreturn_vals = 0;
gimp_install_procedure("plug_in_engrave",
"Engrave the contents of the specified drawable",
"Creates a black-and-white 'engraved' version of an image as seen in old illustrations",
"Spencer Kimball & Peter Mattis, Eiichi Takamori, Torsten Martinsen",
"Spencer Kimball & Peter Mattis, Eiichi Takamori, Torsten Martinsen",
"1995,1996,1997",
"<Image>/Filters/Distorts/Engrave",
"RGBA, GRAYA",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
static void
run(gchar * name,
gint nparams,
GParam * param,
gint * nreturn_vals,
GParam ** return_vals)
{
static GParam values[1];
GDrawable *drawable;
GRunModeType run_mode;
GStatusType status = STATUS_SUCCESS;
run_mode = param[0].data.d_int32;
*nreturn_vals = 1;
*return_vals = values;
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
/* Get the specified drawable */
drawable = gimp_drawable_get(param[2].data.d_drawable);
switch (run_mode) {
case RUN_INTERACTIVE:
/* Possibly retrieve data */
gimp_get_data("plug_in_engrave", &pvals);
/* First acquire information with a dialog */
if (!engrave_dialog()) {
gimp_drawable_detach(drawable);
return;
}
break;
case RUN_NONINTERACTIVE:
/* Make sure all the arguments are there! */
if (nparams != 5)
status = STATUS_CALLING_ERROR;
if (status == STATUS_SUCCESS) {
pvals.height = param[3].data.d_int32;
pvals.limit = (param[4].data.d_int32) ? TRUE : FALSE;
}
if ((status == STATUS_SUCCESS) &&
pvals.height < 0)
status = STATUS_CALLING_ERROR;
break;
case RUN_WITH_LAST_VALS:
/* Possibly retrieve data */
gimp_get_data("plug_in_engrave", &pvals);
break;
default:
break;
}
if (status == STATUS_SUCCESS) {
gimp_progress_init("Engraving...");
gimp_tile_cache_ntiles(TILE_CACHE_SIZE);
engrave(drawable);
if (run_mode != RUN_NONINTERACTIVE)
gimp_displays_flush();
/* Store data */
if (run_mode == RUN_INTERACTIVE)
gimp_set_data("plug_in_engrave", &pvals, sizeof(EngraveValues));
}
values[0].data.d_status = status;
gimp_drawable_detach(drawable);
}
static gint
engrave_dialog()
{
GtkWidget *dlg;
GtkWidget *frame;
GtkWidget *table;
GtkWidget *button;
GtkWidget *toggle;
gchar **argv;
gint argc;
argc = 1;
argv = g_new(gchar *, 1);
argv[0] = g_strdup("engrave");
gtk_init(&argc, &argv);
gtk_rc_parse(gimp_gtkrc());
dlg = gtk_dialog_new();
gtk_window_set_title(GTK_WINDOW(dlg), "Engrave");
gtk_window_position(GTK_WINDOW(dlg), GTK_WIN_POS_MOUSE);
gtk_signal_connect(GTK_OBJECT(dlg), "destroy",
(GtkSignalFunc) engrave_close_callback,
NULL);
/* Action area */
button = gtk_button_new_with_label("OK");
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
(GtkSignalFunc) engrave_ok_callback,
dlg);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area), button, TRUE, TRUE, 0);
gtk_widget_grab_default(button);
gtk_widget_show(button);
button = gtk_button_new_with_label("Cancel");
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
(GtkSignalFunc) gtk_widget_destroy,
GTK_OBJECT(dlg));
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->action_area), button, TRUE, TRUE, 0);
gtk_widget_show(button);
/* parameter settings */
frame = gtk_frame_new("Parameter Settings");
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width(GTK_CONTAINER(frame), 10);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), frame, TRUE, TRUE, 0);
table = gtk_table_new(2, 3, FALSE);
gtk_container_border_width(GTK_CONTAINER(table), 10);
gtk_container_add(GTK_CONTAINER(frame), table);
toggle = gtk_check_button_new_with_label ("Limit line width");
gtk_table_attach (GTK_TABLE (table), toggle, 0, 2, 0, 1, GTK_FILL, 0, 0, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
(GtkSignalFunc) engrave_toggle_update,
&pvals.limit);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), pvals.limit);
gtk_widget_show (toggle);
dialog_create_value("Height", GTK_TABLE(table), 1, &pvals.height, 2.0, 16.0);
gtk_widget_show(frame);
gtk_widget_show(table);
gtk_widget_show(dlg);
gtk_main();
gdk_flush();
return pint.run;
}
/* Engrave interface functions */
static void
engrave_close_callback(GtkWidget * widget,
gpointer data)
{
gtk_main_quit();
}
static void
engrave_ok_callback(GtkWidget * widget,
gpointer data)
{
pint.run = TRUE;
gtk_widget_destroy(GTK_WIDGET(data));
}
static void
engrave(GDrawable * drawable)
{
gint tile_width;
gint height;
gint limit;
tile_width = gimp_tile_width();
height = (gint) pvals.height;
limit = (gint) pvals.limit;
if (height >= tile_width)
engrave_large(drawable, height, limit);
else
engrave_small(drawable, height, limit, tile_width);
}
static void
engrave_large(GDrawable * drawable, gint height, gint limit)
{
GPixelRgn src_rgn, dest_rgn;
guchar *src_row, *dest_row;
guchar *src, *dest;
gulong *average;
gint row, col, b, bpp;
gint x, y, y_step, inten, v;
gulong count;
gint x1, y1, x2, y2;
gint progress, max_progress;
gpointer pr;
gimp_drawable_mask_bounds(drawable->id, &x1, &y1, &x2, &y2);
if (gimp_drawable_color(drawable->id))
bpp = 3;
else
bpp = 1;
average = g_new(gulong, bpp);
/* Initialize progress */
progress = 0;
max_progress = 2 * (x2 - x1) * (y2 - y1);
for (y = y1; y < y2; y += height - (y % height)) {
for (x = x1; x < x2; ++x) {
y_step = height - (y % height);
y_step = MIN(y_step, x2 - x);
gimp_pixel_rgn_init(&src_rgn, drawable, x, y, 1, y_step, FALSE, FALSE);
for (b = 0; b < bpp; b++)
average[b] = 0;
count = 0;
for (pr = gimp_pixel_rgns_register(1, &src_rgn);
pr != NULL;
pr = gimp_pixel_rgns_process(pr)) {
src_row = src_rgn.data;
for (row = 0; row < src_rgn.h; row++) {
src = src_row;
for (col = 0; col < src_rgn.w; col++) {
for (b = 0; b < bpp; b++)
average[b] += src[b];
src += src_rgn.bpp;
count += 1;
}
src_row += src_rgn.rowstride;
}
/* Update progress */
progress += src_rgn.w * src_rgn.h;
gimp_progress_update((double) progress / (double) max_progress);
}
if (count > 0)
for (b = 0; b < bpp; b++)
average[b] = (guchar) (average[b] / count);
if (bpp < 3)
inten = average[0]/254.0*height;
else
inten = INTENSITY(average[0],
average[1],
average[2])/254.0*height;
gimp_pixel_rgn_init(&dest_rgn, drawable, x, y, 1, y_step, TRUE, TRUE);
for (pr = gimp_pixel_rgns_register(1, &dest_rgn);
pr != NULL;
pr = gimp_pixel_rgns_process(pr)) {
dest_row = dest_rgn.data;
for (row = 0; row < dest_rgn.h; row++) {
dest = dest_row;
v = inten > row ? 255 : 0;
if (limit) {
if (row == 0)
v = 255;
else if (row == height-1)
v = 0;
}
for (b = 0; b < bpp; b++)
dest[b] = v;
dest_row += dest_rgn.rowstride;
}
/* Update progress */
progress += dest_rgn.w * dest_rgn.h;
gimp_progress_update((double) progress / (double) max_progress);
}
}
}
g_free(average);
/* update the engraved region */
gimp_drawable_flush(drawable);
gimp_drawable_merge_shadow(drawable->id, TRUE);
gimp_drawable_update(drawable->id, x1, y1, (x2 - x1), (y2 - y1));
}
typedef struct {
gint x, y, h;
gint width;
guchar *data;
} PixelArea;
PixelArea area;
static void
engrave_small(GDrawable * drawable, gint height, gint limit, gint tile_width)
{
GPixelRgn src_rgn, dest_rgn;
gint bpp, color_n;
gint x1, y1, x2, y2;
gint progress, max_progress;
/*
For speed efficiency, operates on PixelAreas, whose each width and
height are less than tile size.
If both ends of area cannot be divided by height ( as
x1%height != 0 etc.), operates on the remainder pixels.
*/
gimp_drawable_mask_bounds(drawable->id, &x1, &y1, &x2, &y2);
gimp_pixel_rgn_init(&src_rgn, drawable, x1, y1, x2 - x1, y2 - y1, FALSE, FALSE);
gimp_pixel_rgn_init(&dest_rgn, drawable, x1, y1, x2 - x1, y2 - y1, TRUE, TRUE);
/* Initialize progress */
progress = 0;
max_progress = (x2 - x1) * (y2 - y1);
bpp = drawable->bpp;
if (gimp_drawable_color(drawable->id))
color_n = 3;
else
color_n = 1;
area.width = (tile_width / height) * height;
area.data = g_new(guchar, (glong) bpp * area.width * area.width);
for (area.y = y1; area.y < y2;
area.y += area.width - (area.y % area.width)) {
area.h = area.width - (area.y % area.width);
area.h = MIN(area.h, y2 - area.y);
for (area.x = x1; area.x < x2; ++area.x) {
gimp_pixel_rgn_get_rect(&src_rgn, area.data, area.x, area.y, 1, area.h);
engrave_sub(height, limit, bpp, color_n);
gimp_pixel_rgn_set_rect(&dest_rgn, area.data, area.x, area.y, 1, area.h);
/* Update progress */
progress += area.h;
gimp_progress_update((double) progress / (double) max_progress);
}
}
g_free(area.data);
/* update the engraved region */
gimp_drawable_flush(drawable);
gimp_drawable_merge_shadow(drawable->id, TRUE);
gimp_drawable_update(drawable->id, x1, y1, (x2 - x1), (y2 - y1));
}
static void
engrave_sub(gint height, gint limit, gint bpp, gint color_n)
{
glong average[3]; /* color_n <= 3 */
gint y, h, inten, v;
guchar *buf_row, *buf;
gint row;
gint rowstride;
gint count;
gint i;
/*
Since there's so many nested FOR's,
put a few of them here...
*/
rowstride = bpp;
for (y = area.y; y < area.y + area.h; y += height - (y % height)) {
h = height - (y % height);
h = MIN(h, area.y + area.h - y);
for (i = 0; i < color_n; i++)
average[i] = 0;
count = 0;
/* Read */
buf_row = area.data + (y - area.y) * rowstride;
for (row = 0; row < h; row++) {
buf = buf_row;
for (i = 0; i < color_n; i++)
average[i] += buf[i];
count++;
buf_row += rowstride;
}
/* Average */
if (count > 0)
for (i = 0; i < color_n; i++)
average[i] /= count;
if (bpp < 3)
inten = average[0]/254.0*height;
else
inten = INTENSITY(average[0],
average[1],
average[2])/254.0*height;
/* Write */
buf_row = area.data + (y - area.y) * rowstride;
for (row = 0; row < h; row++) {
buf = buf_row;
v = inten > row ? 255 : 0;
if (limit) {
if (row == 0)
v = 255;
else if (row == height-1)
v = 0;
}
for (i = 0; i < color_n; i++)
buf[i] = v;
buf_row += rowstride;
}
}
}
static void
engrave_toggle_update (GtkWidget *widget,
gpointer data)
{
int *toggle_val;
toggle_val = (int *) data;
if (GTK_TOGGLE_BUTTON (widget)->active)
*toggle_val = TRUE;
else
*toggle_val = FALSE;
}
/*
* Thanks to Quartic for these.
*/
static void
dialog_create_value(char *title, GtkTable *table, int row, gint *value, int left, int right)
{
GtkWidget *label;
GtkWidget *scale;
GtkWidget *entry;
GtkObject *scale_data;
char buf[256];
label = gtk_label_new(title);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(table, label, 0, 1, row, row + 1, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(label);
scale_data = gtk_adjustment_new(*value, left, right,
1.0,
1.0,
0.0);
gtk_signal_connect(GTK_OBJECT(scale_data), "value_changed",
(GtkSignalFunc) engrave_scale_update,
value);
scale = gtk_hscale_new(GTK_ADJUSTMENT(scale_data));
gtk_widget_set_usize(scale, SCALE_WIDTH, 0);
gtk_table_attach(table, scale, 1, 2, row, row + 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
gtk_scale_set_draw_value(GTK_SCALE(scale), FALSE);
gtk_scale_set_digits(GTK_SCALE(scale), 0);
gtk_range_set_update_policy(GTK_RANGE(scale), GTK_UPDATE_CONTINUOUS);
gtk_widget_show(scale);
entry = gtk_entry_new();
gtk_object_set_user_data(GTK_OBJECT(entry), scale_data);
gtk_object_set_user_data(scale_data, entry);
gtk_widget_set_usize(entry, ENTRY_WIDTH, 0);
sprintf(buf, "%d", *value);
gtk_entry_set_text(GTK_ENTRY(entry), buf);
gtk_signal_connect(GTK_OBJECT(entry), "changed",
(GtkSignalFunc) engrave_entry_update,
value);
gtk_table_attach(GTK_TABLE(table), entry, 2, 3, row, row + 1, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(entry);
}
static void
engrave_entry_update(GtkWidget *widget, gint *value)
{
GtkAdjustment *adjustment;
gint new_value;
new_value = atoi(gtk_entry_get_text(GTK_ENTRY(widget)));
if (*value != new_value) {
adjustment = gtk_object_get_user_data(GTK_OBJECT(widget));
if ((new_value >= adjustment->lower) &&
(new_value <= adjustment->upper)) {
*value = new_value;
adjustment->value = new_value;
gtk_signal_emit_by_name(GTK_OBJECT(adjustment), "value_changed");
} /* if */
} /* if */
}
static void
engrave_scale_update (GtkAdjustment *adjustment, gint *value)
{
GtkWidget *entry;
char buf[256];
if (*value != adjustment->value) {
*value = adjustment->value;
entry = gtk_object_get_user_data(GTK_OBJECT(adjustment));
sprintf(buf, "%d", *value);
gtk_signal_handler_block_by_data(GTK_OBJECT(entry), value);
gtk_entry_set_text(GTK_ENTRY(entry), buf);
gtk_signal_handler_unblock_by_data(GTK_OBJECT(entry), value);
} /* if */
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
exchange

View file

@ -1,36 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = exchange
exchange_SOURCES = \
exchange.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
exchange_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,535 +0,0 @@
/*
* This is a plug-in for the GIMP.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*/
/*
* Exchange one color with the other (settable threshold to convert from
* one color-shade to another...might do wonders on certain images, or be
* totally useless on others).
*
* Author: robert@experimental.net
*
* TODO:
* - locken van scales met elkaar
*/
/*
* 1999/03/17 Fixed RUN_NONINTERACTIVE and RUN_WITH_LAST_VALS.
* There were uninitialized variables.
* --Sven <sven@gimp.org>
*/
#include <stdio.h>
#include <stdlib.h>
#include "libgimp/gimp.h"
#include "gtk/gtk.h"
/* big scales */
#define SCALE_WIDTH 225
/* preview width/height */
#define PREVIEW_SIZE 128
/* datastructure to store parameters in */
typedef struct
{
guchar fromred, fromgreen, fromblue, tored, togreen, toblue;
guchar red_threshold, green_threshold, blue_threshold;
gint32 image;
gint32 drawable;
} myParams;
/* lets prototype */
static void query();
static void run(char *, int, GParam *, int *, GParam **);
static int doDialog();
static void exchange();
static void real_exchange(gint, gint, gint, gint, int);
static void doLabelAndScale(char *, GtkWidget *, guchar *);
static void update_preview();
static void ok_callback(GtkWidget *, gpointer);
static void lock_callback(GtkWidget *, gpointer);
static void scale_callback(GtkAdjustment *, gpointer);
/* some global variables */
GDrawable *drw;
myParams xargs = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int running = 0;
GPixelRgn origregion;
GtkWidget *preview;
gint sel_x1, sel_y1, sel_x2, sel_y2;
gint prev_width, prev_height, sel_width, sel_height;
gint lock_thres = 0;
/* lets declare what we want to do */
GPlugInInfo PLUG_IN_INFO =
{
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run, /* run_proc */
};
/* run program */
MAIN()
/* tell GIMP who we are */
static
void query()
{
static GParamDef args[] =
{
{ PARAM_INT32, "run_mode", "Interactive" },
{ PARAM_IMAGE, "image", "Input image" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_INT8, "fromred", "Red value (from)" },
{ PARAM_INT8, "fromgreen", "Green value (from)" },
{ PARAM_INT8, "fromblue", "Blue value (from)" },
{ PARAM_INT8, "tored", "Red value (to)" },
{ PARAM_INT8, "togreen", "Green value (to)" },
{ PARAM_INT8, "toblue", "Blue value (to)" },
{ PARAM_INT8, "red_threshold", "Red threshold" },
{ PARAM_INT8, "green_threshold", "Green threshold" },
{ PARAM_INT8, "blue_threshold", "Blue threshold" },
};
static GParamDef *return_vals = NULL;
static int nargs = sizeof(args) / sizeof(args[0]);
static int nreturn_vals = 0;
gimp_install_procedure("plug_in_exchange",
"Color Exchange",
"Exchange one color with another, optionally setting a threshold to convert from one shade to another",
"robert@experimental.net",
"robert@experimental.net",
"June 17th, 1997",
"<Image>/Filters/Colors/Color Exchange",
"RGB*",
PROC_PLUG_IN,
nargs, nreturn_vals,
args, return_vals);
}
/* main function */
static
void run(char *name, int nparams, GParam *param, int *nreturn_vals, GParam **return_vals)
{
static GParam values[1];
GRunModeType runmode;
GStatusType status = STATUS_SUCCESS;
*nreturn_vals = 1;
*return_vals = values;
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
runmode = param[0].data.d_int32;
xargs.image = param[1].data.d_image;
xargs.drawable = param[2].data.d_drawable;
drw = gimp_drawable_get(xargs.drawable);
switch (runmode)
{
case RUN_INTERACTIVE:
/* retrieve stored arguments (if any) */
gimp_get_data("plug_in_exchange", &xargs);
/* initialize using foreground color */
gimp_palette_get_foreground(&xargs.fromred, &xargs.fromgreen, &xargs.fromblue);
/* and initialize some other things */
gimp_drawable_mask_bounds(drw->id, &sel_x1, &sel_y1, &sel_x2, &sel_y2);
sel_width = sel_x2 - sel_x1;
sel_height = sel_y2 - sel_y1;
if (sel_width > PREVIEW_SIZE)
prev_width = PREVIEW_SIZE;
else
prev_width = sel_width;
if (sel_height > PREVIEW_SIZE)
prev_height = PREVIEW_SIZE;
else
prev_height = sel_height;
if (!doDialog())
return;
break;
case RUN_WITH_LAST_VALS:
gimp_get_data("plug_in_exchange", &xargs);
/*
* instead of recalling the last-set values,
* run with the current foreground as 'from'
* color, making ALT-F somewhat more useful.
*/
gimp_palette_get_foreground(&xargs.fromred, &xargs.fromgreen, &xargs.fromblue);
break;
case RUN_NONINTERACTIVE:
if (nparams != 10)
status = STATUS_EXECUTION_ERROR;
if (status == STATUS_SUCCESS)
{
xargs.fromred = param[3].data.d_int8;
xargs.fromgreen = param[4].data.d_int8;
xargs.fromblue = param[5].data.d_int8;
xargs.tored = param[6].data.d_int8;
xargs.togreen = param[7].data.d_int8;
xargs.toblue = param[8].data.d_int8;
xargs.red_threshold = param[9].data.d_int32;
xargs.green_threshold = param[10].data.d_int32;
xargs.blue_threshold = param[11].data.d_int32;
}
break;
default:
break;
}
if (status == STATUS_SUCCESS)
{
if (gimp_drawable_color(drw->id))
{
gimp_progress_init("Color Exchange...");
gimp_tile_cache_ntiles(2 * (drw->width / gimp_tile_width() + 1));
exchange();
gimp_drawable_detach(drw);
/* store our settings */
if (runmode == RUN_INTERACTIVE)
gimp_set_data("plug_in_exchange", &xargs, sizeof(myParams));
/* and flush */
if (runmode != RUN_NONINTERACTIVE)
gimp_displays_flush ();
}
else
status = STATUS_EXECUTION_ERROR;
}
values[0].data.d_status = status;
}
/* do the exchanging */
static
void exchange()
{
/* do the real exchange */
real_exchange(-1, -1, -1, -1, 0);
}
/* show our dialog */
static
int doDialog()
{
GtkWidget *dialog;
GtkWidget *button;
GtkWidget *frame;
GtkWidget *table;
GtkWidget *mainbox;
GtkWidget *tobox;
GtkWidget *frombox;
GtkWidget *prevbox;
guchar *color_cube;
gchar **argv;
gint argc;
int framenumber;
argc = 1;
argv = g_new(gchar *, 1);
argv[0] = g_strdup("exchange");
gtk_init(&argc, &argv);
gtk_rc_parse(gimp_gtkrc());
/* stuff for preview */
gtk_preview_set_gamma(gimp_gamma());
gtk_preview_set_install_cmap(gimp_install_cmap());
color_cube = gimp_color_cube();
gtk_preview_set_color_cube(color_cube[0], color_cube[1], color_cube[2], color_cube[3]);
gtk_widget_set_default_visual(gtk_preview_get_visual());
gtk_widget_set_default_colormap(gtk_preview_get_cmap());
/* load pixelregion */
gimp_pixel_rgn_init(&origregion, drw, 0, 0, PREVIEW_SIZE, PREVIEW_SIZE, FALSE, FALSE);
/* set up the dialog */
dialog = gtk_dialog_new();
gtk_window_set_title(GTK_WINDOW(dialog), "Color Exchange");
gtk_window_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
gtk_signal_connect(GTK_OBJECT(dialog), "destroy",
(GtkSignalFunc) gtk_main_quit,
NULL);
/* lets create some buttons */
button = gtk_button_new_with_label("Ok");
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect(GTK_OBJECT(button), "clicked",
(GtkSignalFunc) ok_callback,
dialog);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
button, TRUE, TRUE, 0);
gtk_widget_grab_default(button);
gtk_widget_show(button);
button = gtk_button_new_with_label("Cancel");
GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
(GtkSignalFunc) gtk_widget_destroy,
GTK_OBJECT(dialog));
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
button, TRUE, TRUE, 0);
gtk_widget_show(button);
/* do some boxes here */
mainbox = gtk_vbox_new(FALSE, 5);
gtk_container_border_width(GTK_CONTAINER(mainbox), 10);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), mainbox, TRUE, TRUE, 0);
prevbox = gtk_hbox_new(FALSE, 5);
gtk_container_border_width(GTK_CONTAINER(prevbox), 0);
gtk_box_pack_start(GTK_BOX(mainbox), prevbox, TRUE, TRUE, 0);
frombox = gtk_hbox_new(FALSE, 5);
gtk_container_border_width(GTK_CONTAINER(frombox), 0);
gtk_box_pack_start(GTK_BOX(mainbox), frombox, TRUE, TRUE, 0);
tobox = gtk_hbox_new(FALSE, 5);
gtk_container_border_width(GTK_CONTAINER(tobox), 0);
gtk_box_pack_start(GTK_BOX(mainbox), tobox, TRUE, TRUE, 0);
frame = gtk_frame_new("Preview");
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width(GTK_CONTAINER(frame), 0);
gtk_box_pack_start(GTK_BOX(prevbox), frame, TRUE, TRUE, 0);
gtk_widget_show(frame);
preview = gtk_preview_new(GTK_PREVIEW_COLOR);
gtk_preview_size(GTK_PREVIEW(preview), prev_width, prev_height);
gtk_container_add(GTK_CONTAINER(frame), preview);
update_preview();
gtk_widget_show(preview);
/* and our scales */
for (framenumber = 0; framenumber < 2; framenumber++)
{
frame = gtk_frame_new(framenumber ? "To color" : "From color");
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width(GTK_CONTAINER(frame), 0);
gtk_box_pack_start(framenumber ? GTK_BOX(tobox) : GTK_BOX(frombox),
frame, TRUE, TRUE, 0);
gtk_widget_show(frame);
table = gtk_table_new(8, 2, FALSE);
gtk_container_border_width(GTK_CONTAINER(table), 0);
gtk_container_add(GTK_CONTAINER(frame), table);
doLabelAndScale("Red", table, framenumber ? &xargs.tored : &xargs.fromred);
if (! framenumber)
doLabelAndScale("Red threshold", table, &xargs.red_threshold);
doLabelAndScale("Green", table, framenumber ? &xargs.togreen : &xargs.fromgreen);
if (! framenumber)
doLabelAndScale("Green threshold", table, &xargs.green_threshold);
doLabelAndScale("Blue", table, framenumber ? &xargs.toblue : &xargs.fromblue);
if (! framenumber)
doLabelAndScale("Blue threshold", table, &xargs.blue_threshold);
if (! framenumber)
{
GtkWidget *button;
button = gtk_check_button_new_with_label("Lock thresholds");
gtk_table_attach(GTK_TABLE(table), button, 1, 2, 6, 7, GTK_FILL, 0, 0, 0);
gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) lock_callback, dialog);
gtk_widget_show(button);
}
gtk_widget_show(table);
}
/* show everything */
gtk_widget_show(prevbox);
gtk_widget_show(tobox);
gtk_widget_show(frombox);
gtk_widget_show(mainbox);
gtk_widget_show(dialog);
gtk_main();
gdk_flush();
return running;
}
static
void doLabelAndScale(char *labelname, GtkWidget *table, guchar *dest)
{
static int idx = -1;
GtkWidget *label, *scale;
GtkObject *scale_data;
idx++;
label = gtk_label_new(labelname);
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, idx, idx + 1, GTK_FILL, 0, 0, 0);
scale_data = gtk_adjustment_new(*dest, 0.0, 255.0, 0.0, 0.0, 0.0);
scale = gtk_hscale_new(GTK_ADJUSTMENT(scale_data));
gtk_widget_set_usize(scale, SCALE_WIDTH, 0);
/* just need 1:1 resolution on scales */
gtk_scale_set_digits(GTK_SCALE(scale), 0);
gtk_table_attach(GTK_TABLE(table), scale, 1, 2, idx, idx + 1, GTK_FILL, 0, 0, 0);
gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_TOP);
gtk_range_set_update_policy(GTK_RANGE(scale), GTK_UPDATE_DISCONTINUOUS);
gtk_signal_connect(GTK_OBJECT(scale_data), "value_changed",
(GtkSignalFunc) scale_callback,
dest);
gtk_widget_show(label);
gtk_widget_show(scale);
}
static
void ok_callback(GtkWidget *widget, gpointer data)
{
running = 1;
gtk_widget_destroy(GTK_WIDGET(data));
}
static
void lock_callback(GtkWidget *widget, gpointer data)
{
lock_thres = 1 - lock_thres;
}
static
void scale_callback(GtkAdjustment *adj, gpointer data)
{
guchar *val = data;
*val = (guchar) adj->value;
update_preview();
}
static
void update_preview()
{
real_exchange(sel_x1, sel_y1, sel_x1 + prev_width, sel_y1 + prev_height, 1);
gtk_widget_draw(preview, NULL);
gdk_flush();
}
static
void real_exchange(gint x1, gint y1, gint x2, gint y2, int dopreview)
{
GPixelRgn srcPR, destPR;
guchar *src_row, *dest_row;
int x, y, bpp = drw->bpp;
int width, height;
/* fill if necessary */
if (x1 == -1 || y1 == -1 || x2 == -1 || y2 == -1)
{
x1 = sel_x1;
y1 = sel_y1;
x2 = sel_x2;
y2 = sel_y2;
}
/* check for valid coordinates */
width = x2 - x1;
height = y2 - y1;
/* allocate memory */
src_row = g_malloc(drw->width * bpp * sizeof(guchar));
dest_row = g_malloc(drw->width * bpp * sizeof(guchar));
/* initialize the pixel regions */
/*
gimp_pixel_rgn_init(&srcPR, drw, x1, y1, width, height, FALSE, FALSE);
*/
gimp_pixel_rgn_init(&srcPR, drw, 0, 0, drw->width, drw->height, FALSE, FALSE);
if (! dopreview)
gimp_pixel_rgn_init(&destPR, drw, 0, 0, width, height, TRUE, TRUE);
for (y = y1; y < y2; y++)
{
gimp_pixel_rgn_get_row(&srcPR, src_row, 0, y, drw->width);
for (x = x1; x < x2; x++)
{
gint pixel_red, pixel_green, pixel_blue;
gint min_red, max_red,
min_green, max_green,
min_blue, max_blue;
gint new_red, new_green, new_blue;
gint idx, rest;
/* get boundary values */
min_red = MAX(xargs.fromred - xargs.red_threshold, 0);
min_green = MAX(xargs.fromgreen - xargs.green_threshold, 0);
min_blue = MAX(xargs.fromblue - xargs.blue_threshold, 0);
max_red = MIN(xargs.fromred + xargs.red_threshold, 255);
max_green = MIN(xargs.fromgreen + xargs.green_threshold, 255);
max_blue = MIN(xargs.fromblue + xargs.blue_threshold, 255);
/* get current pixel-values */
pixel_red = src_row[x * bpp];
pixel_green = src_row[x * bpp + 1];
pixel_blue = src_row[x * bpp + 2];
/* shift down for preview */
if (dopreview)
idx = (x - x1) * bpp;
else
idx = x * bpp;
/* want this pixel? */
if (pixel_red >= min_red && pixel_red <= max_red && pixel_green >= min_green && pixel_green <= max_green && pixel_blue >= min_blue && pixel_blue <= max_blue)
{
gint red_delta, green_delta, blue_delta;
red_delta = pixel_red - xargs.fromred;
green_delta = pixel_green - xargs.fromgreen;
blue_delta = pixel_blue - xargs.fromblue;
new_red = (guchar) MAX(MIN(xargs.tored + red_delta, 255), 0);
new_green = (guchar) MAX(MIN(xargs.togreen + green_delta, 255), 0);
new_blue = (guchar) MAX(MIN(xargs.toblue + blue_delta, 255), 0);
}
else
{
new_red = pixel_red;
new_green = pixel_green;
new_blue = pixel_blue;
}
/* fill buffer (cast it too) */
dest_row[idx + 0] = (guchar) new_red;
dest_row[idx + 1] = (guchar) new_green;
dest_row[idx + 2] = (guchar) new_blue;
/* copy rest (most likely alpha-channel) */
for (rest = 3; rest < bpp; rest++)
dest_row[idx + rest] = src_row[x * bpp + rest];
}
/* store the dest */
if (dopreview)
gtk_preview_draw_row(GTK_PREVIEW(preview), dest_row, 0, y - y1, width);
else
gimp_pixel_rgn_set_row(&destPR, dest_row, 0, y, drw->width);
/* and tell the user what we're doing */
if (! dopreview && (y % 10) == 0)
gimp_progress_update((double) y / (double) height);
}
g_free(src_row);
g_free(dest_row);
if (! dopreview)
{
/* update the processed region */
gimp_drawable_flush(drw);
gimp_drawable_merge_shadow(drw->id, TRUE);
gimp_drawable_update(drw->id, x1, y1, width, height);
}
}

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
film

View file

@ -1,36 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = film
film_SOURCES = \
film.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
film_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
flarefx

View file

@ -1,36 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = flarefx
flarefx_SOURCES = \
flarefx.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
flarefx_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
fractaltrace

View file

@ -1,36 +0,0 @@
## Process this file with automake to produce Makefile.in
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = fractaltrace
fractaltrace_SOURCES = \
fractaltrace.c
INCLUDES = \
-I$(top_srcdir) \
$(GTK_CFLAGS) \
-I$(includedir)
LDADD = \
$(top_builddir)/libgimp/libgimp.la \
$(GTK_LIBS) \
$(INTLLIBS)
DEPS = \
$(top_builddir)/libgimp/libgimp.la
fractaltrace_DEPENDENCIES = $(DEPS)
.PHONY: files
files:
@files=`ls $(DISTFILES) 2> /dev/null`; for p in $$files; do \
echo $$p; \
done
@for subdir in $(SUBDIRS); do \
files=`cd $$subdir; $(MAKE) files | grep -v "make\[[1-9]\]"`; \
for file in $$files; do \
echo $$subdir/$$file; \
done; \
done

View file

@ -1,893 +0,0 @@
/*******************************************************************************
fractaltrace.c -- This is a plug-in for the GIMP 1.0
Copyright (C) 1997 Hirotsuna Mizuno
s1041150@u-aizu.ac.jp
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.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*******************************************************************************/
#define PLUG_IN_NAME "plug_in_fractal_trace"
#define PLUG_IN_TITLE "Fractal Trace"
#define PLUG_IN_VERSION "v0.4 test version (Dec. 25 1997)"
#define PLUG_IN_CATEGORY "<Image>/Filters/Map/Fractal Trace"
/******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <math.h>
#include <libgimp/gimp.h>
#ifndef PI_2
#define PI_2 (3.14159265358979323*2.0)
#endif
/******************************************************************************/
static void query( void );
static void run( char*, int, GParam*, int*, GParam** );
static void filter( GDrawable* );
static void pixels_init( GDrawable* );
static void pixels_free( void );
static int dialog_show( void );
static void dialog_preview_draw( void );
/******************************************************************************/
GPlugInInfo PLUG_IN_INFO = {
NULL, /* init_proc */
NULL, /* quit_proc */
query, /* query_proc */
run /* run_proc */
};
MAIN()
/******************************************************************************/
typedef struct {
gint32 wrap;
gint32 transparent;
gint32 black;
gint32 white;
} outside_type_t;
#define OUTSIDE_TYPE_WRAP 0
#define OUTSIDE_TYPE_TRANSPARENT 1
#define OUTSIDE_TYPE_BLACK 2
#define OUTSIDE_TYPE_WHITE 3
static outside_type_t outside_type = {
OUTSIDE_TYPE_WRAP,
OUTSIDE_TYPE_TRANSPARENT,
OUTSIDE_TYPE_BLACK,
OUTSIDE_TYPE_WHITE
};
typedef struct {
gdouble x1;
gdouble x2;
gdouble y1;
gdouble y2;
gint32 depth;
gint32 outside_type;
} parameter_t;
static parameter_t parameters = {
-1.0,
+0.5,
-1.0,
+1.0,
3,
OUTSIDE_TYPE_WRAP
};
/******************************************************************************/
static void query( void )
{
static GParamDef args[] = {
{ PARAM_INT32, "run_mode", "interactive / non-interactive" },
{ PARAM_IMAGE, "image", "input image (not used)" },
{ PARAM_DRAWABLE, "drawable", "input drawable" },
{ PARAM_FLOAT, "xmin", "xmin fractal image delimiter" },
{ PARAM_FLOAT, "xmax", "xmax fractal image delimiter" },
{ PARAM_FLOAT, "ymin", "ymin fractal image delimiter" },
{ PARAM_FLOAT, "ymax", "ymax fractal image delimiter" },
{ PARAM_INT32, "depth", "trace depth" },
{ PARAM_INT32, "outside_type", "outside type"
"(0=WRAP/1=TRANS/2=BLACK/3=WHITE)" },
};
static int nargs = sizeof( args ) / sizeof( args[0] );
static GParamDef *rets = NULL;
static int nrets = 0;
gimp_install_procedure(
PLUG_IN_NAME,
"transform image with the Mandelbrot Fractal",
"transform image with the Mandelbrot Fractal",
"Hirotsuna Mizuno <s1041150@u-aizu.ac.jp>",
"Copyright (C) 1997 Hirotsuna Mizuno",
PLUG_IN_VERSION,
PLUG_IN_CATEGORY,
"RGB*, GRAY*",
PROC_PLUG_IN,
nargs,
nrets,
args,
rets
);
}
/******************************************************************************/
typedef struct {
gint x1;
gint x2;
gint y1;
gint y2;
gint width;
gint height;
gdouble center_x;
gdouble center_y;
} selection_t;
typedef struct {
gint width;
gint height;
gint bpp;
gint alpha;
} image_t;
static selection_t selection;
static image_t image;
/******************************************************************************/
static void run( char *name, int argc, GParam *args, int *retc, GParam **rets )
{
GDrawable *drawable;
GRunModeType run_mode;
GStatusType status;
static GParam returns[1];
run_mode = args[0].data.d_int32;
status = STATUS_SUCCESS;
drawable = gimp_drawable_get( args[2].data.d_drawable );
image.width = gimp_drawable_width( drawable->id );
image.height = gimp_drawable_height( drawable->id );
image.bpp = gimp_drawable_bpp( drawable->id );
image.alpha = gimp_drawable_has_alpha( drawable->id );
gimp_drawable_mask_bounds( drawable->id, &selection.x1, &selection.y1,
&selection.x2, &selection.y2 );
selection.width = selection.x2 - selection.y1;
selection.height = selection.y2 - selection.y1;
selection.center_x = selection.x1 + (gdouble)selection.width / 2.0;
selection.center_y = selection.y1 + (gdouble)selection.height / 2.0;
pixels_init( drawable );
if( !gimp_drawable_color( drawable->id ) &&
!gimp_drawable_gray( drawable->id ) ){
status = STATUS_EXECUTION_ERROR;
}
switch( run_mode ){
case RUN_WITH_LAST_VALS:
gimp_get_data( PLUG_IN_NAME, &parameters );
break;
case RUN_INTERACTIVE:
gimp_get_data( PLUG_IN_NAME, &parameters );
if( !dialog_show() ){
status = STATUS_EXECUTION_ERROR;
break;
}
gimp_set_data( PLUG_IN_NAME, &parameters, sizeof( parameter_t ) );
break;
case RUN_NONINTERACTIVE:
if( argc != 9 ){
status = STATUS_CALLING_ERROR;
} else {
parameters.x1 = args[3].data.d_float;
parameters.x2 = args[4].data.d_float;
parameters.y1 = args[5].data.d_float;
parameters.y2 = args[6].data.d_float;
parameters.depth = args[7].data.d_int32;
parameters.outside_type = args[8].data.d_int32;
}
break;
}
if( status == STATUS_SUCCESS ){
gimp_tile_cache_ntiles( 2 * ( drawable->width / gimp_tile_width() + 1 ) );
filter( drawable );
if( run_mode != RUN_NONINTERACTIVE ) gimp_displays_flush();
}
gimp_drawable_detach( drawable );
pixels_free();
returns[0].type = PARAM_STATUS;
returns[0].data.d_status = status;
*retc = 1;
*rets = returns;
}
/******************************************************************************/
static guchar **spixels;
static guchar **dpixels;
static GPixelRgn sPR;
static GPixelRgn dPR;
typedef struct {
guchar r;
guchar g;
guchar b;
guchar a;
} pixel_t;
static void pixels_init( GDrawable *drawable )
{
gint y;
gimp_pixel_rgn_init( &sPR, drawable,
0, 0, image.width, image.height, FALSE, FALSE );
gimp_pixel_rgn_init( &dPR, drawable,
0, 0, image.width, image.height, TRUE, TRUE );
spixels = (guchar**)g_malloc( image.height * sizeof( guchar* ) );
dpixels = (guchar**)g_malloc( image.height * sizeof( guchar* ) );
for( y = 0; y < image.height; y++ ){
spixels[y] = (guchar*)g_malloc( image.width * image.bpp * sizeof( guchar ) );
dpixels[y] = (guchar*)g_malloc( image.width * image.bpp * sizeof( guchar ) );
gimp_pixel_rgn_get_row( &sPR, spixels[y], 0, y, image.width );
}
}
static void pixels_free( void )
{
gint y;
for( y = 0; y < image.height; y++ ){
g_free( spixels[y] );
g_free( dpixels[y] );
}
g_free( spixels );
g_free( dpixels );
}
static void pixels_get( gint x, gint y, pixel_t *pixel )
{
if( x < 0 ) x = 0; else if( image.width <= x ) x = image.width - 1;
if( y < 0 ) y = 0; else if( image.height <= y ) y = image.height - 1;
switch( image.bpp ){
case 1: /* GRAY */
pixel->r = spixels[y][x*image.bpp];
pixel->g = spixels[y][x*image.bpp];
pixel->b = spixels[y][x*image.bpp];
pixel->a = 255;
break;
case 2: /* GRAY+A */
pixel->r = spixels[y][x*image.bpp];
pixel->g = spixels[y][x*image.bpp];
pixel->b = spixels[y][x*image.bpp];
pixel->a = spixels[y][x*image.bpp+1];
break;
case 3: /* RGB */
pixel->r = spixels[y][x*image.bpp];
pixel->g = spixels[y][x*image.bpp+1];
pixel->b = spixels[y][x*image.bpp+2];
pixel->a = 255;
break;
case 4: /* RGB+A */
pixel->r = spixels[y][x*image.bpp];
pixel->g = spixels[y][x*image.bpp+1];
pixel->b = spixels[y][x*image.bpp+2];
pixel->a = spixels[y][x*image.bpp+3];
break;
}
}
static void pixels_get_biliner( gdouble x, gdouble y, pixel_t *pixel )
{
pixel_t A, B, C, D;
gdouble a, b, c, d;
gint x1, y1, x2, y2;
gdouble dx, dy;
x1 = (gint)floor( x );
x2 = x1 + 1;
y1 = (gint)floor( y );
y2 = y1 + 1;
dx = x - (gdouble)x1;
dy = y - (gdouble)y1;
a = ( 1.0 - dx ) * ( 1.0 - dy );
b = dx * ( 1.0 - dy );
c = ( 1.0 - dx ) * dy;
d = dx * dy;
pixels_get( x1, y1, &A );
pixels_get( x2, y1, &B );
pixels_get( x1, y2, &C );
pixels_get( x2, y2, &D );
pixel->r = (guchar)( a * (gdouble)A.r + b * (gdouble)B.r +
c * (gdouble)C.r + d * (gdouble)D.r );
pixel->g = (guchar)( a * (gdouble)A.g + b * (gdouble)B.g +
c * (gdouble)C.g + d * (gdouble)D.g );
pixel->b = (guchar)( a * (gdouble)A.b + b * (gdouble)B.b +
c * (gdouble)C.b + d * (gdouble)D.b );
pixel->a = (guchar)( a * (gdouble)A.a + b * (gdouble)B.a +
c * (gdouble)C.a + d * (gdouble)D.a );
}
static void pixels_set( gint x, gint y, pixel_t *pixel )
{
switch( image.bpp ){
case 1: /* GRAY */
dpixels[y][x*image.bpp] = pixel->r;
break;
case 2: /* GRAY+A */
dpixels[y][x*image.bpp] = pixel->r;
dpixels[y][x*image.bpp+1] = pixel->a;
break;
case 3: /* RGB */
dpixels[y][x*image.bpp] = pixel->r;
dpixels[y][x*image.bpp+1] = pixel->g;
dpixels[y][x*image.bpp+2] = pixel->b;
break;
case 4: /* RGB+A */
dpixels[y][x*image.bpp] = pixel->r;
dpixels[y][x*image.bpp+1] = pixel->g;
dpixels[y][x*image.bpp+2] = pixel->b;
dpixels[y][x*image.bpp+3] = pixel->a;
break;
}
}
static void pixels_store( void )
{
gint y;
for( y = selection.y1; y < selection.y2; y++ ){
gimp_pixel_rgn_set_row( &dPR, dpixels[y], 0, y, image.width );
}
}
/******************************************************************************/
static void mandelbrot( gdouble x, gdouble y, gdouble *u, gdouble *v )
{
gint iter = 0;
gdouble xx = x;
gdouble yy = y;
gdouble x2 = xx * xx;
gdouble y2 = yy * yy;
gdouble tmp;
while( iter < parameters.depth ){
tmp = x2 - y2 + x;
yy = 2 * xx * yy + y;
xx = tmp;
x2 = xx * xx;
y2 = yy * yy;
iter++;
}
*u = xx;
*v = yy;
}
/******************************************************************************/
static void filter( GDrawable *drawable )
{
gint x, y;
pixel_t pixel;
gdouble scale_x, scale_y;
gdouble cx, cy;
gdouble px, py;
gimp_progress_init( PLUG_IN_TITLE );
scale_x = ( parameters.x2 - parameters.x1 ) / selection.width;
scale_y = ( parameters.y2 - parameters.y1 ) / selection.height;
for( y = selection.y1; y < selection.y2; y++ ){
cy = parameters.y1 + ( y - selection.y1 ) * scale_y;
for( x = selection.x1; x < selection.x2; x++ ){
cx = parameters.x1 + ( x - selection.x1 ) * scale_x;
mandelbrot( cx, cy, &px, &py );
px = ( px - parameters.x1 ) / scale_x + selection.x1;
py = ( py - parameters.y1 ) / scale_y + selection.y1;
if( 0 <= px && px < image.width && 0 <= py && py < image.height ){
pixels_get_biliner( px, py, &pixel );
} else {
switch( parameters.outside_type ){
case OUTSIDE_TYPE_WRAP:
px = fmod( px, image.width );
py = fmod( py, image.height );
if( px < 0.0 ) px += image.width;
if( py < 0.0 ) py += image.height;
pixels_get_biliner( px, py, &pixel );
break;
case OUTSIDE_TYPE_TRANSPARENT:
pixel.r = pixel.g = pixel.b = 0;
pixel.a = 0;
break;
case OUTSIDE_TYPE_BLACK:
pixel.r = pixel.g = pixel.b = 0;
pixel.a = 255;
break;
case OUTSIDE_TYPE_WHITE:
pixel.r = pixel.g = pixel.b = 255;
pixel.a = 255;
break;
}
}
pixels_set( x, y, &pixel );
}
gimp_progress_update( (gdouble)(y-selection.y1)/selection.height );
}
pixels_store();
gimp_drawable_flush( drawable );
gimp_drawable_merge_shadow( drawable->id, TRUE );
gimp_drawable_update( drawable->id,
selection.x1, selection.y1, selection.width, selection.height );
}
/*
GUI
*/
/******************************************************************************/
static int dialog_status;
/******************************************************************************/
static void dialog_entry_gint32_callback( GtkWidget *widget, gpointer *data )
{
gint32 value = (gint32)atof( gtk_entry_get_text( GTK_ENTRY( widget ) ) );
if( *(gint32*)data != value ){
*(gint32*)data = value;
dialog_preview_draw();
}
}
static void dialog_entry_gint32_new( char *caption, gint32 *value,
GtkWidget *table, gint row )
{
GtkWidget *label;
GtkWidget *entry;
char buffer[256];
label = gtk_label_new( caption );
gtk_table_attach_defaults( GTK_TABLE( table ), label, 0, 1, row, row + 1 );
gtk_widget_show( label );
entry = gtk_entry_new();
sprintf( buffer, "%d", *value );
gtk_entry_set_text( GTK_ENTRY( entry ), buffer );
gtk_signal_connect( GTK_OBJECT( entry ), "changed",
GTK_SIGNAL_FUNC( dialog_entry_gint32_callback ), value );
gtk_table_attach_defaults( GTK_TABLE( table ), entry, 1, 2, row, row + 1 );
gtk_widget_show( entry );
}
/******************************************************************************/
static void dialog_entry_gdouble_callback( GtkWidget *widget, gpointer *data )
{
gdouble value = (gdouble)atof( gtk_entry_get_text( GTK_ENTRY( widget ) ) );
if( *(gdouble*)data != value ){
*(gdouble*)data = value;
dialog_preview_draw();
}
}
static void dialog_entry_gdouble_new( char *caption, gdouble *value,
GtkWidget *table, gint row )
{
GtkWidget *label;
GtkWidget *entry;
char buffer[256];
label = gtk_label_new( caption );
gtk_table_attach_defaults( GTK_TABLE( table ), label, 0, 1, row, row + 1 );
gtk_widget_show( label );
entry = gtk_entry_new();
sprintf( buffer, "%f", *value );
gtk_entry_set_text( GTK_ENTRY( entry ), buffer );
gtk_signal_connect( GTK_OBJECT( entry ), "changed",
GTK_SIGNAL_FUNC( dialog_entry_gdouble_callback ), value );
gtk_table_attach_defaults( GTK_TABLE( table ), entry, 1, 2, row, row + 1 );
gtk_widget_show( entry );
}
/******************************************************************************/
static GtkWidget* dialog_entry_table( void )
{
GtkWidget *table;
table = gtk_table_new( 5, 2, FALSE );
gtk_table_set_row_spacings( GTK_TABLE( table ), 2 );
gtk_table_set_col_spacings( GTK_TABLE( table ), 10 );
dialog_entry_gdouble_new( "X1", &parameters.x1, table, 0 );
dialog_entry_gdouble_new( "X2", &parameters.x2, table, 1 );
dialog_entry_gdouble_new( "Y1", &parameters.y1, table, 2 );
dialog_entry_gdouble_new( "Y2", &parameters.y2, table, 3 );
dialog_entry_gint32_new( "DEPTH", &parameters.depth, table, 4 );
return table;
}
/******************************************************************************/
static void dialog_destroy_callback( GtkWidget *widget, gpointer data )
{
gtk_main_quit();
gdk_flush();
}
static void dialog_ok_callback( GtkWidget *widget, gpointer data )
{
dialog_status = TRUE;
gtk_widget_destroy( GTK_WIDGET( data ) );
}
static void dialog_cancel_callback( GtkWidget *widget, gpointer data )
{
dialog_status = FALSE;
gtk_widget_destroy( GTK_WIDGET( data ) );
}
static void dialog_help_callback( GtkWidget *widget, gpointer data )
{
}
/******************************************************************************/
static void dialog_outside_type_callback( GtkWidget *widget, gpointer *data )
{
gint32 value = *(gint32*)data;
if( parameters.outside_type != value ){
parameters.outside_type = value;
dialog_preview_draw();
}
}
/******************************************************************************/
#define PREVIEW_SIZE 200
typedef struct {
GtkWidget *preview;
guchar **source;
guchar **pixels;
gdouble scale;
gint width;
gint height;
gint bpp;
} preview_t;
static preview_t preview;
static void dialog_preview_setpixel( gint x, gint y, pixel_t *pixel )
{
switch( preview.bpp ){
case 1:
preview.pixels[y][x*preview.bpp] = pixel->r;
break;
case 3:
preview.pixels[y][x*preview.bpp] = pixel->r;
preview.pixels[y][x*preview.bpp+1] = pixel->g;
preview.pixels[y][x*preview.bpp+2] = pixel->b;
break;
}
}
static void dialog_preview_store( void )
{
gint y;
for( y = 0; y < preview.height; y++ ){
gtk_preview_draw_row( GTK_PREVIEW( preview.preview ),
preview.pixels[y], 0, y, preview.width );
}
gtk_widget_draw( preview.preview, NULL );
gdk_flush();
}
static void dialog_preview_init( void )
{
{
guchar *cube;
gtk_preview_set_gamma( gimp_gamma() );
gtk_preview_set_install_cmap( gimp_install_cmap() );
cube = gimp_color_cube();
gtk_preview_set_color_cube( cube[0], cube[1], cube[2], cube[3] );
gtk_widget_set_default_visual( gtk_preview_get_visual() );
gtk_widget_set_default_colormap( gtk_preview_get_cmap() );
}
if( image.width < image.height )
preview.scale = (gdouble)selection.height / (gdouble)PREVIEW_SIZE;
else
preview.scale = (gdouble)selection.width / (gdouble)PREVIEW_SIZE;
preview.width = (gdouble)selection.width / preview.scale;
preview.height = (gdouble)selection.height / preview.scale;
if( image.bpp < 3 ){
preview.bpp = 1;
preview.preview = gtk_preview_new( GTK_PREVIEW_GRAYSCALE );
} else {
preview.bpp = 3;
preview.preview = gtk_preview_new( GTK_PREVIEW_COLOR );
}
gtk_preview_size( GTK_PREVIEW( preview.preview ), preview.width, preview.height );
{
gint y;
preview.source = (guchar**)g_malloc( preview.height * sizeof( guchar* ) );
preview.pixels = (guchar**)g_malloc( preview.height * sizeof( guchar* ) );
for( y = 0; y < preview.height; y++ ){
preview.source[y] = (guchar*)g_malloc( preview.width * preview.bpp * sizeof( guchar ) );
preview.pixels[y] = (guchar*)g_malloc( preview.width * preview.bpp * sizeof( guchar ) );
}
}
{
pixel_t pixel;
gint x, y;
gdouble cx, cy;
for( y = 0; y < preview.height; y++ ){
cy = selection.y1 + (gdouble)y * preview.scale;
for( x = 0; x < preview.width; x++ ){
cx = selection.x1 + (gdouble)x * preview.scale;
pixels_get_biliner( cx, cy, &pixel );
dialog_preview_setpixel( x, y, &pixel );
}
}
dialog_preview_store();
}
}
static void dialog_preview_draw( void )
{
gint x, y;
pixel_t pixel;
gdouble scale_x, scale_y;
gdouble cx, cy;
gdouble px, py;
scale_x = ( parameters.x2 - parameters.x1 ) / preview.width;
scale_y = ( parameters.y2 - parameters.y1 ) / preview.height;
for( y = 0; y < preview.height; y++ ){
cy = parameters.y1 + y * scale_y;
for( x = 0; x < preview.width; x++ ){
cx = parameters.x1 + x * scale_x;
mandelbrot( cx, cy, &px, &py );
px = ( px - parameters.x1 ) / scale_x * preview.scale + selection.x1;
py = ( py - parameters.y1 ) / scale_y * preview.scale + selection.y1;
if( 0 <= px && px < image.width && 0 <= py && py < image.height ){
pixels_get_biliner( px, py, &pixel );
} else {
switch( parameters.outside_type ){
case OUTSIDE_TYPE_WRAP:
px = fmod( px, image.width );
py = fmod( py, image.height );
if( px < 0.0 ) px += image.width;
if( py < 0.0 ) py += image.height;
pixels_get_biliner( px, py, &pixel );
break;
case OUTSIDE_TYPE_TRANSPARENT:
case OUTSIDE_TYPE_BLACK:
pixel.r = pixel.g = pixel.b = 0;
break;
case OUTSIDE_TYPE_WHITE:
pixel.r = pixel.g = pixel.b = 255;
break;
}
}
dialog_preview_setpixel( x, y, &pixel );
}
}
dialog_preview_store();
}
/******************************************************************************/
static gint dialog_show( void )
{
GtkWidget *dialog;
GtkWidget *mainbox;
dialog_status = FALSE;
{
gint argc = 1;
gchar **argv = g_new( gchar *, 1 );
argv[0] = g_strdup( PLUG_IN_TITLE );
gtk_init( &argc, &argv );
gtk_rc_parse( gimp_gtkrc() );
}
dialog = gtk_dialog_new();
gtk_signal_connect( GTK_OBJECT( dialog ), "destroy",
GTK_SIGNAL_FUNC( dialog_destroy_callback ), NULL );
mainbox = gtk_hbox_new( FALSE, 0 );
gtk_container_add( GTK_CONTAINER( GTK_DIALOG( dialog )->vbox ), mainbox );
gtk_widget_show( mainbox );
{
GtkWidget *button;
button = gtk_button_new_with_label( "OK" );
gtk_signal_connect( GTK_OBJECT( button ), "clicked",
GTK_SIGNAL_FUNC( dialog_ok_callback ),
GTK_OBJECT( dialog ) );
gtk_box_pack_start( GTK_BOX( GTK_DIALOG( dialog )->action_area ),
button, TRUE, TRUE, 0 );
GTK_WIDGET_SET_FLAGS( button, GTK_CAN_DEFAULT );
gtk_widget_grab_default( button );
gtk_widget_show( button );
button = gtk_button_new_with_label( "Cancel" );
gtk_signal_connect( GTK_OBJECT( button ), "clicked",
GTK_SIGNAL_FUNC( dialog_cancel_callback ),
GTK_OBJECT( dialog ) );
gtk_box_pack_start( GTK_BOX( GTK_DIALOG( dialog )->action_area ),
button, TRUE, TRUE, 0 );
gtk_widget_show( button );
button = gtk_button_new_with_label( "Help" );
gtk_signal_connect( GTK_OBJECT( button ), "clicked",
GTK_SIGNAL_FUNC( dialog_help_callback ),
GTK_OBJECT( dialog ) );
gtk_box_pack_start( GTK_BOX( GTK_DIALOG( dialog )->action_area ),
button, TRUE, TRUE, 0 );
gtk_widget_show( button );
}
{
GtkWidget *vbox;
GtkWidget *frame;
vbox = gtk_vbox_new( TRUE, 0 );
gtk_container_border_width( GTK_CONTAINER( vbox ), 10 );
gtk_box_pack_start( GTK_BOX( mainbox ), vbox, FALSE, FALSE, 0 );
gtk_widget_show( vbox );
frame = gtk_frame_new( NULL );
gtk_frame_set_shadow_type( GTK_FRAME( frame ), GTK_SHADOW_IN );
gtk_box_pack_start( GTK_BOX( vbox ), frame, FALSE, FALSE, 0 );
gtk_widget_show( frame );
dialog_preview_init();
gtk_container_add( GTK_CONTAINER( frame ), preview.preview );
gtk_widget_show( preview.preview );
}
{
GtkWidget *vbox;
GtkWidget *entrytable;
GtkWidget *separator;
GtkWidget *frame;
GtkWidget *framebox;
GtkWidget *button;
GSList *group;
vbox = gtk_vbox_new( FALSE, 0 );
gtk_container_border_width( GTK_CONTAINER( vbox ), 10 );
gtk_box_pack_start( GTK_BOX( mainbox ), vbox, FALSE, FALSE, 0 );
gtk_widget_show( vbox );
entrytable = dialog_entry_table();
gtk_box_pack_start( GTK_BOX( vbox ), entrytable, FALSE, FALSE, 0 );
gtk_widget_show( entrytable );
separator = gtk_hseparator_new();
gtk_box_pack_start( GTK_BOX( vbox ), separator, FALSE, FALSE, 0 );
gtk_widget_show( entrytable );
frame = gtk_frame_new( "Outside Type" );
gtk_container_border_width( GTK_CONTAINER( frame ), 5 );
gtk_box_pack_start( GTK_BOX( vbox ), frame, TRUE, TRUE, 0 );
gtk_widget_show( frame );
framebox = gtk_vbox_new( FALSE, 0 );
gtk_container_border_width( GTK_CONTAINER( framebox ), 5 );
gtk_container_add( GTK_CONTAINER( frame ), framebox );
gtk_widget_show( framebox );
group = NULL;
button = gtk_radio_button_new_with_label( group, "Wrap" );
gtk_box_pack_start( GTK_BOX( framebox ), button, FALSE, FALSE, 0 );
gtk_signal_connect( GTK_OBJECT( button ), "toggled",
GTK_SIGNAL_FUNC( dialog_outside_type_callback ),
&outside_type.wrap );
gtk_widget_show( button );
if( parameters.outside_type == OUTSIDE_TYPE_WRAP ){
gtk_toggle_button_toggled( GTK_TOGGLE_BUTTON( button ) );
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), TRUE );
}
group = gtk_radio_button_group( GTK_RADIO_BUTTON( button ) );
button = gtk_radio_button_new_with_label( group, "Transparent" );
gtk_box_pack_start( GTK_BOX( framebox ), button, FALSE, FALSE, 0 );
gtk_signal_connect( GTK_OBJECT( button ), "toggled",
GTK_SIGNAL_FUNC( dialog_outside_type_callback ),
&outside_type.transparent );
gtk_widget_show( button );
if( parameters.outside_type == OUTSIDE_TYPE_TRANSPARENT ){
gtk_toggle_button_toggled( GTK_TOGGLE_BUTTON( button ) );
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), TRUE );
}
if( !image.alpha ){
gtk_widget_set_sensitive( button, FALSE );
}
group = gtk_radio_button_group( GTK_RADIO_BUTTON( button ) );
button = gtk_radio_button_new_with_label( group, "Black" );
gtk_box_pack_start( GTK_BOX( framebox ), button, FALSE, FALSE, 0 );
gtk_signal_connect( GTK_OBJECT( button ), "toggled",
GTK_SIGNAL_FUNC( dialog_outside_type_callback ),
&outside_type.black );
gtk_widget_show( button );
if( parameters.outside_type == OUTSIDE_TYPE_BLACK ){
gtk_toggle_button_toggled( GTK_TOGGLE_BUTTON( button ) );
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), TRUE );
}
group = gtk_radio_button_group( GTK_RADIO_BUTTON( button ) );
button = gtk_radio_button_new_with_label( group, "White" );
gtk_box_pack_start( GTK_BOX( framebox ), button, FALSE, FALSE, 0 );
gtk_signal_connect( GTK_OBJECT( button ), "toggled",
GTK_SIGNAL_FUNC( dialog_outside_type_callback ),
&outside_type.white );
gtk_widget_show( button );
if( parameters.outside_type == OUTSIDE_TYPE_WHITE ){
gtk_toggle_button_toggled( GTK_TOGGLE_BUTTON( button ) );
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), TRUE );
}
group = gtk_radio_button_group( GTK_RADIO_BUTTON( button ) );
}
gtk_widget_show( dialog );
dialog_preview_draw();
gtk_main();
return dialog_status;
}
/******************************************************************************/

View file

@ -1,6 +0,0 @@
Makefile.in
Makefile
.deps
_libs
.libs
gauss_iir

Some files were not shown because too many files have changed in this diff Show more