Plugin updates Properly generated aa Makefile (still not built by default)

Plugin updates
Properly generated aa Makefile (still not built by default)
Sven's no args script patch

-Yosh
This commit is contained in:
Manish Singh 1998-01-25 09:29:29 +00:00
parent c56e1b18e7
commit 4cebd76133
26 changed files with 1577 additions and 922 deletions

View File

@ -1,3 +1,13 @@
Sun Jan 25 01:25:55 PST 1998 Manish Singh <yosh@gimp.org>
* plugin updates from the registry (align_layers,
despeckle, mathmap, print)
* plug-ins/script-fu/script-fu-scripts.c
* plug-ins/script-fu/scripts/copy-visible.scm:
Applied Sven's no arguments script patch and copy-visible
fix
Sun Jan 25 00:12:15 EST 1998 Adrian Likins <adrian@gimp.org>
* added plug-ins/script-fu-scripts/chip-away.scm

View File

@ -2,10 +2,9 @@
pluginlibdir = $(gimpplugindir)/plug-ins
pluginlib_PROGRAMS = #STD#
pluginlib_PROGRAMS = aa
#STD#_SOURCES = \
#STD#.c
aa_SOURCES = aa.c
INCLUDES = \
$(X_CFLAGS) \
@ -16,6 +15,7 @@ LDADD = \
$(top_builddir)/libgimp/libgimpui.la \
$(top_builddir)/libgimp/libgimp.la \
$(X_LIBS) \
-laa \
-lc
DEPS = \

View File

@ -7,5 +7,4 @@ So dont send us or Tim newsome bug reports about this yet.
ftp://ftp.ta.jcu.cz/pub/aa
NOTE: You need aalib version 1.1.6 for this plugin.

View File

@ -1,9 +1,9 @@
/* align_layers.c -- This is a plug-in for the GIMP (1.0's API)
* Author: Shuji Narazaki <narazaki@InetQ.or.jp>
* Time-stamp: <1997/10/23 23:44:11 narazaki@InetQ.or.jp>
* Version: 0.25
* Time-stamp: <1998/01/17 00:32:23 narazaki@InetQ.or.jp>
* Version: 0.26
*
* Copyright (C) 1997 Shuji Narazaki <narazaki@InetQ.or.jp>
* Copyright (C) 1997-1998 Shuji Narazaki <narazaki@InetQ.or.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
@ -220,7 +220,7 @@ query ()
gimp_install_procedure (PLUG_IN_NAME,
"Align visible layers",
"align visible layers",
"Shuji Narazaki (narazaki@InetQ.or.jp)",
"Shuji Narazaki <narazaki@InetQ.or.jp>",
"Shuji Narazaki",
"1997",
MENU_POSITION,
@ -285,6 +285,8 @@ run (char *name,
static GStatusType
align_layers (gint32 image_id)
{
GParam* return_vals;
gint retvals;
gint layer_num = 0;
gint visible_layer_num = 1;
gint *layers = NULL;
@ -361,6 +363,12 @@ align_layers (gint32 image_id)
base_y = min_y;
}
return_vals = gimp_run_procedure ("gimp_undo_push_group_start",
&retvals,
PARAM_IMAGE, image_id,
PARAM_END);
gimp_destroy_params (return_vals, retvals);
for (vindex = -1, index = 0; index < layer_num; index++)
{
if (gimp_layer_get_visible (layers[index]))
@ -413,10 +421,14 @@ align_layers (gint32 image_id)
}
gimp_layer_set_offsets (layers[index], x, y);
}
return_vals = gimp_run_procedure ("gimp_undo_push_group_end",
&retvals,
PARAM_IMAGE, image_id,
PARAM_END);
gimp_destroy_params (return_vals, retvals);
return STATUS_SUCCESS;
}
static void
align_layers_get_align_offsets (gint32 drawable_id,
gint *x,

View File

@ -1,9 +1,9 @@
/* align_layers.c -- This is a plug-in for the GIMP (1.0's API)
* Author: Shuji Narazaki <narazaki@InetQ.or.jp>
* Time-stamp: <1997/10/23 23:44:11 narazaki@InetQ.or.jp>
* Version: 0.25
* Time-stamp: <1998/01/17 00:32:23 narazaki@InetQ.or.jp>
* Version: 0.26
*
* Copyright (C) 1997 Shuji Narazaki <narazaki@InetQ.or.jp>
* Copyright (C) 1997-1998 Shuji Narazaki <narazaki@InetQ.or.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
@ -220,7 +220,7 @@ query ()
gimp_install_procedure (PLUG_IN_NAME,
"Align visible layers",
"align visible layers",
"Shuji Narazaki (narazaki@InetQ.or.jp)",
"Shuji Narazaki <narazaki@InetQ.or.jp>",
"Shuji Narazaki",
"1997",
MENU_POSITION,
@ -285,6 +285,8 @@ run (char *name,
static GStatusType
align_layers (gint32 image_id)
{
GParam* return_vals;
gint retvals;
gint layer_num = 0;
gint visible_layer_num = 1;
gint *layers = NULL;
@ -361,6 +363,12 @@ align_layers (gint32 image_id)
base_y = min_y;
}
return_vals = gimp_run_procedure ("gimp_undo_push_group_start",
&retvals,
PARAM_IMAGE, image_id,
PARAM_END);
gimp_destroy_params (return_vals, retvals);
for (vindex = -1, index = 0; index < layer_num; index++)
{
if (gimp_layer_get_visible (layers[index]))
@ -413,10 +421,14 @@ align_layers (gint32 image_id)
}
gimp_layer_set_offsets (layers[index], x, y);
}
return_vals = gimp_run_procedure ("gimp_undo_push_group_end",
&retvals,
PARAM_IMAGE, image_id,
PARAM_END);
gimp_destroy_params (return_vals, retvals);
return STATUS_SUCCESS;
}
static void
align_layers_get_align_offsets (gint32 drawable_id,
gint *x,

View File

@ -4,8 +4,7 @@
* Despeckle (adaptive median) filter for The GIMP -- an image manipulation
* program
*
* Copyright 1997 Michael Sweet. This code is based off Quartic's bumpmap
* filter and the median filter (described in most image processing books...)
* Copyright 1997-1998 Michael Sweet (mike@easysw.com)
*
* 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
@ -44,23 +43,20 @@
* Revision History:
*
* $Log$
* Revision 1.4 1998/01/25 02:18:21 yosh
* Applied Sven's menu patch
* Revision 1.5 1998/01/25 09:29:23 yosh
* Plugin updates
* Properly generated aa Makefile (still not built by default)
* Sven's no args script patch
*
* -Yosh
*
* Revision 1.3 1998/01/04 19:20:55 scott
* * plug-ins/despeckle/despeckle.c: realloc buffers when the radius
* of effect changes; save all values (not just radius) in plugin
* data store; adjusted parameter handling to match PDB registration.
* The algorithm still generates artifacts in the top rows of the
* image. --sg
* #
* Revision 1.16 1998/01/22 14:35:03 mike
* Added black & white level controls.
* Fixed bug in despeckle code that caused the borders to darken.
*
* Revision 1.2 1997/12/09 05:57:27 adrian
* added glasstile, colorify, papertile, and illusion plugins
*
* updated despeckle, and math map
* Revision 1.15 1998/01/21 21:33:47 mike
* Fixed malloc buffer overflow bug - wasn't realloc'ing buffers
* when the filter radius changed.
*
* Revision 1.14 1997/11/14 17:17:59 mike
* Updated to dynamically allocate return params in the run() function.
@ -136,7 +132,7 @@
*/
#define PLUG_IN_NAME "plug_in_despeckle"
#define PLUG_IN_VERSION "1.1.3 - 14 November 1997"
#define PLUG_IN_VERSION "1.2 - 22 January 1998"
#define PREVIEW_SIZE 128
#define SCALE_WIDTH 64
#define ENTRY_WIDTH 64
@ -145,11 +141,10 @@
#define FILTER_ADAPTIVE 0x01
#define FILTER_RECURSIVE 0x02
typedef struct _despeckle_values
{
int radius;
int filter_type;
} DespeckleVals;
#define despeckle_radius (despeckle_vals[0]) /* Radius of filter */
#define filter_type (despeckle_vals[1]) /* Type of filter */
#define black_level (despeckle_vals[2]) /* Black level */
#define white_level (despeckle_vals[3]) /* White level */
/*
* Local functions...
@ -193,8 +188,7 @@ int preview_width, /* Width of preview widget */
preview_y1, /* Upper-left Y of preview */
preview_x2, /* Lower-right X of preview */
preview_y2; /* Lower-right Y of preview */
int preview_buf_size; /* Allocated buffer size */
guchar *preview_src, /* Source pixel rows */
guchar *preview_src = NULL, /* Source pixel rows */
*preview_dst, /* Destination pixel row */
*preview_sort; /* Pixel value sort array */
GtkObject *hscroll_data, /* Horizontal scrollbar data */
@ -209,11 +203,8 @@ int sel_width, /* Selection width */
sel_height; /* Selection height */
int img_bpp; /* Bytes-per-pixel in image */
gint run_filter = FALSE; /* True if we should run the filter */
DespeckleVals despeckle_vals =
{
3, /* Radius of median filter box */
FILTER_ADAPTIVE /* Type of filter */
};
int despeckle_vals[4] = { 3, FILTER_ADAPTIVE, 7, 248 };
/*
* 'main()' - Main entry - just call gimp_main()...
@ -240,7 +231,9 @@ query(void)
{ PARAM_IMAGE, "image", "Input image" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_INT32, "radius", "Filter box radius (default = 3)" },
{ PARAM_INT32, "type", "Filter type (0 = median, 1 = adaptive, 2 = recursive-median, 3 = recursive-adaptive)" }
{ PARAM_INT32, "type", "Filter type (0 = median, 1 = adaptive, 2 = recursive-median, 3 = recursive-adaptive)" },
{ PARAM_INT32, "black", "Black level (0 to 255)" },
{ PARAM_INT32, "white", "White level (0 to 255)" }
};
static GParamDef *return_vals = NULL;
static int nargs = sizeof(args) / sizeof(args[0]),
@ -312,7 +305,7 @@ run(char *name, /* I - Name of filter program. */
* Possibly retrieve data...
*/
gimp_get_data(PLUG_IN_NAME, &despeckle_vals);
gimp_get_data(PLUG_IN_NAME, &despeckle_radius);
/*
* Get information from the dialog...
@ -327,13 +320,36 @@ run(char *name, /* I - Name of filter program. */
* Make sure all the arguments are present...
*/
if (nparams != 5)
if (nparams < 4 || nparams > 7)
status = STATUS_CALLING_ERROR;
else
{
despeckle_vals.radius = param[3].data.d_int32;
despeckle_vals.filter_type = param[4].data.d_int32;
}
else if (nparams == 4)
{
despeckle_radius = param[3].data.d_int32;
filter_type = FILTER_ADAPTIVE;
black_level = 7;
white_level = 248;
}
else if (nparams == 5)
{
despeckle_radius = param[3].data.d_int32;
filter_type = param[4].data.d_int32;
black_level = 7;
white_level = 248;
}
else if (nparams == 6)
{
despeckle_radius = param[3].data.d_int32;
filter_type = param[4].data.d_int32;
black_level = param[5].data.d_int32;
white_level = 248;
}
else
{
despeckle_radius = param[3].data.d_int32;
filter_type = param[4].data.d_int32;
black_level = param[5].data.d_int32;
white_level = param[6].data.d_int32;
};
break;
case RUN_WITH_LAST_VALS :
@ -341,7 +357,7 @@ run(char *name, /* I - Name of filter program. */
* Possibly retrieve data...
*/
gimp_get_data(PLUG_IN_NAME, &despeckle_vals);
gimp_get_data(PLUG_IN_NAME, despeckle_vals);
break;
default :
@ -383,7 +399,7 @@ run(char *name, /* I - Name of filter program. */
*/
if (run_mode == RUN_INTERACTIVE)
gimp_set_data(PLUG_IN_NAME, &despeckle_vals, sizeof(despeckle_vals));
gimp_set_data(PLUG_IN_NAME, despeckle_vals, sizeof(despeckle_vals));
}
else
status = STATUS_EXECUTION_ERROR;
@ -456,7 +472,7 @@ despeckle(void)
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);
size = despeckle_vals.radius * 2 + 1;
size = despeckle_radius * 2 + 1;
max_row = 2 * gimp_tile_height();
width = sel_width * img_bpp;
@ -490,7 +506,7 @@ despeckle(void)
for (y = sel_y1 ; y < sel_y2; y ++)
{
if ((y + despeckle_vals.radius) >= lasty &&
if ((y + despeckle_radius) >= lasty &&
lasty < sel_y2)
{
/*
@ -512,86 +528,97 @@ despeckle(void)
* Now find the median pixels and save the results...
*/
radius = despeckle_vals.radius;
radius = despeckle_radius;
for (x = 0; x < width; x ++)
memcpy(dst_row, src_rows[(row + y - lasty + max_row) % max_row], width);
if (y >= (sel_y1 + radius) && y < (sel_y2 - radius))
{
hist0 = 0;
hist255 = 0;
xmin = x - radius * img_bpp;
xmax = x + (radius + 1) * img_bpp;
for (x = 0; x < width; x ++)
{
hist0 = 0;
hist255 = 0;
xmin = x - radius * img_bpp;
xmax = x + (radius + 1) * img_bpp;
if (xmin < 0)
xmin = x % img_bpp;
if (xmin < 0)
xmin = x % img_bpp;
if (xmax > width)
xmax = width;
if (xmax > width)
xmax = width;
startrow = (row + y - lasty - radius + max_row) % max_row;
endrow = (row + y - lasty + radius + 1 + max_row) % max_row;
startrow = (row + y - lasty - radius + max_row) % max_row;
endrow = (row + y - lasty + radius + 1 + max_row) % max_row;
for (sort_ptr = sort, trow = startrow;
trow != endrow;
trow = (trow + 1) % max_row)
for (tx = xmin, src_ptr = src_rows[trow] + xmin;
tx < xmax;
tx += img_bpp, sort_ptr ++, src_ptr += img_bpp)
for (sort_ptr = sort, trow = startrow;
trow != endrow;
trow = (trow + 1) % max_row)
for (tx = xmin, src_ptr = src_rows[trow] + xmin;
tx < xmax;
tx += img_bpp, src_ptr += img_bpp)
{
if ((*sort_ptr = *src_ptr) <= black_level)
hist0 ++;
else if (*sort_ptr >= white_level)
hist255 ++;
if (*sort_ptr < white_level)
sort_ptr ++;
};
/*
* Shell sort the color values...
*/
sort_count = sort_ptr - sort;
if (sort_count > 1)
{
if ((*sort_ptr = *src_ptr) == 0)
hist0 ++;
else if (*sort_ptr == 255)
hist255 ++;
for (d = sort_count / 2; d > 0; d = d / 2)
for (i = d; i < sort_count; i ++)
for (j = i - d, sort_ptr = sort + j;
j >= 0 && sort_ptr[0] > sort_ptr[d];
j -= d, sort_ptr -= d)
{
t = sort_ptr[0];
sort_ptr[0] = sort_ptr[d];
sort_ptr[d] = t;
};
/*
* Assign the median value...
*/
t = sort_count / 2;
if (sort_count & 1)
dst_row[x] = (sort[t] + sort[t + 1]) / 2;
else
dst_row[x] = sort[t];
/*
* Save the change to the source image too if the user wants the
* recursive method...
*/
if (filter_type & FILTER_RECURSIVE)
src_rows[(row + y - lasty + max_row) % max_row][x] = dst_row[x];
};
/*
* Shell sort the color values...
*/
/*
* Check the histogram and adjust the radius accordingly...
*/
sort_count = sort_ptr - sort;
for (d = sort_count / 2; d > 0; d = d / 2)
for (i = d; i < sort_count; i ++)
for (j = i - d, sort_ptr = sort + j;
j >= 0 && sort_ptr[0] > sort_ptr[d];
j -= d, sort_ptr -= d)
{
t = sort_ptr[0];
sort_ptr[0] = sort_ptr[d];
sort_ptr[d] = t;
};
/*
* Assign the median value...
*/
t = sort_count / 2;
if (sort_count & 1)
dst_row[x] = (sort[t] + sort[t + 1]) / 2;
else
dst_row[x] = sort[t];
/*
* Save the change to the source image too if the user wants the
* recursive method...
*/
if (despeckle_vals.filter_type & FILTER_RECURSIVE)
src_rows[(row + y - lasty + max_row) % max_row][x] = dst_row[x];
/*
* Check the histogram and adjust the radius accordingly...
*/
if (despeckle_vals.filter_type & FILTER_ADAPTIVE)
{
if (hist0 >= radius || hist255 >= radius)
if (filter_type & FILTER_ADAPTIVE)
{
if (radius < despeckle_vals.radius)
radius ++;
}
else if (radius > 1)
radius --;
if (hist0 >= radius || hist255 >= radius)
{
if (radius < despeckle_radius)
radius ++;
}
else if (radius > 1)
radius --;
};
};
};
@ -666,7 +693,7 @@ despeckle_dialog(void)
*/
dialog = gtk_dialog_new();
gtk_window_set_title(GTK_WINDOW(dialog), "Despeckle");
gtk_window_set_title(GTK_WINDOW(dialog), "Despeckle " PLUG_IN_VERSION);
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",
@ -677,7 +704,7 @@ despeckle_dialog(void)
* Top-level table for dialog...
*/
table = gtk_table_new(3, 3, FALSE);
table = gtk_table_new(5, 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);
@ -731,11 +758,16 @@ despeckle_dialog(void)
preview_init();
preview_x1 = sel_x1;
preview_y1 = sel_y1;
preview_x2 = preview_x1 + MIN(preview_width, sel_width);
preview_y2 = preview_y1 + MIN(preview_height, sel_height);
/*
* Filter type controls...
*/
ftable = gtk_table_new(4, 1, FALSE);
ftable = gtk_table_new(6, 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);
@ -744,7 +776,7 @@ despeckle_dialog(void)
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_state(GTK_TOGGLE_BUTTON(button),
(despeckle_vals.filter_type & FILTER_ADAPTIVE) ? TRUE : FALSE);
(filter_type & FILTER_ADAPTIVE) ? TRUE : FALSE);
gtk_signal_connect(GTK_OBJECT(button), "toggled",
(GtkSignalFunc)dialog_adaptive_callback,
NULL);
@ -754,7 +786,7 @@ despeckle_dialog(void)
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_state(GTK_TOGGLE_BUTTON(button),
(despeckle_vals.filter_type & FILTER_RECURSIVE) ? TRUE : FALSE);
(filter_type & FILTER_RECURSIVE) ? TRUE : FALSE);
gtk_signal_connect(GTK_OBJECT(button), "toggled",
(GtkSignalFunc)dialog_recursive_callback,
NULL);
@ -764,7 +796,19 @@ despeckle_dialog(void)
* Box size (radius) control...
*/
dialog_create_ivalue("Radius", GTK_TABLE(table), 2, &despeckle_vals.radius, 1, MAX_RADIUS);
dialog_create_ivalue("Radius", GTK_TABLE(table), 2, &despeckle_radius, 1, MAX_RADIUS);
/*
* Black level control...
*/
dialog_create_ivalue("Black Level", GTK_TABLE(table), 3, &black_level, 0, 256);
/*
* White level control...
*/
dialog_create_ivalue("White Level", GTK_TABLE(table), 4, &white_level, 0, 256);
/*
* OK, cancel buttons...
@ -821,7 +865,7 @@ despeckle_dialog(void)
static void
preview_init(void)
{
int size, /* Size of filter box */
int size, /* Size of filter box */
width; /* Byte width of the image */
@ -829,17 +873,19 @@ preview_init(void)
* Setup for preview filter...
*/
preview_buf_size = size = despeckle_vals.radius * 2 + 1;
size = despeckle_radius * 2 + 1;
width = preview_width * img_bpp;
if (preview_src != NULL)
{
g_free(preview_src);
g_free(preview_dst);
g_free(preview_sort);
};
preview_src = g_malloc(width * preview_height * sizeof(guchar *));
preview_dst = g_malloc(width * sizeof(guchar));
preview_sort = g_malloc(size * size * sizeof(guchar));
preview_x1 = sel_x1;
preview_y1 = sel_y1;
preview_x2 = preview_x1 + MIN(preview_width, sel_width);
preview_y2 = preview_y1 + MIN(preview_height, sel_height);
}
@ -893,19 +939,9 @@ preview_update(void)
* Pre-load the preview rectangle...
*/
size = despeckle_vals.radius * 2 + 1;
size = despeckle_radius * 2 + 1;
width = preview_width * img_bpp;
if (size != preview_buf_size)
{
preview_src = g_realloc(preview_src,
width * preview_height * sizeof(guchar *));
preview_dst = g_realloc(preview_dst,
width * sizeof(guchar));
preview_sort = g_realloc(preview_sort,
size * size * sizeof(guchar));
}
gimp_pixel_rgn_get_rect(&src_rgn, preview_src, preview_x1, preview_y1,
preview_width, preview_height);
@ -919,11 +955,11 @@ preview_update(void)
* Now find the median pixels and save the results...
*/
radius = despeckle_vals.radius;
radius = despeckle_radius;
if (y < radius || y >= (preview_height - radius))
memcpy(preview_dst, preview_src + y * width, width);
else
memcpy(preview_dst, preview_src + y * width, width);
if (y >= radius && y < (preview_height - radius))
{
for (x = 0, dst_ptr = preview_dst; x < width; x ++, dst_ptr ++)
{
@ -942,12 +978,15 @@ preview_update(void)
src_ptr = preview_src + width * (y - radius);
i <= radius;
i ++, src_ptr += width)
for (tx = xmin; tx < xmax; tx += img_bpp, sort_ptr ++)
for (tx = xmin; tx < xmax; tx += img_bpp)
{
if ((*sort_ptr = src_ptr[tx]) == 0)
if ((*sort_ptr = src_ptr[tx]) <= black_level)
hist0 ++;
else if (*sort_ptr == 255)
else if (*sort_ptr >= white_level)
hist255 ++;
if (*sort_ptr < white_level)
sort_ptr ++;
};
/*
@ -956,45 +995,48 @@ preview_update(void)
sort_count = sort_ptr - preview_sort;
for (d = sort_count / 2; d > 0; d = d / 2)
for (i = d; i < sort_count; i ++)
for (j = i - d, sort_ptr = preview_sort + j;
j >= 0 && sort_ptr[0] > sort_ptr[d];
j -= d, sort_ptr -= d)
{
t = sort_ptr[0];
sort_ptr[0] = sort_ptr[d];
sort_ptr[d] = t;
};
if (sort_count > 1)
{
for (d = sort_count / 2; d > 0; d = d / 2)
for (i = d; i < sort_count; i ++)
for (j = i - d, sort_ptr = preview_sort + j;
j >= 0 && sort_ptr[0] > sort_ptr[d];
j -= d, sort_ptr -= d)
{
t = sort_ptr[0];
sort_ptr[0] = sort_ptr[d];
sort_ptr[d] = t;
};
/*
* Assign the median value...
*/
/*
* Assign the median value...
*/
t = sort_count / 2;
t = sort_count / 2;
if (sort_count & 1)
*dst_ptr = (preview_sort[t] + preview_sort[t + 1]) / 2;
else
*dst_ptr = preview_sort[t];
if (sort_count & 1)
*dst_ptr = (preview_sort[t] + preview_sort[t + 1]) / 2;
else
*dst_ptr = preview_sort[t];
/*
* Save the change to the source image too if the user wants the
* recursive method...
*/
/*
* Save the change to the source image too if the user wants the
* recursive method...
*/
if (despeckle_vals.filter_type & FILTER_RECURSIVE)
preview_src[y * width + x] = *dst_ptr;
if (filter_type & FILTER_RECURSIVE)
preview_src[y * width + x] = *dst_ptr;
};
/*
* Check the histogram and adjust the radius accordingly...
*/
if (despeckle_vals.filter_type & FILTER_ADAPTIVE)
if (filter_type & FILTER_ADAPTIVE)
{
if (hist0 >= radius || hist255 >= radius)
{
if (radius < despeckle_vals.radius)
if (radius < despeckle_radius)
radius ++;
}
else if (radius > 1)
@ -1051,7 +1093,8 @@ preview_update(void)
static void
preview_exit(void)
{
int size; /* Size of row buffer */
int row, /* Looping var */
size; /* Size of row buffer */
size = MAX_RADIUS * 2 + 1;
@ -1148,6 +1191,9 @@ dialog_iscale_update(GtkAdjustment *adjustment, /* I - New value */
gtk_entry_set_text(GTK_ENTRY(entry), buf);
gtk_signal_handler_unblock_by_data(GTK_OBJECT(entry), value);
if (value == &despeckle_radius)
preview_init();
preview_update();
};
}
@ -1179,6 +1225,9 @@ dialog_ientry_update(GtkWidget *widget, /* I - Entry widget */
gtk_signal_emit_by_name(GTK_OBJECT(adjustment), "value_changed");
if (value == &despeckle_radius)
preview_init();
preview_update();
};
};
@ -1194,9 +1243,9 @@ dialog_adaptive_callback(GtkWidget *widget, /* I - Toggle button */
gpointer data) /* I - Data */
{
if (GTK_TOGGLE_BUTTON(widget)->active)
despeckle_vals.filter_type |= FILTER_ADAPTIVE;
filter_type |= FILTER_ADAPTIVE;
else
despeckle_vals.filter_type &= ~FILTER_ADAPTIVE;
filter_type &= ~FILTER_ADAPTIVE;
preview_update();
}
@ -1211,9 +1260,9 @@ dialog_recursive_callback(GtkWidget *widget, /* I - Toggle button */
gpointer data) /* I - Data */
{
if (GTK_TOGGLE_BUTTON(widget)->active)
despeckle_vals.filter_type |= FILTER_RECURSIVE;
filter_type |= FILTER_RECURSIVE;
else
despeckle_vals.filter_type &= ~FILTER_RECURSIVE;
filter_type &= ~FILTER_RECURSIVE;
preview_update();
}

