2000-01-13 Michael Natterer <mitch@gimp.org> * app/gimpui.[ch] * app/preferences_dialog.c: removed & renamed some functions from gimpui.[ch] (see below). * libgimp/Makefile.am * libgimp/gimpwidgets.[ch]; new files. Functions moved from app/gimpui.[ch]. Added a constructor for the label + hscale + entry combination used in many plugins (now hscale + spinbutton). * libgimp/gimpui.h: include gimpwidgets.h * plug-ins/megawidget/megawidget.[ch]: removed all functions except the preview stuff (I'm not yet sure how to implement this in libgimp because the libgimp preview should be general enough to replace all the other plugin previews, too). * plug-ins/borderaverage/Makefile.am * plug-ins/borderaverage/borderaverage.c * plug-ins/common/plugin-defs.pl * plug-ins/common/Makefile.am * plug-ins/common/aa.c * plug-ins/common/align_layers.c * plug-ins/common/animationplay.c * plug-ins/common/apply_lens.c * plug-ins/common/blinds.c * plug-ins/common/bumpmap.c * plug-ins/common/checkerboard.c * plug-ins/common/colorify.c * plug-ins/common/convmatrix.c * plug-ins/common/cubism.c * plug-ins/common/curve_bend.c * plug-ins/common/deinterlace.c * plug-ins/common/despeckle.c * plug-ins/common/destripe.c * plug-ins/common/displace.c * plug-ins/common/edge.c * plug-ins/common/emboss.c * plug-ins/common/hot.c * plug-ins/common/nlfilt.c * plug-ins/common/pixelize.c * plug-ins/common/waves.c * plug-ins/sgi/sgi.c * plug-ins/sinus/sinus.c: ui updates like removing megawidget, using the dialog constructor, I18N fixes, indentation, ...
423 lines
9.7 KiB
C
423 lines
9.7 KiB
C
/**
|
|
* aa.c version 1.0
|
|
* A plugin that uses libaa (ftp://ftp.ta.jcu.cz/pub/aa) to save images as
|
|
* ASCII.
|
|
* NOTE: This plugin *requires* aalib 1.2 or later. Earlier versions will
|
|
* not work.
|
|
* Code copied from all over the GIMP source.
|
|
* Tim Newsome <nuisance@cmu.edu>
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <aalib.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include <libgimp/gimp.h>
|
|
#include <libgimp/gimpui.h>
|
|
|
|
#include "libgimp/stdplugins-intl.h"
|
|
|
|
/*
|
|
* Declare some local functions.
|
|
*/
|
|
static void query (void);
|
|
static void run (gchar *name,
|
|
gint nparams,
|
|
GParam *param,
|
|
gint *nreturn_vals,
|
|
GParam **return_vals);
|
|
static void init_gtk (void);
|
|
static gboolean aa_savable (gint32 drawable_ID);
|
|
static gboolean save_aa (gint output_type,
|
|
gchar *filename,
|
|
gint32 image,
|
|
gint32 drawable);
|
|
static void gimp2aa (gint32 image,
|
|
gint32 drawable_ID,
|
|
aa_context *context);
|
|
|
|
static gint type_dialog (int selected);
|
|
static void type_dialog_ok_callback (GtkWidget *widget,
|
|
gpointer data);
|
|
static void type_dialog_toggle_update (GtkWidget *widget,
|
|
gpointer data);
|
|
static void type_dialog_cancel_callback (GtkWidget *widget,
|
|
gpointer data);
|
|
|
|
/*
|
|
* Some global variables.
|
|
*/
|
|
|
|
GPlugInInfo PLUG_IN_INFO =
|
|
{
|
|
NULL, /* init_proc */
|
|
NULL, /* quit_proc */
|
|
query, /* query_proc */
|
|
run, /* run_proc */
|
|
};
|
|
|
|
/**
|
|
* Type the user selected. (Global for easier UI coding.)
|
|
*/
|
|
static gint selected_type = 0;
|
|
|
|
|
|
MAIN ()
|
|
|
|
static void
|
|
query (void)
|
|
{
|
|
static GParamDef save_args[] =
|
|
{
|
|
{PARAM_INT32, "run_mode", "Interactive, non-interactive"},
|
|
{PARAM_IMAGE, "image", "Input image"},
|
|
{PARAM_DRAWABLE, "drawable", "Drawable to save"},
|
|
{PARAM_STRING, "filename", "The name of the file to save the image in"},
|
|
{PARAM_STRING, "raw_filename", "The name entered"},
|
|
{PARAM_STRING, "file_type", "File type to use"}
|
|
};
|
|
static int nsave_args = sizeof(save_args) / sizeof(save_args[0]);
|
|
|
|
INIT_I18N();
|
|
|
|
gimp_install_procedure ("file_aa_save",
|
|
_("Saves files in various text formats"),
|
|
_("Saves files in various text formats"),
|
|
"Tim Newsome <nuisance@cmu.edu>",
|
|
"Tim Newsome <nuisance@cmu.edu>",
|
|
"1997",
|
|
"<Save>/AA",
|
|
"GRAY*", /* support grayscales */
|
|
PROC_PLUG_IN,
|
|
nsave_args, 0,
|
|
save_args, NULL);
|
|
|
|
gimp_register_save_handler ("file_aa_save", "ansi,txt,text,html", "");
|
|
}
|
|
|
|
/**
|
|
* Searches aa_formats defined by aalib to find the index of the type
|
|
* specified by string.
|
|
* -1 means it wasn't found.
|
|
*/
|
|
static int
|
|
get_type_from_string (char *string)
|
|
{
|
|
int type = 0;
|
|
aa_format **p = aa_formats;
|
|
|
|
while (*p && strcmp ((*p)->formatname, string))
|
|
{
|
|
p++;
|
|
type++;
|
|
}
|
|
|
|
if (*p == NULL)
|
|
return -1;
|
|
|
|
return type;
|
|
}
|
|
|
|
static void
|
|
run (gchar *name,
|
|
gint nparams,
|
|
GParam *param,
|
|
gint *nreturn_vals,
|
|
GParam **return_vals)
|
|
{
|
|
static GParam values[2];
|
|
GStatusType status = STATUS_SUCCESS;
|
|
GRunModeType run_mode;
|
|
gint output_type = 0;
|
|
static int last_type = 0;
|
|
gint32 image_ID;
|
|
gint32 drawable_ID;
|
|
GimpExportReturnType export = EXPORT_CANCEL;
|
|
|
|
/* Set us up to return a status. */
|
|
*nreturn_vals = 1;
|
|
*return_vals = values;
|
|
values[0].type = PARAM_STATUS;
|
|
values[0].data.d_status = STATUS_CALLING_ERROR;
|
|
|
|
run_mode = param[0].data.d_int32;
|
|
image_ID = param[1].data.d_int32;
|
|
drawable_ID = param[2].data.d_int32;
|
|
|
|
/* eventually export the image */
|
|
switch (run_mode)
|
|
{
|
|
case RUN_INTERACTIVE:
|
|
case RUN_WITH_LAST_VALS:
|
|
INIT_I18N_UI();
|
|
init_gtk ();
|
|
export = gimp_export_image (&image_ID, &drawable_ID, "AA",
|
|
(CAN_HANDLE_GRAY | CAN_HANDLE_ALPHA));
|
|
if (export == EXPORT_CANCEL)
|
|
{
|
|
values[0].data.d_status = STATUS_EXECUTION_ERROR;
|
|
return;
|
|
}
|
|
break;
|
|
default:
|
|
INIT_I18N();
|
|
break;
|
|
}
|
|
|
|
if (!aa_savable (drawable_ID))
|
|
{
|
|
values[0].data.d_status = STATUS_CALLING_ERROR;
|
|
goto finish;
|
|
}
|
|
|
|
switch (run_mode)
|
|
{
|
|
case RUN_INTERACTIVE:
|
|
gimp_get_data ("file_aa_save", &last_type);
|
|
output_type = type_dialog (last_type);
|
|
break;
|
|
|
|
case RUN_NONINTERACTIVE:
|
|
/* Make sure all the arguments are there! */
|
|
if (nparams != 6)
|
|
status = STATUS_CALLING_ERROR;
|
|
else
|
|
output_type = get_type_from_string (param[5].data.d_string);
|
|
break;
|
|
|
|
case RUN_WITH_LAST_VALS:
|
|
gimp_get_data ("file_aa_save", &last_type);
|
|
output_type = last_type;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (output_type < 0)
|
|
{
|
|
status = STATUS_CALLING_ERROR;
|
|
goto finish;
|
|
}
|
|
|
|
if (save_aa (output_type, param[3].data.d_string, image_ID, drawable_ID))
|
|
{
|
|
values[0].data.d_status = STATUS_EXECUTION_ERROR;
|
|
last_type = output_type;
|
|
gimp_set_data ("file_aa_save", &last_type, sizeof(last_type));
|
|
}
|
|
else
|
|
values[0].data.d_status = STATUS_SUCCESS;
|
|
|
|
finish:
|
|
|
|
if (export == EXPORT_EXPORT)
|
|
gimp_image_delete (image_ID);
|
|
}
|
|
|
|
/**
|
|
* The actual save function. What it's all about.
|
|
* The image type has to be GRAY.
|
|
*/
|
|
static gboolean
|
|
save_aa (gint output_type,
|
|
gchar *filename,
|
|
gint32 image_ID,
|
|
gint32 drawable_ID)
|
|
{
|
|
aa_savedata savedata = {NULL, NULL};
|
|
aa_context *context = NULL;
|
|
GDrawable *drawable = NULL;
|
|
aa_format format;
|
|
|
|
/*fprintf(stderr, "save %s\n", filename); */
|
|
|
|
drawable = gimp_drawable_get (drawable_ID);
|
|
memcpy (&format, aa_formats[output_type], sizeof (format));
|
|
format.width = drawable->width / 2;
|
|
format.height = drawable->height / 2;
|
|
|
|
/*fprintf(stderr, "save_aa %i x %i\n", format.width, format.height); */
|
|
|
|
/* Get a libaa context which will save its output to filename. */
|
|
savedata.name = filename;
|
|
savedata.format = &format;
|
|
|
|
context = aa_init (&save_d, &aa_defparams, &savedata);
|
|
if (context == NULL)
|
|
return TRUE;
|
|
|
|
gimp2aa (image_ID, drawable_ID, context);
|
|
aa_flush (context);
|
|
aa_close (context);
|
|
|
|
/*fprintf(stderr, "Success!\n"); */
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
gimp2aa (gint32 image,
|
|
gint32 drawable_ID,
|
|
aa_context *context)
|
|
{
|
|
gint width, height, x, y;
|
|
guchar *buffer;
|
|
GDrawable *drawable = NULL;
|
|
GPixelRgn pixel_rgn;
|
|
aa_renderparams *renderparams = NULL;
|
|
gint bpp;
|
|
|
|
width = aa_imgwidth (context);
|
|
height = aa_imgheight (context);
|
|
/*fprintf(stderr, "gimp2aa %i x %i\n", width, height); */
|
|
|
|
drawable = gimp_drawable_get (drawable_ID);
|
|
|
|
bpp = drawable->bpp;
|
|
buffer = g_new (guchar, width * bpp);
|
|
|
|
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width,
|
|
drawable->height, FALSE, FALSE);
|
|
|
|
for (y = 0; y < height; y++)
|
|
{
|
|
gimp_pixel_rgn_get_row (&pixel_rgn, buffer, 0, y, width);
|
|
for (x = 0; x < width; x++)
|
|
{
|
|
/* Just copy one byte. If it's indexed that's all we need. Otherwise
|
|
* it'll be the most significant one. */
|
|
aa_putpixel (context, x, y, buffer[x * bpp]);
|
|
}
|
|
}
|
|
|
|
renderparams = aa_getrenderparams ();
|
|
renderparams->dither = AA_FLOYD_S;
|
|
aa_render (context, renderparams, 0, 0,
|
|
aa_scrwidth (context), aa_scrheight (context));
|
|
}
|
|
|
|
static gboolean
|
|
aa_savable (gint32 drawable_ID)
|
|
{
|
|
GDrawableType drawable_type;
|
|
|
|
drawable_type = gimp_drawable_type (drawable_ID);
|
|
|
|
if (drawable_type != GRAY_IMAGE && drawable_type != GRAYA_IMAGE)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* User Interface dialog thingie.
|
|
*/
|
|
|
|
static void
|
|
init_gtk (void)
|
|
{
|
|
gchar **argv;
|
|
gint argc;
|
|
|
|
argc = 1;
|
|
argv = g_new (gchar *, 1);
|
|
argv[0] = g_strdup ("aa");
|
|
|
|
gtk_init (&argc, &argv);
|
|
gtk_rc_parse (gimp_gtkrc ());
|
|
}
|
|
|
|
static gint
|
|
type_dialog (int selected)
|
|
{
|
|
GtkWidget *dlg;
|
|
GtkWidget *toggle;
|
|
GtkWidget *frame;
|
|
GtkWidget *toggle_vbox;
|
|
GSList *group;
|
|
|
|
/* Create the actual window. */
|
|
dlg = gimp_dialog_new (_("Save as Text"), "aa",
|
|
gimp_plugin_help_func, "filters/aa.html",
|
|
GTK_WIN_POS_MOUSE,
|
|
FALSE, TRUE, FALSE,
|
|
|
|
_("OK"), gtk_widget_destroy,
|
|
NULL, 1, NULL, TRUE, FALSE,
|
|
_("Cancel"), type_dialog_cancel_callback,
|
|
NULL, NULL, NULL, FALSE, TRUE,
|
|
|
|
NULL);
|
|
|
|
gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
|
|
GTK_SIGNAL_FUNC (gtk_main_quit),
|
|
NULL);
|
|
|
|
/* file save type */
|
|
frame = gtk_frame_new (_("Data Formatting"));
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
|
|
gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
|
|
gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dlg)->vbox), frame, TRUE, TRUE, 0);
|
|
|
|
toggle_vbox = gtk_vbox_new (FALSE, 2);
|
|
gtk_container_set_border_width (GTK_CONTAINER(toggle_vbox), 4);
|
|
gtk_container_add (GTK_CONTAINER (frame), toggle_vbox);
|
|
|
|
group = NULL;
|
|
{
|
|
aa_format **p = aa_formats;
|
|
gint current = 0;
|
|
|
|
while (*p != NULL)
|
|
{
|
|
toggle = gtk_radio_button_new_with_label (group, (*p)->formatname);
|
|
group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
|
|
gtk_box_pack_start (GTK_BOX (toggle_vbox), toggle, FALSE, FALSE, 0);
|
|
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
|
|
GTK_SIGNAL_FUNC (type_dialog_toggle_update),
|
|
(*p)->formatname);
|
|
if (current == selected)
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), TRUE);
|
|
|
|
gtk_widget_show (toggle);
|
|
p++;
|
|
current++;
|
|
}
|
|
}
|
|
|
|
gtk_widget_show (toggle_vbox);
|
|
gtk_widget_show (frame);
|
|
|
|
gtk_widget_show (dlg);
|
|
|
|
gtk_main ();
|
|
gdk_flush ();
|
|
|
|
return selected_type;
|
|
}
|
|
|
|
/*
|
|
* Callbacks for the dialog.
|
|
*/
|
|
|
|
static void
|
|
type_dialog_cancel_callback (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
selected_type = -1;
|
|
gtk_widget_destroy (GTK_WIDGET (data));
|
|
}
|
|
|
|
static void
|
|
type_dialog_toggle_update (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
selected_type = get_type_from_string ((char *)data);
|
|
}
|