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 / sunras.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-21  |  42.0 KB  |  1,639 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  * SUN raster reading and writing code Copyright (C) 1996 Peter Kirchgessner
  4.  * (email: peter@kirchgessner.net, WWW: http://www.kirchgessner.net)
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19.  *
  20.  */
  21.  
  22. /* This program was written using pages 625-629 of the book
  23.  * "Encyclopedia of Graphics File Formats", Murray/van Ryper,
  24.  * O'Reilly & Associates Inc.
  25.  * Bug reports or suggestions should be e-mailed to peter@kirchgessner.net
  26.  */
  27.  
  28. /* Event history:
  29.  * V 1.00, PK, 25-Jul-96: First try
  30.  * V 1.90, PK, 15-Mar-97: Upgrade to work with GIMP V0.99
  31.  * V 1.91, PK, 05-Apr-97: Return all arguments, even in case of an error
  32.  * V 1.92, PK, 18-May-97: Ignore EOF-error on reading image data
  33.  * V 1.93, PK, 05-Oct-97: Parse rc file
  34.  * V 1.94, PK, 12-Oct-97: No progress bars for non-interactive mode
  35.  * V 1.95, nn, 20-Dec-97: Initialize some variable
  36.  * V 1.96, PK, 21-Nov-99: Internationalization
  37.  * V 1.97, PK, 20-Dec-00: Recognize extensions .rs and .ras too
  38.  */
  39. static char ident[] = "@(#) GIMP SunRaster file-plugin v1.97  20-Dec-00";
  40.  
  41. #include "config.h"
  42.  
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #ifdef HAVE_UNISTD_H
  47. #include <unistd.h>
  48. #endif
  49.  
  50. #include <gtk/gtk.h>
  51.  
  52. #include <libgimp/gimp.h>
  53. #include <libgimp/gimpui.h>
  54.  
  55. #include "libgimp/stdplugins-intl.h"
  56.  
  57.  
  58. typedef int WRITE_FUN(void*,size_t,size_t,FILE*);
  59.  
  60. typedef gulong  L_CARD32;
  61. typedef gushort L_CARD16;
  62. typedef guchar  L_CARD8;
  63.  
  64. /* Fileheader of SunRaster files */
  65. typedef struct
  66. {
  67.   L_CARD32 l_ras_magic;    /* Magic Number */
  68.   L_CARD32 l_ras_width;    /* Width */
  69.   L_CARD32 l_ras_height;   /* Height */
  70.   L_CARD32 l_ras_depth;    /* Number of bits per pixel (1,8,24,32) */
  71.   L_CARD32 l_ras_length;   /* Length of image data (but may also be 0) */
  72.   L_CARD32 l_ras_type;     /* Encoding */
  73.   L_CARD32 l_ras_maptype;  /* Type of colormap */
  74.   L_CARD32 l_ras_maplength;/* Number of bytes for colormap */
  75. } L_SUNFILEHEADER;
  76.  
  77. /* Sun-raster magic */
  78. #define RAS_MAGIC 0x59a66a95
  79.  
  80. #define RAS_TYPE_STD 1    /* Standard uncompressed format */
  81. #define RAS_TYPE_RLE 2    /* Runlength compression format */
  82.  
  83. typedef struct
  84. {
  85.   gint val;   /* The value that is to be repeated */
  86.   gint n;     /* How many times it is repeated */
  87. } RLEBUF;
  88.  
  89.  
  90. /* Declare some local functions.
  91.  */
  92. static void   query      (void);
  93. static void   run        (gchar   *name,
  94.                           gint     nparams,
  95.                           GimpParam  *param,
  96.                           gint    *nreturn_vals,
  97.                           GimpParam **return_vals);
  98.  
  99. static gint32 load_image (gchar   *filename);
  100. static gint   save_image (gchar   *filename,
  101.                           gint32   image_ID,
  102.                           gint32   drawable_ID);
  103.  
  104. static void set_color_table (gint32, L_SUNFILEHEADER *, unsigned char *);
  105.  
  106. static gint32 create_new_image (char *filename, guint width, guint height,
  107.                 GimpImageBaseType type, gint32 *layer_ID, GimpDrawable **drawable,
  108.                 GimpPixelRgn *pixel_rgn);
  109.  
  110. static gint32 load_sun_d1   (char *, FILE *, L_SUNFILEHEADER *, unsigned char *);
  111. static gint32 load_sun_d8   (char *, FILE *, L_SUNFILEHEADER *, unsigned char *);
  112. static gint32 load_sun_d24  (char *, FILE *, L_SUNFILEHEADER *, unsigned char *);
  113. static gint32 load_sun_d32  (char *, FILE *, L_SUNFILEHEADER *, unsigned char *);
  114.  
  115. static L_CARD32 read_card32 (FILE *, int *);
  116.  
  117. static void write_card32    (FILE *, L_CARD32);
  118.  
  119. static void byte2bit        (unsigned char *, int, unsigned char *, int);
  120.  
  121. static void rle_startread   (FILE *);
  122. static int  rle_fread       (char *, int, int, FILE *);
  123. static int  rle_fgetc       (FILE *);
  124. #define rle_getc(fp) ((rlebuf.n > 0) ? (rlebuf.n)--,rlebuf.val : rle_fgetc (fp))
  125.  
  126. static void rle_startwrite  (FILE *);
  127. static int  rle_fwrite      (char *, int, int, FILE *);
  128. static int  rle_fputc       (int, FILE *);
  129. static int  rle_putrun      (int, int, FILE *);
  130. static void rle_endwrite    (FILE *);
  131. #define rle_putc rle_fputc
  132.  
  133. static void read_sun_header  (FILE *, L_SUNFILEHEADER *);
  134. static void write_sun_header (FILE *, L_SUNFILEHEADER *);
  135. static void read_sun_cols    (FILE *, L_SUNFILEHEADER *, unsigned char *);
  136. static void write_sun_cols   (FILE *, L_SUNFILEHEADER *, unsigned char *);
  137.  
  138. static gint save_index       (FILE *, gint32, gint32 , int, int);
  139. static gint save_rgb         (FILE *, gint32, gint32, int);
  140.  
  141. static int read_msb_first = 1;
  142. static RLEBUF rlebuf;
  143.  
  144. /* Dialog-handling */
  145. static gint   save_dialog              (void);
  146. static void   save_ok_callback         (GtkWidget *widget,
  147.                                         gpointer   data);
  148.  
  149. /* Portability kludge */
  150. static int my_fwrite (void *ptr, int size, int nmemb, FILE *stream);
  151.  
  152. GimpPlugInInfo PLUG_IN_INFO =
  153. {
  154.   NULL,  /* init_proc  */
  155.   NULL,  /* quit_proc  */
  156.   query, /* query_proc */
  157.   run,   /* run_proc   */
  158. };
  159.  
  160.  
  161. /* Save info  */
  162. typedef struct
  163. {
  164.   gint  rle;  /*  rle or standard */
  165. } SUNRASSaveVals;
  166.  
  167. typedef struct
  168. {
  169.   gint  run;  /*  run  */
  170. } SUNRASSaveInterface;
  171.  
  172.  
  173. static SUNRASSaveVals psvals =
  174. {
  175.   TRUE     /* rle */
  176. };
  177.  
  178. static SUNRASSaveInterface psint =
  179. {
  180.   FALSE     /* run */
  181. };
  182.  
  183.  
  184. /* The run mode */
  185. static GimpRunModeType l_run_mode;
  186.  
  187. MAIN ()
  188.  
  189. static void
  190. query (void)
  191. {
  192.   static GimpParamDef load_args[] =
  193.   {
  194.     { GIMP_PDB_INT32,  "run_mode",      "Interactive, non-interactive" },
  195.     { GIMP_PDB_STRING, "filename",      "The name of the file to load" },
  196.     { GIMP_PDB_STRING, "raw_filename",  "The name of the file to load" }
  197.   };
  198.   static gint nload_args = sizeof (load_args) / sizeof (load_args[0]);
  199.  
  200.   static GimpParamDef load_return_vals[] =
  201.   {
  202.     { GIMP_PDB_IMAGE,  "image",         "Output image" }
  203.   };
  204.   static gint nload_return_vals = (sizeof (load_return_vals) /
  205.                    sizeof (load_return_vals[0]));
  206.  
  207.   static GimpParamDef save_args[] =
  208.   {
  209.     { GIMP_PDB_INT32,    "run_mode",     "Interactive, non-interactive" },
  210.     { GIMP_PDB_IMAGE,    "image",        "Input image" },
  211.     { GIMP_PDB_DRAWABLE, "drawable",     "Drawable to save" },
  212.     { GIMP_PDB_STRING,   "filename",     "The name of the file to save the image in" },
  213.     { GIMP_PDB_STRING,   "raw_filename", "The name of the file to save the image in" },
  214.     { GIMP_PDB_INT32,    "rle",          "Specify non-zero for rle output, zero for standard output" }
  215.   };
  216.   static gint nsave_args = sizeof (save_args) / sizeof (save_args[0]);
  217.  
  218.   gimp_install_procedure ("file_sunras_load",
  219.                           "load file of the SunRaster file format",
  220.                           "load file of the SunRaster file format",
  221.                           "Peter Kirchgessner",
  222.                           "Peter Kirchgessner",
  223.                           "1996",
  224.                           "<Load>/SUNRAS",
  225.                           NULL,
  226.                           GIMP_PLUGIN,
  227.                           nload_args, nload_return_vals,
  228.                           load_args, load_return_vals);
  229.  
  230.   gimp_install_procedure ("file_sunras_save",
  231.                           "save file in the SunRaster file format",
  232.                           "SUNRAS saving handles all image types except "
  233.               "those with alpha channels.",
  234.                           "Peter Kirchgessner",
  235.                           "Peter Kirchgessner",
  236.                           "1996",
  237.                           "<Save>/SUNRAS",
  238.                           "RGB, GRAY, INDEXED",
  239.                           GIMP_PLUGIN,
  240.                           nsave_args, 0,
  241.                           save_args, NULL);
  242.  
  243.   /* Magic information for sunras would be "0,long,0x59a66a95" */
  244.   gimp_register_magic_load_handler ("file_sunras_load", 
  245.                     "im1,im8,im24,im32,rs,ras",
  246.                     "",
  247.                     "0,long,0x59a66a95");
  248.   gimp_register_save_handler       ("file_sunras_save", 
  249.                     "im1,im8,im24,im32,rs,ras",
  250.                     "");
  251. }
  252.  
  253.  
  254. static void
  255. run (gchar   *name,
  256.      gint     nparams,
  257.      GimpParam  *param,
  258.      gint    *nreturn_vals,
  259.      GimpParam **return_vals)
  260. {
  261.   static GimpParam values[2];
  262.   GimpRunModeType  run_mode;
  263.   GimpPDBStatusType   status = GIMP_PDB_SUCCESS;
  264.   gint32        image_ID;
  265.   gint32        drawable_ID;
  266.   GimpExportReturnType export = GIMP_EXPORT_CANCEL;
  267.  
  268.   l_run_mode = run_mode = param[0].data.d_int32;
  269.  
  270.   *nreturn_vals = 1;
  271.   *return_vals  = values;
  272.   values[0].type          = GIMP_PDB_STATUS;
  273.   values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
  274.  
  275.   if (strcmp (name, "file_sunras_load") == 0)
  276.     {
  277.       INIT_I18N_UI();
  278.  
  279.       image_ID = load_image (param[1].data.d_string);
  280.  
  281.       if (image_ID != -1)
  282.     {
  283.       *nreturn_vals = 2;
  284.       values[1].type         = GIMP_PDB_IMAGE;
  285.       values[1].data.d_image = image_ID;
  286.     }
  287.       else
  288.     {
  289.       status = GIMP_PDB_EXECUTION_ERROR;
  290.     }
  291.     }
  292.   else if (strcmp (name, "file_sunras_save") == 0)
  293.     {
  294.       INIT_I18N_UI();
  295.  
  296.       image_ID = param[1].data.d_int32;
  297.       drawable_ID = param[2].data.d_int32;
  298.  
  299.       /*  eventually export the image */ 
  300.       switch (run_mode)
  301.     {
  302.     case GIMP_RUN_INTERACTIVE:
  303.     case GIMP_RUN_WITH_LAST_VALS:
  304.       gimp_ui_init ("sunras", FALSE);
  305.       export = gimp_export_image (&image_ID, &drawable_ID, "SUNRAS", 
  306.                       (GIMP_EXPORT_CAN_HANDLE_RGB |
  307.                        GIMP_EXPORT_CAN_HANDLE_GRAY |
  308.                        GIMP_EXPORT_CAN_HANDLE_INDEXED));
  309.       if (export == GIMP_EXPORT_CANCEL)
  310.         {
  311.           values[0].data.d_status = GIMP_PDB_CANCEL;
  312.           return;
  313.       }
  314.       break;
  315.     default:
  316.       break;
  317.     }
  318.  
  319.       switch (run_mode)
  320.         {
  321.         case GIMP_RUN_INTERACTIVE:
  322.           /*  Possibly retrieve data  */
  323.           gimp_get_data ("file_sunras_save", &psvals);
  324.  
  325.           /*  First acquire information with a dialog  */
  326.           if (! save_dialog ())
  327.             status = GIMP_PDB_CANCEL;
  328.           break;
  329.  
  330.         case GIMP_RUN_NONINTERACTIVE:
  331.           /*  Make sure all the arguments are there!  */
  332.           if (nparams != 6)
  333.         {
  334.           status = GIMP_PDB_CALLING_ERROR;
  335.         }
  336.           else
  337.         {
  338.           psvals.rle = (param[5].data.d_int32) ? TRUE : FALSE;
  339.         }
  340.           break;
  341.  
  342.         case GIMP_RUN_WITH_LAST_VALS:
  343.           /*  Possibly retrieve data  */
  344.           gimp_get_data ("file_sunras_save", &psvals);
  345.           break;
  346.  
  347.         default:
  348.           break;
  349.         }
  350.  
  351.       if (status == GIMP_PDB_SUCCESS)
  352.     {
  353.       if (save_image (param[3].data.d_string, image_ID, drawable_ID))
  354.         {
  355.           /*  Store psvals data  */
  356.           gimp_set_data ("file_sunras_save", &psvals,
  357.                  sizeof (SUNRASSaveVals));
  358.         }
  359.       else
  360.         {
  361.           status = GIMP_PDB_EXECUTION_ERROR;
  362.         }
  363.     }
  364.  
  365.       if (export == GIMP_EXPORT_EXPORT)
  366.     gimp_image_delete (image_ID);
  367.     }
  368.   else
  369.     {
  370.       status = GIMP_PDB_CALLING_ERROR;
  371.     }
  372.  
  373.   values[0].data.d_status = status;
  374. }
  375.  
  376.  
  377. static gint32
  378. load_image (gchar *filename)
  379. {
  380.   gint32 image_ID;
  381.   FILE *ifp;
  382.   char *temp = ident; /* Just to satisfy gcc/lint */
  383.   L_SUNFILEHEADER sunhdr;
  384.   guchar *suncolmap = NULL;
  385.  
  386.   ifp = fopen (filename, "rb");
  387.   if (!ifp)
  388.     {
  389.       g_message (_("Can't open file for reading"));
  390.       return (-1);
  391.     }
  392.  
  393.   read_msb_first = 1;   /* SUN raster is always most significant byte first */
  394.  
  395.   read_sun_header (ifp, &sunhdr);
  396.   if (sunhdr.l_ras_magic != RAS_MAGIC)
  397.     {
  398.       g_message (_("Can't open file as SUN-raster-file"));
  399.       fclose (ifp);
  400.       return (-1);
  401.     }
  402.  
  403.   if ((sunhdr.l_ras_type < 0) || (sunhdr.l_ras_type > 5))
  404.     {
  405.       g_message (_("The type of this SUN-rasterfile is not supported"));
  406.       fclose (ifp);
  407.       return (-1);
  408.     }
  409.  
  410.   /* Is there a RGB colourmap ? */
  411.   if ((sunhdr.l_ras_maptype == 1) && (sunhdr.l_ras_maplength > 0))
  412.     {
  413.       suncolmap = g_new (guchar, sunhdr.l_ras_maplength);
  414.  
  415.       read_sun_cols (ifp, &sunhdr, suncolmap);
  416. #ifdef DEBUG
  417.       {
  418.     int j, ncols;
  419.     printf ("File %s\n",filename);
  420.     ncols = sunhdr.l_ras_maplength/3;
  421.     for (j=0; j < ncols; j++)
  422.       printf ("Entry 0x%08x: 0x%04x,  0x%04x, 0x%04x\n",
  423.           j,suncolmap[j],suncolmap[j+ncols],suncolmap[j+2*ncols]);
  424.       }
  425. #endif
  426.       if (sunhdr.l_ras_magic != RAS_MAGIC)
  427.     {
  428.       g_message (_("Can't read color entries"));
  429.       fclose (ifp);
  430.       return (-1);
  431.     }
  432.     }
  433.   else if (sunhdr.l_ras_maplength > 0)
  434.     {
  435.       g_message (_("Type of colormap not supported"));
  436.       fseek (ifp, (sizeof (L_SUNFILEHEADER)/sizeof (L_CARD32))
  437.          *4 + sunhdr.l_ras_maplength, SEEK_SET);
  438.     }
  439.   
  440.   if (l_run_mode != GIMP_RUN_NONINTERACTIVE)
  441.     {
  442.       temp = g_strdup_printf (_("Loading %s:"), filename);
  443.       gimp_progress_init (temp);
  444.       g_free (temp);
  445.     }
  446.  
  447.   switch (sunhdr.l_ras_depth)
  448.     {
  449.     case 1:    /* bitmap */
  450.       image_ID = load_sun_d1 (filename, ifp, &sunhdr, suncolmap);
  451.       break;
  452.  
  453.     case 8:    /* 256 colours */
  454.       image_ID = load_sun_d8 (filename, ifp, &sunhdr, suncolmap);
  455.       break;
  456.  
  457.     case 24:   /* True color */
  458.       image_ID = load_sun_d24 (filename, ifp, &sunhdr, suncolmap);
  459.       break;
  460.  
  461.     case 32:   /* True color with extra byte */
  462.       image_ID = load_sun_d32 (filename, ifp, &sunhdr, suncolmap);
  463.       break;
  464.  
  465.     default:
  466.       image_ID = -1;
  467.       break;
  468.     }
  469.  
  470.   fclose (ifp);
  471.  
  472.   g_free (suncolmap);
  473.  
  474.   if (image_ID == -1)
  475.     {
  476.       g_message (_("This image depth is not supported"));
  477.       return (-1);
  478.     }
  479.  
  480.   return (image_ID);
  481. }
  482.  
  483.  
  484. static gint
  485. save_image (gchar  *filename,
  486.             gint32  image_ID,
  487.             gint32  drawable_ID)
  488. {
  489.   FILE* ofp;
  490.   GimpImageType drawable_type;
  491.   gint retval;
  492.   char *temp;
  493.  
  494.   drawable_type = gimp_drawable_type (drawable_ID);
  495.  
  496.   /*  Make sure we're not saving an image with an alpha channel  */
  497.   if (gimp_drawable_has_alpha (drawable_ID))
  498.     {
  499.       g_message (_("SUNRAS save cannot handle images with alpha channels"));
  500.       return FALSE;
  501.     }
  502.  
  503.   switch (drawable_type)
  504.     {
  505.     case GIMP_INDEXED_IMAGE:
  506.     case GIMP_GRAY_IMAGE:
  507.     case GIMP_RGB_IMAGE:
  508.       break;
  509.     default:
  510.       g_message (_("Can't operate on unknown image types"));
  511.       return (FALSE);
  512.       break;
  513.     }
  514.  
  515.   /* Open the output file. */
  516.   ofp = fopen (filename, "wb");
  517.   if (!ofp)
  518.     {
  519.       g_message (_("Can't open file for writing"));
  520.       return (FALSE);
  521.     }
  522.  
  523.   if (l_run_mode != GIMP_RUN_NONINTERACTIVE)
  524.     {
  525.       temp = g_strdup_printf (_("Saving %s:"), filename);
  526.       gimp_progress_init (temp);
  527.       g_free (temp);
  528.     }
  529.  
  530.   if (drawable_type == GIMP_INDEXED_IMAGE)
  531.     retval = save_index (ofp,image_ID, drawable_ID, 0, (int)psvals.rle);
  532.   else if (drawable_type == GIMP_GRAY_IMAGE)
  533.     retval = save_index (ofp,image_ID, drawable_ID, 1, (int)psvals.rle);
  534.   else if (drawable_type == GIMP_RGB_IMAGE)
  535.     retval = save_rgb (ofp,image_ID, drawable_ID, (int)psvals.rle);
  536.   else
  537.     retval = FALSE;
  538.  
  539.   fclose (ofp);
  540.  
  541.   return (retval);
  542. }
  543.  
  544.  
  545. static L_CARD32
  546. read_card32 (FILE *ifp,
  547.          gint *err)
  548. {
  549.   L_CARD32 c;
  550.  
  551.   if (read_msb_first)
  552.     {
  553.       c = (((L_CARD32)(getc (ifp))) << 24);
  554.       c |= (((L_CARD32)(getc (ifp))) << 16);
  555.       c |= (((L_CARD32)(getc (ifp))) << 8);
  556.       c |= ((L_CARD32)(*err = getc (ifp)));
  557.     }
  558.   else
  559.     {
  560.       c = ((L_CARD32)(getc (ifp)));
  561.       c |= (((L_CARD32)(getc (ifp))) << 8);
  562.       c |= (((L_CARD32)(getc (ifp))) << 16);
  563.       c |= (((L_CARD32)(*err = getc (ifp))) << 24);
  564.     }
  565.  
  566.   *err = (*err < 0);
  567.   return (c);
  568. }
  569.  
  570.  
  571. static void 
  572. write_card32 (FILE     *ofp,
  573.           L_CARD32  c)
  574. {
  575.   putc ((int)((c >> 24) & 0xff), ofp);
  576.   putc ((int)((c >> 16) & 0xff), ofp);
  577.   putc ((int)((c >> 8) & 0xff), ofp);
  578.   putc ((int)((c) & 0xff), ofp);
  579. }
  580.  
  581.  
  582. /* Convert n bytes of 0/1 to a line of bits */
  583. static void 
  584. byte2bit (guchar *byteline,
  585.       gint    width,
  586.       guchar *bitline,
  587.       gint    invert)
  588. {
  589.   register guchar bitval;
  590.   guchar rest[8];
  591.  
  592.   while (width >= 8)
  593.     {
  594.       bitval = 0;
  595.       if (*(byteline++)) bitval |= 0x80;
  596.       if (*(byteline++)) bitval |= 0x40;
  597.       if (*(byteline++)) bitval |= 0x20;
  598.       if (*(byteline++)) bitval |= 0x10;
  599.       if (*(byteline++)) bitval |= 0x08;
  600.       if (*(byteline++)) bitval |= 0x04;
  601.       if (*(byteline++)) bitval |= 0x02;
  602.       if (*(byteline++)) bitval |= 0x01;
  603.       *(bitline++) = invert ? ~bitval : bitval;
  604.       width -= 8;
  605.     }
  606.   if (width > 0)
  607.     {
  608.       memset (rest, 0, 8);
  609.       memcpy (rest, byteline, width);
  610.       bitval = 0;
  611.       byteline = rest;
  612.       if (*(byteline++)) bitval |= 0x80;
  613.       if (*(byteline++)) bitval |= 0x40;
  614.       if (*(byteline++)) bitval |= 0x20;
  615.       if (*(byteline++)) bitval |= 0x10;
  616.       if (*(byteline++)) bitval |= 0x08;
  617.       if (*(byteline++)) bitval |= 0x04;
  618.       if (*(byteline++)) bitval |= 0x02;
  619.       *bitline = invert ? ~bitval : bitval;
  620.     }
  621. }
  622.  
  623.  
  624. /* Start reading Runlength Encoded Data */
  625. static void 
  626. rle_startread (FILE *ifp)
  627. { /* Clear RLE-buffer */
  628.   rlebuf.val = rlebuf.n = 0;
  629. }
  630.  
  631.  
  632. /* Read uncompressed elements from RLE-stream */
  633. static gint
  634. rle_fread (gchar *ptr,
  635.        gint   sz,
  636.        gint   nelem,
  637.        FILE  *ifp)
  638. {
  639.   int elem_read, cnt, val, err = 0;
  640.  
  641.   for (elem_read = 0; elem_read < nelem; elem_read++)
  642.     {
  643.       for (cnt = 0; cnt < sz; cnt++)
  644.     {
  645.       val = rle_getc (ifp);
  646.       if (val < 0) { err = 1; break; }
  647.       *(ptr++) = (char)val;
  648.     }
  649.       if (err) break;
  650.     }
  651.   return (elem_read);
  652. }
  653.  
  654.  
  655. /* Get one byte of uncompressed data from RLE-stream */
  656. static gint
  657. rle_fgetc (FILE *ifp)
  658. {
  659.   int flag, runcnt, runval;
  660.   
  661.   if (rlebuf.n > 0)    /* Something in the buffer ? */
  662.     {
  663.       (rlebuf.n)--;
  664.       return (rlebuf.val);
  665.     }
  666.   
  667.   /* Nothing in the buffer. We have to read something */
  668.   if ((flag = getc (ifp)) < 0) return (-1);
  669.   if (flag != 0x0080) return (flag);    /* Single byte run ? */
  670.   
  671.   if ((runcnt = getc (ifp)) < 0) return (-1);
  672.   if (runcnt == 0) return (0x0080);     /* Single 0x80 ? */
  673.   
  674.   /* The run */
  675.   if ((runval = getc (ifp)) < 0) return (-1);
  676.   rlebuf.n = runcnt;
  677.   rlebuf.val = runval;
  678.   return (runval);
  679. }
  680.  
  681.  
  682. /* Start writing Runlength Encoded Data */
  683. static void 
  684. rle_startwrite (FILE *ofp)
  685. { /* Clear RLE-buffer */
  686.   rlebuf.val = rlebuf.n = 0;
  687. }
  688.  
  689.  
  690. /* Write uncompressed elements to RLE-stream */
  691. static gint
  692. rle_fwrite (gchar *ptr,
  693.         gint   sz,
  694.         gint   nelem,
  695.         FILE  *ofp)
  696. {
  697.   int elem_write, cnt, val, err = 0;
  698.   guchar *pixels = (unsigned char *)ptr;
  699.   
  700.   for (elem_write = 0; elem_write < nelem; elem_write++)
  701.     {
  702.       for (cnt = 0; cnt < sz; cnt++)
  703.     {
  704.       val = rle_fputc (*(pixels++), ofp);
  705.       if (val < 0) { err = 1; break; }
  706.     }
  707.       if (err) break;
  708.     }
  709.   return (elem_write);
  710. }
  711.  
  712.  
  713. /* Write uncompressed character to RLE-stream */
  714. static gint
  715. rle_fputc (gint  val,
  716.        FILE *ofp)
  717. {
  718.   int retval;
  719.   
  720.   if (rlebuf.n == 0)    /* Nothing in the buffer ? Save the value */
  721.     {
  722.       rlebuf.n = 1;
  723.       return (rlebuf.val = val);
  724.     }
  725.   
  726.   /* Something in the buffer */
  727.   
  728.   if (rlebuf.val == val)   /* Same value in the buffer ? */
  729.     {
  730.       (rlebuf.n)++;
  731.       if (rlebuf.n == 257) /* Can not be encoded in a single run ? */
  732.     {
  733.       retval = rle_putrun (256, rlebuf.val, ofp);
  734.       if (retval < 0) return (retval);
  735.       rlebuf.n -= 256;
  736.     }
  737.       return (val);
  738.     }
  739.   
  740.   /* Something different in the buffer ? Write out the run */
  741.   
  742.   retval = rle_putrun (rlebuf.n, rlebuf.val, ofp);
  743.   if (retval < 0) return (retval);
  744.   
  745.   /* Save the new value */
  746.   rlebuf.n = 1;
  747.   return (rlebuf.val = val);
  748. }
  749.  
  750.  
  751. /* Write out a run with 0 < n < 257 */
  752. static gint 
  753. rle_putrun (gint  n,
  754.         gint  val,
  755.         FILE *ofp)
  756. {
  757.   int retval, flag = 0x80;
  758.  
  759.   /* Useful to write a 3 byte run ? */
  760.   if ((n > 2) || ((n == 2) && (val == flag)))
  761.     {
  762.       putc (flag, ofp);
  763.       putc (n-1, ofp);
  764.       retval = putc (val, ofp);
  765.     }
  766.   else if (n == 2) /* Write two single runs (could not be value 0x80) */
  767.     {
  768.       putc (val, ofp);
  769.       retval = putc (val, ofp);
  770.     }
  771.   else  /* Write a single run */
  772.     {
  773.       if (val == flag)
  774.     retval = putc (flag, ofp), putc (0x00, ofp);
  775.       else
  776.     retval = putc (val, ofp);
  777.     }
  778.   
  779.   return ((retval < 0) ? retval : val);
  780. }
  781.  
  782.  
  783. /* End writing Runlength Encoded Data */
  784. static void 
  785. rle_endwrite (FILE *ofp)    
  786. {
  787.   if (rlebuf.n > 0)
  788.     {
  789.       rle_putrun (rlebuf.n, rlebuf.val, ofp);
  790.       rlebuf.val = rlebuf.n = 0; /* Clear RLE-buffer */
  791.     }
  792. }
  793.  
  794.  
  795. static void
  796. read_sun_header (FILE            *ifp,
  797.                  L_SUNFILEHEADER *sunhdr)
  798. {
  799.   int j, err;
  800.   L_CARD32 *cp;
  801.   
  802.   cp = (L_CARD32 *)sunhdr;
  803.   
  804.   /* Read in all 32-bit values of the header and check for byte order */
  805.   for (j = 0; j < sizeof (L_SUNFILEHEADER)/sizeof(sunhdr->l_ras_magic); j++)
  806.     {
  807.       *(cp++) = read_card32 (ifp, &err);
  808.       if (err) break;
  809.     }
  810.   
  811.   if (err) sunhdr->l_ras_magic = 0;  /* Not a valid SUN-raster file */
  812. }
  813.  
  814.  
  815. /* Write out a SUN-fileheader */
  816.  
  817. static void
  818. write_sun_header (FILE            *ofp,
  819.                   L_SUNFILEHEADER *sunhdr)
  820. {
  821.   int j, hdr_entries;
  822.   L_CARD32 *cp;
  823.   
  824.   hdr_entries = sizeof (L_SUNFILEHEADER)/sizeof(sunhdr->l_ras_magic);
  825.   
  826.   cp = (L_CARD32 *)sunhdr;
  827.   
  828.   /* Write out all 32-bit values of the header and check for byte order */
  829.   for (j = 0; j < sizeof (L_SUNFILEHEADER)/sizeof(sunhdr->l_ras_magic); j++)
  830.     {
  831.       write_card32 (ofp, *(cp++));
  832.     }
  833. }
  834.  
  835.  
  836. /* Read the sun colourmap */
  837.  
  838. static void
  839. read_sun_cols (FILE            *ifp,
  840.                L_SUNFILEHEADER *sunhdr,
  841.                guchar          *colormap)
  842. {
  843.   int ncols, err = 0;
  844.   
  845.   /* Read in SUN-raster Colormap */
  846.   ncols = sunhdr->l_ras_maplength / 3;
  847.   if (ncols <= 0)
  848.     err = 1;
  849.   else
  850.     err = (fread (colormap, 3, ncols, ifp) != ncols);
  851.   
  852.   if (err) sunhdr->l_ras_magic = 0;  /* Not a valid SUN-raster file */
  853. }
  854.  
  855.  
  856. /* Write a sun colourmap */
  857.  
  858. static void
  859. write_sun_cols (FILE            *ofp,
  860.                 L_SUNFILEHEADER *sunhdr,
  861.                 guchar          *colormap)
  862. {
  863.   int ncols;
  864.   
  865.   ncols = sunhdr->l_ras_maplength / 3;
  866.   fwrite (colormap, 3, ncols, ofp);
  867. }
  868.  
  869.  
  870. /* Set a GIMP colourtable using the sun colourmap */
  871.  
  872. static void
  873. set_color_table (gint32           image_ID,
  874.          L_SUNFILEHEADER *sunhdr,
  875.          guchar          *suncolmap)
  876. {
  877.   int ncols, j;
  878.   guchar ColorMap[256*3];
  879.  
  880.   ncols = sunhdr->l_ras_maplength / 3;
  881.   if (ncols <= 0) return;
  882.  
  883.   for (j = 0; j < ncols; j++)
  884.     {
  885.       ColorMap[j*3]   = suncolmap[j];
  886.       ColorMap[j*3+1] = suncolmap[j+ncols];
  887.       ColorMap[j*3+2] = suncolmap[j+2*ncols];
  888.     }
  889.  
  890. #ifdef DEBUG
  891.   printf ("Set GIMP colortable:\n");
  892.   for (j = 0; j < ncols; j++)
  893.     printf ("%3d: 0x%02x 0x%02x 0x%02x\n", j,
  894.         ColorMap[j*3], ColorMap[j*3+1], ColorMap[j*3+2]);
  895. #endif
  896.   gimp_image_set_cmap (image_ID, ColorMap, ncols);
  897. }
  898.  
  899.  
  900. /* Create an image. Sets layer_ID, drawable and rgn. Returns image_ID */
  901. static gint32
  902. create_new_image (gchar              *filename,
  903.                   guint               width,
  904.                   guint               height,
  905.                   GimpImageBaseType   type,
  906.                   gint32             *layer_ID,
  907.                   GimpDrawable      **drawable,
  908.                   GimpPixelRgn       *pixel_rgn)
  909. {
  910.   gint32 image_ID;
  911.   GimpImageType gdtype;
  912.  
  913.   switch (type)
  914.     {
  915.     case GIMP_RGB:
  916.       gdtype = GIMP_RGB_IMAGE;
  917.       break;
  918.     case GIMP_GRAY: 
  919.       gdtype = GIMP_GRAY_IMAGE;
  920.       break;
  921.     case GIMP_INDEXED:
  922.       gdtype = GIMP_INDEXED_IMAGE;
  923.       break;
  924.     default:
  925.       g_warning ("Unsupported image type");
  926.       return -1;
  927.     }
  928.  
  929.   image_ID = gimp_image_new (width, height, type);
  930.   gimp_image_set_filename (image_ID, filename);
  931.  
  932.   *layer_ID = gimp_layer_new (image_ID, _("Background"), width, height,
  933.                             gdtype, 100, GIMP_NORMAL_MODE);
  934.   gimp_image_add_layer (image_ID, *layer_ID, 0);
  935.  
  936.   *drawable = gimp_drawable_get (*layer_ID);
  937.   gimp_pixel_rgn_init (pixel_rgn, *drawable, 0, 0, (*drawable)->width,
  938.                (*drawable)->height, TRUE, FALSE);
  939.  
  940.   return (image_ID);
  941. }
  942.  
  943.  
  944. /* Load SUN-raster-file with depth 1 */
  945. static gint32
  946. load_sun_d1 (gchar           *filename,
  947.              FILE            *ifp,
  948.              L_SUNFILEHEADER *sunhdr,
  949.              guchar          *suncolmap)
  950. {
  951.   register int pix8;
  952.   int width, height, linepad, scan_lines, tile_height;
  953.   int i, j;
  954.   guchar *dest, *data;
  955.   gint32 layer_ID, image_ID;
  956.   GimpPixelRgn pixel_rgn;
  957.   GimpDrawable *drawable;
  958.   guchar bit2byte[256*8];
  959.   L_SUNFILEHEADER sun_bwhdr;
  960.   guchar sun_bwcolmap[6] = { 255,0,255,0,255,0 };
  961.   int err = 0, rle = (sunhdr->l_ras_type == RAS_TYPE_RLE);
  962.  
  963.   width = sunhdr->l_ras_width;
  964.   height = sunhdr->l_ras_height;
  965.  
  966.   image_ID = create_new_image (filename, width, height, GIMP_INDEXED,
  967.                    &layer_ID, &drawable, &pixel_rgn);
  968.  
  969.   tile_height = gimp_tile_height ();
  970.   data = g_malloc (tile_height * width);
  971.  
  972.   if (suncolmap != NULL)   /* Set up the specified colour map */
  973.     {
  974.       set_color_table (image_ID, sunhdr, suncolmap);
  975.     }
  976.   else   /* No colourmap available. Set up a dummy b/w-colourmap */
  977.     {      /* Copy the original header and simulate b/w-colourmap */
  978.       memcpy ((char *)&sun_bwhdr,(char *)sunhdr,sizeof (L_SUNFILEHEADER));
  979.       sun_bwhdr.l_ras_maptype = 2;
  980.       sun_bwhdr.l_ras_maplength = 6;
  981.       set_color_table (image_ID, &sun_bwhdr, sun_bwcolmap);
  982.     }
  983.  
  984.   /* Get an array for mapping 8 bits in a byte to 8 bytes */
  985.   dest = bit2byte;
  986.   for (j = 0; j < 256; j++)
  987.     for (i = 7; i >= 0; i--)
  988.       *(dest++) = ((j & (1 << i)) != 0);
  989.  
  990.   linepad = (((sunhdr->l_ras_width+7)/8) % 2); /* Check for 16bit align */
  991.  
  992.   if (rle) rle_startread (ifp);
  993.  
  994.   dest = data;
  995.   scan_lines = 0;
  996.  
  997.   for (i = 0; i < height; i++)
  998.     {
  999.       j = width;
  1000.       while (j >= 8)
  1001.     {
  1002.       pix8 = rle ? rle_getc (ifp) : getc (ifp);
  1003.       if (pix8 < 0) { err = 1; pix8 = 0; }
  1004.  
  1005.       memcpy (dest, bit2byte + pix8*8, 8);
  1006.       dest += 8;
  1007.       j -= 8;
  1008.     }
  1009.  
  1010.       if (j > 0)
  1011.     {
  1012.       pix8 = rle ? rle_getc (ifp) : getc (ifp);
  1013.       if (pix8 < 0) { err = 1; pix8 = 0; }
  1014.  
  1015.       memcpy (dest, bit2byte + pix8*8, j);
  1016.       dest += j;
  1017.     }
  1018.  
  1019.       if (linepad)
  1020.     err |= ((rle ? rle_getc (ifp) : getc (ifp)) < 0);
  1021.  
  1022.       scan_lines++;
  1023.  
  1024.       if ((l_run_mode != GIMP_RUN_NONINTERACTIVE) && ((i % 20) == 0))
  1025.     gimp_progress_update ((double)(i+1) / (double)height);
  1026.  
  1027.       if ((scan_lines == tile_height) || ((i+1) == height))
  1028.     {
  1029.       gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
  1030.                    width, scan_lines);
  1031.       scan_lines = 0;
  1032.       dest = data;
  1033.     }
  1034.     }
  1035.  
  1036.   g_free (data);
  1037.  
  1038.   if (err)
  1039.     g_message (_("EOF encountered on reading"));
  1040.  
  1041.   gimp_drawable_flush (drawable);
  1042.  
  1043.   return (image_ID);
  1044. }
  1045.  
  1046.  
  1047. /* Load SUN-raster-file with depth 8 */
  1048.  
  1049. static gint32
  1050. load_sun_d8 (gchar           *filename,
  1051.              FILE            *ifp,
  1052.              L_SUNFILEHEADER *sunhdr,
  1053.              guchar          *suncolmap)
  1054. {
  1055.   int width, height, linepad, i, j;
  1056.   int greyscale, ncols;
  1057.   int scan_lines, tile_height;
  1058.   guchar *dest, *data;
  1059.   gint32 layer_ID, image_ID;
  1060.   GimpPixelRgn pixel_rgn;
  1061.   GimpDrawable *drawable;
  1062.   int err = 0, rle = (sunhdr->l_ras_type == RAS_TYPE_RLE);
  1063.  
  1064.   width = sunhdr->l_ras_width;
  1065.   height = sunhdr->l_ras_height;
  1066.  
  1067.   /* This could also be a greyscale image. Check it */
  1068.   ncols = sunhdr->l_ras_maplength / 3;
  1069.  
  1070.   greyscale = 1;  /* Also greyscale if no colourmap present */
  1071.  
  1072.   if ((ncols > 0) && (suncolmap != NULL))
  1073.     {
  1074.       for (j = 0; j < ncols; j++)
  1075.     {
  1076.       if (   (suncolmap[j] != j)
  1077.          || (suncolmap[j+ncols] != j)
  1078.          || (suncolmap[j+2*ncols] != j))
  1079.         {
  1080.           greyscale = 0;
  1081.           break;
  1082.         }
  1083.     }
  1084.     }
  1085.  
  1086.   image_ID = create_new_image (filename, width, height,
  1087.                    greyscale ? GIMP_GRAY : GIMP_INDEXED,
  1088.                    &layer_ID, &drawable, &pixel_rgn);
  1089.  
  1090.   tile_height = gimp_tile_height ();
  1091.   data = g_malloc (tile_height * width);
  1092.  
  1093.   if (!greyscale)
  1094.     set_color_table (image_ID, sunhdr, suncolmap);
  1095.  
  1096.   linepad = (sunhdr->l_ras_width % 2);
  1097.  
  1098.   if (rle) rle_startread (ifp);  /* Initialize RLE-buffer */
  1099.  
  1100.   dest = data;
  1101.   scan_lines = 0;
  1102.  
  1103.   for (i = 0; i < height; i++)
  1104.     {
  1105.       memset ((char *)dest, 0, width);
  1106.       err |= ((rle ? rle_fread ((char *)dest, 1, width, ifp)
  1107.                : fread ((char *)dest, 1, width, ifp)) != width);
  1108.  
  1109.       if (linepad)
  1110.     err |= ((rle ? rle_getc (ifp) : getc (ifp)) < 0);
  1111.  
  1112.       dest += width;
  1113.       scan_lines++;
  1114.  
  1115.       if ((l_run_mode != GIMP_RUN_NONINTERACTIVE) && ((i % 20) == 0))
  1116.     gimp_progress_update ((double)(i+1) / (double)height);
  1117.  
  1118.       if ((scan_lines == tile_height) || ((i+1) == height))
  1119.     {
  1120.       gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
  1121.                    width, scan_lines);
  1122.       scan_lines = 0;
  1123.       dest = data;
  1124.     }
  1125.     }
  1126.  
  1127.   g_free (data);
  1128.  
  1129.   if (err)
  1130.     g_message (_("EOF encountered on reading"));
  1131.  
  1132.   gimp_drawable_flush (drawable);
  1133.  
  1134.   return (image_ID);
  1135. }
  1136.  
  1137.  
  1138. /* Load SUN-raster-file with depth 24 */
  1139. static gint32
  1140. load_sun_d24 (gchar            *filename,
  1141.               FILE             *ifp,
  1142.               L_SUNFILEHEADER  *sunhdr,
  1143.               guchar           *suncolmap)
  1144. {
  1145.   register guchar *dest, blue;
  1146.   guchar *data;
  1147.   int width, height, linepad, tile_height, scan_lines;
  1148.   int i, j;
  1149.   gint32 layer_ID, image_ID;
  1150.   GimpPixelRgn pixel_rgn;
  1151.   GimpDrawable *drawable;
  1152.   int err = 0, rle = (sunhdr->l_ras_type == RAS_TYPE_RLE);
  1153.  
  1154.   width = sunhdr->l_ras_width;
  1155.   height = sunhdr->l_ras_height;
  1156.  
  1157.   image_ID = create_new_image (filename, width, height, GIMP_RGB,
  1158.                    &layer_ID, &drawable, &pixel_rgn);
  1159.  
  1160.   tile_height = gimp_tile_height ();
  1161.   data = g_malloc (tile_height * width * 3);
  1162.  
  1163.   linepad = ((sunhdr->l_ras_width*3) % 2);
  1164.  
  1165.   if (rle) rle_startread (ifp);  /* Initialize RLE-buffer */
  1166.  
  1167.   dest = data;
  1168.   scan_lines = 0;
  1169.  
  1170.   for (i = 0; i < height; i++)
  1171.     {
  1172.       memset ((char *)dest, 0, 3*width);
  1173.       err |= ((rle ? rle_fread ((char *)dest, 3, width, ifp)
  1174.                : fread ((char *)dest, 3, width, ifp)) != width);
  1175.  
  1176.       if (linepad)
  1177.     err |= ((rle ? rle_getc (ifp) : getc (ifp)) < 0);
  1178.  
  1179.       if (sunhdr->l_ras_type == 3) /* RGB-format ? That is what GIMP wants */
  1180.     {
  1181.       dest += width*3;
  1182.     }
  1183.       else                         /* We have BGR format. Correct it */
  1184.     {
  1185.       for (j = 0; j < width; j++)
  1186.         {
  1187.           blue = *dest;
  1188.           *dest = *(dest+2);
  1189.           *(dest+2) = blue;
  1190.           dest += 3;
  1191.         }
  1192.     }
  1193.  
  1194.       scan_lines++;
  1195.  
  1196.       if ((l_run_mode != GIMP_RUN_NONINTERACTIVE) && ((i % 20) == 0))
  1197.     gimp_progress_update ((double)(i+1) / (double)height);
  1198.  
  1199.       if ((scan_lines == tile_height) || ((i+1) == height))
  1200.     {
  1201.       gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
  1202.                    width, scan_lines);
  1203.       scan_lines = 0;
  1204.       dest = data;
  1205.     }
  1206.     }
  1207.  
  1208.   g_free (data);
  1209.  
  1210.   if (err)
  1211.     g_message (_("EOF encountered on reading"));
  1212.  
  1213.   gimp_drawable_flush (drawable);
  1214.  
  1215.   return (image_ID);
  1216. }
  1217.  
  1218.  
  1219. /* Load SUN-raster-file with depth 32 */
  1220.  
  1221. static gint32
  1222. load_sun_d32 (gchar           *filename,
  1223.               FILE            *ifp,
  1224.               L_SUNFILEHEADER *sunhdr,
  1225.               guchar          *suncolmap)
  1226. {
  1227.   register guchar *dest, blue;
  1228.   guchar *data;
  1229.   int width, height, tile_height, scan_lines;
  1230.   int i, j;
  1231.   gint32 layer_ID, image_ID;
  1232.   GimpPixelRgn pixel_rgn;
  1233.   GimpDrawable *drawable;
  1234.   int err = 0, cerr, rle = (sunhdr->l_ras_type == RAS_TYPE_RLE);
  1235.   width = sunhdr->l_ras_width;
  1236.   height = sunhdr->l_ras_height;
  1237.  
  1238.   /* initialize */
  1239.  
  1240.   cerr = 0;
  1241.  
  1242.   image_ID = create_new_image (filename, width, height, GIMP_RGB,
  1243.                    &layer_ID, &drawable, &pixel_rgn);
  1244.  
  1245.   tile_height = gimp_tile_height ();
  1246.   data = g_malloc (tile_height * width * 3);
  1247.  
  1248.   if (rle) rle_startread (ifp);  /* Initialize RLE-buffer */
  1249.  
  1250.   dest = data;
  1251.   scan_lines = 0;
  1252.  
  1253.   for (i = 0; i < height; i++)
  1254.     {
  1255.       if (rle)
  1256.     {
  1257.       for (j = 0; j < width; j++)
  1258.         {
  1259.           rle_getc (ifp);   /* Skip unused byte */
  1260.           *(dest++) = rle_getc (ifp);
  1261.           *(dest++) = rle_getc (ifp);
  1262.           *(dest++) = (cerr = (rle_getc (ifp)));
  1263.         }
  1264.     }
  1265.       else
  1266.     {
  1267.       for (j = 0; j < width; j++)
  1268.         {
  1269.           getc (ifp);   /* Skip unused byte */
  1270.           *(dest++) = getc (ifp);
  1271.           *(dest++) = getc (ifp);
  1272.           *(dest++) = (cerr = (getc (ifp)));
  1273.         }
  1274.     }
  1275.       err |= (cerr < 0);
  1276.  
  1277.       if (sunhdr->l_ras_type != 3) /* BGR format ? Correct it */
  1278.     {
  1279.       for (j = 0; j < width; j++)
  1280.         {
  1281.           dest -= 3;
  1282.           blue = *dest;
  1283.           *dest = *(dest+2);
  1284.           *(dest+2) = blue;
  1285.         }
  1286.       dest += width*3;
  1287.     }
  1288.  
  1289.       scan_lines++;
  1290.  
  1291.       if ((l_run_mode != GIMP_RUN_NONINTERACTIVE) && ((i % 20) == 0))
  1292.     gimp_progress_update ((double)(i+1) / (double)height);
  1293.  
  1294.       if ((scan_lines == tile_height) || ((i+1) == height))
  1295.     {
  1296.       gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
  1297.                    width, scan_lines);
  1298.       scan_lines = 0;
  1299.       dest = data;
  1300.     }
  1301.     }
  1302.  
  1303.   g_free (data);
  1304.  
  1305.   if (err)
  1306.     g_message (_("EOF encountered on reading"));
  1307.  
  1308.   gimp_drawable_flush (drawable);
  1309.  
  1310.   return (image_ID);
  1311. }
  1312.  
  1313.  
  1314. static gint
  1315. save_index (FILE    *ofp,
  1316.             gint32  image_ID,
  1317.             gint32  drawable_ID,
  1318.             gint    grey,
  1319.             gint    rle)
  1320.   int height, width, linepad, i, j;
  1321.   int ncols, bw, is_bw, is_wb, bpl;
  1322.   int tile_height;
  1323.   long tmp = 0;
  1324.   guchar *cmap, *bwline = NULL;
  1325.   guchar *data, *src;
  1326.   L_SUNFILEHEADER sunhdr;
  1327.   guchar sun_colormap[256*3];
  1328.   static guchar sun_bwmap[6] = { 0,255,0,255,0,255 };
  1329.   static guchar sun_wbmap[6] = { 255,0,255,0,255,0 };
  1330.   unsigned char *suncolmap = sun_colormap;
  1331.   GimpPixelRgn pixel_rgn;
  1332.   GimpDrawable *drawable;
  1333.   GimpImageType drawable_type;
  1334.   WRITE_FUN *write_fun;
  1335.  
  1336.   drawable = gimp_drawable_get (drawable_ID);
  1337.   drawable_type = gimp_drawable_type (drawable_ID);
  1338.   width = drawable->width;
  1339.   height = drawable->height;
  1340.   tile_height = gimp_tile_height ();
  1341.   gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, FALSE, FALSE);
  1342.  
  1343.   /* allocate a buffer for retrieving information from the pixel region  */
  1344.   src = data = (unsigned char *)g_malloc (tile_height * width * drawable->bpp);
  1345.  
  1346.   /* Fill SUN-color map */
  1347.   if (grey)
  1348.     {
  1349.       ncols = 256;
  1350.  
  1351.       for (j = 0; j < ncols; j++)
  1352.     {
  1353.       suncolmap[j] = j;
  1354.       suncolmap[j+ncols] = j;
  1355.       suncolmap[j+ncols*2] = j;
  1356.     }
  1357.     }
  1358.   else
  1359.     {
  1360.       cmap = gimp_image_get_cmap (image_ID, &ncols);
  1361.  
  1362.       for (j = 0; j < ncols; j++)
  1363.     {
  1364.       suncolmap[j] = *(cmap++);
  1365.       suncolmap[j+ncols] = *(cmap++);
  1366.       suncolmap[j+ncols*2] = *(cmap++);
  1367.     }
  1368.     }
  1369.  
  1370.   bw = (ncols == 2);   /* Maybe this is a two-colour image */
  1371.   if (bw)
  1372.     {
  1373.       bwline = g_malloc ((width+7)/8);
  1374.       if (bwline == NULL) bw = 0;
  1375.     }
  1376.  
  1377.   is_bw = is_wb = 0;
  1378.   if (bw)    /* The Sun-OS imagetool generates index 0 for white and */
  1379.     {          /* index 1 for black. Do the same without colourtable. */
  1380.       is_bw = (memcmp (suncolmap, sun_bwmap, 6) == 0);
  1381.       is_wb = (memcmp (suncolmap, sun_wbmap, 6) == 0);
  1382.     }
  1383.  
  1384.   /* Number of data bytes per line */
  1385.   bpl = bw ?  (width+7)/8 : width;
  1386.   linepad = bpl % 2;
  1387.  
  1388.   /* Fill in the SUN header */
  1389.   sunhdr.l_ras_magic = RAS_MAGIC;
  1390.   sunhdr.l_ras_width = width;
  1391.   sunhdr.l_ras_height = height;
  1392.   sunhdr.l_ras_depth = bw ? 1 : 8;
  1393.   sunhdr.l_ras_length = (bpl+linepad) * height;
  1394.   sunhdr.l_ras_type = (rle) ? RAS_TYPE_RLE : RAS_TYPE_STD;
  1395.   if (is_bw || is_wb)   /* No colourtable for real b/w images */
  1396.     {
  1397.       sunhdr.l_ras_maptype = 0;   /* No colourmap */
  1398.       sunhdr.l_ras_maplength = 0; /* Length of colourmap */
  1399.     }
  1400.   else
  1401.     {
  1402.       sunhdr.l_ras_maptype = 1;   /* RGB colourmap */
  1403.       sunhdr.l_ras_maplength = ncols*3; /* Length of colourmap */
  1404.     }
  1405.  
  1406.   write_sun_header (ofp, &sunhdr);
  1407.  
  1408.   if (sunhdr.l_ras_maplength > 0)
  1409.     write_sun_cols (ofp, &sunhdr, suncolmap);
  1410.  
  1411. #define GET_INDEX_TILE(begin) \
  1412.   {int scan_lines; \
  1413.     scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
  1414.     gimp_pixel_rgn_get_rect (&pixel_rgn, begin, 0, i, width, scan_lines); \
  1415.     src = begin; }
  1416.  
  1417.   if (rle) { write_fun = (WRITE_FUN *)&rle_fwrite; rle_startwrite (ofp); }
  1418.   else write_fun = (WRITE_FUN *)&my_fwrite;
  1419.  
  1420.   if (bw)  /* Two colour image */
  1421.     {
  1422.       for (i = 0; i < height; i++)
  1423.     {
  1424.       if ((i % tile_height) == 0) GET_INDEX_TILE (data); /* Get more data */
  1425.       byte2bit (src, width, bwline, is_bw);
  1426.       (*write_fun) (bwline, bpl, 1, ofp);
  1427.       if (linepad) (*write_fun) ((char *)&tmp, linepad, 1, ofp);
  1428.       src += width;
  1429.  
  1430.       if ((l_run_mode != GIMP_RUN_NONINTERACTIVE) && ((i % 20) == 0))
  1431.         gimp_progress_update ((double) i / (double) height);
  1432.     }
  1433.     }
  1434.   else   /* Colour or grey-image */
  1435.     {
  1436.       for (i = 0; i < height; i++)
  1437.     {
  1438.       if ((i % tile_height) == 0) GET_INDEX_TILE (data); /* Get more data */
  1439.       (*write_fun) ((char *)src, width, 1, ofp);
  1440.       if (linepad) (*write_fun) ((char *)&tmp, linepad, 1, ofp);
  1441.       src += width;
  1442.  
  1443.       if ((l_run_mode != GIMP_RUN_NONINTERACTIVE) && ((i % 20) == 0))
  1444.         gimp_progress_update ((double) i / (double) height);
  1445.     }
  1446.     }
  1447.  
  1448.   if (rle) 
  1449.     rle_endwrite (ofp);
  1450.  
  1451.   g_free (data);
  1452.  
  1453.   if (bwline) 
  1454.     g_free (bwline);
  1455.  
  1456.   gimp_drawable_detach (drawable);
  1457.  
  1458.   if (ferror (ofp))
  1459.     {
  1460.       g_message (_("Write error occured"));
  1461.       return (FALSE);
  1462.     }
  1463.   return (TRUE);
  1464. #undef GET_INDEX_TILE
  1465. }
  1466.  
  1467.  
  1468. static gint
  1469. save_rgb (FILE   *ofp,
  1470.           gint32  image_ID,
  1471.           gint32  drawable_ID,
  1472.           gint    rle)
  1473. {
  1474.   int height, width, tile_height, linepad;
  1475.   int i, j, bpp;
  1476.   guchar *data, *src;
  1477.   L_SUNFILEHEADER sunhdr;
  1478.   GimpPixelRgn pixel_rgn;
  1479.   GimpDrawable *drawable;
  1480.   GimpImageType drawable_type;
  1481.  
  1482.   drawable = gimp_drawable_get (drawable_ID);
  1483.   drawable_type = gimp_drawable_type (drawable_ID);
  1484.   width = drawable->width;
  1485.   height = drawable->height;
  1486.   tile_height = gimp_tile_height ();
  1487.   gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, FALSE, FALSE);
  1488.  
  1489.   /* allocate a buffer for retrieving information from the pixel region  */
  1490.   src = data = (guchar *) g_malloc (tile_height * width * drawable->bpp);
  1491.  
  1492. /* #define SUNRAS_32 */
  1493. #ifdef SUNRAS_32
  1494.   bpp = 4;
  1495. #else
  1496.   bpp = 3;
  1497. #endif
  1498.   linepad = (width * bpp) % 2;
  1499.  
  1500.   /* Fill in the SUN header */
  1501.   sunhdr.l_ras_magic = RAS_MAGIC;
  1502.   sunhdr.l_ras_width = width;
  1503.   sunhdr.l_ras_height = height;
  1504.   sunhdr.l_ras_depth = 8 * bpp;
  1505.   sunhdr.l_ras_length = (width*bpp + linepad)*height;
  1506.   sunhdr.l_ras_type = (rle) ? RAS_TYPE_RLE : RAS_TYPE_STD;
  1507.   sunhdr.l_ras_maptype = 0;   /* No colourmap */
  1508.   sunhdr.l_ras_maplength = 0; /* Length of colourmap */
  1509.  
  1510.   write_sun_header (ofp, &sunhdr);
  1511.  
  1512. #define GET_RGB_TILE(begin) \
  1513.   {int scan_lines; \
  1514.     scan_lines = (i+tile_height-1 < height) ? tile_height : (height-i); \
  1515.     gimp_pixel_rgn_get_rect (&pixel_rgn, begin, 0, i, width, scan_lines); \
  1516.     src = begin; }
  1517.  
  1518.   if (!rle)
  1519.     {
  1520.       for (i = 0; i < height; i++)
  1521.     {
  1522.       if ((i % tile_height) == 0) GET_RGB_TILE (data); /* Get more data */
  1523.       for (j = 0; j < width; j++)
  1524.         {
  1525.           if (bpp == 4) putc (0, ofp);   /* Dummy */
  1526.           putc (*(src+2), ofp);          /* Blue */
  1527.           putc (*(src+1), ofp);          /* Green */
  1528.           putc (*src, ofp);              /* Red */
  1529.           src += 3;
  1530.         }
  1531.       for (j = 0; j < linepad; j++)
  1532.         putc (0, ofp);
  1533.       
  1534.       if ((l_run_mode != GIMP_RUN_NONINTERACTIVE) && ((i % 20) == 0))
  1535.         gimp_progress_update ((double) i / (double) height);
  1536.     }
  1537.     }
  1538.   else  /* Write runlength encoded */
  1539.     {
  1540.       rle_startwrite (ofp);
  1541.  
  1542.       for (i = 0; i < height; i++)
  1543.     {
  1544.       if ((i % tile_height) == 0) GET_RGB_TILE (data); /* Get more data */
  1545.       for (j = 0; j < width; j++)
  1546.         {
  1547.           if (bpp == 4) rle_putc (0, ofp);   /* Dummy */
  1548.           rle_putc (*(src+2), ofp);          /* Blue */
  1549.           rle_putc (*(src+1), ofp);          /* Green */
  1550.           rle_putc (*src, ofp);              /* Red */
  1551.           src += 3;
  1552.         }
  1553.       for (j = 0; j < linepad; j++)
  1554.         rle_putc (0, ofp);
  1555.  
  1556.       if ((l_run_mode != GIMP_RUN_NONINTERACTIVE) && ((i % 20) == 0))
  1557.         gimp_progress_update ((double) i / (double) height);
  1558.     }
  1559.  
  1560.       rle_endwrite (ofp);
  1561.     }
  1562.   g_free (data);
  1563.  
  1564.   gimp_drawable_detach (drawable);
  1565.  
  1566.   if (ferror (ofp))
  1567.     {
  1568.       g_message (_("Write error occured"));
  1569.       return (FALSE);
  1570.     }
  1571.   return (TRUE);
  1572. #undef GET_RGB_TILE
  1573. }
  1574.  
  1575.  
  1576. /*  Save interface functions  */
  1577.  
  1578. static gint
  1579. save_dialog (void)
  1580. {
  1581.   GtkWidget *dlg;
  1582.   GtkWidget *frame;
  1583.  
  1584.   dlg = gimp_dialog_new (_("Save as SUNRAS"), "sunras",
  1585.              gimp_standard_help_func, "filters/sunras.html",
  1586.              GTK_WIN_POS_MOUSE,
  1587.              FALSE, TRUE, FALSE,
  1588.  
  1589.              _("OK"), save_ok_callback,
  1590.              NULL, NULL, NULL, TRUE, FALSE,
  1591.              _("Cancel"), gtk_widget_destroy,
  1592.              NULL, 1, NULL, FALSE, TRUE,
  1593.  
  1594.              NULL);
  1595.  
  1596.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  1597.                       GTK_SIGNAL_FUNC (gtk_main_quit),
  1598.                       NULL);
  1599.  
  1600.   /*  file save type  */
  1601.   frame = gimp_radio_group_new2 (TRUE, _("Data Formatting"),
  1602.                  gimp_radio_button_update,
  1603.                  &psvals.rle, (gpointer) psvals.rle,
  1604.  
  1605.                  _("RunLength Encoded"), (gpointer) TRUE, NULL,
  1606.                  _("Standard"),          (gpointer) FALSE, NULL,
  1607.  
  1608.                  NULL);
  1609.   gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
  1610.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, TRUE, TRUE, 0);
  1611.   gtk_widget_show (frame);
  1612.  
  1613.   gtk_widget_show (dlg);
  1614.  
  1615.   gtk_main ();
  1616.   gdk_flush ();
  1617.  
  1618.   return psint.run;
  1619. }
  1620.  
  1621. static void
  1622. save_ok_callback (GtkWidget *widget,
  1623.                   gpointer   data)
  1624. {
  1625.   psint.run = TRUE;
  1626.  
  1627.   gtk_widget_destroy (GTK_WIDGET (data));
  1628. }
  1629.  
  1630. static int 
  1631. my_fwrite (void *ptr, 
  1632.        int   size, 
  1633.        int   nmemb, 
  1634.        FILE *stream)
  1635. {
  1636.   return fwrite (ptr, size, nmemb, stream);
  1637. }
  1638.