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

  1. /*
  2.  * "$Id: sgi.c,v 1.26 2000/08/24 14:17:34 neo Exp $"
  3.  *
  4.  *   SGI image file plug-in for the GIMP.
  5.  *
  6.  *   Copyright 1997-1998 Michael Sweet (mike@easysw.com)
  7.  *
  8.  *   This program is free software; you can redistribute it and/or modify it
  9.  *   under the terms of the GNU General Public License as published by the Free
  10.  *   Software Foundation; either version 2 of the License, or (at your option)
  11.  *   any later version.
  12.  *
  13.  *   This program is distributed in the hope that it will be useful, but
  14.  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  15.  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16.  *   for more details.
  17.  *
  18.  *   You should have received a copy of the GNU General Public License
  19.  *   along with this program; if not, write to the Free Software
  20.  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21.  *
  22.  * Contents:
  23.  *
  24.  *   main()                      - Main entry - just call gimp_main()...
  25.  *   query()                     - Respond to a plug-in query...
  26.  *   run()                       - Run the plug-in...
  27.  *   load_image()                - Load a PNG image into a new image window.
  28.  *   save_image()                - Save the specified image to a PNG file.
  29.  *   save_ok_callback()          - Destroy the save dialog and save the image.
  30.  *   save_dialog()               - Pop up the save dialog.
  31.  *
  32.  */
  33.  
  34. #include "config.h"
  35.  
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <signal.h>
  39.  
  40. #include <gtk/gtk.h>
  41.  
  42. #include <libgimp/gimp.h>
  43. #include <libgimp/gimpui.h>
  44.  
  45. #include "libgimp/stdplugins-intl.h"
  46.  
  47. #include "sgi.h"        /* SGI image library definitions */
  48.  
  49.  
  50.  
  51. /*
  52.  * Constants...
  53.  */
  54.  
  55. #define PLUG_IN_VERSION  "1.1.1 - 17 May 1998"
  56.  
  57.  
  58. /*
  59.  * Local functions...
  60.  */
  61.  
  62. static void    query       (void);
  63. static void    run         (gchar   *name,
  64.                  gint     nparams,
  65.                  GimpParam  *param,
  66.                  gint    *nreturn_vals,
  67.                  GimpParam **return_vals);
  68.  
  69. static gint32    load_image  (gchar   *filename);
  70. static gint    save_image  (gchar   *filename,
  71.                  gint32   image_ID,
  72.                  gint32   drawable_ID);
  73.  
  74. static gint    save_dialog (void);
  75.  
  76. /*
  77.  * Globals...
  78.  */
  79.  
  80. GimpPlugInInfo    PLUG_IN_INFO =
  81. {
  82.   NULL,  /* init_proc  */
  83.   NULL,  /* quit_proc  */
  84.   query, /* query_proc */
  85.   run,   /* run_proc   */
  86. };
  87.  
  88. static gint  compression = SGI_COMP_RLE;
  89. static gint  runme       = FALSE;
  90.  
  91.  
  92. MAIN ()
  93.  
  94. static void
  95. query (void)
  96. {
  97.   static GimpParamDef load_args[] =
  98.   {
  99.     { GIMP_PDB_INT32,      "run_mode",     "Interactive, non-interactive" },
  100.     { GIMP_PDB_STRING,     "filename",     "The name of the file to load" },
  101.     { GIMP_PDB_STRING,     "raw_filename", "The name of the file to load" },
  102.   };
  103.   static GimpParamDef load_return_vals[] =
  104.   {
  105.     { GIMP_PDB_IMAGE,      "image",        "Output image" },
  106.   };
  107.   static gint nload_args = sizeof (load_args) / sizeof (load_args[0]);
  108.   static gint nload_return_vals = (sizeof (load_return_vals) /
  109.                    sizeof (load_return_vals[0]));
  110.  
  111.   static GimpParamDef save_args[] =
  112.   {
  113.     { GIMP_PDB_INT32,    "run_mode",    "Interactive, non-interactive" },
  114.     { GIMP_PDB_IMAGE,    "image",    "Input image" },
  115.     { GIMP_PDB_DRAWABLE,    "drawable",    "Drawable to save" },
  116.     { GIMP_PDB_STRING,    "filename",    "The name of the file to save the image in" },
  117.     { GIMP_PDB_STRING,    "raw_filename",    "The name of the file to save the image in" },
  118.     { GIMP_PDB_INT32,    "compression",    "Compression level (0 = none, 1 = RLE, 2 = ARLE)" }
  119.   };
  120.   static gint     nsave_args = sizeof (save_args) / sizeof (save_args[0]);
  121.  
  122.   INIT_I18N();
  123.  
  124.   gimp_install_procedure ("file_sgi_load",
  125.               "Loads files in SGI image file format",
  126.               "This plug-in loads SGI image files.",
  127.               "Michael Sweet <mike@easysw.com>",
  128.               "Copyright 1997-1998 by Michael Sweet",
  129.               PLUG_IN_VERSION,
  130.               "<Load>/SGI",
  131.               NULL,
  132.               GIMP_PLUGIN,
  133.               nload_args,
  134.               nload_return_vals,
  135.               load_args,
  136.               load_return_vals);
  137.  
  138.   gimp_install_procedure ("file_sgi_save",
  139.               "Saves files in SGI image file format",
  140.               "This plug-in saves SGI image files.",
  141.               "Michael Sweet <mike@easysw.com>",
  142.               "Copyright 1997-1998 by Michael Sweet",
  143.               PLUG_IN_VERSION,
  144.               "<Save>/SGI",
  145.               "RGB*,GRAY*",
  146.               GIMP_PLUGIN,
  147.               nsave_args,
  148.               0,
  149.               save_args,
  150.               NULL);
  151.  
  152.   gimp_register_magic_load_handler ("file_sgi_load",
  153.                     "rgb,bw,sgi,icon",
  154.                     "",
  155.                     "0,short,474");
  156.   gimp_register_save_handler       ("file_sgi_save",
  157.                     "rgb,bw,sgi,icon",
  158.                     "");
  159. }
  160.  
  161. static void
  162. run (gchar   *name,
  163.      gint     nparams,
  164.      GimpParam  *param,
  165.      gint    *nreturn_vals,
  166.      GimpParam **return_vals)
  167. {
  168.   static GimpParam values[2];
  169.   GimpRunModeType  run_mode;       
  170.   GimpPDBStatusType   status = GIMP_PDB_SUCCESS;
  171.   gint32    image_ID;    
  172.   gint32        drawable_ID;
  173.   GimpExportReturnType export = GIMP_EXPORT_CANCEL;
  174.  
  175.   run_mode = param[0].data.d_int32;
  176.  
  177.   *nreturn_vals = 1;
  178.   *return_vals  = values;
  179.   values[0].type          = GIMP_PDB_STATUS;
  180.   values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
  181.  
  182.   INIT_I18N_UI();
  183.  
  184.   if (strcmp (name, "file_sgi_load") == 0)
  185.     {
  186.       image_ID = load_image (param[1].data.d_string);
  187.  
  188.       if (image_ID != -1)
  189.     {
  190.       *nreturn_vals = 2;
  191.       values[1].type         = GIMP_PDB_IMAGE;
  192.       values[1].data.d_image = image_ID;
  193.     }
  194.       else
  195.     {
  196.       status = GIMP_PDB_EXECUTION_ERROR;
  197.     }
  198.     }
  199.   else if (strcmp (name, "file_sgi_save") == 0)
  200.     {
  201.       image_ID    = param[1].data.d_int32;
  202.       drawable_ID = param[2].data.d_int32;
  203.  
  204.       /*  eventually export the image */ 
  205.       switch (run_mode)
  206.     {
  207.     case GIMP_RUN_INTERACTIVE:
  208.     case GIMP_RUN_WITH_LAST_VALS:
  209.       gimp_ui_init ("sgi", FALSE);
  210.       export = gimp_export_image (&image_ID, &drawable_ID, "SGI", 
  211.                       (GIMP_EXPORT_CAN_HANDLE_RGB |
  212.                        GIMP_EXPORT_CAN_HANDLE_GRAY |
  213.                        GIMP_EXPORT_CAN_HANDLE_ALPHA ));
  214.       if (export == GIMP_EXPORT_CANCEL)
  215.         {
  216.           values[0].data.d_status = GIMP_PDB_CANCEL;
  217.           return;
  218.         }
  219.       break;
  220.     default:
  221.       break;
  222.     }
  223.  
  224.       switch (run_mode)
  225.     {
  226.     case GIMP_RUN_INTERACTIVE:
  227.       /*
  228.        * Possibly retrieve data...
  229.        */
  230.           gimp_get_data ("file_sgi_save", &compression);
  231.  
  232.       /*
  233.        * Then acquire information with a dialog...
  234.        */
  235.           if (!save_dialog ())
  236.             status = GIMP_PDB_CANCEL;
  237.           break;
  238.  
  239.     case GIMP_RUN_NONINTERACTIVE:
  240.       /*
  241.        * Make sure all the arguments are there!
  242.        */
  243.           if (nparams != 6)
  244.         {
  245.           status = GIMP_PDB_CALLING_ERROR;
  246.         }
  247.           else
  248.         {
  249.           compression = param[5].data.d_int32;
  250.  
  251.           if (compression < 0 || compression > 2)
  252.         status = GIMP_PDB_CALLING_ERROR;
  253.         };
  254.           break;
  255.  
  256.     case GIMP_RUN_WITH_LAST_VALS:
  257.       /*
  258.        * Possibly retrieve data...
  259.        */
  260.           gimp_get_data ("file_sgi_save", &compression);
  261.           break;
  262.  
  263.     default:
  264.           break;
  265.     };
  266.  
  267.       if (status == GIMP_PDB_SUCCESS)
  268.     {
  269.       if (save_image (param[3].data.d_string, image_ID, drawable_ID))
  270.         {
  271.           gimp_set_data ("file_sgi_save",
  272.                  &compression, sizeof (compression));
  273.         }
  274.       else
  275.         {
  276.           status = GIMP_PDB_EXECUTION_ERROR;
  277.         }
  278.     }
  279.  
  280.       if (export == GIMP_EXPORT_EXPORT)
  281.     gimp_image_delete (image_ID);
  282.     }
  283.   else
  284.     {
  285.       status = GIMP_PDB_CALLING_ERROR;
  286.     }
  287.  
  288.   values[0].data.d_status = status;
  289. }
  290.  
  291.  
  292. /*
  293.  * 'load_image()' - Load a PNG image into a new image window.
  294.  */
  295.  
  296. static gint32
  297. load_image (gchar *filename)    /* I - File to load */
  298. {
  299.   int        i,        /* Looping var */
  300.         x,        /* Current X coordinate */
  301.         y,        /* Current Y coordinate */
  302.         image_type,    /* Type of image */
  303.         layer_type,    /* Type of drawable/layer */
  304.         tile_height,    /* Height of tile in GIMP */
  305.         count;        /* Count of rows to put in image */
  306.   sgi_t        *sgip;        /* File pointer */
  307.   gint32    image,        /* Image */
  308.         layer;        /* Layer */
  309.   GimpDrawable    *drawable;    /* Drawable for layer */
  310.   GimpPixelRgn    pixel_rgn;    /* Pixel region for layer */
  311.   guchar    **pixels,    /* Pixel rows */
  312.         *pixel,        /* Pixel data */
  313.         *pptr;        /* Current pixel */
  314.   gushort      **rows;            /* SGI image data */
  315.   gchar        *progress;    /* Title for progress display... */
  316.  
  317.  
  318.  /*
  319.   * Open the file for reading...
  320.   */
  321.  
  322.   sgip = sgiOpen(filename, SGI_READ, 0, 0, 0, 0, 0);
  323.   if (sgip == NULL)
  324.     {
  325.       g_message ("can't open image file\n");
  326.       return -1;
  327.     };
  328.  
  329.   if (strrchr(filename, '/') != NULL)
  330.     progress = g_strdup_printf (_("Loading %s:"), strrchr(filename, '/') + 1);
  331.   else
  332.     progress = g_strdup_printf (_("Loading %s:"), filename);
  333.  
  334.   gimp_progress_init(progress);
  335.   g_free (progress);
  336.  
  337.   /*
  338.    * Get the image dimensions and create the image...
  339.    */
  340.   image_type = 0; /* shut up warnings */
  341.   layer_type = 0;
  342.   switch (sgip->zsize)
  343.     {
  344.     case 1 :    /* Grayscale */
  345.       image_type = GIMP_GRAY;
  346.       layer_type = GIMP_GRAY_IMAGE;
  347.       break;
  348.  
  349.     case 2 :    /* Grayscale + alpha */
  350.       image_type = GIMP_GRAY;
  351.       layer_type = GIMP_GRAYA_IMAGE;
  352.       break;
  353.  
  354.     case 3 :    /* RGB */
  355.       image_type = GIMP_RGB;
  356.       layer_type = GIMP_RGB_IMAGE;
  357.       break;
  358.  
  359.     case 4 :    /* RGBA */
  360.       image_type = GIMP_RGB;
  361.       layer_type = GIMP_RGBA_IMAGE;
  362.       break;
  363.     }
  364.  
  365.   image = gimp_image_new(sgip->xsize, sgip->ysize, image_type);
  366.   if (image == -1)
  367.     {
  368.       g_message ("can't allocate new image\n");
  369.       return -1;
  370.     }
  371.  
  372.   gimp_image_set_filename(image, filename);
  373.  
  374.   /*
  375.    * Create the "background" layer to hold the image...
  376.    */
  377.  
  378.   layer = gimp_layer_new (image, _("Background"), sgip->xsize, sgip->ysize,
  379.               layer_type, 100, GIMP_NORMAL_MODE);
  380.   gimp_image_add_layer(image, layer, 0);
  381.  
  382.   /*
  383.    * Get the drawable and set the pixel region for our load...
  384.    */
  385.  
  386.   drawable = gimp_drawable_get(layer);
  387.  
  388.   gimp_pixel_rgn_init(&pixel_rgn, drawable, 0, 0, drawable->width,
  389.                       drawable->height, TRUE, FALSE);
  390.  
  391.   /*
  392.    * Temporary buffers...
  393.    */
  394.  
  395.   tile_height = gimp_tile_height();
  396.   pixel       = g_new(guchar, tile_height * sgip->xsize * sgip->zsize);
  397.   pixels      = g_new(guchar *, tile_height);
  398.  
  399.   for (i = 0; i < tile_height; i ++)
  400.     pixels[i] = pixel + sgip->xsize * sgip->zsize * i;
  401.  
  402.   rows    = g_new(unsigned short *, sgip->zsize);
  403.   rows[0] = g_new(unsigned short, sgip->xsize * sgip->zsize);
  404.  
  405.   for (i = 1; i < sgip->zsize; i ++)
  406.     rows[i] = rows[0] + i * sgip->xsize;
  407.  
  408.   /*
  409.    * Load the image...
  410.    */
  411.  
  412.   for (y = 0, count = 0;
  413.        y < sgip->ysize;
  414.        y ++, count ++)
  415.     {
  416.       if (count >= tile_height)
  417.     {
  418.       gimp_pixel_rgn_set_rect (&pixel_rgn, pixel,
  419.                    0, y - count, drawable->width, count);
  420.       count = 0;
  421.  
  422.       gimp_progress_update((double)y / (double)sgip->ysize);
  423.     }
  424.  
  425.       for (i = 0; i < sgip->zsize; i ++)
  426.     if (sgiGetRow(sgip, rows[i], sgip->ysize - 1 - y, i) < 0)
  427.       printf("sgiGetRow(sgip, rows[i], %d, %d) failed!\n",
  428.          sgip->ysize - 1 - y, i);
  429.  
  430.       if (sgip->bpp == 1)
  431.     {
  432.       /*
  433.        * 8-bit (unsigned) pixels...
  434.        */
  435.  
  436.       for (x = 0, pptr = pixels[count]; x < sgip->xsize; x ++)
  437.         for (i = 0; i < sgip->zsize; i ++, pptr ++)
  438.           *pptr = rows[i][x];
  439.     }
  440.       else
  441.     {
  442.       /*
  443.        * 16-bit (unsigned) pixels...
  444.        */
  445.  
  446.       for (x = 0, pptr = pixels[count]; x < sgip->xsize; x ++)
  447.         for (i = 0; i < sgip->zsize; i ++, pptr ++)
  448.           *pptr = rows[i][x] >> 8;
  449.     }
  450.     }
  451.  
  452.   /*
  453.    * Do the last n rows (count always > 0)
  454.    */
  455.  
  456.   gimp_pixel_rgn_set_rect (&pixel_rgn, pixel, 0,
  457.                y - count, drawable->width, count);
  458.  
  459.   /*
  460.    * Done with the file...
  461.    */
  462.  
  463.   sgiClose (sgip);
  464.  
  465.   g_free (pixel);
  466.   g_free (pixels);
  467.   g_free (rows[0]);
  468.   g_free (rows);
  469.  
  470.   /*
  471.    * Update the display...
  472.    */
  473.  
  474.   gimp_drawable_flush (drawable);
  475.   gimp_drawable_detach (drawable);
  476.  
  477.   return (image);
  478. }
  479.  
  480.  
  481. /*
  482.  * 'save_image()' - Save the specified image to a SGI file.
  483.  */
  484.  
  485. static gint
  486. save_image (gchar  *filename,
  487.         gint32  image_ID,
  488.         gint32  drawable_ID)
  489. {
  490.   gint        i, j,        /* Looping var */
  491.               x,           /* Current X coordinate */
  492.               y,           /* Current Y coordinate */
  493.               tile_height, /* Height of tile in GIMP */
  494.               count,       /* Count of rows to put in image */
  495.               zsize;       /* Number of channels in file */
  496.   sgi_t         *sgip;        /* File pointer */
  497.   GimpDrawable  *drawable;    /* Drawable for layer */
  498.   GimpPixelRgn   pixel_rgn;   /* Pixel region for layer */
  499.   guchar    **pixels,      /* Pixel rows */
  500.              *pixel,       /* Pixel data */
  501.              *pptr;        /* Current pixel */
  502.   gushort   **rows;        /* SGI image data */
  503.   gchar      *progress;    /* Title for progress display... */
  504.  
  505.   /*
  506.    * Get the drawable for the current image...
  507.    */
  508.  
  509.   drawable = gimp_drawable_get (drawable_ID);
  510.  
  511.   gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width,
  512.                drawable->height, FALSE, FALSE);
  513.  
  514.   zsize = 0;
  515.   switch (gimp_drawable_type(drawable_ID))
  516.     {
  517.     case GIMP_GRAY_IMAGE :
  518.       zsize = 1;
  519.       break;
  520.     case GIMP_GRAYA_IMAGE :
  521.       zsize = 2;
  522.       break;
  523.     case GIMP_RGB_IMAGE :
  524.       zsize = 3;
  525.       break;
  526.     case GIMP_RGBA_IMAGE :
  527.       zsize = 4;
  528.       break;
  529.     default:
  530.       g_message ("SGI: Image must be of type RGB or GRAY\n");
  531.       return FALSE;
  532.       break;
  533.     }
  534.  
  535.   /*
  536.    * Open the file for writing...
  537.    */
  538.  
  539.   sgip = sgiOpen (filename, SGI_WRITE, compression, 1, drawable->width,
  540.           drawable->height, zsize);
  541.   if (sgip == NULL)
  542.     {
  543.       g_message ("SGI: Can't create image file\n");
  544.       return FALSE;
  545.     };
  546.  
  547.   if (strrchr(filename, '/') != NULL)
  548.     progress = g_strdup_printf (_("Saving %s:"), strrchr(filename, '/') + 1);
  549.   else
  550.     progress = g_strdup_printf (_("Saving %s:"), filename);
  551.  
  552.   gimp_progress_init(progress);
  553.   g_free (progress);
  554.  
  555.   /*
  556.    * Allocate memory for "tile_height" rows...
  557.    */
  558.  
  559.   tile_height = gimp_tile_height();
  560.   pixel       = g_new(guchar, tile_height * drawable->width * zsize);
  561.   pixels      = g_new(guchar *, tile_height);
  562.  
  563.   for (i = 0; i < tile_height; i ++)
  564.     pixels[i]= pixel + drawable->width * zsize * i;
  565.  
  566.   rows    = g_new (gushort *, sgip->zsize);
  567.   rows[0] = g_new (gushort, sgip->xsize * sgip->zsize);
  568.  
  569.   for (i = 1; i < sgip->zsize; i ++)
  570.     rows[i] = rows[0] + i * sgip->xsize;
  571.  
  572.   /*
  573.    * Save the image...
  574.    */
  575.  
  576.   for (y = 0; y < drawable->height; y += count)
  577.     {
  578.       /*
  579.        * Grab more pixel data...
  580.        */
  581.  
  582.       if ((y + tile_height) >= drawable->height)
  583.     count = drawable->height - y;
  584.       else
  585.     count = tile_height;
  586.  
  587.       gimp_pixel_rgn_get_rect (&pixel_rgn, pixel, 0, y, drawable->width, count);
  588.  
  589.       /*
  590.        * Convert to shorts and write each color plane separately...
  591.        */
  592.  
  593.       for (i = 0, pptr = pixels[0]; i < count; i ++)
  594.     {
  595.       for (x = 0; x < drawable->width; x ++)
  596.         for (j = 0; j < zsize; j ++, pptr ++)
  597.           rows[j][x] = *pptr;
  598.  
  599.       for (j = 0; j < zsize; j ++)
  600.         sgiPutRow (sgip, rows[j], drawable->height - 1 - y - i, j);
  601.     };
  602.  
  603.       gimp_progress_update ((double) y / (double) drawable->height);
  604.     };
  605.  
  606.   /*
  607.    * Done with the file...
  608.    */
  609.  
  610.   sgiClose (sgip);
  611.  
  612.   g_free (pixel);
  613.   g_free (pixels);
  614.   g_free (rows[0]);
  615.   g_free (rows);
  616.  
  617.   return TRUE;
  618. }
  619.  
  620. static void
  621. save_ok_callback (GtkWidget *widget,
  622.                   gpointer   data)
  623. {
  624.   runme = TRUE;
  625.  
  626.   gtk_widget_destroy (GTK_WIDGET (data));
  627. }
  628.  
  629. static gint
  630. save_dialog (void)
  631. {
  632.   GtkWidget *dlg;
  633.   GtkWidget *frame;
  634.  
  635.   dlg = gimp_dialog_new (_("Save as SGI"), "sgi",
  636.              gimp_standard_help_func, "filters/sgi.html",
  637.              GTK_WIN_POS_MOUSE,
  638.              FALSE, FALSE, FALSE,
  639.  
  640.              _("OK"), save_ok_callback,
  641.              NULL, NULL, NULL, TRUE, FALSE,
  642.              _("Cancel"), gtk_widget_destroy,
  643.              NULL, 1, NULL, FALSE, TRUE,
  644.  
  645.              NULL);
  646.  
  647.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  648.               GTK_SIGNAL_FUNC (gtk_main_quit),
  649.               NULL);
  650.  
  651.   frame = gimp_radio_group_new2 (TRUE, _("Compression Type"),
  652.                  gimp_radio_button_update,
  653.                  &compression, (gpointer) compression,
  654.  
  655.                  _("No Compression"),
  656.                  (gpointer) SGI_COMP_NONE, NULL,
  657.                  _("RLE Compression"),
  658.                  (gpointer) SGI_COMP_RLE, NULL,
  659.                  _("Aggressive RLE\n(Not Supported by SGI)"),
  660.                  (gpointer) SGI_COMP_ARLE, NULL,
  661.  
  662.                  NULL);
  663.  
  664.   gtk_container_set_border_width (GTK_CONTAINER(frame), 6);
  665.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, TRUE, TRUE, 0);
  666.   gtk_widget_show (frame);
  667.  
  668.   gtk_widget_show (dlg);
  669.  
  670.   gtk_main ();
  671.   gdk_flush ();
  672.  
  673.   return runme;
  674. }
  675.