sgi.c 18.7 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1
/*
2
 * SGI image file plug-in for GIMP.
Elliot Lee's avatar
Elliot Lee committed
3
 *
4
 * Copyright 1997-1998 Michael Sweet (mike@easysw.com)
Elliot Lee's avatar
Elliot Lee committed
5
 *
6 7 8 9
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 3 of the License, or (at your option)
 * any later version.
Elliot Lee's avatar
Elliot Lee committed
10
 *
11 12 13 14
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
Elliot Lee's avatar
Elliot Lee committed
15
 *
16 17
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Elliot Lee's avatar
Elliot Lee committed
18 19 20 21 22 23 24 25 26 27 28 29 30
 *
 * Contents:
 *
 *   main()                      - Main entry - just call gimp_main()...
 *   query()                     - Respond to a plug-in query...
 *   run()                       - Run the plug-in...
 *   load_image()                - Load a PNG image into a new image window.
 *   save_image()                - Save the specified image to a PNG file.
 *   save_ok_callback()          - Destroy the save dialog and save the image.
 *   save_dialog()               - Pop up the save dialog.
 *
 */

Sven Neumann's avatar
Sven Neumann committed
31 32
#include "config.h"

33
#include <string.h>
34

Elliot Lee's avatar
Elliot Lee committed
35
#include <libgimp/gimp.h>
36
#include <libgimp/gimpui.h>
37

38
#include "sgi-lib.h"
39

40
#include "libgimp/stdplugins-intl.h"
41

Elliot Lee's avatar
Elliot Lee committed
42 43 44 45 46

/*
 * Constants...
 */

47 48
#define LOAD_PROC        "file-sgi-load"
#define SAVE_PROC        "file-sgi-save"
49
#define PLUG_IN_BINARY   "file-sgi"
50
#define PLUG_IN_VERSION  "1.1.1 - 17 May 1998"
Elliot Lee's avatar
Elliot Lee committed
51 52 53 54 55 56


/*
 * Local functions...
 */

57 58 59 60 61 62
static void     query       (void);
static void     run         (const gchar      *name,
                             gint              nparams,
                             const GimpParam  *param,
                             gint             *nreturn_vals,
                             GimpParam       **return_vals);
63

64 65
static gint32   load_image  (const gchar      *filename,
                             GError          **error);
66 67
static gint     save_image  (const gchar      *filename,
                             gint32            image_ID,
68 69
                             gint32            drawable_ID,
                             GError          **error);
Elliot Lee's avatar
Elliot Lee committed
70

71
static gboolean save_dialog (void);
Elliot Lee's avatar
Elliot Lee committed
72 73 74 75 76

/*
 * Globals...
 */

77
const GimpPlugInInfo  PLUG_IN_INFO =
Elliot Lee's avatar
Elliot Lee committed
78
{
79 80 81 82
  NULL,  /* init_proc  */
  NULL,  /* quit_proc  */
  query, /* query_proc */
  run,   /* run_proc   */
Elliot Lee's avatar
Elliot Lee committed
83 84
};

85
static gint  compression = SGI_COMP_RLE;
Elliot Lee's avatar
Elliot Lee committed
86 87


88
MAIN ()
Elliot Lee's avatar
Elliot Lee committed
89 90

