home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / common / aa.c next >
Encoding:
C/C++ Source or Header  |  2000-08-24  |  10.1 KB  |  416 lines

  1. /**
  2.  * aa.c version 1.0
  3.  * A plugin that uses libaa (ftp://ftp.ta.jcu.cz/pub/aa) to save images as
  4.  * ASCII.
  5.  * NOTE: This plugin *requires* aalib 1.2 or later. Earlier versions will
  6.  * not work.
  7.  * Code copied from all over the GIMP source.
  8.  * Tim Newsome <nuisance@cmu.edu>
  9.  */
  10.  
  11. #include "config.h"
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16.  
  17. #include <aalib.h>
  18.  
  19. #include <gtk/gtk.h>
  20.  
  21. #include <libgimp/gimp.h>
  22. #include <libgimp/gimpui.h>
  23.  
  24. #include "libgimp/stdplugins-intl.h"
  25.  
  26. /* 
  27.  * Declare some local functions.
  28.  */
  29. static void       query      (void);
  30. static void       run        (gchar      *name, 
  31.                   gint        nparams, 
  32.                   GimpParam     *param, 
  33.                   gint       *nreturn_vals, 
  34.                   GimpParam    **return_vals);
  35. static gboolean   aa_savable (gint32      drawable_ID);
  36. static gboolean   save_aa    (gint        output_type, 
  37.                   gchar      *filename, 
  38.                   gint32      image,
  39.                   gint32      drawable);
  40. static void       gimp2aa    (gint32      image, 
  41.                   gint32      drawable_ID, 
  42.                   aa_context *context);
  43.  
  44. static gint   type_dialog                 (int        selected);
  45. static void   type_dialog_toggle_update   (GtkWidget *widget, 
  46.                        gpointer   data);
  47. static void   type_dialog_cancel_callback (GtkWidget *widget, 
  48.                        gpointer   data);
  49.  
  50. /* 
  51.  * Some global variables.
  52.  */
  53.  
  54. GimpPlugInInfo PLUG_IN_INFO =
  55. {
  56.   NULL,  /* init_proc  */
  57.   NULL,  /* quit_proc  */
  58.   query, /* query_proc */
  59.   run,   /* run_proc   */
  60. };
  61.  
  62. /**
  63.  * Type the user selected. (Global for easier UI coding.)
  64.  */
  65. static gint selected_type = 0;
  66.  
  67.  
  68. MAIN ()
  69.  
  70. static void 
  71. query (void)
  72. {
  73.   static GimpParamDef save_args[] =
  74.   {
  75.     {GIMP_PDB_INT32,    "run_mode",     "Interactive, non-interactive"},
  76.     {GIMP_PDB_IMAGE,    "image",        "Input image"},
  77.     {GIMP_PDB_DRAWABLE, "drawable",     "Drawable to save"},
  78.     {GIMP_PDB_STRING,   "filename",     "The name of the file to save the image in"},
  79.     {GIMP_PDB_STRING,   "raw_filename", "The name entered"},
  80.     {GIMP_PDB_STRING,   "file_type",    "File type to use"}
  81.   };
  82.   static gint nsave_args = sizeof(save_args) / sizeof(save_args[0]);
  83.  
  84.   gimp_install_procedure ("file_aa_save",
  85.               "Saves files in various text formats",
  86.               "Saves files in various text formats",
  87.               "Tim Newsome <nuisance@cmu.edu>",
  88.               "Tim Newsome <nuisance@cmu.edu>",
  89.               "1997",
  90.               "<Save>/AA",
  91.               "GRAY*",        /* support grayscales */
  92.               GIMP_PLUGIN,
  93.               nsave_args, 0,
  94.               save_args, NULL);
  95.  
  96.   gimp_register_save_handler ("file_aa_save",
  97.                   "ansi,txt,text,html",
  98.                   "");
  99. }
  100.  
  101. /**
  102.  * Searches aa_formats defined by aalib to find the index of the type
  103.  * specified by string.
  104.  * -1 means it wasn't found.
  105.  */
  106. static int 
  107. get_type_from_string (gchar *string)
  108. {
  109.   gint type = 0;
  110.   aa_format **p = aa_formats;
  111.  
  112.   while (*p && strcmp ((*p)->formatname, string))
  113.     {
  114.       p++;
  115.       type++;
  116.     }
  117.  
  118.   if (*p == NULL)
  119.     return -1;
  120.  
  121.   return type;
  122. }
  123.  
  124. static void 
  125. run (gchar   *name, 
  126.      gint     nparams, 
  127.      GimpParam  *param, 
  128.      gint    *nreturn_vals,
  129.      GimpParam **return_vals)
  130. {
  131.   static GimpParam values[2];
  132.   GimpRunModeType  run_mode;
  133.   GimpPDBStatusType   status = GIMP_PDB_SUCCESS;
  134.   gint          output_type = 0;
  135.   static int    last_type = 0;
  136.   gint32        image_ID;
  137.   gint32        drawable_ID;
  138.   GimpExportReturnType export = GIMP_EXPORT_CANCEL;
  139.  
  140.   /* Set us up to return a status. */
  141.   *nreturn_vals = 1;
  142.   *return_vals  = values;
  143.   values[0].type          = GIMP_PDB_STATUS;
  144.   values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
  145.  
  146.   run_mode    = param[0].data.d_int32;
  147.   image_ID    = param[1].data.d_int32;
  148.   drawable_ID = param[2].data.d_int32;
  149.  
  150.   /*  eventually export the image */ 
  151.   switch (run_mode)
  152.     {
  153.     case GIMP_RUN_INTERACTIVE:
  154.     case GIMP_RUN_WITH_LAST_VALS:
  155.       INIT_I18N_UI();
  156.       gimp_ui_init ("aa", FALSE);
  157.       export = gimp_export_image (&image_ID, &drawable_ID, "AA", 
  158.                   (GIMP_EXPORT_CAN_HANDLE_GRAY |
  159.                    GIMP_EXPORT_CAN_HANDLE_ALPHA ));
  160.       if (export == GIMP_EXPORT_CANCEL)
  161.     {
  162.       values[0].data.d_status = GIMP_PDB_CANCEL;
  163.       return;
  164.     }
  165.       break;
  166.     default:
  167.       INIT_I18N();
  168.       break;
  169.     }
  170.  
  171.   if (!aa_savable (drawable_ID)) 
  172.     {
  173.       status = GIMP_PDB_CALLING_ERROR;
  174.     }
  175.  
  176.   if (status == GIMP_PDB_SUCCESS)
  177.     {
  178.       switch (run_mode) 
  179.     {
  180.     case GIMP_RUN_INTERACTIVE:
  181.       gimp_get_data ("file_aa_save", &last_type);
  182.       output_type = type_dialog (last_type);
  183.       if (output_type < 0)
  184.         status = GIMP_PDB_CANCEL;
  185.       break;
  186.  
  187.     case GIMP_RUN_NONINTERACTIVE:
  188.       /*  Make sure all the arguments are there!  */
  189.       if (nparams != 6)
  190.         {
  191.           status = GIMP_PDB_CALLING_ERROR;
  192.         }
  193.       else
  194.         {
  195.           output_type = get_type_from_string (param[5].data.d_string);
  196.           if (output_type < 0)
  197.         status = GIMP_PDB_CALLING_ERROR;
  198.         }
  199.       break;
  200.  
  201.     case GIMP_RUN_WITH_LAST_VALS:
  202.       gimp_get_data ("file_aa_save", &last_type);
  203.       output_type = last_type;
  204.       break;
  205.  
  206.     default:
  207.       break;
  208.     }
  209.     }
  210.  
  211.   if (status == GIMP_PDB_SUCCESS)
  212.     {
  213.       if (save_aa (output_type, param[3].data.d_string, image_ID, drawable_ID))
  214.     {
  215.       status = GIMP_PDB_EXECUTION_ERROR;
  216.     }
  217.       else
  218.     {
  219.       last_type = output_type;
  220.       gimp_set_data ("file_aa_save", &last_type, sizeof (last_type));
  221.     }
  222.     }
  223.  
  224.   if (export == GIMP_EXPORT_EXPORT)
  225.     gimp_image_delete (image_ID);  
  226.  
  227.   values[0].data.d_status = status;
  228. }
  229.  
  230. /**
  231.  * The actual save function. What it's all about.
  232.  * The image type has to be GRAY.
  233.  */
  234. static gboolean
  235. save_aa (gint    output_type, 
  236.      gchar  *filename, 
  237.      gint32  image_ID,
  238.      gint32  drawable_ID)
  239. {
  240.   aa_savedata savedata = {NULL, NULL};
  241.   aa_context *context  = NULL;
  242.   GimpDrawable *drawable  = NULL;
  243.   aa_format format;
  244.  
  245.   /*fprintf(stderr, "save %s\n", filename); */
  246.  
  247.   drawable = gimp_drawable_get (drawable_ID);
  248.   memcpy (&format, aa_formats[output_type], sizeof (format));
  249.   format.width = drawable->width / 2;
  250.   format.height = drawable->height / 2;
  251.  
  252.   /*fprintf(stderr, "save_aa %i x %i\n", format.width, format.height); */
  253.  
  254.   /* Get a libaa context which will save its output to filename. */
  255.   savedata.name = filename;
  256.   savedata.format = &format;
  257.  
  258.   context = aa_init (&save_d, &aa_defparams, &savedata);
  259.   if (context == NULL)
  260.     return TRUE;
  261.  
  262.   gimp2aa (image_ID, drawable_ID, context);
  263.   aa_flush (context);
  264.   aa_close (context);
  265.  
  266.   /*fprintf(stderr, "Success!\n"); */
  267.  
  268.   return FALSE;
  269. }
  270.  
  271. static void
  272. gimp2aa (gint32      image, 
  273.      gint32      drawable_ID, 
  274.      aa_context *context)
  275. {
  276.   gint width, height, x, y;
  277.   guchar *buffer;
  278.   GimpDrawable *drawable = NULL;
  279.   GimpPixelRgn pixel_rgn;
  280.   aa_renderparams *renderparams = NULL;
  281.   gint bpp;
  282.  
  283.   width = aa_imgwidth (context);
  284.   height = aa_imgheight (context);
  285.   /*fprintf(stderr, "gimp2aa %i x %i\n", width, height); */
  286.  
  287.   drawable = gimp_drawable_get (drawable_ID);
  288.  
  289.   bpp = drawable->bpp;
  290.   buffer = g_new (guchar, width * bpp);
  291.  
  292.   gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width,
  293.                drawable->height, FALSE, FALSE);
  294.  
  295.   for (y = 0; y < height; y++) 
  296.     {
  297.       gimp_pixel_rgn_get_row (&pixel_rgn, buffer, 0, y, width);
  298.       for (x = 0; x < width; x++) 
  299.     {
  300.       /* Just copy one byte. If it's indexed that's all we need. Otherwise
  301.        * it'll be the most significant one. */
  302.       aa_putpixel (context, x, y, buffer[x * bpp]);
  303.     }
  304.     }
  305.  
  306.   renderparams = aa_getrenderparams ();
  307.   renderparams->dither = AA_FLOYD_S;
  308.   aa_render (context, renderparams, 0, 0, 
  309.          aa_scrwidth (context), aa_scrheight (context));
  310. }
  311.  
  312. static gboolean 
  313. aa_savable (gint32 drawable_ID)
  314. {
  315.   GimpImageType drawable_type;
  316.  
  317.   drawable_type = gimp_drawable_type (drawable_ID);
  318.  
  319.   if (drawable_type != GIMP_GRAY_IMAGE && drawable_type != GIMP_GRAYA_IMAGE)
  320.     return FALSE;
  321.  
  322.   return TRUE;
  323. }
  324.  
  325. /* 
  326.  * User Interface dialog thingie.
  327.  */
  328.  
  329. static gint 
  330. type_dialog (int selected) 
  331. {
  332.   GtkWidget *dlg;
  333.   GtkWidget *toggle;
  334.   GtkWidget *frame;
  335.   GtkWidget *toggle_vbox;
  336.   GSList *group;
  337.  
  338.   /* Create the actual window. */
  339.   dlg = gimp_dialog_new (_("Save as Text"), "aa",
  340.              gimp_standard_help_func, "filters/aa.html",
  341.              GTK_WIN_POS_MOUSE,
  342.              FALSE, TRUE, FALSE,
  343.  
  344.              _("OK"), gtk_widget_destroy,
  345.              NULL, 1, NULL, TRUE, FALSE,
  346.              _("Cancel"), type_dialog_cancel_callback,
  347.              NULL, NULL, NULL, FALSE, TRUE,
  348.  
  349.              NULL);
  350.  
  351.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  352.               GTK_SIGNAL_FUNC (gtk_main_quit),
  353.               NULL);
  354.  
  355.   /*  file save type  */
  356.   frame = gtk_frame_new (_("Data Formatting"));
  357.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  358.   gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
  359.   gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dlg)->vbox), frame, TRUE, TRUE, 0);
  360.  
  361.   toggle_vbox = gtk_vbox_new (FALSE, 2);
  362.   gtk_container_set_border_width (GTK_CONTAINER(toggle_vbox), 4);
  363.   gtk_container_add (GTK_CONTAINER (frame), toggle_vbox);
  364.   
  365.   group = NULL;
  366.   {
  367.     aa_format **p = aa_formats;
  368.     gint current = 0;
  369.  
  370.     while (*p != NULL) 
  371.       {
  372.     toggle = gtk_radio_button_new_with_label (group, (*p)->formatname);
  373.     group = gtk_radio_button_group (GTK_RADIO_BUTTON (toggle));
  374.     gtk_box_pack_start (GTK_BOX  (toggle_vbox), toggle, FALSE, FALSE, 0);
  375.     gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  376.                 GTK_SIGNAL_FUNC (type_dialog_toggle_update),
  377.                 (*p)->formatname);
  378.     if (current == selected)
  379.       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), TRUE);
  380.     
  381.     gtk_widget_show (toggle);
  382.     p++;
  383.     current++;
  384.       }
  385.   }
  386.  
  387.   gtk_widget_show (toggle_vbox);
  388.   gtk_widget_show (frame);
  389.  
  390.   gtk_widget_show (dlg);
  391.  
  392.   gtk_main ();
  393.   gdk_flush ();
  394.  
  395.   return selected_type;
  396. }
  397.  
  398. /*
  399.  * Callbacks for the dialog.
  400.  */
  401.  
  402. static void 
  403. type_dialog_cancel_callback (GtkWidget *widget, 
  404.                  gpointer   data) 
  405. {
  406.   selected_type = -1;
  407.   gtk_widget_destroy (GTK_WIDGET (data));
  408. }
  409.  
  410. static void 
  411. type_dialog_toggle_update (GtkWidget *widget, 
  412.                gpointer   data) 
  413. {
  414.   selected_type = get_type_from_string ((char *) data);
  415. }
  416.