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 / gicon.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-24  |  12.5 KB  |  495 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. /*  saves and loads gimp icon files (For toolbox, etc)...
  20.  */
  21.  
  22. #include "config.h"
  23.  
  24. #include <setjmp.h>
  25. #include <sys/types.h>
  26. #include <sys/stat.h>
  27. #include <fcntl.h>
  28. #ifdef HAVE_UNISTD_H
  29. #include <unistd.h>
  30. #endif
  31. #include <ctype.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <math.h>
  36.  
  37. #include <gtk/gtk.h>
  38.  
  39. #include <libgimp/gimp.h>
  40. #include <libgimp/gimpui.h>
  41.  
  42. #include "libgimp/stdplugins-intl.h"
  43.  
  44.  
  45. typedef struct
  46. {
  47.   gchar icon_name[256];
  48. } GIconSaveVals;
  49.  
  50. typedef struct
  51. {
  52.   gint  run;
  53. } GIconSaveInterface;
  54.  
  55. /* Declare some local functions.
  56.  */
  57. static void   query         (void);
  58. static void   run           (gchar   *name,
  59.                  gint     nparams,
  60.                  GimpParam  *param,
  61.                  gint    *nreturn_vals,
  62.                  GimpParam **return_vals);
  63. static gint32 load_image    (gchar   *filename);
  64. static gint   save_image    (gchar   *filename,
  65.                  gint32   image_ID,
  66.                  gint32   drawable_ID);
  67.  
  68. static gint   save_dialog    (void);
  69.  
  70. static void   ok_callback    (GtkWidget *widget,
  71.                   gpointer   data);
  72. static void   entry_callback (GtkWidget *widget,
  73.                   gpointer   data);
  74.  
  75. GimpPlugInInfo PLUG_IN_INFO =
  76. {
  77.   NULL,  /* init_proc  */
  78.   NULL,  /* quit_proc  */
  79.   query, /* query_proc */
  80.   run,   /* run_proc   */
  81. };
  82.  
  83. static GIconSaveVals givals =
  84. {
  85.   "gicon" /*  icon_name  */
  86. };
  87.  
  88. static GIconSaveInterface giint =
  89. {
  90.   FALSE   /*  run  */
  91. };
  92.  
  93. MAIN ()
  94.  
  95. static void
  96. query (void)
  97. {
  98.   static GimpParamDef load_args[] =
  99.   {
  100.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  101.     { GIMP_PDB_STRING, "filename", "The name of the file to load" },
  102.     { GIMP_PDB_STRING, "raw_filename", "The name of the file to load" }
  103.   };
  104.   static GimpParamDef load_return_vals[] =
  105.   {
  106.     { GIMP_PDB_IMAGE, "image", "Output image" },
  107.   };
  108.   static gint nload_args = sizeof (load_args) / sizeof (load_args[0]);
  109.   static gint nload_return_vals = (sizeof (load_return_vals) /
  110.                    sizeof (load_return_vals[0]));
  111.  
  112.   static GimpParamDef save_args[] =
  113.   {
  114.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  115.     { GIMP_PDB_IMAGE, "image", "Input image" },
  116.     { GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" },
  117.     { GIMP_PDB_STRING, "filename", "The name of the file to save the image in" },
  118.     { GIMP_PDB_STRING, "raw_filename", "The name of the file to save the image in" },
  119.     { GIMP_PDB_STRING, "icon_name", "The name of the icon" }
  120.   };
  121.   static gint nsave_args = sizeof (save_args) / sizeof (save_args[0]);
  122.  
  123.   gimp_install_procedure ("file_gicon_load",
  124.                           "loads files of the .ico file format",
  125.                           "FIXME: write help",
  126.               "Spencer Kimball",
  127.               "Spencer Kimball",
  128.                           "1997",
  129.                           "<Load>/GIcon",
  130.                           NULL,
  131.                           GIMP_PLUGIN,
  132.                           nload_args, nload_return_vals,
  133.                           load_args, load_return_vals);
  134.  
  135.   gimp_install_procedure ("file_gicon_save",
  136.                           "saves files in the .ico file format",
  137.                           "FIXME: write help",
  138.               "Spencer Kimball",
  139.               "Spencer Kimball",
  140.                           "1997",
  141.                           "<Save>/GIcon",
  142.                           "GRAY*",
  143.                           GIMP_PLUGIN,
  144.                           nsave_args, 0,
  145.                           save_args, NULL);
  146.  
  147.   gimp_register_magic_load_handler ("file_gicon_load",
  148.                     "ico",
  149.                     "",
  150.                     "0,string,"
  151.                     "/*\\040\\040GIMP\\040icon\\040image");
  152.   gimp_register_save_handler ("file_gicon_save",
  153.                   "ico",
  154.                   "");
  155. }
  156.  
  157. static void
  158. run (gchar   *name,
  159.      gint     nparams,
  160.      GimpParam  *param,
  161.      gint    *nreturn_vals,
  162.      GimpParam **return_vals)
  163. {
  164.   static GimpParam values[2];
  165.   GimpRunModeType  run_mode;
  166.   GimpPDBStatusType   status = GIMP_PDB_SUCCESS;
  167.   gint32        image_ID;
  168.   gint32        drawable_ID;
  169.   GimpExportReturnType export = GIMP_EXPORT_CANCEL;
  170.  
  171.   run_mode = param[0].data.d_int32;
  172.  
  173.   *nreturn_vals = 1;
  174.   *return_vals  = values;
  175.   values[0].type          = GIMP_PDB_STATUS;
  176.   values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
  177.  
  178.   if (strcmp (name, "file_gicon_load") == 0)
  179.     {
  180.       image_ID = load_image (param[1].data.d_string);
  181.  
  182.       if (image_ID != -1)
  183.     {
  184.       *nreturn_vals = 2;
  185.       values[1].type         = GIMP_PDB_IMAGE;
  186.       values[1].data.d_image = image_ID;
  187.     }
  188.       else
  189.     {
  190.       status = GIMP_PDB_EXECUTION_ERROR;
  191.     }
  192.     }
  193.   else if (strcmp (name, "file_gicon_save") == 0)
  194.     {
  195.       image_ID    = param[1].data.d_int32;
  196.       drawable_ID = param[2].data.d_int32;
  197.  
  198.       /*  eventually export the image */ 
  199.       switch (run_mode)
  200.     {
  201.     case GIMP_RUN_INTERACTIVE:
  202.     case GIMP_RUN_WITH_LAST_VALS:
  203.       INIT_I18N_UI();
  204.       gimp_ui_init ("gicon", FALSE);
  205.       export = gimp_export_image (&image_ID, &drawable_ID, "GIcon", 
  206.                       (GIMP_EXPORT_CAN_HANDLE_GRAY |
  207.                        GIMP_EXPORT_CAN_HANDLE_ALPHA ));
  208.       if (export == GIMP_EXPORT_CANCEL)
  209.         {
  210.           values[0].data.d_status = GIMP_PDB_CANCEL;
  211.           return;
  212.         }
  213.       break;
  214.     default:
  215.       INIT_I18N();
  216.       break;
  217.     }
  218.  
  219.       switch (run_mode)
  220.     {
  221.     case GIMP_RUN_INTERACTIVE:
  222.       /*  Possibly retrieve data  */
  223.       gimp_get_data ("file_gicon_save", &givals);
  224.  
  225.       /*  First acquire information with a dialog  */
  226.       if (! save_dialog ())
  227.         status = GIMP_PDB_CANCEL;
  228.       break;
  229.  
  230.     case GIMP_RUN_NONINTERACTIVE:
  231.       /*  Make sure all the arguments are there!  */
  232.       if (nparams != 6)
  233.         {
  234.           status = GIMP_PDB_CALLING_ERROR;
  235.         }
  236.       else
  237.         {
  238.           strncpy (givals.icon_name, param[5].data.d_string, 256);
  239.         }
  240.       break;
  241.  
  242.     case GIMP_RUN_WITH_LAST_VALS:
  243.       /*  Possibly retrieve data  */
  244.       gimp_get_data ("file_gicon_save", &givals);
  245.       break;
  246.  
  247.     default:
  248.       break;
  249.     }
  250.  
  251.       if (status == GIMP_PDB_SUCCESS)
  252.     {
  253.       if (save_image (param[3].data.d_string, image_ID, drawable_ID))
  254.         {
  255.           /*  Store persistent data  */
  256.           gimp_set_data ("file_gicon_save", &givals, sizeof (GIconSaveVals));
  257.         }
  258.       else
  259.         {
  260.           status = GIMP_PDB_EXECUTION_ERROR;
  261.         }
  262.     }
  263.  
  264.       if (export == GIMP_EXPORT_EXPORT)
  265.     gimp_image_delete (image_ID);
  266.     }
  267.   else
  268.     {
  269.       status = GIMP_PDB_CALLING_ERROR;
  270.     }
  271.  
  272.   values[0].data.d_status = status;
  273. }
  274.  
  275. static gint32
  276. load_image (gchar *filename)
  277. {
  278.   GimpDrawable *drawable;
  279.   GimpPixelRgn pixel_rgn;
  280.   FILE * fp;
  281.   gint32 image_ID;
  282.   gint32 layer_ID;
  283.   char name_buf[256];
  284.   char * data_buf;
  285.   unsigned char *dest;
  286.   int val;
  287.   int width, height;
  288.   int i, j;
  289.  
  290.   /*  Open the requested file  */
  291.   if (! (fp = fopen (filename, "r")))
  292.     {
  293.       fprintf (stderr, "gicon: can't open \"%s\"\n", filename);
  294.       return -1;
  295.     }
  296.  
  297.   /*  Check the identifier string  */
  298.   fscanf (fp, "/*  %s icon image format -- S. Kimball, P. Mattis  */\n", name_buf);
  299.   if (strcmp ("GIMP", name_buf))
  300.     {
  301.       fprintf (stderr, "Not a GIcon file: %s!\n", filename);
  302.       return -1;
  303.     }
  304.  
  305.   /*  Parse the icon name  */
  306.   fscanf (fp, "/*  Image name: %s  */\n", name_buf);
  307.  
  308.   /*  Get the width and height  */
  309.   fscanf (fp, "#define %s %d\n", name_buf, &width);
  310.   fscanf (fp, "#define %s %d\n", name_buf, &height);
  311.   fscanf (fp, "static char *%s [] = \n{\n", name_buf);
  312.  
  313.   /*  Get a new image structure  */
  314.   image_ID = gimp_image_new (width, height, GIMP_GRAY);
  315.   gimp_image_set_filename (image_ID, filename);
  316.  
  317.   layer_ID = gimp_layer_new (image_ID, "Background", width, height,
  318.                  GIMP_GRAYA_IMAGE, 100, GIMP_NORMAL_MODE);
  319.   gimp_image_add_layer (image_ID, layer_ID, 0);
  320.  
  321.   drawable = gimp_drawable_get (layer_ID);
  322.   gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width,
  323.                drawable->height, TRUE, FALSE);
  324.  
  325.   data_buf = g_new (char, width);
  326.   dest     = g_new (guchar, width * 2);
  327.  
  328.   for (i = 0; i < height; i++)
  329.     {
  330.       fscanf (fp, "  \"%s\",\n", data_buf);
  331.       for (j = 0; j < width; j++)
  332.     {
  333.       val = data_buf[j];
  334.       if (val == '.')
  335.         {
  336.           dest[j*2+0] = 0;
  337.           dest[j*2+1] = 0;  /*  set alpha channel to transparent  */
  338.         }
  339.       else
  340.         {
  341.           dest[j*2+0] = (255 * (val - 'a')) / 7;
  342.           dest[j*2+1] = 255;  /*  set alpha channel to opaque  */
  343.         }
  344.     }
  345.  
  346.       gimp_pixel_rgn_set_row (&pixel_rgn, dest, 0, i, width);
  347.     }
  348.  
  349.   /*  Clean up  */
  350.   fclose (fp);
  351.  
  352.   gimp_drawable_flush(drawable);
  353.  
  354.   g_free (data_buf);
  355.   g_free (dest);
  356.  
  357.   return image_ID;
  358. }
  359.  
  360. static gint
  361. save_image (char   *filename,
  362.         gint32  image_ID,
  363.         gint32  drawable_ID)
  364. {
  365.   GimpDrawable *drawable;
  366.   GimpPixelRgn  pixel_rgn;
  367.   FILE * fp;
  368.   int i, j;
  369.   int w, h;
  370.   int has_alpha;
  371.   int val;
  372.   char ch;
  373.   unsigned char *src_buf, *src;
  374.  
  375.   drawable = gimp_drawable_get (drawable_ID);
  376.   gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width,
  377.                drawable->height, FALSE, FALSE);
  378.  
  379.   w = drawable->width;
  380.   h = drawable->height;
  381.   has_alpha = gimp_drawable_has_alpha (drawable_ID);
  382.  
  383.   /*  open the file for writing  */
  384.   if ((fp = fopen (filename, "w")))
  385.     {
  386.       fprintf (fp, "/*  GIMP icon image format -- S. Kimball, P. Mattis  */\n");
  387.       fprintf (fp, "/*  Image name: %s  */\n", givals.icon_name);
  388.       fprintf (fp, "\n\n");
  389.       fprintf (fp, "#define %s_width %d\n", givals.icon_name, w);
  390.       fprintf (fp, "#define %s_height %d\n", givals.icon_name, h);
  391.       fprintf (fp, "static char *%s_bits [] = \n{\n", givals.icon_name);
  392.  
  393.       /*  write the brush data to the file  */
  394.       src_buf = g_new (guchar, w * drawable->bpp);
  395.       for (i = 0; i < h; i++)
  396.     {
  397.       gimp_pixel_rgn_get_row (&pixel_rgn, src_buf, 0, i, w);
  398.       src = src_buf;
  399.  
  400.       fprintf (fp, "  \"");
  401.       for (j = 0; j < w; j++)
  402.         {
  403.           if (has_alpha && !src[1])
  404.         {
  405.           ch = '.';
  406.         }
  407.           else
  408.         {
  409.           val = (int) ((double) src[0] * 7.0 / 255.0 + 0.5);
  410.           ch = 'a' + val;
  411.         }
  412.           fputc (ch, fp);
  413.  
  414.           src += drawable->bpp;
  415.         }
  416.  
  417.       fprintf (fp, (i == (h-1)) ? "\"\n};\n" : "\",\n");
  418.     }
  419.  
  420.       /*  Clean up  */
  421.       g_free (src_buf);
  422.  
  423.       fclose (fp);
  424.     }
  425.  
  426.   return TRUE;
  427. }
  428.  
  429. static gint
  430. save_dialog (void)
  431. {
  432.   GtkWidget *dlg;
  433.   GtkWidget *table;
  434.   GtkWidget *entry;
  435.  
  436.   dlg = gimp_dialog_new (_("Save as GIcon"), "gicon",
  437.              gimp_standard_help_func, "filters/gicon.html",
  438.              GTK_WIN_POS_MOUSE,
  439.              FALSE, TRUE, FALSE,
  440.  
  441.              _("OK"), ok_callback,
  442.              NULL, NULL, NULL, TRUE, FALSE,
  443.              _("Cancel"), gtk_widget_destroy,
  444.              NULL, 1, NULL, FALSE, TRUE,
  445.  
  446.              NULL);
  447.  
  448.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  449.               GTK_SIGNAL_FUNC (gtk_main_quit),
  450.               NULL);
  451.  
  452.   /* The main table */
  453.   table = gtk_table_new (1, 2, FALSE);
  454.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  455.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  456.   gtk_container_set_border_width (GTK_CONTAINER (table), 6);
  457.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), table, TRUE, TRUE, 0);
  458.   gtk_widget_show (table);
  459.  
  460.  
  461.   entry = gtk_entry_new ();
  462.   gtk_widget_set_usize (entry, 200, 0);
  463.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  464.                  _("Icon Name:"), 1.0, 0.5,
  465.                  entry, 1, FALSE);
  466.   gtk_entry_set_text (GTK_ENTRY (entry), givals.icon_name);
  467.   gtk_signal_connect (GTK_OBJECT (entry), "changed",
  468.               GTK_SIGNAL_FUNC (entry_callback),
  469.               givals.icon_name);
  470.   gtk_widget_show (entry);
  471.  
  472.   gtk_widget_show (dlg);
  473.  
  474.   gtk_main ();
  475.   gdk_flush ();
  476.  
  477.   return giint.run;
  478. }
  479.  
  480. static void
  481. ok_callback (GtkWidget *widget,
  482.          gpointer   data)
  483. {
  484.   giint.run = TRUE;
  485.  
  486.   gtk_widget_destroy (GTK_WIDGET (data));
  487. }
  488.  
  489. static void
  490. entry_callback (GtkWidget *widget,
  491.         gpointer   data)
  492. {
  493.   strncpy (givals.icon_name, gtk_entry_get_text (GTK_ENTRY (widget)), 256);
  494. }
  495.