static void
91
query (void)
Elliot Lee's avatar
Elliot Lee committed
92
{
93
  static const GimpParamDef load_args[] =
Elliot Lee's avatar
Elliot Lee committed
94
  {
95
    { GIMP_PDB_INT32,      "run-mode",     "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
96
    { GIMP_PDB_STRING,     "filename",     "The name of the file to load" },
97
    { GIMP_PDB_STRING,     "raw-filename", "The name of the file to load" },
Elliot Lee's avatar
Elliot Lee committed
98
  };
99
  static const GimpParamDef load_return_vals[] =
Elliot Lee's avatar
Elliot Lee committed
100
  {
101
    { GIMP_PDB_IMAGE,      "image",        "Output image" },
Elliot Lee's avatar
Elliot Lee committed
102
  };
103

104
  static const GimpParamDef save_args[] =
Elliot Lee's avatar
Elliot Lee committed
105
  {
106
    { GIMP_PDB_INT32,    "run-mode",     "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
107 108 109 110 111
    { GIMP_PDB_IMAGE,    "image",        "Input image" },
    { GIMP_PDB_DRAWABLE, "drawable",     "Drawable to save" },
    { GIMP_PDB_STRING,   "filename",     "The name of the file to save the image in" },
    { GIMP_PDB_STRING,   "raw-filename", "The name of the file to save the image in" },
    { GIMP_PDB_INT32,    "compression",  "Compression level (0 = none, 1 = RLE, 2 = ARLE)" }
Elliot Lee's avatar
Elliot Lee committed
112 113
  };

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
  gimp_install_procedure (LOAD_PROC,
                          "Loads files in SGI image file format",
                          "This plug-in loads SGI image files.",
                          "Michael Sweet <mike@easysw.com>",
                          "Copyright 1997-1998 by Michael Sweet",
                          PLUG_IN_VERSION,
                          N_("Silicon Graphics IRIS image"),
                          NULL,
                          GIMP_PLUGIN,
                          G_N_ELEMENTS (load_args),
                          G_N_ELEMENTS (load_return_vals),
                          load_args,
                          load_return_vals);

  gimp_register_file_handler_mime (LOAD_PROC, "image/x-sgi");
  gimp_register_magic_load_handler (LOAD_PROC,
130
                                    "sgi,rgb,rgba,bw,icon",
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
                                    "",
                                    "0,short,474");

  gimp_install_procedure (SAVE_PROC,
                          "Saves files in SGI image file format",
                          "This plug-in saves SGI image files.",
                          "Michael Sweet <mike@easysw.com>",
                          "Copyright 1997-1998 by Michael Sweet",
                          PLUG_IN_VERSION,
                          N_("Silicon Graphics IRIS image"),
                          "RGB*,GRAY*",
                          GIMP_PLUGIN,
                          G_N_ELEMENTS (save_args),
                          0,
                          save_args,
                          NULL);

  gimp_register_file_handler_mime (SAVE_PROC, "image/x-sgi");
149
  gimp_register_save_handler (SAVE_PROC, "sgi,rgb,rgba,bw,icon", "");
Elliot Lee's avatar
Elliot Lee committed
150 151 152
}

static void
153 154 155 156 157
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
Elliot Lee's avatar
Elliot Lee committed
158
{
159 160 161 162 163 164 165
  static GimpParam   values[2];
  GimpRunMode        run_mode;
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
  gint32             image_ID;
  gint32             drawable_ID;
  GimpExportReturn   export = GIMP_EXPORT_CANCEL;
  GError            *error  = NULL;
Elliot Lee's avatar
Elliot Lee committed
166

167
  run_mode = param[0].data.d_int32;
Elliot Lee's avatar
Elliot Lee committed
168

169 170
  *nreturn_vals = 1;
  *return_vals  = values;
171 172
  values[0].type          = GIMP_PDB_STATUS;
  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
Elliot Lee's avatar
Elliot Lee committed
173

174
  INIT_I18N ();
Sven Neumann's avatar
Sven Neumann committed
175

176
  if (strcmp (name, LOAD_PROC) == 0)
177
    {
178
      image_ID = load_image (param[1].data.d_string, &error);
Elliot Lee's avatar
Elliot Lee committed
179

180
      if (image_ID != -1)
181 182 183 184 185
        {
          *nreturn_vals = 2;
          values[1].type         = GIMP_PDB_IMAGE;
          values[1].data.d_image = image_ID;
        }
186
      else
187 188 189
        {
          status = GIMP_PDB_EXECUTION_ERROR;
        }
Elliot Lee's avatar
Elliot Lee committed
190
    }
191
  else if (strcmp (name, SAVE_PROC) == 0)
Elliot Lee's avatar
Elliot Lee committed
192
    {
193 194 195
      image_ID    = param[1].data.d_int32;
      drawable_ID = param[2].data.d_int32;

196
      /*  eventually export the image */
197
      switch (run_mode)
198 199 200 201
        {
        case GIMP_RUN_INTERACTIVE:
        case GIMP_RUN_WITH_LAST_VALS:
          gimp_ui_init (PLUG_IN_BINARY, FALSE);
202
          export = gimp_export_image (&image_ID, &drawable_ID, NULL,
203 204 205 206 207 208 209 210 211 212 213 214
                                      (GIMP_EXPORT_CAN_HANDLE_RGB  |
                                       GIMP_EXPORT_CAN_HANDLE_GRAY |
                                       GIMP_EXPORT_CAN_HANDLE_ALPHA));
          if (export == GIMP_EXPORT_CANCEL)
            {
              values[0].data.d_status = GIMP_PDB_CANCEL;
              return;
            }
          break;
        default:
          break;
        }
215 216

      switch (run_mode)
217 218 219 220 221 222 223 224 225 226
        {
        case GIMP_RUN_INTERACTIVE:
          /*
           * Possibly retrieve data...
           */
          gimp_get_data (SAVE_PROC, &compression);

          /*
           * Then acquire information with a dialog...
           */
227
          if (!save_dialog ())
228
            status = GIMP_PDB_CANCEL;
Elliot Lee's avatar
Elliot Lee committed
229 230
          break;

231 232 233 234
        case GIMP_RUN_NONINTERACTIVE:
          /*
           * Make sure all the arguments are there!
           */
Elliot Lee's avatar
Elliot Lee committed
235
          if (nparams != 6)
236 237 238
            {
              status = GIMP_PDB_CALLING_ERROR;
            }
Elliot Lee's avatar
Elliot Lee committed
239
          else
240 241
            {
              compression = param[5].data.d_int32;
Elliot Lee's avatar
Elliot Lee committed
242

243 244 245
              if (compression < 0 || compression > 2)
                status = GIMP_PDB_CALLING_ERROR;
            };
Elliot Lee's avatar
Elliot Lee committed
246 247
          break;

248 249 250 251 252
        case GIMP_RUN_WITH_LAST_VALS:
          /*
           * Possibly retrieve data...
           */
          gimp_get_data (SAVE_PROC, &compression);
Elliot Lee's avatar
Elliot Lee committed
253 254
          break;

255
        default:
Elliot Lee's avatar
Elliot Lee committed
256
          break;
257
        };
Elliot Lee's avatar
Elliot Lee committed
258

259
      if (status == GIMP_PDB_SUCCESS)
260
        {
261 262
          if (save_image (param[3].data.d_string, image_ID, drawable_ID,
                          &error))
263 264 265 266 267 268 269 270
            {
              gimp_set_data (SAVE_PROC, &compression, sizeof (compression));
            }
          else
            {
              status = GIMP_PDB_EXECUTION_ERROR;
            }
        }
271

272
      if (export == GIMP_EXPORT_EXPORT)
273
        gimp_image_delete (image_ID);
274
    }
Elliot Lee's avatar
Elliot Lee committed
275
  else
276
    {
277
      status = GIMP_PDB_CALLING_ERROR;
278 279
    }

280 281 282 283 284 285 286
  if (status != GIMP_PDB_SUCCESS && error)
    {
      *nreturn_vals = 2;
      values[1].type          = GIMP_PDB_STRING;
      values[1].data.d_string = error->message;
    }

287
  values[0].data.d_status = status;
Elliot Lee's avatar
Elliot Lee committed
288 289 290 291 292 293 294 295
}


/*
 * 'load_image()' - Load a PNG image into a new image window.
 */

static gint32
296 297
load_image (const gchar  *filename,
            GError      **error)
Elliot Lee's avatar
Elliot Lee committed
298
{
299
  gint           i,           /* Looping var */
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
                 x,           /* Current X coordinate */
                 y,           /* Current Y coordinate */
                 image_type,  /* Type of image */
                 layer_type,  /* Type of drawable/layer */
                 tile_height, /* Height of tile in GIMP */
                 count,       /* Count of rows to put in image */
                 bytes;       /* Number of channels to use */
  sgi_t         *sgip;        /* File pointer */
  gint32         image,       /* Image */
                 layer;       /* Layer */
  GimpDrawable  *drawable;    /* Drawable for layer */
  GimpPixelRgn   pixel_rgn;   /* Pixel region for layer */
  guchar       **pixels,      /* Pixel rows */
                *pptr;        /* Current pixel */
  gushort      **rows;        /* SGI image data */
Elliot Lee's avatar
Elliot Lee committed
315 316 317 318 319

 /*
  * Open the file for reading...
  */

320
  sgip = sgiOpen (filename, SGI_READ, 0, 0, 0, 0, 0);
Elliot Lee's avatar
Elliot Lee committed
321
  if (sgip == NULL)
322
    {
323 324 325
      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
                   _("Could not open '%s' for reading."),
                   gimp_filename_to_utf8 (filename));
326 327
      return -1;
    };
Elliot Lee's avatar
Elliot Lee committed
328

329
  gimp_progress_init_printf (_("Opening '%s'"),
330
                             gimp_filename_to_utf8 (filename));
Elliot Lee's avatar
Elliot Lee committed
331

332 333 334
  /*
   * Get the image dimensions and create the image...
   */
335

Nils Philippsen's avatar
Nils Philippsen committed
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
  /* Sanitize dimensions */
  if (sgip->xsize == 0 || sgip->xsize > GIMP_MAX_IMAGE_SIZE)
    {
      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
              _("Invalid width: %hu"), sgip->xsize);
      return -1;
    }

  if (sgip->ysize == 0 || sgip->ysize > GIMP_MAX_IMAGE_SIZE)
    {
      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
              _("Invalid height: %hu"), sgip->ysize);
      return -1;
    }

  if (sgip->zsize == 0 || sgip->zsize > GIMP_MAX_IMAGE_SIZE)
    {
      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
              _("Invalid number of channels: %hu"), sgip->zsize);
      return -1;
    }