View File

@ -4,8 +4,7 @@
* Despeckle (adaptive median) filter for The GIMP -- an image manipulation
* program
*
* Copyright 1997 Michael Sweet. This code is based off Quartic's bumpmap
* filter and the median filter (described in most image processing books...)
* Copyright 1997-1998 Michael Sweet (mike@easysw.com)
*
* 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
@ -44,23 +43,20 @@
* Revision History:
*
* $Log$
* Revision 1.4 1998/01/25 02:18:21 yosh
* Applied Sven's menu patch
* Revision 1.5 1998/01/25 09:29:23 yosh
* Plugin updates
* Properly generated aa Makefile (still not built by default)
* Sven's no args script patch
*
* -Yosh
*
* Revision 1.3 1998/01/04 19:20:55 scott
* * plug-ins/despeckle/despeckle.c: realloc buffers when the radius
* of effect changes; save all values (not just radius) in plugin
* data store; adjusted parameter handling to match PDB registration.
* The algorithm still generates artifacts in the top rows of the
* image. --sg
* #
* Revision 1.16 1998/01/22 14:35:03 mike
* Added black & white level controls.
* Fixed bug in despeckle code that caused the borders to darken.
*
* Revision 1.2 1997/12/09 05:57:27 adrian
* added glasstile, colorify, papertile, and illusion plugins
*
* updated despeckle, and math map
* Revision 1.15 1998/01/21 21:33:47 mike
* Fixed malloc buffer overflow bug - wasn't realloc'ing buffers
* when the filter radius changed.
*
* Revision 1.14 1997/11/14 17:17:59 mike
* Updated to dynamically allocate return params in the run() function.
@ -136,7 +132,7 @@
*/
#define PLUG_IN_NAME "plug_in_despeckle"
#define PLUG_IN_VERSION "1.1.3 - 14 November 1997"
#define PLUG_IN_VERSION "1.2 - 22 January 1998"
#define PREVIEW_SIZE 128
#define SCALE_WIDTH 64
#define ENTRY_WIDTH 64
@ -145,11 +141,10 @@
#define FILTER_ADAPTIVE 0x01
#define FILTER_RECURSIVE 0x02
typedef struct _despeckle_values
{
int radius;
int filter_type;
} DespeckleVals;
#define despeckle_radius (despeckle_vals[0]) /* Radius of filter */
#define filter_type (despeckle_vals[1]) /* Type of filter */
#define black_level (despeckle_vals[2]) /* Black level */
#define white_level (despeckle_vals[3]) /* White level */
/*
* Local functions...
@ -193,8 +188,7 @@ int preview_width, /* Width of preview widget */
preview_y1, /* Upper-left Y of preview */
preview_x2, /* Lower-right X of preview */
preview_y2; /* Lower-right Y of preview */
int preview_buf_size; /* Allocated buffer size */
guchar *preview_src, /* Source pixel rows */
guchar *preview_src = NULL, /* Source pixel rows */
*preview_dst, /* Destination pixel row */
*preview_sort; /* Pixel value sort array */
GtkObject *hscroll_data, /* Horizontal scrollbar data */
@ -209,11 +203,8 @@ int sel_width, /* Selection width */
sel_height; /* Selection height */
int img_bpp; /* Bytes-per-pixel in image */
gint run_filter = FALSE; /* True if we should run the filter */
DespeckleVals despeckle_vals =
{
3, /* Radius of median filter box */
FILTER_ADAPTIVE /* Type of filter */
};
int despeckle_vals[4] = { 3, FILTER_ADAPTIVE, 7, 248 };
/*
* 'main()' - Main entry - just call gimp_main()...
@ -240,7 +231,9 @@ query(void)
{ PARAM_IMAGE, "image", "Input image" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_INT32, "radius", "Filter box radius (default = 3)" },
{ PARAM_INT32, "type", "Filter type (0 = median, 1 = adaptive, 2 = recursive-median, 3 = recursive-adaptive)" }
{ PARAM_INT32, "type", "Filter type (0 = median, 1 = adaptive, 2 = recursive-median, 3 = recursive-adaptive)" },
{ PARAM_INT32, "black", "Black level (0 to 255)" },
{ PARAM_INT32, "white", "White level (0 to 255)" }
};
static GParamDef *return_vals = NULL;
static int nargs = sizeof(args) / sizeof(args[0]),
@ -312,7 +305,7 @@ run(char *name, /* I - Name of filter program. */
* Possibly retrieve data...
*/
gimp_get_data(PLUG_IN_NAME, &despeckle_vals);
gimp_get_data(PLUG_IN_NAME, &despeckle_radius);
/*
* Get information from the dialog...
@ -327,13 +320,36 @@ run(char *name, /* I - Name of filter program. */
* Make sure all the arguments are present...
*/
if (nparams != 5)
if (nparams < 4 || nparams > 7)
status = STATUS_CALLING_ERROR;
else
{
despeckle_vals.radius = param[3].data.d_int32;
despeckle_vals.filter_type = param[4].data.d_int32;
}
else if (nparams == 4)
{
despeckle_radius = param[3].data.d_int32;
filter_type = FILTER_ADAPTIVE;
black_level = 7;
white_level = 248;
}
else if (nparams == 5)
{
despeckle_radius = param[3].data.d_int32;
filter_type = param[4].data.d_int32;
black_level = 7;
white_level = 248;
}
else if (nparams == 6)
{
despeckle_radius = param[3].data.d_int32;
filter_type = param[4].data.d_int32;
black_level = param[5].data.d_int32;
white_level = 248;
}
else
{
despeckle_radius = param[3].data.d_int32;
filter_type = param[4].data.d_int32;
black_level = param[5].data.d_int32;
white_level = param[6].data.d_int32;
};
break;
case RUN_WITH_LAST_VALS :
@ -341,7 +357,7 @@ run(char *name, /* I - Name of filter program. */
* Possibly retrieve data...
*/
gimp_get_data(PLUG_IN_NAME, &despeckle_vals);
gimp_get_data(PLUG_IN_NAME, despeckle_vals);
break;
default :
@ -383,7 +399,7 @@ run(char *name, /* I - Name of filter program. */
*/
if (run_mode == RUN_INTERACTIVE)
gimp_set_data(PLUG_IN_NAME, &despeckle_vals, sizeof(despeckle_vals));
gimp_set_data(PLUG_IN_NAME, despeckle_vals, sizeof(despeckle_vals));
}
else
status = STATUS_EXECUTION_ERROR;
@ -456,7 +472,7 @@ despeckle(void)
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);
size = despeckle_vals.radius * 2 + 1;
size = despeckle_radius * 2 + 1;
max_row = 2 * gimp_tile_height();
width = sel_width * img_bpp;
@ -490,7 +506,7 @@ despeckle(void)
for (y = sel_y1 ; y < sel_y2; y ++)
{
if ((y + despeckle_vals.radius) >= lasty &&
if ((y + despeckle_radius) >= lasty &&
lasty < sel_y2)
{
/*
@ -512,86 +528,97 @@ despeckle(void)
* Now find the median pixels and save the results...
*/
radius = despeckle_vals.radius;
radius = despeckle_radius;
for (x = 0; x < width; x ++)
memcpy(dst_row, src_rows[(row + y - lasty + max_row) % max_row], width);
if (y >= (sel_y1 + radius) && y < (sel_y2 - radius))
{
hist0 = 0;
hist255 = 0;
xmin = x - radius * img_bpp;
xmax = x + (radius + 1) * img_bpp;
for (x = 0; x < width; x ++)
{
hist0 = 0;
hist255 = 0;
xmin = x - radius * img_bpp;
xmax = x + (radius + 1) * img_bpp;
if (xmin < 0)
xmin = x % img_bpp;
if (xmin < 0)
xmin = x % img_bpp;
if (xmax > width)
xmax = width;
if (xmax > width)
xmax = width;
startrow = (row + y - lasty - radius + max_row) % max_row;
endrow = (row + y - lasty + radius + 1 + max_row) % max_row;
startrow = (row + y - lasty - radius + max_row) % max_row;
endrow = (row + y - lasty + radius + 1 + max_row) % max_row;
for (sort_ptr = sort, trow = startrow;
trow != endrow;
trow = (trow + 1) % max_row)
for (tx = xmin, src_ptr = src_rows[trow] + xmin;
tx < xmax;
tx += img_bpp, sort_ptr ++, src_ptr += img_bpp)
for (sort_ptr = sort, trow = startrow;
trow != endrow;
trow = (trow + 1) % max_row)
for (tx = xmin, src_ptr = src_rows[trow] + xmin;
tx < xmax;
tx += img_bpp, src_ptr += img_bpp)
{
if ((*sort_ptr = *src_ptr) <= black_level)
hist0 ++;
else if (*sort_ptr >= white_level)
hist255 ++;
if (*sort_ptr < white_level)
sort_ptr ++;
};
/*
* Shell sort the color values...
*/
sort_count = sort_ptr - sort;
if (sort_count > 1)
{
if ((*sort_ptr = *src_ptr) == 0)
hist0 ++;
else if (*sort_ptr == 255)
hist255 ++;
for (d = sort_count / 2; d > 0; d = d / 2)
for (i = d; i < sort_count; i ++)
for (j = i - d, sort_ptr = sort + j;
j >= 0 && sort_ptr[0] > sort_ptr[d];
j -= d, sort_ptr -= d)
{
t = sort_ptr[0];
sort_ptr[0] = sort_ptr[d];
sort_ptr[d] = t;
};
/*
* Assign the median value...
*/
t = sort_count / 2;
if (sort_count & 1)
dst_row[x] = (sort[t] + sort[t + 1]) / 2;
else
dst_row[x] = sort[t];
/*
* Save the change to the source image too if the user wants the
* recursive method...
*/
if (filter_type & FILTER_RECURSIVE)
src_rows[(row + y - lasty + max_row) % max_row][x] = dst_row[x];
};
/*
* Shell sort the color values...
*/
/*
* Check the histogram and adjust the radius accordingly...
*/
sort_count = sort_ptr - sort;
for (d = sort_count / 2; d > 0; d = d / 2)
for (i = d; i < sort_count; i ++)
for (j = i - d, sort_ptr = sort + j;
j >= 0 && sort_ptr[0] > sort_ptr[d];
j -= d, sort_ptr -= d)
{
t = sort_ptr[0];
sort_ptr[0] = sort_ptr[d];
sort_ptr[d] = t;
};
/*
* Assign the median value...
*/
t = sort_count / 2;
if (sort_count & 1)
dst_row[x] = (sort[t] + sort[t + 1]) / 2;
else
dst_row[x] = sort[t];
/*
* Save the change to the source image too if the user wants the
* recursive method...
*/
if (despeckle_vals.filter_type & FILTER_RECURSIVE)
src_rows[(row + y - lasty + max_row) % max_row][x] = dst_row[x];
/*
* Check the histogram and adjust the radius accordingly...
*/
if (despeckle_vals.filter_type & FILTER_ADAPTIVE)
{
if (hist0 >= radius || hist255 >= radius)
if (filter_type & FILTER_ADAPTIVE)
{
if (radius < despeckle_vals.radius)
radius ++;
}
else if (radius > 1)
radius --;
if (hist0 >= radius || hist255 >= radius)
{
if (radius < despeckle_radius)
radius ++;
}
else if (radius > 1)
radius --;
};
};
};
@ -666,7 +693,7 @@ despeckle_dialog(void)
*/
dialog = gtk_dialog_new();
gtk_window_set_title(GTK_WINDOW(dialog), "Despeckle");
gtk_window_set_title(GTK_WINDOW(dialog), "Despeckle " PLUG_IN_VERSION);
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",
@ -677,7 +704,7 @@ despeckle_dialog(void)
* Top-level table for dialog...
*/
table = gtk_table_new(3, 3, FALSE);
table = gtk_table_new(5, 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);
@ -731,11 +758,16 @@ despeckle_dialog(void)
preview_init();
preview_x1 = sel_x1;
preview_y1 = sel_y1;
preview_x2 = preview_x1 + MIN(preview_width, sel_width);
preview_y2 = preview_y1 + MIN(preview_height, sel_height);
/*
* Filter type controls...
*/
ftable = gtk_table_new(4, 1, FALSE);
ftable = gtk_table_new(6, 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);
@ -744,7 +776,7 @@ despeckle_dialog(void)
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_state(GTK_TOGGLE_BUTTON(button),
(despeckle_vals.filter_type & FILTER_ADAPTIVE) ? TRUE : FALSE);
(filter_type & FILTER_ADAPTIVE) ? TRUE : FALSE);
gtk_signal_connect(GTK_OBJECT(button), "toggled",
(GtkSignalFunc)dialog_adaptive_callback,
NULL);
@ -754,7 +786,7 @@ despeckle_dialog(void)
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_state(GTK_TOGGLE_BUTTON(button),
(despeckle_vals.filter_type & FILTER_RECURSIVE) ? TRUE : FALSE);
(filter_type & FILTER_RECURSIVE) ? TRUE : FALSE);
gtk_signal_connect(GTK_OBJECT(button), "toggled",
(GtkSignalFunc)dialog_recursive_callback,
NULL);
@ -764,7 +796,19 @@ despeckle_dialog(void)
* Box size (radius) control...
*/
dialog_create_ivalue("Radius", GTK_TABLE(table), 2, &despeckle_vals.radius, 1, MAX_RADIUS);
dialog_create_ivalue("Radius", GTK_TABLE(table), 2, &despeckle_radius, 1, MAX_RADIUS);
/*
* Black level control...
*/
dialog_create_ivalue("Black Level", GTK_TABLE(table), 3, &black_level, 0, 256);
/*
* White level control...
*/
dialog_create_ivalue("White Level", GTK_TABLE(table), 4, &white_level, 0, 256);
/*
* OK, cancel buttons...
@ -821,7 +865,7 @@ despeckle_dialog(void)
static void
preview_init(void)
{
int size, /* Size of filter box */
int size, /* Size of filter box */
width; /* Byte width of the image */
@ -829,17 +873,19 @@ preview_init(void)
* Setup for preview filter...
*/
preview_buf_size = size = despeckle_vals.radius * 2 + 1;
size = despeckle_radius * 2 + 1;
width = preview_width * img_bpp;
if (preview_src != NULL)
{
g_free(preview_src);
g_free(preview_dst);
g_free(preview_sort);
};
preview_src = g_malloc(width * preview_height * sizeof(guchar *));
preview_dst = g_malloc(width * sizeof(guchar));
preview_sort = g_malloc(size * size * sizeof(guchar));
preview_x1 = sel_x1;
preview_y1 = sel_y1;
preview_x2 = preview_x1 + MIN(preview_width, sel_width);
preview_y2 = preview_y1 + MIN(preview_height, sel_height);
}
@ -893,19 +939,9 @@ preview_update(void)
* Pre-load the preview rectangle...
*/
size = despeckle_vals.radius * 2 + 1;
size = despeckle_radius * 2 + 1;
width = preview_width * img_bpp;
if (size != preview_buf_size)
{
preview_src = g_realloc(preview_src,
width * preview_height * sizeof(guchar *));
preview_dst = g_realloc(preview_dst,
width * sizeof(guchar));
preview_sort = g_realloc(preview_sort,
size * size * sizeof(guchar));
}
gimp_pixel_rgn_get_rect(&src_rgn, preview_src, preview_x1, preview_y1,
preview_width, preview_height);
@ -919,11 +955,11 @@ preview_update(void)
* Now find the median pixels and save the results...
*/
radius = despeckle_vals.radius;
radius = despeckle_radius;
if (y < radius || y >= (preview_height - radius))
memcpy(preview_dst, preview_src + y * width, width);
else
memcpy(preview_dst, preview_src + y * width, width);
if (y >= radius && y < (preview_height - radius))
{
for (x = 0, dst_ptr = preview_dst; x < width; x ++, dst_ptr ++)
{
@ -942,12 +978,15 @@ preview_update(void)
src_ptr = preview_src + width * (y - radius);
i <= radius;
i ++, src_ptr += width)
for (tx = xmin; tx < xmax; tx += img_bpp, sort_ptr ++)
for (tx = xmin; tx < xmax; tx += img_bpp)
{
if ((*sort_ptr = src_ptr[tx]) == 0)
if ((*sort_ptr = src_ptr[tx]) <= black_level)
hist0 ++;
else if (*sort_ptr == 255)
else if (*sort_ptr >= white_level)
hist255 ++;
if (*sort_ptr < white_level)
sort_ptr ++;
};
/*
@ -956,45 +995,48 @@ preview_update(void)
sort_count = sort_ptr - preview_sort;
for (d = sort_count / 2; d > 0; d = d / 2)
for (i = d; i < sort_count; i ++)
for (j = i - d, sort_ptr = preview_sort + j;
j >= 0 && sort_ptr[0] > sort_ptr[d];
j -= d, sort_ptr -= d)
{
t = sort_ptr[0];
sort_ptr[0] = sort_ptr[d];
sort_ptr[d] = t;
};
if (sort_count > 1)
{
for (d = sort_count / 2; d > 0; d = d / 2)
for (i = d; i < sort_count; i ++)
for (j = i - d, sort_ptr = preview_sort + j;
j >= 0 && sort_ptr[0] > sort_ptr[d];
j -= d, sort_ptr -= d)
{
t = sort_ptr[0];
sort_ptr[0] = sort_ptr[d];
sort_ptr[d] = t;
};
/*
* Assign the median value...
*/
/*
* Assign the median value...
*/
t = sort_count / 2;
t = sort_count / 2;
if (sort_count & 1)
*dst_ptr = (preview_sort[t] + preview_sort[t + 1]) / 2;
else
*dst_ptr = preview_sort[t];
if (sort_count & 1)
*dst_ptr = (preview_sort[t] + preview_sort[t + 1]) / 2;
else
*dst_ptr = preview_sort[t];
/*
* Save the change to the source image too if the user wants the
* recursive method...
*/
/*
* Save the change to the source image too if the user wants the
* recursive method...
*/
if (despeckle_vals.filter_type & FILTER_RECURSIVE)
preview_src[y * width + x] = *dst_ptr;
if (filter_type & FILTER_RECURSIVE)
preview_src[y * width + x] = *dst_ptr;
};
/*
* Check the histogram and adjust the radius accordingly...
*/
if (despeckle_vals.filter_type & FILTER_ADAPTIVE)
if (filter_type & FILTER_ADAPTIVE)
{
if (hist0 >= radius || hist255 >= radius)
{
if (radius < despeckle_vals.radius)
if (radius < despeckle_radius)
radius ++;
}
else if (radius > 1)
@ -1051,7 +1093,8 @@ preview_update(void)
static void
preview_exit(void)
{
int size; /* Size of row buffer */
int row, /* Looping var */
size; /* Size of row buffer */
size = MAX_RADIUS * 2 + 1;
@ -1148,6 +1191,9 @@ dialog_iscale_update(GtkAdjustment *adjustment, /* I - New value */
gtk_entry_set_text(GTK_ENTRY(entry), buf);
gtk_signal_handler_unblock_by_data(GTK_OBJECT(entry), value);
if (value == &despeckle_radius)
preview_init();
preview_update();
};
}
@ -1179,6 +1225,9 @@ dialog_ientry_update(GtkWidget *widget, /* I - Entry widget */
gtk_signal_emit_by_name(GTK_OBJECT(adjustment), "value_changed");
if (value == &despeckle_radius)
preview_init();
preview_update();
};
};
@ -1194,9 +1243,9 @@ dialog_adaptive_callback(GtkWidget *widget, /* I - Toggle button */
gpointer data) /* I - Data */
{
if (GTK_TOGGLE_BUTTON(widget)->active)
despeckle_vals.filter_type |= FILTER_ADAPTIVE;
filter_type |= FILTER_ADAPTIVE;
else
despeckle_vals.filter_type &= ~FILTER_ADAPTIVE;
filter_type &= ~FILTER_ADAPTIVE;
preview_update();
}
@ -1211,9 +1260,9 @@ dialog_recursive_callback(GtkWidget *widget, /* I - Toggle button */
gpointer data) /* I - Data */
{
if (GTK_TOGGLE_BUTTON(widget)->active)
despeckle_vals.filter_type |= FILTER_RECURSIVE;
filter_type |= FILTER_RECURSIVE;
else
despeckle_vals.filter_type &= ~FILTER_RECURSIVE;
filter_type &= ~FILTER_RECURSIVE;
preview_update();
}

