3
* A plugin that uses libaa (ftp://ftp.ta.jcu.cz/pub/aa) to save images as
5
* NOTE: This plugin *requires* aalib 1.2 or later. Earlier versions will
7
* Code copied from all over the GIMP source.
8
* Tim Newsome <nuisance@cmu.edu>
11
/* GIMP - The GNU Image Manipulation Program
12
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
14
* This program is free software; you can redistribute it and/or modify
15
* it under the terms of the GNU General Public License as published by
16
* the Free Software Foundation; either version 2 of the License, or
17
* (at your option) any later version.
19
* This program is distributed in the hope that it will be useful,
20
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
* GNU General Public License for more details.
24
* You should have received a copy of the GNU General Public License
25
* along with this program; if not, write to the Free Software
26
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35
#include <libgimp/gimp.h>
36
#include <libgimp/gimpui.h>
38
#include "libgimp/stdplugins-intl.h"
41
#define SAVE_PROC "file-aa-save"
42
#define PLUG_IN_BINARY "aa"
46
* Declare some local functions.
48
static void query (void);
49
static void run (const gchar *name,
51
const GimpParam *param,
53
GimpParam **return_vals);
54
static gboolean save_aa (gint32 drawable_ID,
57
static void gimp2aa (gint32 drawable_ID,
60
static gint aa_dialog (gint selected);
64
* Some global variables.
67
const GimpPlugInInfo PLUG_IN_INFO =
71
query, /* query_proc */
81
static const GimpParamDef save_args[] =
83
{GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive"},
84
{GIMP_PDB_IMAGE, "image", "Input image"},
85
{GIMP_PDB_DRAWABLE, "drawable", "Drawable to save"},
86
{GIMP_PDB_STRING, "filename", "The name of the file to save the image in"},
87
{GIMP_PDB_STRING, "raw-filename", "The name entered"},
88
{GIMP_PDB_STRING, "file-type", "File type to use"}
91
gimp_install_procedure (SAVE_PROC,
92
"Saves grayscale image in various text formats",
93
"This plug-in uses aalib to save grayscale image "
94
"as ascii art into a variety of text formats",
95
"Tim Newsome <nuisance@cmu.edu>",
96
"Tim Newsome <nuisance@cmu.edu>",
101
G_N_ELEMENTS (save_args), 0,
104
gimp_register_file_handler_mime (SAVE_PROC, "text/plain");
105
gimp_register_save_handler (SAVE_PROC, "txt,ansi,text", "");
109
* Searches aa_formats defined by aalib to find the index of the type
110
* specified by string.
111
* -1 means it wasn't found.
114
get_type_from_string (const gchar *string)
117
aa_format **p = (aa_format **) aa_formats;
119
while (*p && strcmp ((*p)->formatname, string))
132
run (const gchar *name,
134
const GimpParam *param,
136
GimpParam **return_vals)
138
static GimpParam values[2];
139
GimpRunMode run_mode;
140
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
141
gint output_type = 0;
144
GimpExportReturn export = GIMP_EXPORT_CANCEL;
148
/* Set us up to return a status. */
150
*return_vals = values;
151
values[0].type = GIMP_PDB_STATUS;
152
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
153
run_mode = param[0].data.d_int32;
154
image_ID = param[1].data.d_int32;
155
drawable_ID = param[2].data.d_int32;
157
/* eventually export the image */
160
case GIMP_RUN_INTERACTIVE:
161
case GIMP_RUN_WITH_LAST_VALS:
162
gimp_ui_init (PLUG_IN_BINARY, FALSE);
163
export = gimp_export_image (&image_ID, &drawable_ID, "AA",
164
(GIMP_EXPORT_CAN_HANDLE_RGB |
165
GIMP_EXPORT_CAN_HANDLE_GRAY |
166
GIMP_EXPORT_CAN_HANDLE_ALPHA ));
167
if (export == GIMP_EXPORT_CANCEL)
169
values[0].data.d_status = GIMP_PDB_CANCEL;
177
if (! (gimp_drawable_is_rgb (drawable_ID) ||
178
gimp_drawable_is_gray (drawable_ID)))
180
status = GIMP_PDB_CALLING_ERROR;
183
if (status == GIMP_PDB_SUCCESS)
187
case GIMP_RUN_INTERACTIVE:
188
gimp_get_data (SAVE_PROC, &output_type);
189
output_type = aa_dialog (output_type);
191
status = GIMP_PDB_CANCEL;
194
case GIMP_RUN_NONINTERACTIVE:
195
/* Make sure all the arguments are there! */
198
status = GIMP_PDB_CALLING_ERROR;
202
output_type = get_type_from_string (param[5].data.d_string);
204
status = GIMP_PDB_CALLING_ERROR;
208
case GIMP_RUN_WITH_LAST_VALS:
209
gimp_get_data (SAVE_PROC, &output_type);
217
if (status == GIMP_PDB_SUCCESS)
219
if (save_aa (drawable_ID, param[3].data.d_string, output_type))
221
gimp_set_data (SAVE_PROC, &output_type, sizeof (output_type));
225
status = GIMP_PDB_EXECUTION_ERROR;
229
if (export == GIMP_EXPORT_EXPORT)
230
gimp_image_delete (image_ID);
232
values[0].data.d_status = status;
236
* The actual save function. What it's all about.
237
* The image type has to be GRAY.
240
save_aa (gint32 drawable_ID,
244
aa_savedata savedata;
246
aa_format format = *aa_formats[output_type];
248
format.width = gimp_drawable_width (drawable_ID) / 2;
249
format.height = gimp_drawable_height (drawable_ID) / 2;
251
/* Get a libaa context which will save its output to filename. */
252
savedata.name = filename;
253
savedata.format = &format;
255
context = aa_init (&save_d, &aa_defparams, &savedata);
259
gimp2aa (drawable_ID, context);
267
gimp2aa (gint32 drawable_ID,
270
GimpDrawable *drawable;
271
GimpPixelRgn pixel_rgn;
272
aa_renderparams *renderparams;
281
drawable = gimp_drawable_get (drawable_ID);
283
width = aa_imgwidth (context);
284
height = aa_imgheight (context);
287
gimp_tile_cache_ntiles ((width / gimp_tile_width ()) + 1);
289
gimp_pixel_rgn_init (&pixel_rgn,
290
drawable, 0, 0, width, height,
293
buffer = g_new (guchar, width * bpp);
295
for (y = 0; y < height; y++)
297
gimp_pixel_rgn_get_row (&pixel_rgn, buffer, 0, y, width);
302
for (x = 0, p = buffer; x < width; x++, p++)
303
aa_putpixel (context, x, y, *p);
306
case 2: /* GRAYA, blend over black */
307
for (x = 0, p = buffer; x < width; x++, p += 2)
308
aa_putpixel (context, x, y, (p[0] * (p[1] + 1)) >> 8);
312
for (x = 0, p = buffer; x < width; x++, p += 3)
313
aa_putpixel (context, x, y,
314
GIMP_RGB_LUMINANCE (p[0], p[1], p[2]) + 0.5);
317
case 4: /* RGBA, blend over black */
318
for (x = 0, p = buffer; x < width; x++, p += 4)
319
aa_putpixel (context, x, y,
320
((guchar) (GIMP_RGB_LUMINANCE (p[0], p[1], p[2]) + 0.5)
325
g_assert_not_reached ();
332
renderparams = aa_getrenderparams ();
333
renderparams->dither = AA_FLOYD_S;
335
aa_render (context, renderparams, 0, 0,
336
aa_scrwidth (context), aa_scrheight (context));
340
aa_dialog (gint selected)
348
/* Create the actual window. */
349
dialog = gimp_dialog_new (_("Save as Text"), PLUG_IN_BINARY,
351
gimp_standard_help_func, SAVE_PROC,
353
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
354
GTK_STOCK_SAVE, GTK_RESPONSE_OK,
358
gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
363
gimp_window_set_transient (GTK_WINDOW (dialog));
365
hbox = gtk_hbox_new (FALSE, 6);
366
gtk_container_set_border_width (GTK_CONTAINER (hbox), 12);
367
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
368
hbox, FALSE, FALSE, 0);
369
gtk_widget_show (hbox);
371
label = gtk_label_new_with_mnemonic (_("_Format:"));
372
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
373
gtk_widget_show (label);
375
combo = g_object_new (GIMP_TYPE_INT_COMBO_BOX, NULL);
376
gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
377
gtk_widget_show (combo);
379
gtk_label_set_mnemonic_widget (GTK_LABEL (label), combo);
381
for (i = 0; aa_formats[i]; i++)
382
gimp_int_combo_box_append (GIMP_INT_COMBO_BOX (combo),
383
GIMP_INT_STORE_VALUE, i,
384
GIMP_INT_STORE_LABEL, aa_formats[i]->formatname,
387
gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), selected,
388
G_CALLBACK (gimp_int_combo_box_get_active),
391
gtk_widget_show (dialog);
393
if (gimp_dialog_run (GIMP_DIALOG (dialog)) != GTK_RESPONSE_OK)
396
gtk_widget_destroy (dialog);