358
  bytes = sgip->zsize;
Sven Neumann's avatar
Sven Neumann committed
359

Elliot Lee's avatar
Elliot Lee committed
360
  switch (sgip->zsize)
361
    {
362
    case 1 :    /* Grayscale */
363 364
      image_type = GIMP_GRAY;
      layer_type = GIMP_GRAY_IMAGE;
365
      break;
Elliot Lee's avatar
Elliot Lee committed
366

367
    case 2 :    /* Grayscale + alpha */
368 369
      image_type = GIMP_GRAY;
      layer_type = GIMP_GRAYA_IMAGE;
370
      break;
Elliot Lee's avatar
Elliot Lee committed
371

372
    case 3 :    /* RGB */
373 374
      image_type = GIMP_RGB;
      layer_type = GIMP_RGB_IMAGE;
375
      break;
Elliot Lee's avatar
Elliot Lee committed
376

377
    case 4 :    /* RGBA */
378 379
      image_type = GIMP_RGB;
      layer_type = GIMP_RGBA_IMAGE;
380
      break;
Sven Neumann's avatar
Sven Neumann committed
381

382 383 384 385 386
    default:
      image_type = GIMP_RGB;
      layer_type = GIMP_RGBA_IMAGE;
      bytes = 4;
      break;
387
    }