View File

@ -1,36 +1,25 @@
CFLAGS=-D_GIMP
CFLAGS=-D_GIMP -Wall -O3
CC = gcc
OBJECTS=mathmap.o builtins.o exprtree.o parser.o scanner.o postfix.o
OBJECTS=mathmap.o builtins.o exprtree.o parser.o scanner.o postfix.o vars.o
mathmap : $(OBJECTS)
gcc -o mathmap -lglib -lgdk -lgtk -lgimp -lm $(OBJECTS)
$(CC) -o mathmap -lglib -lgdk -lgtk -lgimp -lm $(OBJECTS)
mathmap.o : mathmap.c
gcc $(CFLAGS) -c mathmap.c
%.o : %.c
$(CC) $(CFLAGS) -c $<
builtins.o : builtins.c
gcc $(CFLAGS) -c builtins.c
exprtree.o : exprtree.c
gcc $(CFLAGS) -c exprtree.c
postfix.o : postfix.c
gcc $(CFLAGS) -c postfix.c
parser.o : parser.tab.c
gcc $(CFLAGS) -c -o parser.o parser.tab.c
scanner.o : lex.yy.c
gcc $(CFLAGS) -c -o scanner.o lex.yy.c
parser.tab.c : parser.y
parser.c : parser.y
bison -d parser.y
mv parser.tab.c parser.c
mv parser.tab.h parser.h
lex.yy.c : scanner.fl
scanner.c : scanner.fl
flex scanner.fl
mv lex.yy.c scanner.c
install : mathmap
cp mathmap $(HOME)/.gimp/plug-ins/
clean :
rm -f *~ *.o mathmap lex.yy.c parser.tab.[ch]
rm -f *~ *.o mathmap scanner.c parser.[ch]

View File

