Index: plug-ins/common/Makefile.in
===================================================================
--- plug-ins/common/Makefile.in
+++ plug-ins/common/Makefile.in
@@ -43,6 +43,7 @@
channel-mixer$(EXEEXT) checkerboard$(EXEEXT) \
cml-explorer$(EXEEXT) color-cube-analyze$(EXEEXT) \
color-enhance$(EXEEXT) color-exchange$(EXEEXT) \
+ color-range-map$(EXEEXT) \
color-to-alpha$(EXEEXT) colorify$(EXEEXT) \
colormap-remap$(EXEEXT) compose$(EXEEXT) \
contrast-normalize$(EXEEXT) contrast-retinex$(EXEEXT) \
@@ -235,6 +236,12 @@
$(libgimpmodule) $(libgimp) $(libgimpmath) $(libgimpconfig) \
$(libgimpcolor) $(libgimpbase) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_color_range_map_OBJECTS = color-range-map.$(OBJEXT)
+color_range_map_OBJECTS = $(am_color_range_map_OBJECTS)
+color_range_map_DEPENDENCIES = $(libgimpui) $(libgimpwidgets) \
+ $(libgimpmodule) $(libgimp) $(libgimpmath) $(libgimpconfig) \
+ $(libgimpcolor) $(libgimpbase) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
am_color_to_alpha_OBJECTS = color-to-alpha.$(OBJEXT)
color_to_alpha_OBJECTS = $(am_color_to_alpha_OBJECTS)
color_to_alpha_DEPENDENCIES = $(libgimpui) $(libgimpwidgets) \
@@ -1020,6 +1027,7 @@
$(checkerboard_SOURCES) $(cml_explorer_SOURCES) \
$(color_cube_analyze_SOURCES) $(color_enhance_SOURCES) \
$(color_exchange_SOURCES) $(color_to_alpha_SOURCES) \
+ $(color_range_map_SOURCES) \
$(colorify_SOURCES) $(colormap_remap_SOURCES) \
$(compose_SOURCES) $(contrast_normalize_SOURCES) \
$(contrast_retinex_SOURCES) $(contrast_stretch_SOURCES) \
@@ -1081,6 +1089,7 @@
$(checkerboard_SOURCES) $(cml_explorer_SOURCES) \
$(color_cube_analyze_SOURCES) $(color_enhance_SOURCES) \
$(color_exchange_SOURCES) $(color_to_alpha_SOURCES) \
+ $(color_range_map_SOURCES) \
$(colorify_SOURCES) $(colormap_remap_SOURCES) \
$(compose_SOURCES) $(contrast_normalize_SOURCES) \
$(contrast_retinex_SOURCES) $(contrast_stretch_SOURCES) \
@@ -1762,6 +1771,22 @@
$(RT_LIBS) \
$(INTLLIBS)
+color_range_map_SOURCES = \
+ color-range-map.c
+
+color_range_map_LDADD = \
+ $(libgimpui) \
+ $(libgimpwidgets) \
+ $(libgimpmodule) \
+ $(libgimp) \
+ $(libgimpmath) \
+ $(libgimpconfig) \
+ $(libgimpcolor) \
+ $(libgimpbase) \
+ $(GTK_LIBS) \
+ $(RT_LIBS) \
+ $(INTLLIBS)
+
color_to_alpha_SOURCES = \
color-to-alpha.c
@@ -3850,6 +3875,9 @@
color-exchange$(EXEEXT): $(color_exchange_OBJECTS) $(color_exchange_DEPENDENCIES)
@rm -f color-exchange$(EXEEXT)
$(LINK) $(color_exchange_OBJECTS) $(color_exchange_LDADD) $(LIBS)
+color-range-map$(EXEEXT): $(color_range_map_OBJECTS) $(color_range_map_DEPENDENCIES)
+ @rm -f color-range-map$(EXEEXT)
+ $(LINK) $(color_range_map_OBJECTS) $(color_range_map_LDADD) $(LIBS)
color-to-alpha$(EXEEXT): $(color_to_alpha_OBJECTS) $(color_to_alpha_DEPENDENCIES)
@rm -f color-to-alpha$(EXEEXT)
$(LINK) $(color_to_alpha_OBJECTS) $(color_to_alpha_LDADD) $(LIBS)
@@ -4249,6 +4277,7 @@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/color-cube-analyze.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/color-enhance.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/color-exchange.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/color-range-map.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/color-to-alpha.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/colorify.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/colormap-remap.Po@am__quote@
Index: plug-ins/common/Makefile.am
===================================================================
--- plug-ins/common/Makefile.am
+++ plug-ins/common/Makefile.am
@@ -63,6 +63,7 @@ libexec_PROGRAMS = \
color-cube-analyze \
color-enhance \
color-exchange \
+ color-range-map \
color-to-alpha \
colorify \
colormap-remap \
@@ -552,6 +553,23 @@ color_exchange_LDADD = \
$(INTLLIBS) \
$(color_exchange_RC)
+color_range_map_SOURCES = \
+ color-range-map.c
+
+color_range_map_LDADD = \
+ $(libgimpui) \
+ $(libgimpwidgets) \
+ $(libgimpmodule) \
+ $(libgimp) \
+ $(libgimpmath) \
+ $(libgimpconfig) \
+ $(libgimpcolor) \
+ $(libgimpbase) \
+ $(GTK_LIBS) \
+ $(RT_LIBS) \
+ $(INTLLIBS) \
+ $(color_exchange_RC)
+
color_to_alpha_SOURCES = \
color-to-alpha.c
Index: plug-ins/common/color-range-map.c
===================================================================
--- plug-ins/common/color-range-map.c
+++ plug-ins/common/color-range-map.c
@@ -0,0 +1,498 @@
+/*
+ * This is a plug-in for GIMP.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ *
+ */
+
+/*
+ * Exchange one color range with another - very useful for many images,
+ * plugin was removed due to bitrot, then revived and updated.
+ *
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ * Copyright (C) 1998 Peter Kirchgessner
+ * email: peter@kirchgessner.net, WWW: http://www.kirchgessner.net)
+ * Copyright (C) 2011 Owen Swerkstrom (owenswerk@gmail.com)
+ *
+ * Event history:
+ * V 1.00, PK, 26-Oct-98: Creation.
+ * V 1.01, PK, 21-Nov-99: Fix problem with working on layered images
+ * Internationalization
+ * V 1.02, PK, 19-Mar-00: Better explaining text/dialogue
+ * Preview added
+ * Fix problem with divide by zero
+ * V 1.03,neo, 22-May-00: Fixed divide by zero in preview code.
+ * V 2.00, OS, 02-FEB-11: Refactor to use new plug-in architecture
+ */
+
+#include "config.h"
+
+#include
+#include
+
+#include "libgimp/stdplugins-intl.h"
+
+
+#define PLUG_IN_PROC "plug-in-colorrangemap"
+#define PLUG_IN_BINARY "colorrangemap"
+
+#define SCALE_WIDTH 128
+#define PRV_WIDTH 50
+#define PRV_HEIGHT 20
+
+
+/* datastructure to store parameters in */
+typedef struct
+{
+ GimpRGB colors[4];
+ gint32 map_mode;
+ gboolean preview;
+} myParams;
+
+/* lets prototype */
+static void query (void);
+static void run (const gchar *name,
+ gint nparams,
+ const GimpParam *param,
+ gint *nreturn_vals,
+ GimpParam **return_vals);
+static void update_img_preview (GimpDrawable *drawable,
+ GimpPreview *preview);
+static gboolean mapcolor_dialog (GimpDrawable *drawable);
+static void get_mapping (GimpRGB *src_col1,
+ GimpRGB *src_col2,
+ GimpRGB *dst_col1,
+ GimpRGB *dst_col2,
+ gint32 map_mode,
+ guchar *redmap,
+ guchar *greenmap,
+ guchar *bluemap);
+static void add_color_button (gint csel_index,
+ gint left,
+ gint top,
+ GtkWidget *table,
+ GtkWidget *preview);
+static void color_mapping (GimpDrawable *drawable);
+
+
+
+/* some global variables */
+static myParams xargs =
+{
+ {
+ { 0.0, 0.0, 0.0, 1.0 }, /* from col1 */
+ { 1.0, 1.0, 1.0, 1.0 }, /* col2 */
+ { 0.0, 0.0, 0.0, 1.0 }, /* to col1 */
+ { 1.0, 1.0, 1.0, 1.0 } /* col2 */
+ },
+ 0,
+ 0
+};
+static guchar redmap[256], greenmap[256], bluemap[256];
+static gchar *csel_title[4] =
+{
+ N_("First Source Color"),
+ N_("Second Source Color"),
+ N_("First Destination Color"),
+ N_("Second Destination Color")
+};
+
+/* lets declare what we want to do */
+const GimpPlugInInfo PLUG_IN_INFO =
+{
+ NULL, /* init_proc */
+ NULL, /* quit_proc */
+ query, /* query_proc */
+ run, /* run_proc */
+};
+
+/* run program */
+MAIN ()
+
+/* tell GIMP who we are */
+static void
+query (void)
+{
+ static const GimpParamDef args[] =
+ {
+ { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
+ { GIMP_PDB_IMAGE, "image", "Input image" },
+ { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
+ { GIMP_PDB_COLOR, "srccolor-1", "First source color" },
+ { GIMP_PDB_COLOR, "srccolor-2", "Second source color" },
+ { GIMP_PDB_COLOR, "dstcolor-1", "First destination color" },
+ { GIMP_PDB_COLOR, "dstcolor-2", "Second destination color" },
+ { GIMP_PDB_INT32, "map-mode", "Mapping mode (0: linear, others reserved)" }
+ };
+
+ gimp_install_procedure (PLUG_IN_PROC,
+ N_("Map color range specified by two colors "
+ "to another range"),
+ "Map color range specified by two colors"
+ "to color range specified by two other color. "
+ "Intermediate colors are interpolated.",
+ "Peter Kirchgessner",
+ "Peter Kirchgessner",
+ "Feb 8, 2011",
+ N_("_Color Range _Mapping..."),
+ "RGB*",
+ GIMP_PLUGIN,
+ G_N_ELEMENTS (args), 0,
+ args, NULL);
+
+ gimp_plugin_menu_register (PLUG_IN_PROC, "/Colors/Map");
+}
+
+/* main function */
+static void
+run (const gchar *name,
+ gint nparams,
+ const GimpParam *param,
+ gint *nreturn_vals,
+ GimpParam **return_vals)
+{
+ static GimpParam values[1];
+ GimpRunMode run_mode;
+ GimpDrawable *drawable = NULL;
+ GimpPDBStatusType status = GIMP_PDB_SUCCESS;
+ gint j;
+
+ INIT_I18N ();
+
+ run_mode = param[0].data.d_int32;
+
+ *nreturn_vals = 1;
+ *return_vals = values;
+
+ values[0].type = GIMP_PDB_STATUS;
+ values[0].data.d_status = status;
+
+ while (status == GIMP_PDB_SUCCESS)
+ {
+ if (nparams < 3)
+ {
+ status = GIMP_PDB_CALLING_ERROR;
+ break;
+ }
+
+ /* Make sure the drawable is RGB color */
+ drawable = gimp_drawable_get (param[2].data.d_drawable);
+ if (!gimp_drawable_is_rgb (drawable->drawable_id))
+ {
+ g_message (_("Cannot operate on gray or indexed color images."));
+ status = GIMP_PDB_EXECUTION_ERROR;
+ break;
+ }
+
+ if (run_mode == GIMP_RUN_NONINTERACTIVE)
+ {
+ if (nparams != 8) /* Make sure all the arguments are there */
+ {
+ status = GIMP_PDB_CALLING_ERROR;
+ break;
+ }
+
+ for (j = 0; j < 4; j++)
+ {
+ xargs.colors[j] = param[3+j].data.d_color;
+ }
+ xargs.map_mode = param[7].data.d_int32;
+ }
+ else if (run_mode == GIMP_RUN_INTERACTIVE)
+ {
+ gimp_get_data (name, &xargs);
+
+ gimp_context_get_foreground (xargs.colors);
+ gimp_context_get_background (xargs.colors + 1);
+
+ if (!mapcolor_dialog (drawable))
+ break;
+ }
+ else if (run_mode == GIMP_RUN_WITH_LAST_VALS)
+ {
+ gimp_get_data (name, &xargs);
+ }
+ else
+ {
+ status = GIMP_PDB_CALLING_ERROR;
+ break;
+ }
+
+ gimp_progress_init (_("Mapping colors"));
+
+ color_mapping (drawable);
+
+ if (run_mode == GIMP_RUN_INTERACTIVE)
+ gimp_set_data (name, &xargs, sizeof (xargs));
+
+ break;
+
+ status = GIMP_PDB_EXECUTION_ERROR;
+ }
+
+ if ((status == GIMP_PDB_SUCCESS) && (run_mode != GIMP_RUN_NONINTERACTIVE))
+ gimp_displays_flush ();
+
+ if (drawable != NULL)
+ gimp_drawable_detach (drawable);
+
+ values[0].data.d_status = status;
+}
+
+static void
+update_img_preview (GimpDrawable *drawable,
+ GimpPreview *preview)
+{
+ guchar redmap[256], greenmap[256], bluemap[256];
+ gint width, height, bpp;
+ gboolean has_alpha;
+ guchar *src, *dest, *s, *d;
+ gint j;
+
+ get_mapping (xargs.colors,
+ xargs.colors + 1,
+ xargs.colors + 2,
+ xargs.colors + 3,
+ xargs.map_mode,
+ redmap, greenmap, bluemap);
+
+ src = gimp_zoom_preview_get_source (GIMP_ZOOM_PREVIEW (preview),
+ &width, &height, &bpp);
+ has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
+
+ j = width * height;
+ dest = g_new (guchar, j * bpp);
+
+ s = src; d = dest;
+ while (j-- > 0)
+ {
+ *(d++) = redmap[*(s++)];
+ *(d++) = greenmap[*(s++)];
+ *(d++) = bluemap[*(s++)];
+ if (has_alpha)
+ *(d++) = *(s++);
+ }
+
+ gimp_preview_draw_buffer (preview, dest, width * bpp);
+
+ g_free (src);
+ g_free (dest);
+}
+
+static gboolean
+mapcolor_dialog (GimpDrawable *drawable)
+{
+ GtkWidget *dialog;
+ GtkWidget *main_vbox;
+ GtkWidget *preview;
+ GtkWidget *frame;
+ GtkWidget *table;
+ gint j;
+ gboolean run;
+
+ gimp_ui_init (PLUG_IN_BINARY, TRUE);
+
+ dialog = gimp_dialog_new (_("Map Color Range"), PLUG_IN_BINARY,
+ NULL, 0,
+ gimp_standard_help_func, PLUG_IN_PROC,
+
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+
+ NULL);
+
+ gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
+ GTK_RESPONSE_OK,
+ GTK_RESPONSE_CANCEL,
+ -1);
+
+ gimp_window_set_transient (GTK_WINDOW (dialog));
+
+ main_vbox = gtk_vbox_new (FALSE, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
+ gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+ main_vbox);
+ gtk_widget_show (main_vbox);
+
+ preview = gimp_zoom_preview_new (drawable);
+ gtk_box_pack_start_defaults (GTK_BOX (main_vbox), preview);
+ gtk_widget_show (preview);
+ g_signal_connect_swapped (preview, "invalidated",
+ G_CALLBACK (update_img_preview),
+ drawable);
+
+ for (j = 0; j < 2; j++)
+ {
+ frame = gimp_frame_new ((j == 0) ?
+ _("Source Color Range") :
+ _("Destination Color Range"));
+ gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0);
+ gtk_widget_show (frame);
+
+ /* The table keeps the color selections */
+ table = gtk_table_new (1, 4, FALSE);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+ gtk_container_add (GTK_CONTAINER (frame), table);
+ gtk_widget_show (table);
+
+ add_color_button (j * 2, 0, 0, table, preview);
+ add_color_button (j * 2 + 1, 2, 0, table, preview);
+ }
+
+ gtk_widget_show (dialog);
+
+ run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
+
+ if (run)
+ xargs.map_mode = 0; /* Currently always linear mapping */
+
+ gtk_widget_destroy (dialog);
+
+ return run;
+}
+
+static void
+add_color_button (gint csel_index,
+ gint left,
+ gint top,
+ GtkWidget *table,
+ GtkWidget *preview)
+{
+ GtkWidget *button;
+
+ button = gimp_color_button_new (gettext (csel_title[csel_index]),
+ PRV_WIDTH, PRV_HEIGHT,
+ &xargs.colors[csel_index],
+ GIMP_COLOR_AREA_FLAT);
+ gimp_table_attach_aligned (GTK_TABLE (table), left + 1, top,
+ (left == 0) ? _("From:") : _("To:"),
+ 0.0, 0.5,
+ button, 1, TRUE);
+
+ g_signal_connect (button, "color-changed",
+ G_CALLBACK (gimp_color_button_get_color),
+ &xargs.colors[csel_index]);
+ g_signal_connect_swapped (button, "color-changed",
+ G_CALLBACK (gimp_preview_invalidate),
+ preview);
+}
+
+static void
+get_mapping (GimpRGB *src_col1,
+ GimpRGB *src_col2,
+ GimpRGB *dst_col1,
+ GimpRGB *dst_col2,
+ gint32 map_mode,
+ guchar *redmap,
+ guchar *greenmap,
+ guchar *bluemap)
+{
+ guchar src1[3];
+ guchar src2[3];
+ guchar dst1[3];
+ guchar dst2[3];
+ gint rgb, i, a, as, b, bs;
+ guchar *colormap[3];
+
+ /* Currently we always do a linear mapping */
+
+ colormap[0] = redmap;
+ colormap[1] = greenmap;
+ colormap[2] = bluemap;
+
+ gimp_rgb_get_uchar (src_col1, src1, src1 + 1, src1 + 2);
+ gimp_rgb_get_uchar (src_col2, src2, src2 + 1, src2 + 2);
+ gimp_rgb_get_uchar (dst_col1, dst1, dst1 + 1, dst1 + 2);
+ gimp_rgb_get_uchar (dst_col2, dst2, dst2 + 1, dst2 + 2);
+
+ switch (map_mode)
+ {
+ case 0:
+ default:
+ for (rgb = 0; rgb < 3; rgb++)
+ {
+ a = src1[rgb]; as = dst1[rgb];
+ b = src2[rgb]; bs = dst2[rgb];
+
+ if (b == a)
+ {
+ /* For this channel, both source color values are the same. */
+
+ /* Map everything below to the start of the destination range. */
+ for (i = 0; i < a; i++)
+ {
+ colormap[rgb][i] = as;
+ }
+
+ /* Map source color to the middle of the destination range. */
+ colormap[rgb][a] = (as + bs) / 2;
+
+ /* Map everything above to the end of the destination range. */
+ for (i = a + 1; i < 256; i++)
+ {
+ colormap[rgb][i] = bs;
+ }
+ }
+ else
+ {
+ /* Map color ranges. */
+ for (i = 0; i < 256; i++)
+ {
+ gint j = ((i - a) * (bs - as)) / (b - a) + as;
+
+ colormap[rgb][i] = CLAMP0255(j);
+ }
+ }
+ }
+ break;
+ }
+}
+
+static void
+mapcolor_func (const guchar *src,
+ guchar *dest,
+ gint bpp,
+ gpointer data)
+{
+ dest[0] = redmap[src[0]];
+ dest[1] = greenmap[src[1]];
+ dest[2] = bluemap[src[2]];
+ if (bpp > 3)
+ dest[3] = src[3];
+}
+
+
+/* show our dialog */
+static void
+color_mapping (GimpDrawable *drawable)
+
+{
+ if (!gimp_drawable_is_rgb (drawable->drawable_id))
+ {
+ g_message (_("Cannot operate on gray or indexed color images."));
+ return;
+ }
+
+ gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width () + 1));
+
+ get_mapping (xargs.colors,
+ xargs.colors + 1,
+ xargs.colors + 2,
+ xargs.colors + 3,
+ xargs.map_mode,
+ redmap, greenmap, bluemap);
+
+ gimp_rgn_iterate2 (drawable, 0 /* unused */, mapcolor_func, NULL);
+}
Index: plug-ins/common/plugin-defs.pl
===================================================================
--- plug-ins/common/plugin-defs.pl
+++ plug-ins/common/plugin-defs.pl
@@ -19,6 +19,7 @@
'color-cube-analyze' => { ui => 1 },
'color-enhance' => { ui => 1 },
'color-exchange' => { ui => 1 },
+ 'color-range-map' => { ui => 1 },
'color-to-alpha' => { ui => 1 },
'colorify' => { ui => 1 },
'colormap-remap' => { ui => 1 },
Index: plug-ins/makefile.msc
===================================================================
--- plug-ins/makefile.msc
+++ plug-ins/makefile.msc
@@ -34,7 +34,7 @@ FROMPLUGINSDIR=YES # Used to bypass other parts below
# The COMMON* ones are in the common subdirectory
COMMON0 = alien-map align-layers animation-optimize animation-play antialias apply-canvas
COMMON1 = blinds blur-gauss-selective blur-gauss blur-motion blur border-average bump-map
-COMMON2 = cartoon channel-mixer checkerboard cml-explorer color-cube-analyze color-enhance color-exchange color-to-alpha colorify colormap-remap compose contrast-normalize contrast-retinex contrast-stretch-hsv contrast-stretch convolution-matrix crop-auto crop-zealous cubism curve-bend
+COMMON2 = cartoon channel-mixer checkerboard cml-explorer color-cube-analyze color-enhance color-exchange color-range-map color-to-alpha colorify colormap-remap compose contrast-normalize contrast-retinex contrast-stretch-hsv contrast-stretch convolution-matrix crop-auto crop-zealous cubism curve-bend
COMMON3 = decompose deinterlace depth-merge despeckle destripe diffraction displace edge-dog edge-laplace edge-neon edge-sobel edge emboss engrave
## file-aa file-mng file-pdf file-wmf file-xpm
COMMON4 = file-cel file-compressor file-csource file-desktop-link file-dicom file-gbr file-gif-load file-gif-save file-gih file-glob file-header file-html-table file-pat file-pcx file-pix file-png file-pnm file-ps file-psp file-raw file-sunras file-svg file-tga file-tiff-load file-tiff-save file-xbm file-xwd film filter-pack fractal-trace
--
1.7.0.4