Elliot Lee's avatar
Elliot Lee committed
388

389
  image = gimp_image_new (sgip->xsize, sgip->ysize, image_type);
Elliot Lee's avatar
Elliot Lee committed
390
  if (image == -1)
391
    {
392 393 394
      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
                   "Could not allocate new image: %s",
                   gimp_get_pdb_error());
395 396
      return -1;
    }
Elliot Lee's avatar
Elliot Lee committed
397

398
  gimp_image_set_filename (image, filename);
Elliot Lee's avatar
Elliot Lee committed
399

400 401 402
  /*
   * Create the "background" layer to hold the image...
   */
Elliot Lee's avatar
Elliot Lee committed
403

Sven Neumann's avatar
Sven Neumann committed
404
  layer = gimp_layer_new (image, _("Background"), sgip->xsize, sgip->ysize,
405
                          layer_type, 100, GIMP_NORMAL_MODE);
406
  gimp_image_add_layer (image, layer, 0);
Elliot Lee's avatar
Elliot Lee committed
407

408 409 410
  /*
   * Get the drawable and set the pixel region for our load...
   */
Elliot Lee's avatar
Elliot Lee committed
411

412
  drawable = gimp_drawable_get (layer);
Elliot Lee's avatar
Elliot Lee committed
413

414 415
  gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width,
                       drawable->height, TRUE, FALSE);