@ -1,4 +1,5 @@
#include <math.h>
#include <string.h>
#ifdef _GIMP
#include <stdlib.h>
#else
@ -8,53 +9,81 @@
#include "builtins.h"
extern int imageWidth,
imageHeight;
imageHeight,
inputBPP;
extern double middleX,
middleY;
extern unsigned char *imageData;
extern double stack[];
extern int stackp;
extern int intersamplingEnabled,
oversamplingEnabled;
builtin *firstBuiltin = 0;
double
color_to_double (int red, int green, int blue)
color_to_double (unsigned int red, unsigned int green, unsigned int blue, unsigned int alpha)
{
double val;
*(int*)&val = (red << 16) | (green << 8) | blue;
*(unsigned int*)&val = (alpha << 24) | (red << 16) | (green << 8) | blue;
return val;
}
void
double_to_color (double val, int *red, int *green, int *blue)
double
pixel_to_double (unsigned char *pixel)
{
int color = *(int*)&val;
if (inputBPP == 1)
return color_to_double(pixel[0], pixel[0], pixel[0], 255);
else if (inputBPP == 2)
return color_to_double(pixel[0], pixel[0], pixel[0], pixel[1]);
else if (inputBPP == 3)
return color_to_double(pixel[0], pixel[1], pixel[2], 255);
else
return color_to_double(pixel[0], pixel[1], pixel[2], pixel[3]);
}
*red = color >> 16;
void
double_to_color (double val, unsigned int *red, unsigned int *green,
unsigned int *blue, unsigned int *alpha)
{
unsigned int color = *(unsigned int*)&val;
*alpha = color >> 24;
*red = (color >> 16) & 0xff;
*green = (color >> 8) & 0xff;
*blue = color & 0xff;
}
int
red_component (double val)
unsigned int
alpha_component (double val)
{
int color = *(int*)&val;
unsigned int color = *(unsigned int*)&val;
return color >> 16;
return color >> 24;
}
int
unsigned int
red_component (double val)
{
unsigned int color = *(unsigned int*)&val;
return (color >> 16) & 0xff;
}
unsigned int
green_component (double val)
{
int color = *(int*)&val;
unsigned int color = *(unsigned int*)&val;
return (color >> 8) & 0xff;
}
int
unsigned int
blue_component (double val)
{
int color = *(int*)&val;
unsigned int color = *(unsigned int*)&val;
return color & 0xff;
}
@ -95,12 +124,25 @@ builtin_atan (void *arg)
stack[stackp - 1] = atan(stack[stackp - 1]) * 180.0 / M_PI;
}
void
builtin_pow (void *arg)
{
stack[stackp - 2] = pow(stack[stackp - 2], stack[stackp - 1]);
--stackp;
}
void
builtin_abs (void *arg)
{
stack[stackp - 1] = fabs(stack[stackp - 1]);
}
void
builtin_floor (void *arg)
{
stack[stackp - 1] = floor(stack[stackp - 1]);
}
void
builtin_sign (void *arg)
{
@ -128,6 +170,15 @@ builtin_max (void *arg)
--stackp;
}
void
builtin_not (void *arg)
{
if (stack[stackp - 1] != 0.0)
stack[stackp - 1] = 0.0;
else
stack[stackp - 1] = 1.0;
}
void
builtin_or (void *arg)
{
@ -148,6 +199,16 @@ builtin_and (void *arg)
--stackp;
}
void
builtin_equal (void *arg)
{
if (stack[stackp - 2] == stack[stackp - 1])
stack[stackp - 2] = 1.0;
else
stack[stackp - 2] = 0.0;
--stackp;
}
void
builtin_less (void *arg)
{
@ -158,6 +219,46 @@ builtin_less (void *arg)
--stackp;
}
void
builtin_greater (void *arg)
{
if (stack[stackp - 2] > stack[stackp - 1])
stack[stackp - 2] = 1.0;
else
stack[stackp - 2] = 0.0;
--stackp;
}
void
builtin_lessequal (void *arg)
{
if (stack[stackp - 2] <= stack[stackp - 1])
stack[stackp - 2] = 1.0;
else
stack[stackp - 2] = 0.0;
--stackp;
}
void
builtin_greaterequal (void *arg)
{
if (stack[stackp - 2] >= stack[stackp - 1])
stack[stackp - 2] = 1.0;
else
stack[stackp - 2] = 0.0;
--stackp;
}
void
builtin_notequal (void *arg)
{
if (stack[stackp - 2] != stack[stackp - 1])
stack[stackp - 2] = 1.0;
else
stack[stackp - 2] = 0.0;
--stackp;
}
void
builtin_inintv (void *arg)
{
@ -188,13 +289,19 @@ extern int originX,
void
builtin_origValXY (void *arg)
{
int x = stack[stackp - 2],
double x = stack[stackp - 2],
y = stack[stackp - 1];
unsigned char pixel[4];
mathmap_get_pixel(x + originX + middleX, y + originY + middleY, pixel);
if (!oversamplingEnabled)
{
x += 0.5;
y += 0.5;
}
stack[stackp - 2] = color_to_double(pixel[0], pixel[1], pixel[2]);
mathmap_get_pixel(floor(x + originX + middleX), floor(y + originY + middleY), pixel);
stack[stackp - 2] = pixel_to_double(pixel);
--stackp;
}
@ -219,14 +326,13 @@ builtin_origValXYIntersample (void *arg)
unsigned char pixel1a[4],
pixel2a[4],
pixel3a[4],
pixel4a[4];
pixel4a[4],
resultPixel[4];
unsigned char *pixel1 = pixel1a,
*pixel2 = pixel2a,
*pixel3 = pixel3a,
*pixel4 = pixel4a;
int red,
green,
blue;
int i;
if (x1 < 0 || x1 >= wholeImageWidth || y1 < 0 || y1 >= wholeImageHeight)
pixel1 = blackPixel;
@ -248,24 +354,32 @@ builtin_origValXYIntersample (void *arg)
else
mathmap_get_pixel(x2, y2, pixel4);
red = pixel1[0] * p1fact + pixel2[0] * p2fact + pixel3[0] * p3fact + pixel4[0] * p4fact;
green = pixel1[1] * p1fact + pixel2[1] * p2fact + pixel3[1] * p3fact + pixel4[1] * p4fact;
blue = pixel1[2] * p1fact + pixel2[2] * p2fact + pixel3[2] * p3fact + pixel4[2] * p4fact;
for (i = 0; i < inputBPP; ++i)
resultPixel[i] = pixel1[i] * p1fact
+ pixel2[i] * p2fact
+ pixel3[i] * p3fact
+ pixel4[i] * p4fact;
stack[stackp - 2] = color_to_double(red, green, blue);
stack[stackp - 2] = pixel_to_double(resultPixel);
--stackp;
}
void
builtin_origValRA (void *arg)
{
int x = cos(stack[stackp - 1] * M_PI / 180) * stack[stackp - 2] + middleX,
double x = cos(stack[stackp - 1] * M_PI / 180) * stack[stackp - 2] + middleX,
y = sin(stack[stackp - 1] * M_PI / 180) * stack[stackp - 2] + middleY;
unsigned char pixel[4];
if (!oversamplingEnabled)
{
x += 0.5;
y += 0.5;
}
mathmap_get_pixel(x + originX, y + originY, pixel);
mathmap_get_pixel(floor(x + originX), floor(y + originY), pixel);
stack[stackp - 2] = color_to_double(pixel[0], pixel[1], pixel[2]);
stack[stackp - 2] = pixel_to_double(pixel);
--stackp;
}
@ -290,14 +404,13 @@ builtin_origValRAIntersample (void *arg)
unsigned char pixel1a[4],
pixel2a[4],
pixel3a[4],
pixel4a[4];
pixel4a[4],
resultPixel[4];
unsigned char *pixel1 = pixel1a,
*pixel2 = pixel2a,
*pixel3 = pixel3a,
*pixel4 = pixel4a;
int red,
green,
blue;
int i;
if (x1 < 0 || x1 >= wholeImageWidth || y1 < 0 || y1 >= wholeImageHeight)
pixel1 = blackPixel;
@ -319,11 +432,13 @@ builtin_origValRAIntersample (void *arg)
else
mathmap_get_pixel(x2, y2, pixel4);
red = pixel1[0] * p1fact + pixel2[0] * p2fact + pixel3[0] * p3fact + pixel4[0] * p4fact;
green = pixel1[1] * p1fact + pixel2[1] * p2fact + pixel3[1] * p3fact + pixel4[1] * p4fact;
blue = pixel1[2] * p1fact + pixel2[2] * p2fact + pixel3[2] * p3fact + pixel4[2] * p4fact;
for (i = 0; i < inputBPP; ++i)
resultPixel[i] = pixel1[i] * p1fact
+ pixel2[i] * p2fact
+ pixel3[i] * p3fact
+ pixel4[i] * p4fact;
stack[stackp - 2] = color_to_double(red, green, blue);
stack[stackp - 2] = pixel_to_double(resultPixel);
--stackp;
}
@ -497,6 +612,24 @@ builtin_blue (void *arg)
stack[stackp - 1] = blue_component(stack[stackp - 1]) / 255.0;
}
void
builtin_gray (void *arg)
{
int red,
green,
blue,
alpha;
double_to_color(stack[stackp - 1], &red, &green, &blue, &alpha);
stack[stackp - 1] = (0.299 * red + 0.587 * green + 0.114 * blue) / 255.0;
}
void
builtin_alpha (void *arg)
{
stack[stackp - 1] = alpha_component(stack[stackp - 1]) / 255.0;
}
void
builtin_rgbColor (void *arg)
{
@ -521,7 +654,41 @@ builtin_rgbColor (void *arg)
else if (blueComponent > 255)
blueComponent = 255;
stack[stackp - 1] = color_to_double(redComponent, greenComponent, blueComponent);
stack[stackp - 1] = color_to_double(redComponent, greenComponent, blueComponent, 255);
}
void
builtin_rgbaColor (void *arg)
{
int redComponent = stack[stackp - 4] * 255,
greenComponent = stack[stackp - 3] * 255,
blueComponent = stack[stackp - 2] * 255,
alphaComponent = stack[stackp - 1] * 255;
stackp -= 3;
if (redComponent < 0)
redComponent = 0;
else if (redComponent > 255)
redComponent = 255;
if (greenComponent < 0)
greenComponent = 0;
else if (greenComponent > 255)
greenComponent = 255;
if (blueComponent < 0)
blueComponent = 0;
else if (blueComponent > 255)
blueComponent = 255;
if (alphaComponent < 0)
alphaComponent = 0;
else if (alphaComponent > 255)
alphaComponent = 255;
stack[stackp - 1] = color_to_double(redComponent, greenComponent,
blueComponent, alphaComponent);
}
void
@ -534,5 +701,101 @@ builtin_grayColor (void *arg)
else if (grayLevel > 255)
grayLevel = 255;
stack[stackp - 1] = color_to_double(grayLevel, grayLevel, grayLevel);
stack[stackp - 1] = color_to_double(grayLevel, grayLevel, grayLevel, 255);
}
void
builtin_grayaColor (void *arg)
{
int grayLevel = stack[stackp - 2] * 255,
alphaComponent = stack[stackp - 1] * 255;
--stackp;
if (grayLevel < 0)
grayLevel = 0;
else if (grayLevel > 255)
grayLevel = 255;
if (alphaComponent < 0)
alphaComponent = 0;
else if (alphaComponent > 255)
alphaComponent = 255;
stack[stackp - 1] = color_to_double(grayLevel, grayLevel, grayLevel, alphaComponent);
}
builtin*
builtin_with_name (const char *name)
{
builtin *next;
if (intersamplingEnabled)
{
if (strcmp(name, "origValXY") == 0)
return builtin_with_name("origValXYIntersample");
else if (strcmp(name, "origValRA") == 0)
return builtin_with_name("origValRAIntersample");
}
for (next = firstBuiltin; next != 0; next = next->next)
if (strcmp(name, next->name) == 0)
return next;
return 0;
}
void
register_builtin (const char *name, builtinFunction function, int numParams)
{
builtin *theBuiltin = (builtin*)malloc(sizeof(builtin));
strncpy(theBuiltin->name, name, MAX_BUILTIN_LENGTH);
theBuiltin->name[MAX_BUILTIN_LENGTH] = '\0';
theBuiltin->function = function;
theBuiltin->numParams = numParams;
theBuiltin->next = firstBuiltin;
firstBuiltin = theBuiltin;
}
void
init_builtins (void)
{
register_builtin("sin", builtin_sin, 1);
register_builtin("cos", builtin_cos, 1);
register_builtin("tan", builtin_tan, 1);
register_builtin("asin", builtin_asin, 1);
register_builtin("acos", builtin_acos, 1);
register_builtin("atan", builtin_atan, 1);
register_builtin("pow", builtin_pow, 2);
register_builtin("abs", builtin_abs, 1);
register_builtin("floor", builtin_floor, 1);
register_builtin("sign", builtin_sign, 1);
register_builtin("min", builtin_min, 2);
register_builtin("max", builtin_max, 2);
register_builtin("not", builtin_not, 1);
register_builtin("or", builtin_or, 2);
register_builtin("and", builtin_and, 2);
register_builtin("equal", builtin_equal, 2);
register_builtin("less", builtin_less, 2);
register_builtin("greater", builtin_greater, 2);
register_builtin("lessequal", builtin_lessequal, 2);
register_builtin("greaterequal", builtin_greaterequal, 2);
register_builtin("notequal", builtin_notequal, 2);
register_builtin("inintv", builtin_inintv, 3);
register_builtin("rand", builtin_rand, 2);
register_builtin("origValXY", builtin_origValXY, 2);
register_builtin("origValXYIntersample", builtin_origValXYIntersample, 2);
register_builtin("origValRA", builtin_origValRA, 2);
register_builtin("origValRAIntersample", builtin_origValRAIntersample, 2);
register_builtin("red", builtin_red, 1);
register_builtin("green", builtin_green, 1);
register_builtin("blue", builtin_blue, 1);
register_builtin("gray", builtin_gray, 1);
register_builtin("alpha", builtin_alpha, 1);
register_builtin("rgbColor", builtin_rgbColor, 3);
register_builtin("rgbaColor", builtin_rgbaColor, 4);
register_builtin("grayColor", builtin_grayColor, 1);
register_builtin("grayaColor", builtin_grayaColor, 2);
}

View File

@ -1,28 +1,27 @@
/* -*- c -*- */
double color_to_double (int red, int green, int blue);
void double_to_color (double val, int *red, int *green, int *blue);
#ifndef __BUILTINS_H__
#define __BUILTINS_H__
void builtin_sin (void *arg);
void builtin_cos (void *arg);
void builtin_tan (void *arg);
void builtin_asin (void *arg);
void builtin_acos (void *arg);
void builtin_atan (void *arg);
void builtin_abs (void *arg);
void builtin_sign (void *arg);
void builtin_min (void *arg);
void builtin_max (void *arg);
void builtin_or (void *arg);
void builtin_and (void *arg);
void builtin_less (void *arg);
void builtin_inintv (void *arg);
void builtin_rand (void *arg);
void builtin_origValXY (void *arg);
void builtin_origValXYIntersample (void *arg);
void builtin_origValRA (void *arg);
void builtin_origValRAIntersample (void *arg);
void builtin_red (void *arg);
void builtin_green (void *arg);
void builtin_blue (void *arg);
void builtin_rgbColor (void *arg);
void builtin_grayColor (void *arg);
#define MAX_BUILTIN_LENGTH 63
typedef void (*builtinFunction) (void*);
typedef struct _builtin
{
char name[MAX_BUILTIN_LENGTH + 1];
builtinFunction function;
int numParams;
struct _builtin *next;
} builtin;
double color_to_double (unsigned int red, unsigned int green,
unsigned int blue, unsigned int alpha);
void double_to_color (double val, unsigned int *red, unsigned int *green,
unsigned int *blue, unsigned int *alpha);
builtin* builtin_with_name (const char *name);
void init_builtins (void);
#endif

View File