Elliot Lee's avatar
Elliot Lee committed
416

417 418 419
  /*
   * Temporary buffers...
   */
Elliot Lee's avatar
Elliot Lee committed
420

421 422
  tile_height = gimp_tile_height ();
  pixels      = g_new (guchar *, tile_height);
423
  pixels[0]   = g_new (guchar, ((gsize) tile_height) * sgip->xsize * bytes);
Elliot Lee's avatar
Elliot Lee committed
424

425 426
  for (i = 1; i < tile_height; i ++)
    pixels[i] = pixels[0] + sgip->xsize * bytes * i;
Elliot Lee's avatar
Elliot Lee committed
427

428
  rows    = g_new (unsigned short *, sgip->zsize);
429
  rows[0] = g_new (unsigned short, ((gsize) sgip->xsize) * sgip->zsize);
Elliot Lee's avatar
Elliot Lee committed
430 431 432 433

  for (i = 1; i < sgip->zsize; i ++)
    rows[i] = rows[0] + i * sgip->xsize;

434 435 436
  /*
   * Load the image...
   */
Elliot Lee's avatar
Elliot Lee committed
437 438 439 440 441

  for (y = 0, count = 0;
       y < sgip->ysize;
       y ++, count ++)
    {
442
      if (count >= tile_height)
443
        {
444
          gimp_pixel_rgn_set_rect (&pixel_rgn, pixels[0],
445 446
                                   0, y - count, drawable->width, count);
          count = 0;
Elliot Lee's avatar
Elliot Lee committed
447

448 449
          gimp_progress_update ((double) y / (double) sgip->ysize);
        }
Elliot Lee's avatar
Elliot Lee committed
450

451
      for (i = 0; i < sgip->zsize; i ++)
452 453 454
        if (sgiGetRow (sgip, rows[i], sgip->ysize - 1 - y, i) < 0)
          printf("sgiGetRow(sgip, rows[i], %d, %d) failed!\n",
                 sgip->ysize - 1 - y, i);
Elliot Lee's avatar
Elliot Lee committed
455

456
      if (sgip->bpp == 1)
457 458 459 460 461 462 463 464 465
        {
          /*
           * 8-bit (unsigned) pixels...
           */

          for (x = 0, pptr = pixels[count]; x < sgip->xsize; x ++)
            for (i = 0; i < bytes; i ++, pptr ++)
              *pptr = rows[i][x];
        }
466
      else
467 468 469 470 471 472 473 474 475
        {
          /*
           * 16-bit (unsigned) pixels...
           */

          for (x = 0, pptr = pixels[count]; x < sgip->xsize; x ++)
            for (i = 0; i < bytes; i ++, pptr ++)
              *pptr = rows[i][x] >> 8;
        }
476
    }
Elliot Lee's avatar
Elliot Lee committed
477

478 479 480
  /*
   * Do the last n rows (count always > 0)
   */
Elliot Lee's avatar
Elliot Lee committed
481

482
  gimp_pixel_rgn_set_rect (&pixel_rgn, pixels[0], 0,
483
                           y - count, drawable->width, count);
Elliot Lee's avatar
Elliot Lee committed
484

485 486 487
  /*
   * Done with the file...
   */
Elliot Lee's avatar
Elliot Lee committed
488

489
  sgiClose (sgip);
Elliot Lee's avatar
Elliot Lee committed
490

491
  g_free (pixels[0]);
492 493 494
  g_free (pixels);
  g_free (rows[0]);
  g_free (rows);
Elliot Lee's avatar
Elliot Lee committed
495

496 497 498
  /*
   * Update the display...
   */
Elliot Lee's avatar
Elliot Lee committed
499

500 501
  gimp_drawable_flush (drawable);
  gimp_drawable_detach (drawable);
Elliot Lee's avatar
Elliot Lee committed
502

503
  return image;
Elliot Lee's avatar
Elliot Lee committed
504 505 506 507
}


/*
Sven Neumann's avatar
Sven Neumann committed
508
 * 'save_image()' - Save the specified image to a SGI file.
Elliot Lee's avatar
Elliot Lee committed
509 510 511
 */

static gint
512 513 514 515
save_image (const gchar  *filename,
            gint32        image_ID,
            gint32        drawable_ID,
            GError      **error)
Elliot Lee's avatar
Elliot Lee committed
516
{
517 518 519 520 521 522
  gint        i, j,        /* Looping var */
              x,           /* Current X coordinate */
              y,           /* Current Y coordinate */
              tile_height, /* Height of tile in GIMP */
              count,       /* Count of rows to put in image */
              zsize;       /* Number of channels in file */
523
  sgi_t      *sgip;        /* File pointer */
524 525
  GimpDrawable  *drawable;    /* Drawable for layer */
  GimpPixelRgn   pixel_rgn;   /* Pixel region for layer */
526 527 528
  guchar    **pixels,      /* Pixel rows */
             *pptr;        /* Current pixel */
  gushort   **rows;        /* SGI image data */
Elliot Lee's avatar
Elliot Lee committed
529

530 531 532
  /*
   * Get the drawable for the current image...
   */
Elliot Lee's avatar
Elliot Lee committed
533

534
  drawable = gimp_drawable_get (drawable_ID);
Elliot Lee's avatar
Elliot Lee committed
535

536
  gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width,
537
                       drawable->height, FALSE, FALSE);
Elliot Lee's avatar
Elliot Lee committed
538

539
  zsize = 0;
540
  switch (gimp_drawable_type (drawable_ID))
Sven Neumann's avatar
Sven Neumann committed
541
    {
542
    case GIMP_GRAY_IMAGE :
543 544
      zsize = 1;
      break;
545
    case GIMP_GRAYA_IMAGE :
546 547
      zsize = 2;
      break;
548
    case GIMP_RGB_IMAGE :
549 550
      zsize = 3;
      break;
551
    case GIMP_RGBA_IMAGE :
552 553
      zsize = 4;
      break;
Sven Neumann's avatar
Sven Neumann committed
554
    default:
555
      g_message (_("Cannot operate on indexed color images."));
556
      return FALSE;
557
    }
Elliot Lee's avatar
Elliot Lee committed
558

559 560 561
  /*
   * Open the file for writing...
   */
Elliot Lee's avatar
Elliot Lee committed
562

563
  sgip = sgiOpen (filename, SGI_WRITE, compression, 1,
564
                  drawable->width, drawable->height, zsize);
Elliot Lee's avatar
Elliot Lee committed
565
  if (sgip == NULL)
566
    {
567 568 569
      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
                   _("Could not open '%s' for writing."),
                   gimp_filename_to_utf8 (filename));
570 571
      return FALSE;
    };
Elliot Lee's avatar
Elliot Lee committed
572

573
  gimp_progress_init_printf (_("Saving '%s'"),
574
                             gimp_filename_to_utf8 (filename));
Elliot Lee's avatar
Elliot Lee committed
575

576 577 578
  /*
   * Allocate memory for "tile_height" rows...
   */
Elliot Lee's avatar
Elliot Lee committed
579

580 581
  tile_height = gimp_tile_height ();
  pixels      = g_new (guchar *, tile_height);
582
  pixels[0]   = g_new (guchar, ((gsize) tile_height) * drawable->width * zsize);
Elliot Lee's avatar
Elliot Lee committed
583

584 585
  for (i = 1; i < tile_height; i ++)
    pixels[i]= pixels[0] + drawable->width * zsize * i;