@ -35,6 +35,8 @@ make_var (char *name)
tree->type = EXPR_VAR_X;
else if (strcmp(name, "y") == 0)
tree->type = EXPR_VAR_Y;
else if (strcmp(name, "t") == 0)
tree->type = EXPR_VAR_T;
else if (strcmp(name, "r") == 0)
{
tree->type = EXPR_VAR_R;
@ -81,137 +83,13 @@ make_operator (int type, exprtree *left, exprtree *right)
}
exprtree*
make_function (char *name, exprtree *args)
make_function (builtin *theBuiltin, exprtree *args)
{
exprtree *tree = (exprtree*)malloc(sizeof(exprtree));
if (strcmp(name, "sin") == 0)
{
tree->val.func.routine = builtin_sin;
tree->val.func.numArgs = 1;
}
else if (strcmp(name, "cos") == 0)
{
tree->val.func.routine = builtin_cos;
tree->val.func.numArgs = 1;
}
else if (strcmp(name, "tan") == 0)
{
tree->val.func.routine = builtin_tan;
tree->val.func.numArgs = 1;
}
else if (strcmp(name, "asin") == 0)
{
tree->val.func.routine = builtin_asin;
tree->val.func.numArgs = 1;
}
else if (strcmp(name, "acos") == 0)
{
tree->val.func.routine = builtin_acos;
tree->val.func.numArgs = 1;
}
else if (strcmp(name, "atan") == 0)
{
tree->val.func.routine = builtin_atan;
tree->val.func.numArgs = 1;
}
else if (strcmp(name, "abs") == 0)
{
tree->val.func.routine = builtin_abs;
tree->val.func.numArgs = 1;
}
else if (strcmp(name, "sign") == 0)
{
tree->val.func.routine = builtin_sign;
tree->val.func.numArgs = 1;
}
else if (strcmp(name, "min") == 0)
{
tree->val.func.routine = builtin_min;
tree->val.func.numArgs = 2;
}
else if (strcmp(name, "max") == 0)
{
tree->val.func.routine = builtin_max;
tree->val.func.numArgs = 2;
}
else if (strcmp(name, "or") == 0)
{
tree->val.func.routine = builtin_or;
tree->val.func.numArgs = 2;
}
else if (strcmp(name, "and") == 0)
{
tree->val.func.routine = builtin_and;
tree->val.func.numArgs = 2;
}
else if (strcmp(name, "less") == 0)
{
tree->val.func.routine = builtin_less;
tree->val.func.numArgs = 2;
}
else if (strcmp(name, "inintv") == 0)
{
tree->val.func.routine = builtin_inintv;
tree->val.func.numArgs = 3;
}
else if (strcmp(name, "rand") == 0)
{
tree->val.func.routine = builtin_rand;
tree->val.func.numArgs = 2;
}
else if (strcmp(name, "origValXY") == 0)
{
if (intersamplingEnabled)
tree->val.func.routine = builtin_origValXYIntersample;
else
tree->val.func.routine = builtin_origValXY;
tree->val.func.numArgs = 2;
}
else if (strcmp(name, "origValRA") == 0)
{
if (intersamplingEnabled)
tree->val.func.routine = builtin_origValRAIntersample;
else
tree->val.func.routine = builtin_origValRA;
tree->val.func.numArgs = 2;
}
else if (strcmp(name, "red") == 0)
{
tree->val.func.routine = builtin_red;
tree->val.func.numArgs = 1;
}
else if (strcmp(name, "green") == 0)
{
tree->val.func.routine = builtin_green;
tree->val.func.numArgs = 1;
}
else if (strcmp(name, "blue") == 0)
{
tree->val.func.routine = builtin_blue;
tree->val.func.numArgs = 1;
}
else if (strcmp(name, "rgbColor") == 0)
{
tree->val.func.routine = builtin_rgbColor;
tree->val.func.numArgs = 3;
}
else if (strcmp(name, "grayColor") == 0)
{
tree->val.func.routine = builtin_grayColor;
tree->val.func.numArgs = 1;
}
else
{
tree->type = EXPR_NUMBER;
tree->val.number = 0.0;
tree->next = 0;
return tree;
}
tree->type = EXPR_FUNC;
tree->val.func.routine = theBuiltin->function;
tree->val.func.numArgs = theBuiltin->numParams;
tree->val.func.args = args;
tree->next = 0;

View File

@ -2,6 +2,7 @@
#define __EXPRTREE_H__
#include "vars.h"
#include "builtins.h"
#ifdef USE_TREE
typedef double (*function) (double*);
@ -9,7 +10,9 @@ typedef double (*function) (double*);
typedef void (*function) (void*);
#endif
typedef char ident[64];
#define MAX_IDENT_LENGTH 63
typedef char ident[MAX_IDENT_LENGTH + 1];
typedef struct _exprtree
{
@ -55,35 +58,36 @@ typedef struct _exprtree
struct _exprtree *next;
} exprtree;
#define EXPR_NUMBER 1
#define EXPR_ADD 2
#define EXPR_SUB 3
#define EXPR_MUL 4
#define EXPR_DIV 5
#define EXPR_MOD 6
#define EXPR_NEG 7
#define EXPR_FUNC 8
#define EXPR_VAR_X 9
#define EXPR_VAR_Y 10
#define EXPR_VAR_R 11
#define EXPR_VAR_A 12
#define EXPR_VAR_W 13
#define EXPR_VAR_H 14
#define EXPR_VAR_BIG_R 15
#define EXPR_VAR_BIG_X 16
#define EXPR_VAR_BIG_Y 17
#define EXPR_SEQUENCE 18
#define EXPR_ASSIGNMENT 19
#define EXPR_VARIABLE 20
#define EXPR_IF_THEN 21
#define EXPR_IF_THEN_ELSE 22
#define EXPR_WHILE 23
#define EXPR_DO_WHILE 24
#define EXPR_NUMBER 1
#define EXPR_ADD 2
#define EXPR_SUB 3
#define EXPR_MUL 4
#define EXPR_DIV 5
#define EXPR_MOD 6
#define EXPR_NEG 7
#define EXPR_FUNC 8
#define EXPR_VAR_X 9
#define EXPR_VAR_Y 10
#define EXPR_VAR_T 11
#define EXPR_VAR_R 12
#define EXPR_VAR_A 13
#define EXPR_VAR_W 14
#define EXPR_VAR_H 15
#define EXPR_VAR_BIG_R 16
#define EXPR_VAR_BIG_X 17
#define EXPR_VAR_BIG_Y 18
#define EXPR_SEQUENCE 19
#define EXPR_ASSIGNMENT 20
#define EXPR_VARIABLE 21
#define EXPR_IF_THEN 22
#define EXPR_IF_THEN_ELSE 23
#define EXPR_WHILE 24
#define EXPR_DO_WHILE 25
exprtree* make_number (double num);
exprtree* make_var (char *name);
exprtree* make_operator (int type, exprtree *left, exprtree *right);
exprtree* make_function (char *name, exprtree *args);
exprtree* make_function (builtin *theBuiltin, exprtree *args);
exprtree* make_sequence (exprtree *left, exprtree *right);
exprtree* make_assignment (char *name, exprtree *value);
exprtree* make_if_then (exprtree *condition, exprtree *conclusion);

View File

@ -10,7 +10,7 @@
* Copyright (C) 1997 Federico Mena Quintero
* federico@nuclecu.unam.mx
*
* Version 0.2
* Version 0.4
*
* 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
@ -32,6 +32,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
@ -54,17 +55,20 @@
#define ENTRY_WIDTH 60
#define DEFAULT_EXPRESSION "origValXY(x+sin(y*10)*3,y+sin(x*10)*3)"
#define DEFAULT_NUMBER_FRAMES 10
#define FLAG_INTERSAMPLING 1
#define FLAG_OVERSAMPLING 2
#define FLAG_ANIMATION 4
#define MAX_EXPRESSION_LENGTH 1024
#define MAX_EXPRESSION_LENGTH 8192
/***** Types *****/
typedef struct {
gchar expression[MAX_EXPRESSION_LENGTH];
gint flags;
gint frames;
} mathmap_vals_t;
typedef struct {
@ -89,17 +93,23 @@ static void expression_copy (gchar *dest, gchar *src);
static void mathmap (void);
void mathmap_get_pixel(int x, int y, guchar *pixel);
static gint32 mathmap_layer_copy(gint32 layerID);
extern int yyparse (void);
static void build_preview_source_image(void);
static gint mathmap_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_scale_update(GtkAdjustment *adjustment, gdouble *value);
static void dialog_entry_update(GtkWidget *widget, gdouble *value);
*/
static void dialog_scale_update(GtkAdjustment *adjustment, gint *value);
static void dialog_entry_update(GtkWidget *widget, gpointer value);
static void dialog_intersampling_update (GtkWidget *widget, gpointer data);
static void dialog_oversampling_update (GtkWidget *widget, gpointer data);
static void dialog_animation_update (GtkWidget *widget, gpointer data);
static void dialog_preview_callback (GtkWidget *widget, gpointer data);
static void dialog_example_callback (GtkWidget *widget, char *expression);
static void dialog_close_callback(GtkWidget *widget, gpointer data);
@ -118,7 +128,8 @@ GPlugInInfo PLUG_IN_INFO = {
static mathmap_vals_t mmvals = {
DEFAULT_EXPRESSION, /* expression */
FLAG_INTERSAMPLING /* flags */
FLAG_INTERSAMPLING, /* flags */
DEFAULT_NUMBER_FRAMES /* frames */
}; /* mmvals */
static mathmap_interface_t wint = {
@ -128,10 +139,13 @@ static mathmap_interface_t wint = {
FALSE /* run */
}; /* wint */
static GDrawable *drawable;
static gint32 image_id;
static gint32 layer_id;
static GDrawable *input_drawable;
static GDrawable *output_drawable;
static gint tile_width, tile_height;
static gint img_width, img_height, img_bpp;
static gint img_width, img_height;
static gint sel_x1, sel_y1, sel_x2, sel_y2;
static gint sel_width, sel_height;
static gint preview_width, preview_height;
@ -141,7 +155,8 @@ static double cen_x, cen_y;
static double scale_x, scale_y;
static double radius, radius2;
GtkWidget *expressionEntry = 0;
GtkWidget *expression_entry = 0,
*animate_table;
exprtree *theExprtree = 0;
int imageWidth,
@ -149,43 +164,54 @@ int imageWidth,
wholeImageWidth,
wholeImageHeight,
originX,
originY;
originY,
inputBPP,
outputBPP;
int usesRA = 0;
double currentX,
currentY,
currentR,
currentA,
currentT,
imageR,
imageX,
imageY,
middleX,
middleY;
int intersamplingEnabled,
oversamplingEnabled;
oversamplingEnabled,
animationEnabled = 1;
char *examples[][2] = {
{ "wave", "origValXY(x+sin(y*10)*3,y+sin(x*10)*3)" },
{ "wave", "origValXY(x+sin(y*10+t*360)*3,y+sin(x*10+t*360)*3)" },
{ "square", "origValXY(sign(x)*x*x/50,sign(y)*y*y/50)" },
{ "mosaic", "origValXY(x-x%5,y-y%5)" },
{ "slice", "origValXY(x+5*sign(cos(9*y)),y+5*sign(cos(9*x)))" },
{ "mercator", "origValXY(x*cos(90/Y*y),y)" },
{ "pond", "origValRA(r+sin(r*30)*3,a)" },
{ "enhanced pond", "origValRA(r+(sin(500000/(r+100))*7),a)" },
{ "slice", "q=t*360;origValXY(x+5*sign(cos(9*y+q)),y+5*sign(cos(9*x+q)))" },
{ "mercator", "origValXY(x*cos(90/Y*y+t*360),y)" },
{ "pond", "origValRA(r+sin(r*20+t*360)*3,a)" },
{ "enhanced pond", "origValRA(r+(sin(500000/(r+100)+t*360)*7),a)" },
{ "sea 1", "origValXY(x+10*sin(t*360+2000*Y*pow(y+Y+60,-1)),y)" },
{ "sea 2", "origValXY(x,y+5*sin(t*360+2000*Y*pow(y+Y+60,-1)))" },
{ "sea 3", "s=sin(t*360+2000*Y*pow(y+Y+60,-1));origValXY(x+10*s,y+5*s)" },
{ "twirl 90", "origValRA(r,a+(r/R-1)*45)" },
{ "sphere", "p=r/(X*2);origValRA(r*(1-inintv(p,-0.5,0.5))+X/90*asin(inintv(p,-0.5,0.5)*r/X),a)" },
{ "jitter", "origValRA(r,a+a%8-4)" },
{ "jitter", "origValRA(r,a+(a+t*8)%8-4)" },
{ "radial mosaic", "origValRA(r-r%5,a-a%5)" },
{ "circular slice", "origValRA(r,a+(r%5)-2)" },
{ "fisheye", "origValRA(r*r/R,a)" },
{ "circular slice", "origValRA(r,a+(r+t*6)%6-3)" },
{ "fisheye", "origValRA(pow(r,2-t)/pow(R,1-t),a)" },
{ "center shake", "origValXY(x+max(0,cos(x*2))*5*max(0,cos(y*2))*cos(y*10),y+max(0,cos(x*2))*5*max(0,cos(y*2))*cos(x*10))" },
{ "spiral", "p=origValXY(x,y);q=sin((r-a*0.1)*10+t*360)*0.5+0.5;rgbColor(q*red(p),q*green(p),q*blue(p))" },
{ "alpha spiral", "p=origValXY(x,y);rgbaColor(red(p),green(p),blue(p),sin((r-a*0.1)*10+t*360)*0.5+0.5)" },
{ "scatter", "origValXY(x+rand(-3,3),y+rand(-3,3))" },
{ "desaturate", "p=origValXY(x,y);grayaColor(gray(p),alpha(p))" },
{ "darts", "p=origValXY(x,y);p=if inintv((a-9)%36,0,18) then p else rgbColor(1-red(p),1-green(p),1-blue(p)) end;if inintv(r%80,68,80) then p else rgbColor(1-red(p),1-green(p),1-blue(p)) end" },
{ "tile", "origValXY((x+X)*2%W-X,(y+Y)*2%H-Y)" },
{ "?", "origValRA(r,a+sin(a*10)*20)" },
{ "?", "origValRA(r+r%20,a)" },
{ "sine wave", "grayColor(sin(r*10)*0.5+0.5)" },
{ "grid", "grayColor(if (x%20)*(y%20) then 1 else 0 end)" },
{ "moire1", "rgbColor(abs(sin(15*r)+sin(15*a))*0.5,abs(sin(17*r)+sin(17*a))*0.5,abs(sin(19*r)+sin(19*a))*0.5)" },
{ "moire2", "grayColor(sin(x*y)*0.5+0.5)" },
{ "moire1", "q=t*360;rgbColor(abs(sin(15*r+q)+sin(15*a+q))*0.5,abs(sin(17*r+q)+sin(17*a+q))*0.5,abs(sin(19*r+q)+sin(19*a+q))*0.5)" },
{ "moire2", "grayColor(sin(x*y+t*360)*0.5+0.5)" },
{ "mandelbrot",
"tx=1.5*x/X-0.5; "
"ty=1.5*y/X-0; "
@ -194,7 +220,7 @@ char *examples[][2] = {
"xi=0; "
"xrsq=0; "
"xisq=0; "
"while and(less(xrsq+xisq,4),less(iter,31)) "
"while xrsq+xisq<4 && iter<31 "
"do "
"xrsq=xr*xr; "
"xisq=xi*xi; "
@ -234,7 +260,8 @@ query(void)
{ PARAM_IMAGE, "image", "Input image" },
{ PARAM_DRAWABLE, "drawable", "Input drawable" },
{ PARAM_STRING, "expression", "MathMap expression" },
{ PARAM_INT32, "flags", "1: Intersampling 2: Oversampling" }
{ PARAM_INT32, "flags", "1: Intersampling 2: Oversampling 4: Animate" },
{ PARAM_INT32, "frames", "Number of Frames" }
}; /* args */
static GParamDef *return_vals = NULL;
@ -245,12 +272,12 @@ query(void)
"Generate an image using a mathematical expression.",
"Generates an image by means of a mathematical expression. The expression "
"can also refer to the data of an original image. Thus, arbitrary "
"distortions can be constructed.",
"distortions can be constructed. Even animations can be generated.",
"Mark Probst",
"Mark Probst",
"October 1997, 0.1",
"<Image>/Filters/Generic/MathMap",
"RGB",
"January 1998, 0.4",
"<Image>/Filters/Distorts/MathMap",
"RGB*, GRAY*",
PROC_PLUG_IN,
nargs,
nreturn_vals,
@ -278,6 +305,9 @@ run(char *name,
status = STATUS_SUCCESS;
run_mode = param[0].data.d_int32;
image_id = param[1].data.d_int32;
layer_id = gimp_image_get_active_layer(image_id);
values[0].type = PARAM_STATUS;
values[0].data.d_status = status;
@ -286,16 +316,16 @@ run(char *name,
/* Get the active drawable info */
drawable = gimp_drawable_get(param[2].data.d_drawable);
input_drawable = gimp_drawable_get(param[2].data.d_drawable);
tile_width = gimp_tile_width();
tile_height = gimp_tile_height();
img_width = gimp_drawable_width(drawable->id);
img_height = gimp_drawable_height(drawable->id);
img_bpp = gimp_drawable_bpp(drawable->id);
img_width = gimp_drawable_width(input_drawable->id);
img_height = gimp_drawable_height(input_drawable->id);
inputBPP = gimp_drawable_bpp(input_drawable->id);
gimp_drawable_mask_bounds(drawable->id, &sel_x1, &sel_y1, &sel_x2, &sel_y2);
gimp_drawable_mask_bounds(input_drawable->id, &sel_x1, &sel_y1, &sel_x2, &sel_y2);
originX = sel_x1;
originY = sel_y1;
@ -336,6 +366,8 @@ run(char *name,
preview_width = MAX(pwidth, 2); /* Min size is 2 */
preview_height = MAX(pheight, 2);
init_builtins();
/* See how we will run */
switch (run_mode) {
@ -377,20 +409,45 @@ run(char *name,
/* Mathmap the image */
if ((status == STATUS_SUCCESS) &&
(gimp_drawable_color(drawable->id) ||
gimp_drawable_gray(drawable->id))) {
if ((status == STATUS_SUCCESS)
&& (gimp_drawable_color(input_drawable->id)
|| gimp_drawable_gray(input_drawable->id)))
{
intersamplingEnabled = mmvals.flags & FLAG_INTERSAMPLING;
oversamplingEnabled = mmvals.flags & FLAG_OVERSAMPLING;
animationEnabled = mmvals.flags & FLAG_ANIMATION;
/* Set the tile cache size */
gimp_tile_cache_ntiles((drawable->width + gimp_tile_width() - 1) / gimp_tile_width());
gimp_tile_cache_ntiles((input_drawable->width + gimp_tile_width() - 1)
/ gimp_tile_width());
/* Run! */
mathmap();
if (animationEnabled)
{
int frameNum;
for (frameNum = 0; frameNum < mmvals.frames; ++frameNum)
{
gint32 layer;
char layerName[100];
currentT = (double)frameNum / (double)mmvals.frames;
layer = mathmap_layer_copy(layer_id);
sprintf(layerName, "kurdenlayer %d", frameNum);
gimp_layer_set_name(layer, layerName);
output_drawable = gimp_drawable_get(layer);
mathmap();
gimp_image_add_layer(image_id, layer, 0);
}
}
else
{
currentT = 0.0;
output_drawable = input_drawable;
mathmap();
}
/* If run mode is interactive, flush displays */
@ -406,7 +463,7 @@ run(char *name,
values[0].data.d_status = status;
gimp_drawable_detach(drawable);
gimp_drawable_detach(input_drawable);
} /* run */
@ -431,6 +488,27 @@ calc_ra (void)
}
}
static gint32
mathmap_layer_copy(gint32 layerID)
{
GParam *return_vals;
int nreturn_vals;
gint32 nlayer;
return_vals = gimp_run_procedure ("gimp_layer_copy",
&nreturn_vals,
PARAM_LAYER, layerID,
PARAM_INT32, TRUE,
PARAM_END);
if (return_vals[0].data.d_status == STATUS_SUCCESS)
nlayer = return_vals[1].data.d_layer;
else
nlayer = -1;
gimp_destroy_params(return_vals, nreturn_vals);
return nlayer;
}
static void
mathmap(void)
{
@ -440,15 +518,15 @@ mathmap(void)
guchar *dest_row;
guchar *dest;
gint row, col;
guchar pixel[4][4];
guchar values[4];
double cx, cy;
int ix, iy;
int i;
double result;
int red,
green,
blue;
blue,
alpha;
outputBPP = gimp_drawable_bpp(output_drawable->id);
theExprtree = 0;
@ -464,7 +542,7 @@ mathmap(void)
/* Initialize pixel region */
gimp_pixel_rgn_init(&dest_rgn, drawable, sel_x1, sel_y1, sel_width, sel_height,
gimp_pixel_rgn_init(&dest_rgn, output_drawable, sel_x1, sel_y1, sel_width, sel_height,
TRUE, TRUE);
imageWidth = sel_width;
@ -490,7 +568,7 @@ mathmap(void)
progress = 0;
max_progress = sel_width * sel_height;
gimp_progress_init("Mathmaping...");
gimp_progress_init("Mathmapping...");
for (pr = gimp_pixel_rgns_register(1, &dest_rgn);
pr != NULL; pr = gimp_pixel_rgns_process(pr))
@ -512,7 +590,7 @@ mathmap(void)
currentX = col + dest_rgn.x - sel_x1 - middleX;
currentY = 0.0 + dest_rgn.y - sel_y1 - middleY;
calc_ra(); result = eval_postfix();
double_to_color(result, &red, &green, &blue);
double_to_color(result, &red, &green, &blue, &alpha);
line1[col * 3 + 0] = red;
line1[col * 3 + 1] = green;
@ -528,7 +606,7 @@ mathmap(void)
currentX = col + dest_rgn.x - sel_x1 + 0.5 - middleX;
currentY = row + dest_rgn.y - sel_y1 + 0.5 - middleY;
calc_ra(); result = eval_postfix();
double_to_color(result, &red, &green, &blue);
double_to_color(result, &red, &green, &blue, &alpha);
line2[col * 3 + 0] = red;
line2[col * 3 + 1] = green;
@ -539,7 +617,7 @@ mathmap(void)
currentX = col + dest_rgn.x - sel_x1 - middleX;
currentY = row + dest_rgn.y - sel_y1 + 1.0 - middleY;
calc_ra(); result = eval_postfix();
double_to_color(result, &red, &green, &blue);
double_to_color(result, &red, &green, &blue, &alpha);
line3[col * 3 + 0] = red;
line3[col * 3 + 1] = green;
@ -567,7 +645,7 @@ mathmap(void)
dest[0] = red / 6;
dest[1] = green / 6;
dest[2] = blue / 6;
dest += img_bpp;
dest += outputBPP;
}
memcpy(line1, line3, (imageWidth + 1) * 3);
@ -589,18 +667,20 @@ mathmap(void)
iy = (int) cy;
currentX = col - sel_x1 - middleX; currentY = row - sel_y1 - middleY;
if (!intersamplingEnabled)
{
currentX += 0.5;
currentY += 0.5;
}
calc_ra(); result = eval_postfix();
double_to_color(result, &red, &green, &blue);
double_to_color(result, &red, &green, &blue, &alpha);
dest[0] = red;
dest[1] = green;
dest[2] = blue;
dest += img_bpp;
if (outputBPP == 2)
dest[1] = alpha;
else if (outputBPP >= 3)
{
dest[1] = green;
dest[2] = blue;
if (outputBPP == 4)
dest[3] = alpha;
}
dest += outputBPP;
}
dest_row += dest_rgn.rowstride;
@ -617,9 +697,9 @@ mathmap(void)
the_tile = NULL;
} /* if */
gimp_drawable_flush(drawable);
gimp_drawable_merge_shadow(drawable->id, TRUE);
gimp_drawable_update(drawable->id, sel_x1, sel_y1, sel_width, sel_height);
gimp_drawable_flush(output_drawable);
gimp_drawable_merge_shadow(output_drawable->id, TRUE);
gimp_drawable_update(output_drawable->id, sel_x1, sel_y1, sel_width, sel_height);
} /* mathmap */
@ -654,7 +734,7 @@ mathmap_get_pixel(int x, int y, guchar *pixel)
if (the_tile != NULL)
gimp_tile_unref(the_tile, FALSE);
the_tile = gimp_drawable_get_tile(drawable, FALSE, newrow, newcol);
the_tile = gimp_drawable_get_tile(input_drawable, FALSE, newrow, newcol);
assert(the_tile != 0);
gimp_tile_ref(the_tile);
@ -664,7 +744,7 @@ mathmap_get_pixel(int x, int y, guchar *pixel)
p = the_tile->data + the_tile->bpp * (the_tile->ewidth * newrowoff + newcoloff);
for (i = img_bpp; i; i--)
for (i = inputBPP; i; i--)
*pixel++ = *p++;
}
@ -703,7 +783,7 @@ build_preview_source_image(void)
{
mathmap_get_pixel((int) px, (int) py, pixel);
if (img_bpp < 3)
if (inputBPP < 3)
{
pixel[1] = pixel[0];
pixel[2] = pixel[0];
@ -727,12 +807,12 @@ static gint
mathmap_dialog(void)
{
GtkWidget *dialog;
GtkWidget *top_table;
GtkWidget *top_table,
*middle_table;
GtkWidget *frame;
GtkWidget *table;
GtkWidget *button;
GtkWidget *label;
GtkWidget *entry;
GtkWidget *toggle;
GtkWidget *arrow;
GtkWidget *alignment;
@ -741,6 +821,8 @@ mathmap_dialog(void)
GtkWidget *menubaritem;
GtkWidget *menu;
GtkWidget *item;
GtkWidget *scale;
GtkObject *adjustment;
int i;
gint argc;
gchar **argv;
@ -773,13 +855,13 @@ mathmap_dialog(void)
(GtkSignalFunc) dialog_close_callback,
NULL);
top_table = gtk_table_new(6, 3, FALSE);
top_table = gtk_table_new(5, 3, FALSE);
gtk_container_border_width(GTK_CONTAINER(top_table), 6);
gtk_table_set_row_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 */
/* Preview */
frame = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
@ -796,25 +878,112 @@ mathmap_dialog(void)
gtk_table_attach(GTK_TABLE(top_table), button, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
gtk_widget_show(button);
alignment = gtk_alignment_new(0, 0, 0, 0);
toggle = gtk_check_button_new_with_label("Intersampling");
gtk_container_add(GTK_CONTAINER(alignment), toggle);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(toggle), mmvals.flags & FLAG_INTERSAMPLING);
gtk_table_attach(GTK_TABLE(top_table), alignment, 0, 3, 2, 3, GTK_FILL, 0, 0, 0);
gtk_signal_connect(GTK_OBJECT(toggle), "toggled",
(GtkSignalFunc)dialog_intersampling_update, 0);
gtk_widget_show(toggle);
gtk_widget_show(alignment);
middle_table = gtk_table_new(1, 2, FALSE);
gtk_container_border_width(GTK_CONTAINER(middle_table), 6);
gtk_table_set_col_spacings(GTK_TABLE(middle_table), 4);
gtk_table_attach(GTK_TABLE(top_table), middle_table, 0, 3, 2, 3, GTK_FILL, 0, 0, 0);
gtk_widget_show(middle_table);
alignment = gtk_alignment_new(0, 0, 0, 0);
toggle = gtk_check_button_new_with_label("Oversampling");
gtk_container_add(GTK_CONTAINER(alignment), toggle);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(toggle), mmvals.flags & FLAG_OVERSAMPLING);
gtk_table_attach(GTK_TABLE(top_table), alignment, 0, 3, 3, 4, GTK_FILL, 0, 0, 0);
gtk_signal_connect(GTK_OBJECT(toggle), "toggled",
(GtkSignalFunc)dialog_oversampling_update, 0);
gtk_widget_show(toggle);
gtk_widget_show(alignment);
/* Sampling */
table = gtk_table_new(2, 1, FALSE);
gtk_container_border_width(GTK_CONTAINER(table), 6);
gtk_table_set_row_spacings(GTK_TABLE(table), 4);
frame = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
gtk_container_add(GTK_CONTAINER(frame), table);
alignment = gtk_alignment_new(0, 0, 0, 0);
gtk_container_add(GTK_CONTAINER(alignment), frame);
gtk_table_attach(GTK_TABLE(middle_table), alignment, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
gtk_widget_show(table);
gtk_widget_show(frame);
gtk_widget_show(alignment);
/* Intersampling */
alignment = gtk_alignment_new(0, 0, 0, 0);
toggle = gtk_check_button_new_with_label("Intersampling");
gtk_container_add(GTK_CONTAINER(alignment), toggle);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(toggle),
mmvals.flags & FLAG_INTERSAMPLING);
gtk_table_attach(GTK_TABLE(table), alignment, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
gtk_signal_connect(GTK_OBJECT(toggle), "toggled",
(GtkSignalFunc)dialog_intersampling_update, 0);
gtk_widget_show(toggle);
gtk_widget_show(alignment);
/* Oversampling */
alignment = gtk_alignment_new(0, 0, 0, 0);
toggle = gtk_check_button_new_with_label("Oversampling");
gtk_container_add(GTK_CONTAINER(alignment), toggle);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(toggle),
mmvals.flags & FLAG_OVERSAMPLING);
gtk_table_attach(GTK_TABLE(table), alignment, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
gtk_signal_connect(GTK_OBJECT(toggle), "toggled",
(GtkSignalFunc)dialog_oversampling_update, 0);
gtk_widget_show(toggle);
gtk_widget_show(alignment);
/* Animation */
table = gtk_table_new(2, 1, FALSE);
gtk_container_border_width(GTK_CONTAINER(table), 6);
gtk_table_set_row_spacings(GTK_TABLE(table), 4);
gtk_table_set_col_spacings(GTK_TABLE(table), 4);
frame = gtk_frame_new(NULL);
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
gtk_container_add(GTK_CONTAINER(frame), table);
alignment = gtk_alignment_new(0, 0, 0, 0);
gtk_container_add(GTK_CONTAINER(alignment), frame);
gtk_table_attach(GTK_TABLE(middle_table), alignment, 1, 2, 0, 1, GTK_FILL, 0, 0, 0);
gtk_widget_show(table);
gtk_widget_show(frame);
gtk_widget_show(alignment);
/* Animation Toggle */
alignment = gtk_alignment_new(0, 0, 0, 0);
toggle = gtk_check_button_new_with_label("Animate");
gtk_container_add(GTK_CONTAINER(alignment), toggle);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(toggle),
mmvals.flags & FLAG_ANIMATION);
gtk_table_attach(GTK_TABLE(table), alignment, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
gtk_signal_connect(GTK_OBJECT(toggle), "toggled",
(GtkSignalFunc)dialog_animation_update, 0);
gtk_widget_show(toggle);
gtk_widget_show(alignment);
/* Number of Frames */
animate_table = gtk_table_new(1, 2, FALSE);
gtk_table_set_col_spacings(GTK_TABLE(animate_table), 4);
gtk_table_attach(GTK_TABLE(table), animate_table, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
label = gtk_label_new("Frames");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(animate_table), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
adjustment = gtk_adjustment_new(mmvals.frames, 2, 100, 1.0, 1.0, 0.0);
scale = gtk_hscale_new(GTK_ADJUSTMENT(adjustment));
gtk_widget_set_usize(scale, 100, 0);
gtk_table_attach (GTK_TABLE (animate_table), scale, 1, 2, 0, 1, GTK_FILL, 0, 0, 0);
gtk_scale_set_value_pos (GTK_SCALE (scale), GTK_POS_TOP);
gtk_scale_set_digits(GTK_SCALE(scale),0);
gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
(GtkSignalFunc) dialog_scale_update,
&mmvals.frames);
gtk_widget_show(label);
gtk_widget_show(scale);
gtk_widget_show(animate_table);
gtk_widget_set_sensitive(animate_table, mmvals.flags & FLAG_ANIMATION);
/* Menu */
@ -824,7 +993,8 @@ mathmap_dialog(void)
{
item = gtk_menu_item_new_with_label(examples[i][0]);
gtk_menu_append(GTK_MENU(menu), item);
gtk_signal_connect(GTK_OBJECT(item), "activate", (GtkSignalFunc)dialog_example_callback, examples[i][1]);
gtk_signal_connect(GTK_OBJECT(item), "activate",
(GtkSignalFunc)dialog_example_callback, examples[i][1]);
gtk_widget_show(item);
}
@ -843,7 +1013,7 @@ mathmap_dialog(void)
gtk_container_add(GTK_CONTAINER(menubar), menubaritem);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menubaritem), menu);
gtk_table_attach(GTK_TABLE(top_table), alignment, 0, 3, 4, 5, GTK_FILL, 0, 0, 0);
gtk_table_attach(GTK_TABLE(top_table), alignment, 0, 3, 3, 4, GTK_FILL, 0, 0, 0);
gtk_widget_show(arrow);
gtk_widget_show(label);
@ -856,7 +1026,7 @@ mathmap_dialog(void)
table = gtk_table_new(1, 2, FALSE);
gtk_container_border_width(GTK_CONTAINER(table), 0);
gtk_table_attach(GTK_TABLE(top_table), table, 0, 3, 5, 6, GTK_EXPAND | GTK_FILL, 0, 0, 0);
gtk_table_attach(GTK_TABLE(top_table), table, 0, 3, 4, 5, GTK_EXPAND | GTK_FILL, 0, 0, 0);
gtk_widget_show(table);
label = gtk_label_new("Expression");
@ -864,19 +1034,19 @@ mathmap_dialog(void)
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(label);
expressionEntry = gtk_entry_new();
expression_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(expressionEntry, ENTRY_WIDTH, 0);
gtk_entry_set_text(GTK_ENTRY(expressionEntry), mmvals.expression);
gtk_signal_connect(GTK_OBJECT(expressionEntry), "changed",
gtk_widget_set_usize(expression_entry, ENTRY_WIDTH, 0);
gtk_entry_set_text(GTK_ENTRY(expression_entry), mmvals.expression);
gtk_signal_connect(GTK_OBJECT(expression_entry), "changed",
(GtkSignalFunc) dialog_entry_update,
0);
gtk_table_attach(GTK_TABLE(table), expressionEntry, 1, 2, 0, 1,
gtk_table_attach(GTK_TABLE(table), expression_entry, 1, 2, 0, 1,
GTK_EXPAND | GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(expressionEntry);
gtk_widget_show(expression_entry);
/* Buttons */
@ -926,11 +1096,9 @@ dialog_update_preview(void)
{
double left, right, bottom, top;
double dx, dy;
double cx, cy;
int ix, iy;
int x, y;
double scale_x, scale_y;
guchar *p_ul, *p_lr, *i, *p;
guchar *p_ul, *p_lr, *p;
intersamplingEnabled = mmvals.flags & FLAG_INTERSAMPLING;
oversamplingEnabled = mmvals.flags & FLAG_OVERSAMPLING;
@ -985,12 +1153,13 @@ dialog_update_preview(void)
double result;
int red,
green,
blue;
blue,
alpha;
currentX = x * imageWidth / preview_width - middleX;
currentY = y * imageHeight / preview_height - middleY;
calc_ra(); result = eval_postfix();
double_to_color(result, &red, &green, &blue);
double_to_color(result, &red, &green, &blue, &alpha);
p_ul[0] = red;
p_ul[1] = green;
@ -1016,6 +1185,7 @@ dialog_update_preview(void)
/*****/
/*
static void
dialog_create_value(char *title, GtkTable *table, int row, gdouble *value,
double left, double right)
@ -1059,36 +1229,23 @@ dialog_create_value(char *title, GtkTable *table, int row, gdouble *value,
value);
gtk_table_attach(GTK_TABLE(table), entry, 2, 3, row, row + 1, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(entry);
} /* dialog_create_value */
}
*/
/*****/
static void
dialog_scale_update(GtkAdjustment *adjustment, gdouble *value)
dialog_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, "%0.2f", *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);
/* dialog_update_preview(); */
} /* if */
*value = (gint)adjustment->value;
} /* dialog_scale_update */
/*****/
static void
dialog_entry_update(GtkWidget *widget, gdouble *value)
dialog_entry_update(GtkWidget *widget, gpointer value)
{
expression_copy(mmvals.expression, gtk_entry_get_text(GTK_ENTRY(widget)));
} /* dialog_entry_update */
@ -1117,10 +1274,23 @@ dialog_intersampling_update (GtkWidget *widget, gpointer data)
/*****/
static void
dialog_animation_update (GtkWidget *widget, gpointer data)
{
mmvals.flags &= ~FLAG_ANIMATION;
if (GTK_TOGGLE_BUTTON(widget)->active)
mmvals.flags |= FLAG_ANIMATION;
gtk_widget_set_sensitive(animate_table, mmvals.flags & FLAG_ANIMATION);
}
/*****/
static void
dialog_example_callback (GtkWidget *widget, char *expression)
{
gtk_entry_set_text(GTK_ENTRY(expressionEntry), expression);
gtk_entry_set_text(GTK_ENTRY(expression_entry), expression);
}
/*****/

View File

@ -2,6 +2,7 @@
#include <stdio.h>
#include "exprtree.h"
#include "builtins.h"
extern exprtree *theExprtree;
%}
@ -9,17 +10,21 @@ extern exprtree *theExprtree;
%union {
ident ident;
exprtree *exprtree;
builtin *builtin;
}
%token T_IDENT T_NUMBER
%token T_IF T_THEN T_ELSE T_END
%token T_WHILE T_DO
%token T_BUILTIN
%right ';'
%right '='
%left T_OR T_AND
%left T_EQUAL '<' '>' T_LESSEQUAL T_GREATEREQUAL T_NOTEQUAL
%left '+' '-'
%left '*' '/' '%'
%left NEG
%left UNARY
%%
@ -38,10 +43,32 @@ expr : T_NUMBER { $<exprtree>$ = $<exprtree>1; }
$<exprtree>1, $<exprtree>3); }
| expr '%' expr { $<exprtree>$ = make_operator(EXPR_MOD,
$<exprtree>1, $<exprtree>3); }
| '-' expr %prec NEG { $<exprtree>$ = make_operator(EXPR_NEG, $<exprtree>2, 0); }
| expr T_EQUAL expr { $<exprtree>$ = make_function(builtin_with_name("equal"),
arglist_append($<exprtree>1, $<exprtree>3)); }
| expr '<' expr { $<exprtree>$ = make_function(builtin_with_name("less"),
arglist_append($<exprtree>1, $<exprtree>3)); }
| expr '>' expr { $<exprtree>$ = make_function(builtin_with_name("greater"),
arglist_append($<exprtree>1, $<exprtree>3)); }
| expr T_LESSEQUAL expr
{ $<exprtree>$ = make_function(builtin_with_name("lessequal"),
arglist_append($<exprtree>1, $<exprtree>3)); }
| expr T_GREATEREQUAL expr
{ $<exprtree>$ = make_function(builtin_with_name("greaterequal"),
arglist_append($<exprtree>1, $<exprtree>3)); }
| expr T_NOTEQUAL expr
{ $<exprtree>$ = make_function(builtin_with_name("notequal"),
arglist_append($<exprtree>1, $<exprtree>3)); }
| expr T_OR expr { $<exprtree>$ = make_function(builtin_with_name("or"),
arglist_append($<exprtree>1, $<exprtree>3)); }
| expr T_AND expr { $<exprtree>$ = make_function(builtin_with_name("and"),
arglist_append($<exprtree>1, $<exprtree>3)); }
| '-' expr %prec UNARY
{ $<exprtree>$ = make_operator(EXPR_NEG, $<exprtree>2, 0); }
| '!' expr %prec UNARY
{ $<exprtree>$ = make_function(builtin_with_name("not"), $<exprtree>2); }
| '(' expr ')' { $<exprtree>$ = $<exprtree>2; };
| T_IDENT '(' arglist ')'
{ $<exprtree>$ = make_function($<ident>1, $<exprtree>3); }
| T_BUILTIN '(' arglist ')'
{ $<exprtree>$ = make_function($<builtin>1, $<exprtree>3); }
| T_IDENT '=' expr { $<exprtree>$ = make_assignment($<ident>1, $<exprtree>3); }
| expr ';' expr { $<exprtree>$ = make_sequence($<exprtree>1, $<exprtree>3); }
| T_IF expr T_THEN expr T_END

View File

@ -9,6 +9,7 @@
extern double currentX,
currentY,
currentT,
currentR,
currentA,
imageR,
@ -142,6 +143,12 @@ stack_var_y (void *arg)
stack[stackp++] = currentY;
}
void
stack_var_t (void *arg)
{
stack[stackp++] = currentT;
}
void
stack_var_r (void *arg)
{
@ -307,6 +314,10 @@ make_postfix_recursive (exprtree *tree)
expression[exprp++].func = stack_var_y;
break;
case EXPR_VAR_T :
expression[exprp++].func = stack_var_t;
break;
case EXPR_VAR_R :
expression[exprp++].func = stack_var_r;
break;
@ -487,6 +498,8 @@ output_postfix (void)
printf("push x\n");
else if (expression[i].func == stack_var_y)
printf("push y\n");
else if (expression[i].func == stack_var_t)
printf("push t\n");
else if (expression[i].func == stack_var_r)
printf("push r\n");
else if (expression[i].func == stack_var_a)
@ -505,6 +518,7 @@ output_postfix (void)
printf("push %s\n", ((variable*)expression[i].arg)->name);
else if (expression[i].func == (stackfunc)stack_assign)
printf("sto %s\n", ((variable*)expression[i].arg)->name);
/*
else if (expression[i].func == builtin_sin)
printf("sin\n");
else if (expression[i].func == builtin_cos)
@ -537,6 +551,7 @@ output_postfix (void)
printf("origValRA\n");
else if (expression[i].func == builtin_grayColor)
printf("grayColor\n");
*/
else
printf("unknown opcode\n");
}

View File

@ -2,7 +2,8 @@
#include <string.h>
#include "exprtree.h"
#include "parser.tab.h"
#include "builtins.h"
#include "parser.h"
%}
%option noyywrap
@ -15,13 +16,30 @@ else return T_ELSE;
end return T_END;
while return T_WHILE;
do return T_DO;
[a-zA-Z_][a-zA-Z0-9_]* { strncpy(yylval.ident, yytext, 63);
yylval.ident[63] = 0;
return T_IDENT;
[a-zA-Z_][a-zA-Z0-9_]* {
builtin *theBuiltin = builtin_with_name(yytext);
if (theBuiltin != 0)
{
yylval.builtin = theBuiltin;
return T_BUILTIN;
}
else
{
strncpy(yylval.ident, yytext, MAX_IDENT_LENGTH);
yylval.ident[MAX_IDENT_LENGTH] = 0;
return T_IDENT;
}
}
[0-9]+ { yylval.exprtree = make_number(atof(yytext)); return T_NUMBER; }
[0-9]*\.[0-9]+ { yylval.exprtree = make_number(atof(yytext)); return T_NUMBER; }
[-,()+*/%=;] return yytext[0];
"==" return T_EQUAL;
"<=" return T_LESSEQUAL;
">=" return T_GREATEREQUAL;
"!=" return T_NOTEQUAL;
"||" return T_OR;
"&&" return T_AND;
[-<>!,()+*/%=;] return yytext[0];
#.* ;
[ \t\n] ;

View File

@ -1,4 +1,5 @@
#include <assert.h>
#include <stdlib.h>
#include "vars.h"

View File

@ -3,7 +3,7 @@
*
* Print plug-in EPSON ESC/P2 driver for the GIMP.
*
* Copyright 1997 Michael Sweet (mike@easysw.com)
* Copyright 1997-1998 Michael Sweet (mike@easysw.com)
*
* 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
@ -27,21 +27,15 @@
* Revision History:
*
* $Log$
* Revision 1.1.1.1 1997/11/24 22:04:34 sopwith
* Let's try this import one last time.
* Revision 1.2 1998/01/25 09:29:25 yosh
* Plugin updates
* Properly generated aa Makefile (still not built by default)
* Sven's no args script patch
*
* Revision 1.3 1997/11/18 03:04:25 nobody
* fixed ugly comment-bugs introduced by evil darkwing
* keep out configuration empty dirs
* --darkwing
* -Yosh
*
* Revision 1.2 1997/11/17 05:43:56 nobody
* updated ChangeLog
* dropped non-working doc/Makefile entries
* applied many fixes from the registry as well as the devel ML
* applied missing patches by Art Haas
*
* --darkwing
* Revision 1.8 1998/01/21 21:33:47 mike
* Updated copyright.
*
* Revision 1.7 1997/11/12 15:57:48 mike
* Minor changes for clean compiles under Digital UNIX.

View File

@ -3,7 +3,7 @@
*
* Print plug-in HP PCL driver for the GIMP.
*
* Copyright 1997 Michael Sweet (mike@easysw.com)
* Copyright 1997-1998 Michael Sweet (mike@easysw.com)
*
* 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
@ -28,21 +28,15 @@
* Revision History:
*
* $Log$
* Revision 1.1.1.1 1997/11/24 22:04:34 sopwith
* Let's try this import one last time.
* Revision 1.2 1998/01/25 09:29:26 yosh
* Plugin updates
* Properly generated aa Makefile (still not built by default)
* Sven's no args script patch
*
* Revision 1.3 1997/11/18 03:04:26 nobody
* fixed ugly comment-bugs introduced by evil darkwing
* keep out configuration empty dirs
* --darkwing
* -Yosh
*
* Revision 1.2 1997/11/17 05:43:56 nobody
* updated ChangeLog
* dropped non-working doc/Makefile entries
* applied many fixes from the registry as well as the devel ML
* applied missing patches by Art Haas
*
* --darkwing
* Revision 1.8 1998/01/21 21:33:47 mike
* Updated copyright.
*
* Revision 1.7 1997/11/12 15:57:48 mike
* Minor changes for clean compiles under Digital UNIX.

View File

@ -3,7 +3,7 @@
*
* Print plug-in Adobe PostScript driver for the GIMP.
*
* Copyright 1997 Michael Sweet (mike@easysw.com)
* Copyright 1997-1998 Michael Sweet (mike@easysw.com)
*
* 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
@ -21,27 +21,27 @@
*
* Contents:
*
* ps_print() - Print an image to a PostScript printer.
* ps_hex() - Print binary data as a series of hexadecimal numbers.
* ps_print() - Print an image to a PostScript printer.
* ps_hex() - Print binary data as a series of hexadecimal numbers.
* ps_ascii85() - Print binary data as a series of base-85 numbers.
*
* Revision History:
*
* $Log$
* Revision 1.1.1.1 1997/11/24 22:04:34 sopwith
* Let's try this import one last time.
* Revision 1.2 1998/01/25 09:29:27 yosh
* Plugin updates
* Properly generated aa Makefile (still not built by default)
* Sven's no args script patch
*
* Revision 1.3 1997/11/18 03:04:26 nobody
* fixed ugly comment-bugs introduced by evil darkwing
* keep out configuration empty dirs
* --darkwing
* -Yosh
*
* Revision 1.2 1997/11/17 05:43:57 nobody
* updated ChangeLog
* dropped non-working doc/Makefile entries
* applied many fixes from the registry as well as the devel ML
* applied missing patches by Art Haas
* Revision 1.10 1998/01/22 15:38:46 mike
* Updated copyright notice.
* Whoops - wasn't encoding correctly for portrait output to level 2 printers!
*
* --darkwing
* Revision 1.9 1998/01/21 21:33:47 mike
* Added support for Level 2 filters; images are now sent in hex or
* base-85 ASCII as necessary (faster printing).
*
* Revision 1.8 1997/11/12 15:57:48 mike
* Minor changes for clean compiles under Digital UNIX.
@ -86,6 +86,7 @@
*/
static void ps_hex(FILE *, guchar *, int);
static void ps_ascii85(FILE *, guchar *, int, int);
/*
@ -117,11 +118,18 @@ ps_print(FILE *prn, /* I - File to print to */
out_width, /* Width of image on page */
out_height, /* Height of image on page */
out_bpp, /* Output bytes per pixel */
out_length, /* Output length (Level 2 output) */
out_offset, /* Output offset (Level 2 output) */
temp_width, /* Temporary width of image on page */
temp_height, /* Temporary height of image on page */
landscape; /* True if we rotate the output 90 degrees */
time_t curtime; /* Current time of day */
convert_t colorfunc; /* Color conversion function... */
static char *filters[2] = /* PostScript image filters... */
{
"{currentfile picture readhexstring pop}", /* Level 1 */
"currentfile /ASCII85Decode filter" /* Level 2 */
};
/*
@ -226,12 +234,12 @@ ps_print(FILE *prn, /* I - File to print to */
fputs("%!PS-Adobe-3.0\n", prn);
fputs("%%Creator: " PLUG_IN_NAME " plug-in V" PLUG_IN_VERSION " for GIMP.\n", prn);
fprintf(prn, "%%%%CreationDate: %s", ctime(&curtime));
fputs("%%Copyright: 1997 by Michael Sweet (mike@easysw.com)\n", prn);
fputs("%%Copyright: 1997-1998 by Michael Sweet (mike@easysw.com)\n", prn);
fprintf(prn, "%%%%BoundingBox: %d %d %d %d\n",
(page_width - out_width) / 2 + 18, (page_height - out_height) / 2 + 36,
(page_width + out_width) / 2 + 18, (page_height + out_height) / 2 + 36);
fputs("%%DocumentData: Clean7Bit\n", prn);
fprintf(prn, "%%%%LanguageLevel: %d\n", output_type + 1);
fprintf(prn, "%%%%LanguageLevel: %d\n", model + 1);
fputs("%%Pages: 1\n", prn);
fputs("%%Orientation: Portrait\n", prn);
fputs("%%EndComments\n", prn);
@ -260,55 +268,99 @@ ps_print(FILE *prn, /* I - File to print to */
if (landscape)
{
in = g_malloc(drawable->height * drawable->bpp);
out = g_malloc(drawable->height * out_bpp);
out = g_malloc(drawable->height * out_bpp + 3);
fprintf(prn, "/picture %d string def\n", drawable->height * out_bpp);
if (model == 0)
fprintf(prn, "/picture %d string def\n", drawable->height * out_bpp);
if (output_type == OUTPUT_GRAY)
fprintf(prn, "%d %d 8 [%d 0 0 %d 0 %d] {currentfile picture readhexstring pop} image\n",
fprintf(prn, "%d %d 8 [%d 0 0 %d 0 %d] %s image\n",
drawable->height, drawable->width,
drawable->height, drawable->width, 0);
drawable->height, drawable->width, 0,
filters[model]);
else
fprintf(prn, "%d %d 8 [%d 0 0 %d 0 %d] {currentfile picture readhexstring pop} false 3 colorimage\n",
fprintf(prn, "%d %d 8 [%d 0 0 %d 0 %d] %s false 3 colorimage\n",
drawable->height, drawable->width,
drawable->height, drawable->width, 0);
drawable->height, drawable->width, 0,
filters[model]);
for (x = 0; x < drawable->width; x ++)
for (x = 0, out_offset = 0; x < drawable->width; x ++)
{
if ((x & 15) == 0)
gimp_progress_update((double)x / (double)drawable->width);
gimp_pixel_rgn_get_col(&rgn, in, x, 0, drawable->height);
(*colorfunc)(in, out, drawable->height, drawable->bpp, lut, cmap);
(*colorfunc)(in, out + out_offset, drawable->height, drawable->bpp, lut, cmap);
ps_hex(prn, out, drawable->height * out_bpp);
if (model)
{
out_length = out_offset + drawable->height * out_bpp;
if (x < (drawable->width - 1))
{
ps_ascii85(prn, out, out_length & ~3, 0);
out_offset = out_length & 3;
}
else
{
ps_ascii85(prn, out, out_length, 1);
out_offset = 0;
};
if (out_offset > 0)
memcpy(out, out + out_length - out_offset, out_offset);
}
else
ps_hex(prn, out, drawable->height * out_bpp);
};
}
else
{
in = g_malloc(drawable->width * drawable->bpp);
out = g_malloc(drawable->width * out_bpp);
out = g_malloc(drawable->width * out_bpp + 3);
fprintf(prn, "/picture %d string def\n", drawable->width * out_bpp);
if (model == 0)
fprintf(prn, "/picture %d string def\n", drawable->width * out_bpp);
if (output_type == OUTPUT_GRAY)
fprintf(prn, "%d %d 8 [%d 0 0 %d 0 %d] {currentfile picture readhexstring pop} image\n",
fprintf(prn, "%d %d 8 [%d 0 0 %d 0 %d] %s image\n",
drawable->width, drawable->height,
drawable->width, -drawable->height, drawable->height);
drawable->width, -drawable->height, drawable->height,
filters[model]);
else
fprintf(prn, "%d %d 8 [%d 0 0 %d 0 %d] {currentfile picture readhexstring pop} false 3 colorimage\n",
fprintf(prn, "%d %d 8 [%d 0 0 %d 0 %d] %s false 3 colorimage\n",
drawable->width, drawable->height,
drawable->width, -drawable->height, drawable->height);
drawable->width, -drawable->height, drawable->height,
filters[model]);
for (y = 0; y < drawable->height; y ++)
for (y = 0, out_offset = 0; y < drawable->height; y ++)
{
if ((y & 15) == 0)
gimp_progress_update((double)y / (double)drawable->height);
gimp_pixel_rgn_get_row(&rgn, in, 0, y, drawable->width);
(*colorfunc)(in, out, drawable->width, drawable->bpp, lut, cmap);
(*colorfunc)(in, out + out_offset, drawable->width, drawable->bpp, lut, cmap);
ps_hex(prn, out, drawable->width * out_bpp);
if (model)
{
out_length = out_offset + drawable->width * out_bpp;
if (y < (drawable->height - 1))
{
ps_ascii85(prn, out, out_length & ~3, 0);
out_offset = out_length & 3;
}
else
{
ps_ascii85(prn, out, out_length, 1);
out_offset = 0;
};
if (out_offset > 0)
memcpy(out, out + out_length - out_offset, out_offset);
}
else
ps_hex(prn, out, drawable->width * out_bpp);
};
};
@ -352,6 +404,77 @@ ps_hex(FILE *prn, /* I - File to print to */
}
/*
* 'ps_ascii85()' - Print binary data as a series of base-85 numbers.
*/
static void
ps_ascii85(FILE *prn, /* I - File to print to */
guchar *data, /* I - Data to print */
int length, /* I - Number of bytes to print */
int last_line) /* I - Last line of raster data? */
{
unsigned b; /* Binary data word */
unsigned char c[5]; /* ASCII85 encoded chars */
int col; /* Current column */
col = 0;
while (length > 3)
{
b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
if (b == 0)
putc('z', prn);
else
{
c[4] = (b % 85) + '!';
b /= 85;
c[3] = (b % 85) + '!';
b /= 85;
c[2] = (b % 85) + '!';
b /= 85;
c[1] = (b % 85) + '!';
b /= 85;
c[0] = b + '!';
fwrite(c, 5, 1, prn);
};
data += 4;
length -= 4;
col = (col + 1) & 15;
if (col == 0 && length > 0)
putc('\n', prn);
};
if (last_line)
{
if (length > 0)
{
for (b = 0, col = length; col > 0; b = (b << 8) | data[0], data ++, col --);
c[4] = (b % 85) + '!';
b /= 85;
c[3] = (b % 85) + '!';
b /= 85;
c[2] = (b % 85) + '!';
b /= 85;
c[1] = (b % 85) + '!';
b /= 85;
c[0] = b + '!';
fwrite(c, length + 1, 1, prn);
};
fputs("~>\n", prn);
}
else
putc('\n', prn);
}
/*
* End of "$Id$".
*/

View File

@ -3,7 +3,7 @@
*
* Print plug-in driver utility functions for the GIMP.
*
* Copyright 1997 Michael Sweet (mike@easysw.com)
* Copyright 1997-1998 Michael Sweet (mike@easysw.com)
*
* 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
@ -35,21 +35,15 @@
* Revision History:
*
* $Log$
* Revision 1.1.1.1 1997/11/24 22:04:34 sopwith
* Let's try this import one last time.
* Revision 1.2 1998/01/25 09:29:27 yosh
* Plugin updates
* Properly generated aa Makefile (still not built by default)
* Sven's no args script patch
*
* Revision 1.3 1997/11/18 03:04:26 nobody
* fixed ugly comment-bugs introduced by evil darkwing
* keep out configuration empty dirs
* --darkwing
* -Yosh
*
* Revision 1.2 1997/11/17 05:43:57 nobody
* updated ChangeLog
* dropped non-working doc/Makefile entries
* applied many fixes from the registry as well as the devel ML
* applied missing patches by Art Haas
*
* --darkwing
* Revision 1.8 1998/01/21 21:33:47 mike
* Replaced Burkes dither with stochastic (random) dither.
*
* Revision 1.7 1997/10/02 17:57:26 mike
* Replaced ordered dither with Burkes dither (error-diffusion).
@ -127,44 +121,51 @@ dither_black(guchar *gray, /* I - Grayscale pixels */
unsigned char bit, /* Current bit */
*kptr; /* Current black pixel */
int k, /* Current black error */
ditherk, /* Next error value in buffer */
*kerror0, /* Pointer to current error row */
*kerror1; /* Pointer to next error row */
int ditherbit; /* Random dithering bitmask */
xstep = src_width / dst_width;
xmod = src_width % dst_width;
length = (dst_width + 7) / 8;
kerror0 = error[row & 1][3] + 2;
kerror1 = error[1 - (row & 1)][3] + 2;
kerror0 = error[row & 1][3] + 1;
kerror1 = error[1 - (row & 1)][3] + 1;
kerror1[0] = 0;
kerror1[1] = 0;
memset(black, 0, length);
for (x = 0, bit = 128, kptr = black, xerror = 0;
for (x = 0, bit = 128, kptr = black, xerror = 0,
ditherbit = rand(), ditherk = *kerror0;
x < dst_width;
x ++, kerror0 ++, kerror1 ++)
{
k = 255 - *gray + *kerror0;
k = 255 - *gray + ditherk / 4;
if (k > 127)
{
*kptr |= bit;
k -= 255;
};
kerror0[1] += k / 4;
kerror0[2] += k / 8;
kerror1[-2] += k / 16;
kerror1[-1] += k / 8;
kerror1[0] += k / 4;
kerror1[1] += k / 8;
kerror1[2] = k / 16;
if (ditherbit & bit)
{
kerror1[0] = 3 * k;
ditherk = kerror0[1] + k;
}
else
{
kerror1[0] = k;
ditherk = kerror0[1] + 3 * k;
};
if (bit == 1)
{
kptr ++;
bit = 128;
bit = 128;
ditherbit = rand();
}
else
bit >>= 1;
@ -205,18 +206,19 @@ dither_cmyk(guchar *rgb, /* I - RGB pixels */
*mptr, /* Current magenta pixel */
*yptr, /* Current yellow pixel */
*kptr; /* Current black pixel */
int cerror, /* Current cyan error */
int ditherc, /* Next error value in buffer */
*cerror0, /* Pointer to current error row */
*cerror1; /* Pointer to next error row */
int yerror, /* Current yellow error */
int dithery, /* Next error value in buffer */
*yerror0, /* Pointer to current error row */
*yerror1; /* Pointer to next error row */
int merror, /* Current magenta error */
int ditherm, /* Next error value in buffer */
*merror0, /* Pointer to current error row */
*merror1; /* Pointer to next error row */
int kerror, /* Current black error */
int ditherk, /* Next error value in buffer */
*kerror0, /* Pointer to current error row */
*kerror1; /* Pointer to next error row */
int ditherbit; /* Random dither bitmask */
xstep = 3 * (src_width / dst_width);
@ -250,7 +252,8 @@ dither_cmyk(guchar *rgb, /* I - RGB pixels */
memset(black, 0, length);
for (x = 0, bit = 128, cptr = cyan, mptr = magenta, yptr = yellow, kptr=black,
xerror = 0;
xerror = 0, ditherbit = rand(), ditherc = cerror0[0],
ditherm = merror0[0], dithery = yerror0[0], ditherk = kerror0[0];
x < dst_width;
x ++, cerror0 ++, cerror1 ++, merror0 ++, merror1 ++, yerror0 ++,
yerror1 ++, kerror0 ++, kerror1 ++)
@ -272,76 +275,89 @@ dither_cmyk(guchar *rgb, /* I - RGB pixels */
y = 255 * (y - k) / ik;
};
k += *kerror0;
k += ditherk / 4;
if (k > 127)
{
*kptr |= bit;
k -= 255;
};
kerror0[1] += k / 4;
kerror0[2] += k / 8;
kerror1[-2] += k / 16;
kerror1[-1] += k / 8;
kerror1[0] += k / 4;
kerror1[1] += k / 8;
kerror1[2] = k / 16;
if (ditherbit & bit)
{
kerror1[0] = 3 * k;
ditherk = kerror0[1] + k;
}
else
{
kerror1[0] = k;
ditherk = kerror0[1] + 3 * k;
};
if (bit == 1)
kptr ++;
};
c += *cerror0;
c += ditherc / 4;
if (c > 127)
{
*cptr |= bit;
c -= 255;
};
cerror0[1] += c / 4;
cerror0[2] += c / 8;
cerror1[-2] += c / 16;
cerror1[-1] += c / 8;
cerror1[0] += c / 4;
cerror1[1] += c / 8;
cerror1[2] = c / 16;
if (ditherbit & bit)
{
cerror1[0] = 3 * c;
ditherc = cerror0[1] + c;
}
else
{
cerror1[0] = c;
ditherc = cerror0[1] + 3 * c;
};
m += *merror0;
m += ditherm / 4;
if (m > 127)
{
*mptr |= bit;
m -= 255;
};
merror0[1] += m / 4;
merror0[2] += m / 8;
merror1[-2] += m / 16;
merror1[-1] += m / 8;
merror1[0] += m / 4;
merror1[1] += m / 8;
merror1[2] = m / 16;
if (ditherbit & bit)
{
merror1[0] = 3 * m;
ditherm = merror0[1] + m;
}
else
{
merror1[0] = m;
ditherm = merror0[1] + 3 * m;
};
y += *yerror0;
y += dithery / 4;
if (y > 127)
{
*yptr |= bit;
y -= 255;
};
yerror0[1] += y / 4;
yerror0[2] += y / 8;
yerror1[-2] += y / 16;
yerror1[-1] += y / 8;
yerror1[0] += y / 4;
yerror1[1] += y / 8;
yerror1[2] = y / 16;
if (ditherbit & bit)
{
yerror1[0] = 3 * y;
dithery = yerror0[1] + y;
}
else
{
yerror1[0] = y;
dithery = yerror0[1] + 3 * y;
};
if (bit == 1)
{
cptr ++;
mptr ++;
yptr ++;
bit = 128;
bit = 128;
ditherbit = rand();
}
else
bit >>= 1;

View File

@ -3,7 +3,7 @@
*
* Print plug-in for the GIMP.
*
* Copyright 1997 Michael Sweet (mike@easysw.com)
* Copyright 1997-1998 Michael Sweet (mike@easysw.com)
*
* 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
@ -39,21 +39,22 @@
* Revision History:
*
* $Log$
* Revision 1.1.1.1 1997/11/24 22:04:34 sopwith
* Let's try this import one last time.
* Revision 1.2 1998/01/25 09:29:27 yosh
* Plugin updates
* Properly generated aa Makefile (still not built by default)
* Sven's no args script patch
*
* Revision 1.3 1997/11/18 03:04:27 nobody
* fixed ugly comment-bugs introduced by evil darkwing
* keep out configuration empty dirs
* --darkwing
* -Yosh
*
* Revision 1.2 1997/11/17 05:43:57 nobody
* updated ChangeLog
* dropped non-working doc/Makefile entries
* applied many fixes from the registry as well as the devel ML
* applied missing patches by Art Haas
* Revision 1.13 1998/01/22 15:06:31 mike
* Added "file" printer for printing to file.
* Now you don't need the "|" in front of print commands.
* Now "remembers" last selected printer.
*
* --darkwing
* Revision 1.12 1998/01/21 21:33:47 mike
* Added Level 2 PostScript driver.
* Fixed bug in dialog - didn't display correct output file/command
* and driver for the default printer.
*
* Revision 1.11 1997/11/14 17:17:59 mike
* Updated to dynamically allocate return params in the run() function.
@ -180,8 +181,8 @@ struct /* Plug-in variables */
top; /* ... */
} vars =
{
"|lp", /* Name of file or command to print to */
"ps", /* Name of printer "driver" */
"", /* Name of file or command to print to */
"ps2", /* Name of printer "driver" */
MEDIA_LETTER, /* Size of output media */
OUTPUT_COLOR, /* Color or grayscale output */
100, /* Output brightness */
@ -218,6 +219,7 @@ int runme = FALSE, /* True if print should proceed */
printer_t printers[] = /* List of supported printer types */
{
{ "PostScript Printer", "ps", 72, 72, 1, 1, 0, 1.000, 1.000, ps_print },
{ "PostScript Printer (Level 2)", "ps2", 72, 72, 1, 1, 1, 1.000, 1.000, ps_print },
{ "HP DeskJet 500, 520", "pcl-500", 300, 300, 0, 0, 500, 0.541, 0.548, pcl_print },
{ "HP DeskJet 500C, 540C", "pcl-501", 300, 300, 0, 1, 501, 0.541, 0.548, pcl_print },
{ "HP DeskJet 550C, 560C", "pcl-550", 300, 300, 0, 1, 550, 0.541, 0.548, pcl_print },
@ -445,8 +447,8 @@ run(char *name, /* I - Name of print program. */
* Open the file/execute the print command...
*/
if (vars.output_to[0] == '|')
prn = popen(vars.output_to + 1, "w");
if (plist_current > 0)
prn = popen(vars.output_to, "w");
else
prn = fopen(vars.output_to, "w");
@ -491,7 +493,7 @@ run(char *name, /* I - Name of print program. */
vars.output_type, printer->model, lut, cmap,
vars.orientation, vars.scaling, vars.left, vars.top);
if (vars.output_to[0] == '|')
if (plist_current > 0)
pclose(prn);
else
fclose(prn);
@ -573,7 +575,7 @@ print_dialog(void)
*/
dialog = gtk_dialog_new();
gtk_window_set_title(GTK_WINDOW(dialog), "Print");
gtk_window_set_title(GTK_WINDOW(dialog), "Print " PLUG_IN_VERSION);
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",
@ -627,9 +629,6 @@ print_dialog(void)
menu = gtk_menu_new();
for (i = 0; i < plist_count; i ++)
{
if (strcmp(plist[i].command, vars.output_to) == 0)
plist_current = i;
item = gtk_menu_item_new_with_label(plist[i].name);
gtk_menu_append(GTK_MENU(menu), item);
gtk_signal_connect(GTK_OBJECT(item), "activate",
@ -770,7 +769,7 @@ print_dialog(void)
* Print file/command...
*/
label = gtk_label_new("File/|Command:");
label = gtk_label_new("File/Command:");
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 11, 12, GTK_FILL, GTK_FILL, 4, 0);
gtk_widget_show(label);
@ -809,6 +808,8 @@ print_dialog(void)
* Show it and wait for the user to do something...
*/
plist_callback(NULL, plist_current);
gtk_widget_show(dialog);
gtk_main();
@ -1269,9 +1270,18 @@ printrc_load(void)
if (sscanf(line, "%s%s%d%*[ \t]%[^\n]", key.name, key.driver,
&(key.output_type), key.command) == 4)
if ((p = bsearch(&key, plist, plist_count, sizeof(plist_t),
{
/*
* Check to see if this is an old printrc file...
*/
if (key.command[0] == '|')
strcpy(key.command, key.command + 1);
if ((p = bsearch(&key, plist + 1, plist_count - 1, sizeof(plist_t),
(int (*)(const void *, const void *))compare_printers)) != NULL)
memcpy(p, &key, sizeof(plist_t));
};
};
fclose(fp);
@ -1309,7 +1319,7 @@ printrc_save(void)
fputs("#PRINTRC " PLUG_IN_VERSION "\n", fp);
for (i = 0, p = plist; i < plist_count; i ++, p ++)
for (i = 1, p = plist + 1; i < plist_count; i ++, p ++)
fprintf(fp, "%s %s %d %s\n", p->name, p->driver, p->output_type, p->command);
fclose(fp);
@ -1346,10 +1356,14 @@ get_printers(void)
defname[0] = '\0';
memset(plist, 0, sizeof(plist));
plist_count = 1;
strcpy(plist[0].name, "File");
sprintf(plist[0].command, "file.ps", line);
strcpy(plist[0].driver, "ps2");
plist[0].output_type = OUTPUT_COLOR;
#ifndef sun /* Sun Solaris merges LPR and LP queues */
if (access("/usr/etc/lpc", 0) == 0 &&
(pfile = popen("/usr/etc/lpc status", "r")) != NULL)
if ((pfile = popen("lpc status", "r")) != NULL)
{
while (fgets(line, sizeof(line), pfile) != NULL &&
plist_count < MAX_PLIST)
@ -1357,8 +1371,8 @@ get_printers(void)
{
*strchr(line, ':') = '\0';
strcpy(plist[plist_count].name, line);
sprintf(plist[plist_count].command, "|lpr -P%s -l", line);
strcpy(plist[plist_count].driver, "ps");
sprintf(plist[plist_count].command, "lpr -P%s -l", line);
strcpy(plist[plist_count].driver, "ps2");
plist[plist_count].output_type = OUTPUT_COLOR;
plist_count ++;
};
@ -1367,8 +1381,7 @@ get_printers(void)
};
#endif /* !sun */
if (access("/usr/bin/lpstat", 0) == 0 &&
(pfile = popen("/usr/bin/lpstat -d -p", "r")) != NULL)
if ((pfile = popen("lpstat -d -p", "r")) != NULL)
{
while (fgets(line, sizeof(line), pfile) != NULL &&
plist_count < MAX_PLIST)
@ -1377,11 +1390,11 @@ get_printers(void)
{
strcpy(plist[plist_count].name, name);
#ifdef __sgi /* SGI still uses the SVR3 spooler */
sprintf(plist[plist_count].command, "|lp -s -oraw -d%s", name);
sprintf(plist[plist_count].command, "lp -s -d%s", name);
#else
sprintf(plist[plist_count].command, "|lp -s -oraw -d %s", name);
sprintf(plist[plist_count].command, "lp -s -d %s", name);
#endif /* __sgi */
strcpy(plist[plist_count].driver, "ps");
strcpy(plist[plist_count].driver, "ps2");
plist[plist_count].output_type = OUTPUT_COLOR;
plist_count ++;
}
@ -1392,16 +1405,25 @@ get_printers(void)
pclose(pfile);
};
if (plist_count > 1)
qsort(plist, plist_count, sizeof(plist_t),
if (plist_count > 2)
qsort(plist + 1, plist_count - 1, sizeof(plist_t),
(int (*)(const void *, const void *))compare_printers);
if (defname[0] != '\0')
if (defname[0] != '\0' && vars.output_to[0] == '\0')
{
for (i = 0; i < plist_count; i ++)
if (strcmp(defname, plist[i].name) == 0)
break;
if (i < plist_count)
plist_current = i;
}
else if (vars.output_to[0] != '\0')
{
for (i = 0; i < plist_count; i ++)
if (strcmp(vars.output_to, plist[i].command) == 0)
break;
if (i < plist_count)
plist_current = i;
};

View File

@ -3,7 +3,7 @@
*
* Print plug-in header file for the GIMP.
*
* Copyright 1997 Michael Sweet (mike@easysw.com)
* Copyright 1997-1998 Michael Sweet (mike@easysw.com)
*
* 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
@ -22,21 +22,17 @@
* Revision History:
*
* $Log$
* Revision 1.1.1.1 1997/11/24 22:04:34 sopwith
* Let's try this import one last time.
* Revision 1.2 1998/01/25 09:29:28 yosh
* Plugin updates
* Properly generated aa Makefile (still not built by default)
* Sven's no args script patch
*
* Revision 1.3 1997/11/18 03:04:27 nobody
* fixed ugly comment-bugs introduced by evil darkwing
* keep out configuration empty dirs
* --darkwing
* -Yosh
*
* Revision 1.2 1997/11/17 05:43:57 nobody
* updated ChangeLog
* dropped non-working doc/Makefile entries
* applied many fixes from the registry as well as the devel ML
* applied missing patches by Art Haas
*
* --darkwing
* Revision 1.9 1998/01/21 21:33:47 mike
* Added Level 2 PostScript driver.
* Replaced Burkes dither with stochastic (random) dither.
* Now use Level 2 ASCII85 filter for Level 2 printers.
*
* Revision 1.8 1997/11/14 17:17:59 mike
* Updated to dynamically allocate return params in the run() function.
@ -89,7 +85,7 @@
* Constants...
*/
#define PLUG_IN_VERSION "1.2.2 - 14 November 1997"
#define PLUG_IN_VERSION "1.3 - 22 January 1998"
#define PLUG_IN_NAME "Print"
#define MEDIA_LETTER 0 /* 8.5x11" a.k.a. "A" size */

View File

@ -508,6 +508,7 @@ script_fu_script_proc (char *name,
GStatusType status = STATUS_SUCCESS;
GRunModeType run_mode;
SFScript *script;
int min_args;
run_mode = params[0].data.d_int32;
@ -530,8 +531,12 @@ script_fu_script_proc (char *name,
script->image_based = FALSE;
/* First acquire information with a dialog */
script_fu_interface (script);
break;
/* Skip this part if the script takes no parameters */
min_args = (script->image_based) ? 2 : 0;
if (script->num_args > min_args) {
script_fu_interface (script);
break;
}
case RUN_NONINTERACTIVE:
/* Make sure all the arguments are there! */

View File

@ -508,6 +508,7 @@ script_fu_script_proc (char *name,
GStatusType status = STATUS_SUCCESS;
GRunModeType run_mode;
SFScript *script;
int min_args;
run_mode = params[0].data.d_int32;
@ -530,8 +531,12 @@ script_fu_script_proc (char *name,
script->image_based = FALSE;
/* First acquire information with a dialog */
script_fu_interface (script);
break;
/* Skip this part if the script takes no parameters */
min_args = (script->image_based) ? 2 : 0;
if (script->num_args > min_args) {
script_fu_interface (script);
break;
}
case RUN_NONINTERACTIVE:
/* Make sure all the arguments are there! */

View File

@ -15,7 +15,7 @@
; along with this program; if not, write to the Free Software
; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;
; "Copy Visible" version 0.05 10/19/97
; "Copy Visible" version 0.11 01/24/98
; by Adrian Likins <adrian@gimp.org>
; _heavily_ based on:
; cyn-merge.scm version 0.02 10/10/97
@ -26,9 +26,10 @@
drawable)
(let* ((layers (gimp-image-get-layers image))
(num-layers (car layers))
(num-visi-layers 0)
(layer-array (cadr layers)))
(gimp-image-disable-undo image)
(gimp-undo-push-group-start image)
; copy all visible layers and make them invisible
(set! layer-count 1)
@ -42,35 +43,39 @@
(set! copy (car (gimp-layer-copy layer TRUE)))
(gimp-image-add-layer image copy -1)
(gimp-layer-set-visible copy TRUE)
(gimp-layer-set-visible layer FALSE)))
(gimp-layer-set-visible layer FALSE)
(set! num-visi-layers (+ num-visi-layers 1))))
(set! layer-count (+ layer-count 1)))
; merge all visible layers
;changed
(set! merged-layer (car (gimp-image-merge-visible-layers image EXPAND-AS-NECESSARY)))
(if (> num-visi-layers 1)
(set! merged-layer (car (gimp-image-merge-visible-layers image EXPAND-AS-NECESSARY)))
(if (> num-visi-layers 0)
(set! merged-layer copy)))
(if (> num-visi-layers 0)
(begin
(gimp-edit-copy image merged-layer)
(gimp-image-remove-layer image merged-layer)))
; restore the layers visibilty
(set! layer-count 0)
(while (< layer-count num-layers)
(set! layer (aref layer-array layer-count))
(gimp-layer-set-visible layer (aref visi-array layer-count))
(set! layer-count (+ layer-count 1)))
;changed
(gimp-edit-copy image merged-layer)
(gimp-image-set-active-layer image drawable)
(gimp-image-remove-layer image merged-layer)
(gimp-image-enable-undo image)
(gimp-undo-push-group-end image)
(gimp-displays-flush)))
(script-fu-register "script-fu-copy-visible"
; I use the script under the edit menu, but probabaly bad style for a dist version.
; "<Image>/Edit/Copy Visible"
"<Image>/Script-Fu/Selection/Copy Visible"
"<Image>/Edit/Copy Visible"
"Copy the visible selction"
"Sven Neumann (neumanns@uni-duesseldorf.de), Adrian Likins <adrian@gimp.org>"
"Sven Neumann, Adrian Likins"
"10/19/1997"
"01/24/1998"
"RGB* INDEXED* GRAY*"
SF-IMAGE "Image" 0
SF-DRAWABLE "Drawable" 0)