Elliot Lee's avatar
Elliot Lee committed
586

587
  rows    = g_new (gushort *, sgip->zsize);
588
  rows[0] = g_new (gushort, ((gsize) sgip->xsize) * sgip->zsize);
Elliot Lee's avatar
Elliot Lee committed
589 590 591 592

  for (i = 1; i < sgip->zsize; i ++)
    rows[i] = rows[0] + i * sgip->xsize;

593 594 595
  /*
   * Save the image...
   */
Elliot Lee's avatar
Elliot Lee committed
596 597

  for (y = 0; y < drawable->height; y += count)
598 599 600 601
    {
      /*
       * Grab more pixel data...
       */
Elliot Lee's avatar
Elliot Lee committed
602

603
      if ((y + tile_height) >= drawable->height)
604
        count = drawable->height - y;
605
      else
606
        count = tile_height;
Elliot Lee's avatar
Elliot Lee committed
607

608
      gimp_pixel_rgn_get_rect (&pixel_rgn, pixels[0], 0, y, drawable->width, count);
Elliot Lee's avatar
Elliot Lee committed
609

610 611 612
      /*
       * Convert to shorts and write each color plane separately...
       */
Elliot Lee's avatar
Elliot Lee committed
613

614
      for (i = 0, pptr = pixels[0]; i < count; i ++)
615 616 617 618
        {
          for (x = 0; x < drawable->width; x ++)
            for (j = 0; j < zsize; j ++, pptr ++)
              rows[j][x] = *pptr;
619

620 621 622
          for (j = 0; j < zsize; j ++)
            sgiPutRow (sgip, rows[j], drawable->height - 1 - y - i, j);
        };
Elliot Lee's avatar
Elliot Lee committed
623

624
      gimp_progress_update ((double) y / (double) drawable->height);
Manish Singh's avatar
Manish Singh committed
625
    };
Elliot Lee's avatar
Elliot Lee committed
626

627 628 629
  /*
   * Done with the file...
   */
Elliot Lee's avatar
Elliot Lee committed
630

631
  sgiClose (sgip);
Elliot Lee's avatar
Elliot Lee committed
632

633
  g_free (pixels[0]);
634 635 636
  g_free (pixels);
  g_free (rows[0]);
  g_free (rows);
Elliot Lee's avatar
Elliot Lee committed
637

638
  return TRUE;
Elliot Lee's avatar
Elliot Lee committed
639 640
}

641
static gboolean
642
save_dialog (void)
Elliot Lee's avatar
Elliot Lee committed
643
{
644
  GtkWidget *dialog;
645
  GtkWidget *frame;
646
  gboolean   run;
Elliot Lee's avatar
Elliot Lee committed
647

648
  dialog = gimp_export_dialog_new (_("SGI"), PLUG_IN_BINARY, SAVE_PROC);
649

650
  frame = gimp_int_radio_group_new (TRUE, _("Compression type"),
651 652
                                    G_CALLBACK (gimp_radio_button_update),
                                    &compression, compression,
653

654 655 656 657 658 659
                                    _("No compression"),
                                    SGI_COMP_NONE, NULL,
                                    _("RLE compression"),
                                    SGI_COMP_RLE, NULL,
                                    _("Aggressive RLE\n(not supported by SGI)"),
                                    SGI_COMP_ARLE, NULL,
660

661
                                    NULL);
Elliot Lee's avatar
Elliot Lee committed
662

663
  gtk_container_set_border_width (GTK_CONTAINER (frame), 12);
664
  gtk_box_pack_start (GTK_BOX (gimp_export_dialog_get_content_area (dialog)),
665
                      frame, TRUE, TRUE, 0);
666
  gtk_widget_show (frame);
Elliot Lee's avatar
Elliot Lee committed
667

668
  gtk_widget_show (dialog);
Elliot Lee's avatar
Elliot Lee committed
669

670
  run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
671

672
  gtk_widget_destroy (dialog);
Elliot Lee's avatar
Elliot Lee committed
673

674
  return run;
Elliot Lee's avatar
Elliot Lee committed
675
}