~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to plug-ins/common/pnm.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* The GIMP -- an image manipulation program
 
1
/* GIMP - The GNU Image Manipulation Program
2
2
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
3
 * PNM reading and writing code Copyright (C) 1996 Erik Nygren
4
4
 *
17
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
18
 */
19
19
 
20
 
/* $Id: pnm.c,v 1.52 2004/12/12 17:18:03 weskaggs Exp $ */
 
20
/* $Id: pnm.c 22152 2007-03-20 10:41:35Z mitch $ */
21
21
 
22
22
/*
23
23
 * The pnm reading and writing code was written from scratch by Erik Nygren
24
24
 * (nygren@mit.edu) based on the specifications in the man pages and
25
25
 * does not contain any code from the netpbm or pbmplus distributions.
 
26
 *
 
27
 * 2006: pbm saving written by Martin K Collins (martin@mkcollins.org)
26
28
 */
27
29
 
28
30
#include "config.h"
29
31
 
30
32
#include <errno.h>
 
33
#include <string.h>
 
34
#include <stdlib.h>
 
35
 
31
36
#include <setjmp.h>
32
37
#include <sys/types.h>
33
38
#include <sys/stat.h>
34
39
#include <fcntl.h>
 
40
 
35
41
#ifdef HAVE_UNISTD_H
36
42
#include <unistd.h>
37
43
#endif
38
 
#include <stdio.h>
39
 
#include <stdlib.h>
40
 
#include <string.h>
 
44
 
 
45
#include <glib/gstdio.h>
41
46
 
42
47
#include <libgimp/gimp.h>
43
48
#include <libgimp/gimpui.h>
53
58
#define _O_BINARY 0
54
59
#endif
55
60
 
 
61
 
 
62
#define LOAD_PROC      "file-pnm-load"
 
63
#define PNM_SAVE_PROC  "file-pnm-save"
 
64
#define PBM_SAVE_PROC  "file-pbm-save"
 
65
#define PGM_SAVE_PROC  "file-pgm-save"
 
66
#define PPM_SAVE_PROC  "file-ppm-save"
 
67
#define PLUG_IN_BINARY "pnm"
 
68
 
 
69
 
56
70
/* Declare local data types
57
71
 */
58
72
 
59
73
typedef struct _PNMScanner
60
74
{
61
 
  gint    fd;                 /* The file descriptor of the file being read */
62
 
  gchar   cur;                /* The current character in the input stream */
63
 
  gint    eof;                /* Have we reached end of file? */
64
 
  gchar  *inbuf;              /* Input buffer - initially 0 */
65
 
  gint    inbufsize;          /* Size of input buffer */
 
75
  gint    fd;                 /* The file descriptor of the file being read */
 
76
  gchar   cur;                /* The current character in the input stream */
 
77
  gint    eof;                /* Have we reached end of file? */
 
78
  gchar  *inbuf;              /* Input buffer - initially 0 */
 
79
  gint    inbufsize;          /* Size of input buffer */
66
80
  gint    inbufvalidsize;     /* Size of input buffer with valid data */
67
81
  gint    inbufpos;           /* Position in input buffer */
68
82
} PNMScanner;
69
83
 
70
84
typedef struct _PNMInfo
71
85
{
72
 
  gint       xres, yres;        /* The size of the image */
73
 
  gint       maxval;            /* For ascii image files, the max value
74
 
                                 * which we need to normalize to */
75
 
  gint       np;                /* Number of image planes (0 for pbm) */
76
 
  gint       asciibody;         /* 1 if ascii body, 0 if raw body */
77
 
  jmp_buf    jmpbuf;            /* Where to jump to on an error loading */
 
86
  gint       xres, yres;        /* The size of the image */
 
87
  gint       maxval;            /* For ascii image files, the max value
 
88
                                 * which we need to normalize to */
 
89
  gint       np;                /* Number of image planes (0 for pbm) */
 
90
  gint       asciibody;         /* 1 if ascii body, 0 if raw body */
 
91
  jmp_buf    jmpbuf;            /* Where to jump to on an error loading */
78
92
  /* Routine to use to load the pnm body */
79
93
  void    (* loader) (PNMScanner *, struct _PNMInfo *, GimpPixelRgn *);
80
94
} PNMInfo;
82
96
/* Contains the information needed to write out PNM rows */
83
97
typedef struct _PNMRowInfo
84
98
{
85
 
  gint    fd;           /* File descriptor */
86
 
  gchar  *rowbuf;       /* Buffer for writing out rows */
87
 
  gint    xres;         /* X resolution */
88
 
  gint    np;           /* Number of planes */
89
 
  guchar *red;          /* Colormap red */
90
 
  guchar *grn;          /* Colormap green */
91
 
  guchar *blu;          /* Colormap blue */
 
99
  gint    fd;           /* File descriptor */
 
100
  gchar  *rowbuf;       /* Buffer for writing out rows */
 
101
  gint    xres;         /* X resolution */
 
102
  gint    np;           /* Number of planes */
 
103
  guchar *red;          /* Colormap red */
 
104
  guchar *grn;          /* Colormap green */
 
105
  guchar *blu;          /* Colormap blue */
92
106
} PNMRowInfo;
93
107
 
94
108
/* Save info  */
97
111
  gint  raw;  /*  raw or ascii  */
98
112
} PNMSaveVals;
99
113
 
100
 
#define BUFLEN 512              /* The input buffer size for data returned
101
 
                                 * from the scanner.  Note that lines
102
 
                                 * aren't allowed to be over 256 characters
103
 
                                 * by the spec anyways so this shouldn't
104
 
                                 * be an issue. */
 
114
#define BUFLEN 512              /* The input buffer size for data returned
 
115
                                 * from the scanner.  Note that lines
 
116
                                 * aren't allowed to be over 256 characters
 
117
                                 * by the spec anyways so this shouldn't
 
118
                                 * be an issue. */
105
119
 
106
 
#define SAVE_COMMENT_STRING "# CREATOR: The GIMP's PNM Filter Version 1.0\n"
 
120
#define SAVE_COMMENT_STRING "# CREATOR: GIMP PNM Filter Version 1.1\n"
107
121
 
108
122
/* Declare some local functions.
109
123
 */
115
129
                          GimpParam       **return_vals);
116
130
static gint32 load_image (const gchar      *filename);
117
131
static gint   save_image (const gchar      *filename,
118
 
                          gint32            image_ID,
119
 
                          gint32            drawable_ID);
 
132
                          gint32            image_ID,
 
133
                          gint32            drawable_ID,
 
134
                          gboolean          pbm);
120
135
 
121
136
static gint   save_dialog              (void);
122
137
 
123
 
static void   pnm_load_ascii           (PNMScanner *scan,
124
 
                                        PNMInfo    *info,
125
 
                                        GimpPixelRgn  *pixel_rgn);
126
 
static void   pnm_load_raw             (PNMScanner *scan,
127
 
                                        PNMInfo    *info,
128
 
                                        GimpPixelRgn  *pixel_rgn);
129
 
static void   pnm_load_rawpbm          (PNMScanner *scan,
130
 
                                        PNMInfo    *info,
131
 
                                        GimpPixelRgn  *pixel_rgn);
 
138
static void   pnm_load_ascii           (PNMScanner   *scan,
 
139
                                        PNMInfo      *info,
 
140
                                        GimpPixelRgn *pixel_rgn);
 
141
static void   pnm_load_raw             (PNMScanner   *scan,
 
142
                                        PNMInfo      *info,
 
143
                                        GimpPixelRgn *pixel_rgn);
 
144
static void   pnm_load_rawpbm          (PNMScanner   *scan,
 
145
                                        PNMInfo      *info,
 
146
                                        GimpPixelRgn *pixel_rgn);
132
147
 
133
148
static void   pnmsaverow_ascii         (PNMRowInfo *ri,
134
 
                                        guchar     *data);
 
149
                                        guchar     *data);
135
150
static void   pnmsaverow_raw           (PNMRowInfo *ri,
136
 
                                        guchar     *data);
 
151
                                        guchar     *data);
 
152
static void   pnmsaverow_raw_pbm       (PNMRowInfo *ri,
 
153
                                        guchar     *data);
 
154
static void   pnmsaverow_ascii_pbm     (PNMRowInfo *ri,
 
155
                                        guchar     *data);
137
156
static void   pnmsaverow_ascii_indexed (PNMRowInfo *ri,
138
 
                                        guchar     *data);
 
157
                                        guchar     *data);
139
158
static void   pnmsaverow_raw_indexed   (PNMRowInfo *ri,
140
 
                                        guchar     *data);
 
159
                                        guchar     *data);
141
160
 
142
161
static void   pnmscanner_destroy       (PNMScanner *s);
143
162
static void   pnmscanner_createbuffer  (PNMScanner *s,
144
 
                                        gint        bufsize);
 
163
                                        gint        bufsize);
145
164
static void   pnmscanner_getchar       (PNMScanner *s);
146
165
static void   pnmscanner_eatwhitespace (PNMScanner *s);
147
166
static void   pnmscanner_gettoken      (PNMScanner *s,
148
 
                                        gchar      *buf,
149
 
                                        gint        bufsize);
 
167
                                        gchar      *buf,
 
168
                                        gint        bufsize);
150
169
static void   pnmscanner_getsmalltoken (PNMScanner *s,
151
 
                                        gchar      *buf);
 
170
                                        gchar      *buf);
152
171
 
153
172
static PNMScanner * pnmscanner_create  (gint        fd);
154
173
 
179
198
  {  0 , 0, 0,   0, NULL}
180
199
};
181
200
 
182
 
GimpPlugInInfo PLUG_IN_INFO =
 
201
const GimpPlugInInfo PLUG_IN_INFO =
183
202
{
184
203
  NULL,  /* init_proc  */
185
204
  NULL,  /* quit_proc  */
198
217
static void
199
218
query (void)
200
219
{
201
 
  static GimpParamDef load_args[] =
 
220
  static const GimpParamDef load_args[] =
202
221
  {
203
 
    { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
204
 
    { GIMP_PDB_STRING, "filename", "The name of the file to load" },
205
 
    { GIMP_PDB_STRING, "raw_filename", "The name of the file to load" }
 
222
    { GIMP_PDB_INT32,  "run-mode",     "Interactive, non-interactive" },
 
223
    { GIMP_PDB_STRING, "filename",     "The name of the file to load" },
 
224
    { GIMP_PDB_STRING, "raw-filename", "The name of the file to load" }
206
225
  };
207
 
  static GimpParamDef load_return_vals[] =
 
226
  static const GimpParamDef load_return_vals[] =
208
227
  {
209
228
    { GIMP_PDB_IMAGE, "image", "Output image" }
210
229
  };
211
230
 
212
 
  static GimpParamDef save_args[] =
 
231
  static const GimpParamDef save_args[] =
213
232
  {
214
 
    { GIMP_PDB_INT32,    "run_mode",     "Interactive, non-interactive" },
215
 
    { GIMP_PDB_IMAGE,    "image",        "Input image" },
216
 
    { GIMP_PDB_DRAWABLE, "drawable",     "Drawable to save" },
 
233
    { GIMP_PDB_INT32,    "run-mode",     "Interactive, non-interactive" },
 
234
    { GIMP_PDB_IMAGE,    "image",        "Input image"                  },
 
235
    { GIMP_PDB_DRAWABLE, "drawable",     "Drawable to save"             },
217
236
    { GIMP_PDB_STRING,   "filename",     "The name of the file to save the image in" },
218
 
    { GIMP_PDB_STRING,   "raw_filename", "The name of the file to save the image in" },
 
237
    { GIMP_PDB_STRING,   "raw-filename", "The name of the file to save the image in" },
219
238
    { GIMP_PDB_INT32,    "raw",          "Specify non-zero for raw output, zero for ascii output" }
220
239
  };
221
240
 
222
 
  gimp_install_procedure ("file_pnm_load",
 
241
  gimp_install_procedure (LOAD_PROC,
223
242
                          "loads files of the pnm file format",
224
243
                          "FIXME: write help for pnm_load",
225
244
                          "Erik Nygren",
226
245
                          "Erik Nygren",
227
246
                          "1996",
228
247
                          N_("PNM Image"),
229
 
                          NULL,
 
248
                          NULL,
230
249
                          GIMP_PLUGIN,
231
250
                          G_N_ELEMENTS (load_args),
232
251
                          G_N_ELEMENTS (load_return_vals),
233
252
                          load_args, load_return_vals);
234
253
 
235
 
  gimp_register_file_handler_mime ("file_pnm_load", "image/x-portable-anymap");
236
 
  gimp_register_magic_load_handler ("file_pnm_load",
 
254
  gimp_register_file_handler_mime (LOAD_PROC, "image/x-portable-anymap");
 
255
  gimp_register_magic_load_handler (LOAD_PROC,
237
256
                                    "pnm,ppm,pgm,pbm",
238
 
                                    "",
239
 
                                    "0,string,P1,0,string,P2,0,string,P3,0,"
240
 
                                    "string,P4,0,string,P5,0,string,P6");
 
257
                                    "",
 
258
                                    "0,string,P1,0,string,P2,0,string,P3,0,"
 
259
                                    "string,P4,0,string,P5,0,string,P6");
241
260
 
242
 
  gimp_install_procedure ("file_pnm_save",
 
261
  gimp_install_procedure (PNM_SAVE_PROC,
243
262
                          "saves files in the pnm file format",
244
263
                          "PNM saving handles all image types without transparency.",
245
264
                          "Erik Nygren",
246
265
                          "Erik Nygren",
247
266
                          "1996",
248
267
                          N_("PNM image"),
249
 
                          "RGB, GRAY, INDEXED",
250
 
                          GIMP_PLUGIN,
251
 
                          G_N_ELEMENTS (save_args), 0,
252
 
                          save_args, NULL);
253
 
 
254
 
  gimp_install_procedure ("file_pgm_save",
 
268
                          "RGB, GRAY, INDEXED",
 
269
                          GIMP_PLUGIN,
 
270
                          G_N_ELEMENTS (save_args), 0,
 
271
                          save_args, NULL);
 
272
 
 
273
  gimp_install_procedure (PBM_SAVE_PROC,
 
274
                          "saves files in the pnm file format",
 
275
                          "PBM saving produces mono images without transparency.",
 
276
                          "Martin K Collins",
 
277
                          "Erik Nygren",
 
278
                          "2006",
 
279
                          N_("PBM image"),
 
280
                          "RGB, GRAY, INDEXED",
 
281
                          GIMP_PLUGIN,
 
282
                          G_N_ELEMENTS (save_args), 0,
 
283
                          save_args, NULL);
 
284
 
 
285
  gimp_install_procedure (PGM_SAVE_PROC,
255
286
                          "saves files in the pnm file format",
256
287
                          "PGM saving produces grayscale images without transparency.",
257
288
                          "Erik Nygren",
258
289
                          "Erik Nygren",
259
290
                          "1996",
260
291
                          N_("PGM image"),
261
 
                          "RGB, GRAY, INDEXED",
 
292
                          "RGB, GRAY, INDEXED",
262
293
                          GIMP_PLUGIN,
263
294
                          G_N_ELEMENTS (save_args), 0,
264
295
                          save_args, NULL);
265
296
 
266
 
  gimp_install_procedure ("file_ppm_save",
 
297
  gimp_install_procedure (PPM_SAVE_PROC,
267
298
                          "saves files in the pnm file format",
268
299
                          "PPM saving handles RGB images without transparency.",
269
300
                          "Erik Nygren",
270
301
                          "Erik Nygren",
271
302
                          "1996",
272
303
                          N_("PPM image"),
273
 
                          "RGB, GRAY, INDEXED",
 
304
                          "RGB, GRAY, INDEXED",
274
305
                          GIMP_PLUGIN,
275
306
                          G_N_ELEMENTS (save_args), 0,
276
307
                          save_args, NULL);
277
308
 
278
 
  gimp_register_file_handler_mime ("file_pgm_save", "image/x-portable-graymap");
279
 
  gimp_register_file_handler_mime ("file_ppm_save", "image/x-portable-pixmap");
280
 
  gimp_register_save_handler ("file_pgm_save", "pgm", "");
281
 
  gimp_register_save_handler ("file_ppm_save", "ppm", "");
 
309
  gimp_register_file_handler_mime (PNM_SAVE_PROC, "image/x-portable-anymap");
 
310
  gimp_register_file_handler_mime (PBM_SAVE_PROC, "image/x-portable-bitmap");
 
311
  gimp_register_file_handler_mime (PGM_SAVE_PROC, "image/x-portable-graymap");
 
312
  gimp_register_file_handler_mime (PPM_SAVE_PROC, "image/x-portable-pixmap");
 
313
  gimp_register_save_handler (PNM_SAVE_PROC, "pnm", "");
 
314
  gimp_register_save_handler (PBM_SAVE_PROC, "pbm", "");
 
315
  gimp_register_save_handler (PGM_SAVE_PROC, "pgm", "");
 
316
  gimp_register_save_handler (PPM_SAVE_PROC, "ppm", "");
282
317
}
283
318
 
284
319
static void
294
329
  gint32            image_ID;
295
330
  gint32            drawable_ID;
296
331
  GimpExportReturn  export = GIMP_EXPORT_CANCEL;
 
332
  gboolean          pbm = FALSE;  /* flag for PBM output */
297
333
 
298
334
  run_mode = param[0].data.d_int32;
299
335
 
304
340
 
305
341
  INIT_I18N ();
306
342
 
307
 
  if (strcmp (name, "file_pnm_load") == 0)
 
343
  if (strcmp (name, LOAD_PROC) == 0)
308
344
    {
309
345
      image_ID = load_image (param[1].data.d_string);
310
346
 
311
347
      if (image_ID != -1)
312
 
        {
313
 
          *nreturn_vals = 2;
314
 
          values[1].type         = GIMP_PDB_IMAGE;
315
 
          values[1].data.d_image = image_ID;
316
 
        }
 
348
        {
 
349
          *nreturn_vals = 2;
 
350
          values[1].type         = GIMP_PDB_IMAGE;
 
351
          values[1].data.d_image = image_ID;
 
352
        }
317
353
      else
318
 
        {
319
 
          status = GIMP_PDB_EXECUTION_ERROR;
320
 
        }
 
354
        {
 
355
          status = GIMP_PDB_EXECUTION_ERROR;
 
356
        }
321
357
    }
322
 
  else if (strcmp (name, "file_pnm_save") == 0
323
 
           || strcmp (name, "file_pgm_save") == 0
324
 
           || strcmp (name, "file_ppm_save") == 0 )
 
358
  else if (strcmp (name, PNM_SAVE_PROC) == 0 ||
 
359
           strcmp (name, PBM_SAVE_PROC) == 0 ||
 
360
           strcmp (name, PGM_SAVE_PROC) == 0 ||
 
361
           strcmp (name, PPM_SAVE_PROC) == 0)
325
362
    {
326
 
      image_ID      = param[1].data.d_int32;
327
 
      drawable_ID   = param[2].data.d_int32;
 
363
      image_ID    = param[1].data.d_int32;
 
364
      drawable_ID = param[2].data.d_int32;
328
365
 
329
366
      /*  eventually export the image */
330
367
      switch (run_mode)
331
 
        {
332
 
        case GIMP_RUN_INTERACTIVE:
333
 
        case GIMP_RUN_WITH_LAST_VALS:
334
 
          gimp_ui_init ("pnm", FALSE);
335
 
          if (strcmp (name, "file_pnm_save") == 0)
336
 
            export = gimp_export_image (&image_ID, &drawable_ID, "PNM",
337
 
                                        (GIMP_EXPORT_CAN_HANDLE_RGB |
338
 
                                         GIMP_EXPORT_CAN_HANDLE_GRAY |
339
 
                                         GIMP_EXPORT_CAN_HANDLE_INDEXED));
340
 
          else if (strcmp (name, "file_pgm_save") == 0)
341
 
            export = gimp_export_image (&image_ID, &drawable_ID, "PGM",
342
 
                                        (GIMP_EXPORT_CAN_HANDLE_GRAY));
 
368
        {
 
369
        case GIMP_RUN_INTERACTIVE:
 
370
        case GIMP_RUN_WITH_LAST_VALS:
 
371
          gimp_ui_init (PLUG_IN_BINARY, FALSE);
 
372
 
 
373
          if (strcmp (name, PNM_SAVE_PROC) == 0)
 
374
            {
 
375
              export = gimp_export_image (&image_ID, &drawable_ID, "PNM",
 
376
                                          GIMP_EXPORT_CAN_HANDLE_RGB  |
 
377
                                          GIMP_EXPORT_CAN_HANDLE_GRAY |
 
378
                                          GIMP_EXPORT_CAN_HANDLE_INDEXED);
 
379
            }
 
380
          else if (strcmp (name, PBM_SAVE_PROC) == 0)
 
381
            {
 
382
              export = gimp_export_image (&image_ID, &drawable_ID, "PBM",
 
383
                                          GIMP_EXPORT_CAN_HANDLE_BITMAP);
 
384
              pbm = TRUE;  /* gimp has no mono image type so hack it */
 
385
            }
 
386
          else if (strcmp (name, PGM_SAVE_PROC) == 0)
 
387
            {
 
388
              export = gimp_export_image (&image_ID, &drawable_ID, "PGM",
 
389
                                          GIMP_EXPORT_CAN_HANDLE_GRAY);
 
390
            }
343
391
          else
344
 
            export = gimp_export_image (&image_ID, &drawable_ID, "PPM",
345
 
                                        (GIMP_EXPORT_CAN_HANDLE_RGB |
346
 
                                         GIMP_EXPORT_CAN_HANDLE_INDEXED));
347
 
 
348
 
          if (export == GIMP_EXPORT_CANCEL)
349
 
            {
350
 
              values[0].data.d_status = GIMP_PDB_CANCEL;
351
 
              return;
352
 
            }
353
 
        break;
354
 
        default:
355
 
          break;
356
 
        }
 
392
            {
 
393
              export = gimp_export_image (&image_ID, &drawable_ID, "PPM",
 
394
                                          GIMP_EXPORT_CAN_HANDLE_RGB |
 
395
                                          GIMP_EXPORT_CAN_HANDLE_INDEXED);
 
396
            }
 
397
 
 
398
          if (export == GIMP_EXPORT_CANCEL)
 
399
            {
 
400
              values[0].data.d_status = GIMP_PDB_CANCEL;
 
401
              return;
 
402
            }
 
403
        break;
 
404
 
 
405
        default:
 
406
          break;
 
407
        }
357
408
 
358
409
      switch (run_mode)
359
 
        {
360
 
        case GIMP_RUN_INTERACTIVE:
361
 
          /*  Possibly retrieve data  */
362
 
          gimp_get_data (name, &psvals);
363
 
 
364
 
          /*  First acquire information with a dialog  */
365
 
          if (! save_dialog ())
366
 
            status = GIMP_PDB_CANCEL;
367
 
          break;
368
 
 
369
 
        case GIMP_RUN_NONINTERACTIVE:
370
 
          /*  Make sure all the arguments are there!  */
371
 
          if (nparams != 6)
372
 
            {
373
 
              status = GIMP_PDB_CALLING_ERROR;
374
 
            }
375
 
          else
376
 
            {
377
 
              psvals.raw = (param[5].data.d_int32) ? TRUE : FALSE;
378
 
            }
379
 
 
380
 
        case GIMP_RUN_WITH_LAST_VALS:
381
 
          /*  Possibly retrieve data  */
382
 
          gimp_get_data (name, &psvals);
383
 
          break;
384
 
 
385
 
        default:
386
 
          break;
387
 
        }
 
410
        {
 
411
        case GIMP_RUN_INTERACTIVE:
 
412
          /*  Possibly retrieve data  */
 
413
          gimp_get_data (name, &psvals);
 
414
 
 
415
          /*  First acquire information with a dialog  */
 
416
          if (! save_dialog ())
 
417
            status = GIMP_PDB_CANCEL;
 
418
          break;
 
419
 
 
420
        case GIMP_RUN_NONINTERACTIVE:
 
421
          /*  Make sure all the arguments are there!  */
 
422
          if (nparams != 6)
 
423
            {
 
424
              status = GIMP_PDB_CALLING_ERROR;
 
425
            }
 
426
          else
 
427
            {
 
428
              psvals.raw = (param[5].data.d_int32) ? TRUE : FALSE;
 
429
            }
 
430
 
 
431
        case GIMP_RUN_WITH_LAST_VALS:
 
432
          /*  Possibly retrieve data  */
 
433
          gimp_get_data (name, &psvals);
 
434
          break;
 
435
 
 
436
        default:
 
437
          break;
 
438
        }
388
439
 
389
440
      if (status == GIMP_PDB_SUCCESS)
390
 
        {
391
 
          if (save_image (param[3].data.d_string, image_ID, drawable_ID))
392
 
            {
393
 
              /*  Store psvals data  */
394
 
              gimp_set_data (name, &psvals, sizeof (PNMSaveVals));
395
 
            }
396
 
          else
397
 
            {
398
 
              status = GIMP_PDB_EXECUTION_ERROR;
399
 
            }
400
 
        }
 
441
        {
 
442
          if (save_image (param[3].data.d_string, image_ID, drawable_ID, pbm))
 
443
            {
 
444
              /*  Store psvals data  */
 
445
              gimp_set_data (name, &psvals, sizeof (PNMSaveVals));
 
446
            }
 
447
          else
 
448
            {
 
449
              status = GIMP_PDB_EXECUTION_ERROR;
 
450
            }
 
451
        }
401
452
 
402
453
      if (export == GIMP_EXPORT_EXPORT)
403
 
        gimp_image_delete (image_ID);
 
454
        gimp_image_delete (image_ID);
404
455
    }
405
456
  else
406
457
    {
413
464
static gint32
414
465
load_image (const gchar *filename)
415
466
{
416
 
  GimpPixelRgn pixel_rgn;
 
467
  GimpPixelRgn    pixel_rgn;
417
468
  gint32 volatile image_ID = -1;
418
 
  gint32 layer_ID;
419
 
  GimpDrawable *drawable;
420
 
  int fd;                       /* File descriptor */
421
 
  char *temp;
422
 
  char buf[BUFLEN];             /* buffer for random things like scanning */
423
 
  PNMInfo *pnminfo;
 
469
  gint32          layer_ID;
 
470
  GimpDrawable   *drawable;
 
471
  int             fd;           /* File descriptor */
 
472
  char            buf[BUFLEN];  /* buffer for random things like scanning */
 
473
  PNMInfo        *pnminfo;
424
474
  PNMScanner * volatile scan;
425
 
  int ctr;
 
475
  int             ctr;
426
476
 
427
477
  /* open the file */
428
 
  fd = open (filename, O_RDONLY | _O_BINARY);
 
478
  fd = g_open (filename, O_RDONLY | _O_BINARY, 0);
429
479
 
430
480
  if (fd == -1)
431
481
    {
434
484
      return -1;
435
485
    }
436
486
 
437
 
  temp = g_strdup_printf (_("Opening '%s'..."),
438
 
                          gimp_filename_to_utf8 (filename));
439
 
  gimp_progress_init (temp);
440
 
  g_free (temp);
 
487
  gimp_progress_init_printf (_("Opening '%s'"),
 
488
                             gimp_filename_to_utf8 (filename));
441
489
 
442
490
  /* allocate the necessary structures */
443
491
  pnminfo = g_new (PNMInfo, 1);
448
496
    {
449
497
      /* If we get here, we had a problem reading the file */
450
498
      if (scan)
451
 
        pnmscanner_destroy (scan);
 
499
        pnmscanner_destroy (scan);
452
500
      close (fd);
453
501
      g_free (pnminfo);
454
502
      if (image_ID != -1)
455
 
        gimp_image_delete (image_ID);
 
503
        gimp_image_delete (image_ID);
456
504
      return -1;
457
505
    }
458
506
 
459
 
  if (!(scan = pnmscanner_create(fd)))
460
 
    longjmp(pnminfo->jmpbuf,1);
 
507
  if (!(scan = pnmscanner_create (fd)))
 
508
    longjmp (pnminfo->jmpbuf, 1);
461
509
 
462
510
  /* Get magic number */
463
511
  pnmscanner_gettoken (scan, buf, BUFLEN);
464
 
  CHECK_FOR_ERROR(pnmscanner_eof(scan), pnminfo->jmpbuf,
465
 
                  _("PNM: Premature end of file."));
466
 
  CHECK_FOR_ERROR((buf[0] != 'P' || buf[2]), pnminfo->jmpbuf,
467
 
                  _("PNM: Invalid file."));
 
512
  CHECK_FOR_ERROR (pnmscanner_eof (scan), pnminfo->jmpbuf,
 
513
                   _("Premature end of file."));
 
514
  CHECK_FOR_ERROR ((buf[0] != 'P' || buf[2]), pnminfo->jmpbuf,
 
515
                   _("Invalid file."));
468
516
 
469
517
  /* Look up magic number to see what type of PNM this is */
470
 
  for (ctr=0; pnm_types[ctr].name; ctr++)
 
518
  for (ctr = 0; pnm_types[ctr].name; ctr++)
471
519
    if (buf[1] == pnm_types[ctr].name)
472
520
      {
473
 
        pnminfo->np        = pnm_types[ctr].np;
474
 
        pnminfo->asciibody = pnm_types[ctr].asciibody;
475
 
        pnminfo->maxval    = pnm_types[ctr].maxval;
476
 
        pnminfo->loader    = pnm_types[ctr].loader;
 
521
        pnminfo->np        = pnm_types[ctr].np;
 
522
        pnminfo->asciibody = pnm_types[ctr].asciibody;
 
523
        pnminfo->maxval    = pnm_types[ctr].maxval;
 
524
        pnminfo->loader    = pnm_types[ctr].loader;
477
525
      }
 
526
 
478
527
  if (!pnminfo->loader)
479
528
    {
480
529
      g_message (_("File not in a supported format."));
481
 
      longjmp(pnminfo->jmpbuf,1);
 
530
      longjmp (pnminfo->jmpbuf,1);
482
531
    }
483
532
 
484
 
  pnmscanner_gettoken(scan, buf, BUFLEN);
485
 
  CHECK_FOR_ERROR(pnmscanner_eof(scan), pnminfo->jmpbuf,
486
 
                  _("PNM: Premature end of file."));
487
 
  pnminfo->xres = g_ascii_isdigit(*buf)?atoi(buf):0;
488
 
  CHECK_FOR_ERROR(pnminfo->xres<=0, pnminfo->jmpbuf,
489
 
                  _("PNM: Invalid X resolution."));
490
 
 
491
 
  pnmscanner_gettoken(scan, buf, BUFLEN);
492
 
  CHECK_FOR_ERROR(pnmscanner_eof(scan), pnminfo->jmpbuf,
493
 
                  _("PNM: Premature end of file."));
494
 
  pnminfo->yres = g_ascii_isdigit(*buf)?atoi(buf):0;
495
 
  CHECK_FOR_ERROR(pnminfo->yres<=0, pnminfo->jmpbuf,
496
 
                  _("PNM: Invalid Y resolution."));
497
 
 
498
 
  if (pnminfo->np != 0)         /* pbm's don't have a maxval field */
 
533
  pnmscanner_gettoken (scan, buf, BUFLEN);
 
534
  CHECK_FOR_ERROR (pnmscanner_eof (scan), pnminfo->jmpbuf,
 
535
                   _("Premature end of file."));
 
536
  pnminfo->xres = g_ascii_isdigit(*buf) ? atoi (buf) : 0;
 
537
  CHECK_FOR_ERROR (pnminfo->xres <= 0, pnminfo->jmpbuf,
 
538
                   _("Invalid X resolution."));
 
539
 
 
540
  pnmscanner_gettoken (scan, buf, BUFLEN);
 
541
  CHECK_FOR_ERROR (pnmscanner_eof (scan), pnminfo->jmpbuf,
 
542
                   _("Premature end of file."));
 
543
  pnminfo->yres = g_ascii_isdigit (*buf) ? atoi (buf) : 0;
 
544
  CHECK_FOR_ERROR (pnminfo->yres <= 0, pnminfo->jmpbuf,
 
545
                   _("Invalid Y resolution."));
 
546
 
 
547
  if (pnminfo->np != 0)         /* pbm's don't have a maxval field */
499
548
    {
500
 
      pnmscanner_gettoken(scan, buf, BUFLEN);
501
 
      CHECK_FOR_ERROR(pnmscanner_eof(scan), pnminfo->jmpbuf,
502
 
                      _("PNM: Premature end of file."));
 
549
      pnmscanner_gettoken (scan, buf, BUFLEN);
 
550
      CHECK_FOR_ERROR (pnmscanner_eof (scan), pnminfo->jmpbuf,
 
551
                       _("Premature end of file."));
503
552
 
504
 
      pnminfo->maxval = g_ascii_isdigit(*buf)?atoi(buf):0;
505
 
      CHECK_FOR_ERROR(((pnminfo->maxval<=0)
506
 
                       || (pnminfo->maxval>255 && !pnminfo->asciibody)),
507
 
                      pnminfo->jmpbuf,
508
 
                      _("PNM: Invalid maximum value."));
 
553
      pnminfo->maxval = g_ascii_isdigit (*buf) ? atoi (buf) : 0;
 
554
      CHECK_FOR_ERROR (((pnminfo->maxval<=0)
 
555
                        || (pnminfo->maxval>255 && !pnminfo->asciibody)),
 
556
                       pnminfo->jmpbuf,
 
557
                       _("Invalid maximum value."));
509
558
    }
510
559
 
511
560
  /* Create a new image of the proper size and associate the filename with it.
512
561
   */
513
562
  image_ID = gimp_image_new (pnminfo->xres, pnminfo->yres,
514
 
                             (pnminfo->np >= 3) ? GIMP_RGB : GIMP_GRAY);
 
563
                             (pnminfo->np >= 3) ? GIMP_RGB : GIMP_GRAY);
515
564
  gimp_image_set_filename (image_ID, filename);
516
565
 
517
566
  layer_ID = gimp_layer_new (image_ID, _("Background"),
518
 
                             pnminfo->xres, pnminfo->yres,
519
 
                             (pnminfo->np >= 3) ? GIMP_RGB_IMAGE : GIMP_GRAY_IMAGE,
520
 
                             100, GIMP_NORMAL_MODE);
 
567
                             pnminfo->xres, pnminfo->yres,
 
568
                             (pnminfo->np >= 3) ? GIMP_RGB_IMAGE : GIMP_GRAY_IMAGE,
 
569
                             100, GIMP_NORMAL_MODE);
521
570
  gimp_image_add_layer (image_ID, layer_ID, 0);
522
571
 
523
572
  drawable = gimp_drawable_get (layer_ID);
524
573
  gimp_pixel_rgn_init (&pixel_rgn, drawable,
525
 
                       0, 0, drawable->width, drawable->height, TRUE, FALSE);
 
574
                       0, 0, drawable->width, drawable->height, TRUE, FALSE);
526
575
 
527
576
  pnminfo->loader (scan, pnminfo, &pixel_rgn);
528
577
 
543
592
}
544
593
 
545
594
static void
546
 
pnm_load_ascii (PNMScanner *scan,
547
 
                PNMInfo    *info,
548
 
                GimpPixelRgn  *pixel_rgn)
 
595
pnm_load_ascii (PNMScanner   *scan,
 
596
                PNMInfo      *info,
 
597
                GimpPixelRgn *pixel_rgn)
549
598
{
550
 
  unsigned char *data, *d;
551
 
  int            x, y, i, b;
552
 
  int            start, end, scanlines;
553
 
  int            np;
554
 
  char           buf[BUFLEN];
 
599
  guchar *data, *d;
 
600
  gint    x, y, i, b;
 
601
  gint    start, end, scanlines;
 
602
  gint    np;
 
603
  gchar   buf[BUFLEN];
555
604
 
556
 
  np = (info->np)?(info->np):1;
557
 
  data = g_malloc (gimp_tile_height () * info->xres * np);
 
605
  np = (info->np) ? (info->np) : 1;
 
606
  data = g_new (guchar, gimp_tile_height () * info->xres * np);
558
607
 
559
608
  /* Buffer reads to increase performance */
560
 
  pnmscanner_createbuffer(scan, 4096);
 
609
  pnmscanner_createbuffer (scan, 4096);
561
610
 
562
611
  for (y = 0; y < info->yres; )
563
612
    {
568
617
      d = data;
569
618
 
570
619
      for (i = 0; i < scanlines; i++)
571
 
        for (x = 0; x < info->xres; x++)
572
 
          {
573
 
            for (b = 0; b < np; b++)
574
 
              {
575
 
                /* Truncated files will just have all 0's at the end of the images */
576
 
                CHECK_FOR_ERROR(pnmscanner_eof(scan), info->jmpbuf,
577
 
                                _("PNM: Premature end of file."));
578
 
                if (info->np)
579
 
                  pnmscanner_gettoken(scan, buf, BUFLEN);
580
 
                else
581
 
                  pnmscanner_getsmalltoken(scan, buf);
582
 
                switch (info->maxval)
583
 
                  {
584
 
                  case 255:
585
 
                    d[b] = g_ascii_isdigit (*buf) ? atoi (buf) : 0;
586
 
                    break;
587
 
                  case 1:
588
 
                    d[b] = (*buf=='0')?0xff:0x00;
589
 
                    break;
590
 
                  default:
591
 
                    d[b] = (255.0 * (((gdouble)(g_ascii_isdigit (*buf) ? atoi (buf) : 0))
 
620
        for (x = 0; x < info->xres; x++)
 
621
          {
 
622
            for (b = 0; b < np; b++)
 
623
              {
 
624
                /* Truncated files will just have all 0's at the end of the images */
 
625
                if (pnmscanner_eof (scan))
 
626
                  g_message (_("Premature end of file."));
 
627
                if (info->np)
 
628
                  pnmscanner_gettoken (scan, buf, BUFLEN);
 
629
                else
 
630
                  pnmscanner_getsmalltoken (scan, buf);
 
631
 
 
632
                switch (info->maxval)
 
633
                  {
 
634
                  case 255:
 
635
                    d[b] = g_ascii_isdigit (*buf) ? atoi (buf) : 0;
 
636
                    break;
 
637
 
 
638
                  case 1:
 
639
                    d[b] = (*buf == '0') ? 0xff : 0x00;
 
640
                    break;
 
641
 
 
642
                  default:
 
643
                    d[b] = (255.0 * (((gdouble)(g_ascii_isdigit (*buf) ? atoi (buf) : 0))
592
644
                                     / (gdouble)(info->maxval)));
593
 
                  }
594
 
              }
 
645
                  }
 
646
              }
595
647
 
596
 
            d += np;
597
 
          }
 
648
            d += np;
 
649
          }
598
650
 
599
651
      gimp_progress_update ((double) y / (double) info->yres);
600
652
      gimp_pixel_rgn_set_rect (pixel_rgn, data, 0, y, info->xres, scanlines);
601
653
      y += scanlines;
602
654
    }
603
655
 
 
656
  gimp_progress_update (1.0);
 
657
 
604
658
  g_free (data);
605
659
}
606
660
 
607
661
static void
608
 
pnm_load_raw (PNMScanner *scan,
609
 
              PNMInfo    *info,
610
 
              GimpPixelRgn  *pixel_rgn)
 
662
pnm_load_raw (PNMScanner   *scan,
 
663
              PNMInfo      *info,
 
664
              GimpPixelRgn *pixel_rgn)
611
665
{
612
666
  guchar *data, *d;
613
667
  gint    x, y, i;
614
668
  gint    start, end, scanlines;
615
669
  gint    fd;
616
670
 
617
 
  data = g_malloc (gimp_tile_height () * info->xres * info->np);
618
 
  fd = pnmscanner_fd(scan);
 
671
  data = g_new (guchar, gimp_tile_height () * info->xres * info->np);
 
672
  fd = pnmscanner_fd (scan);
619
673
 
620
674
  for (y = 0; y < info->yres; )
621
675
    {
626
680
      d = data;
627
681
 
628
682
      for (i = 0; i < scanlines; i++)
629
 
        {
630
 
          CHECK_FOR_ERROR((info->xres*info->np
631
 
                           != read(fd, d, info->xres*info->np)),
632
 
                          info->jmpbuf,
633
 
                          _("PNM: Premature end of file."));
 
683
        {
 
684
          CHECK_FOR_ERROR ((info->xres*info->np
 
685
                            != read(fd, d, info->xres*info->np)),
 
686
                           info->jmpbuf,
 
687
                           _("Premature end of file."));
634
688
 
635
 
          if (info->maxval != 255)      /* Normalize if needed */
636
 
            {
637
 
              for (x = 0; x < info->xres * info->np; x++)
638
 
                {
 
689
          if (info->maxval != 255)      /* Normalize if needed */
 
690
            {
 
691
              for (x = 0; x < info->xres * info->np; x++)
 
692
                {
639
693
                  d[x] = MIN (d[x], info->maxval); /* guard against overflow */
640
694
                  d[x] = 255.0 * (gdouble) d[x] / (gdouble) info->maxval;
641
695
                }
642
696
            }
643
697
 
644
 
          d += info->xres * info->np;
645
 
        }
 
698
          d += info->xres * info->np;
 
699
        }
646
700
 
647
701
      gimp_progress_update ((double) y / (double) info->yres);
648
702
      gimp_pixel_rgn_set_rect (pixel_rgn, data, 0, y, info->xres, scanlines);
649
703
      y += scanlines;
650
704
    }
651
705
 
 
706
  gimp_progress_update (1.0);
 
707
 
652
708
  g_free (data);
653
709
}
654
710
 
655
711
static void
656
 
pnm_load_rawpbm (PNMScanner *scan,
657
 
                 PNMInfo    *info,
658
 
                 GimpPixelRgn  *pixel_rgn)
 
712
pnm_load_rawpbm (PNMScanner   *scan,
 
713
                 PNMInfo      *info,
 
714
                 GimpPixelRgn *pixel_rgn)
659
715
{
660
 
  unsigned char *buf;
661
 
  unsigned char  curbyte;
662
 
  unsigned char *data, *d;
663
 
  int            x, y, i;
664
 
  int            start, end, scanlines;
665
 
  int            fd;
666
 
  int            rowlen, bufpos;
 
716
  guchar *buf;
 
717
  guchar  curbyte;
 
718
  guchar *data, *d;
 
719
  gint    x, y, i;
 
720
  gint    start, end, scanlines;
 
721
  gint    fd;
 
722
  gint    rowlen, bufpos;
667
723
 
668
 
  fd = pnmscanner_fd(scan);
669
 
  rowlen = (int)ceil((double)(info->xres)/8.0);
670
 
  data = g_malloc (gimp_tile_height () * info->xres);
671
 
  buf = g_new (unsigned char, rowlen);
 
724
  fd = pnmscanner_fd (scan);
 
725
  rowlen = (int)ceil ((double)(info->xres)/8.0);
 
726
  data = g_new (guchar, gimp_tile_height () * info->xres);
 
727
  buf = g_new (guchar, rowlen);
672
728
 
673
729
  for (y = 0; y < info->yres; )
674
730
    {
679
735
      d = data;
680
736
 
681
737
      for (i = 0; i < scanlines; i++)
682
 
        {
683
 
          CHECK_FOR_ERROR((rowlen != read(fd, buf, rowlen)),
684
 
                          info->jmpbuf, _("PNM: Error reading file."));
685
 
          bufpos = 0;
686
 
          curbyte = buf[0];
687
 
 
688
 
          for (x = 0; x < info->xres; x++)
689
 
            {
690
 
              if ((x % 8) == 0)
691
 
                curbyte = buf[bufpos++];
692
 
              d[x] = (curbyte&0x80) ? 0x00 : 0xff;
693
 
              curbyte <<= 1;
694
 
            }
695
 
 
696
 
          d += info->xres;
697
 
        }
 
738
        {
 
739
          CHECK_FOR_ERROR ((rowlen != read(fd, buf, rowlen)),
 
740
                           info->jmpbuf, _("Error reading file."));
 
741
          bufpos = 0;
 
742
          curbyte = buf[0];
 
743
 
 
744
          for (x = 0; x < info->xres; x++)
 
745
            {
 
746
              if ((x % 8) == 0)
 
747
                curbyte = buf[bufpos++];
 
748
              d[x] = (curbyte & 0x80) ? 0x00 : 0xff;
 
749
              curbyte <<= 1;
 
750
            }
 
751
 
 
752
          d += info->xres;
 
753
        }
698
754
 
699
755
      gimp_progress_update ((double) y / (double) info->yres);
700
756
      gimp_pixel_rgn_set_rect (pixel_rgn, data, 0, y, info->xres, scanlines);
701
757
      y += scanlines;
702
758
    }
703
759
 
704
 
  g_free(buf);
 
760
  gimp_progress_update (1.0);
 
761
 
 
762
  g_free (buf);
705
763
  g_free (data);
706
764
}
707
765
 
 
766
/* Writes out mono raw rows */
 
767
static void
 
768
pnmsaverow_raw_pbm (PNMRowInfo *ri,
 
769
                   guchar     *data)
 
770
{
 
771
  gint    b, i, p = 0;
 
772
  gchar  *rbcur = ri->rowbuf;
 
773
  gint32  len = (int)ceil ((double)(ri->xres)/8.0);
 
774
 
 
775
  for (b = 0; b < len; b++) /* each output byte */
 
776
    {
 
777
      *(rbcur+b) = 0;
 
778
      for (i = 0; i < 8; i++) /* each bit in this byte */
 
779
        {
 
780
          if (p >= ri->xres)
 
781
              break;
 
782
 
 
783
          if (*(data+p) == 0)
 
784
              *(rbcur+b) |= (char) (1 << (7 - i));
 
785
 
 
786
          p++;
 
787
        }
 
788
    }
 
789
 
 
790
  write (ri->fd, ri->rowbuf, len);
 
791
}
 
792
 
 
793
/* Writes out mono ascii rows */
 
794
static void
 
795
pnmsaverow_ascii_pbm (PNMRowInfo *ri,
 
796
                      guchar     *data)
 
797
{
 
798
  static gint  line_len = 0;  /* ascii pbm lines must be <= 70 chars long */
 
799
  gint32       len = 0;
 
800
  gint         i;
 
801
  gchar       *rbcur = ri->rowbuf;
 
802
 
 
803
  for (i = 0; i < ri->xres; i++)
 
804
    {
 
805
      if (line_len > 69)
 
806
        {
 
807
          *(rbcur+i) = '\n';
 
808
          line_len = 0;
 
809
          len++;
 
810
          rbcur++;
 
811
        }
 
812
 
 
813
      if (*(data+i) == 0)
 
814
        *(rbcur+i) = '1';
 
815
      else
 
816
        *(rbcur+i) = '0';
 
817
 
 
818
      line_len++;
 
819
      len++;
 
820
    }
 
821
 
 
822
  *(rbcur+i) = '\n';
 
823
 
 
824
  write (ri->fd, ri->rowbuf, len);
 
825
}
 
826
 
708
827
/* Writes out RGB and greyscale raw rows */
709
828
static void
710
 
pnmsaverow_raw (PNMRowInfo    *ri,
711
 
                unsigned char *data)
 
829
pnmsaverow_raw (PNMRowInfo *ri,
 
830
                guchar     *data)
712
831
{
713
 
  write(ri->fd, data, ri->xres*ri->np);
 
832
  write (ri->fd, data, ri->xres*ri->np);
714
833
}
715
834
 
716
835
/* Writes out indexed raw rows */
717
836
static void
718
 
pnmsaverow_raw_indexed (PNMRowInfo    *ri,
719
 
                        unsigned char *data)
 
837
pnmsaverow_raw_indexed (PNMRowInfo *ri,
 
838
                        guchar     *data)
720
839
{
721
 
  int i;
722
 
  char *rbcur = ri->rowbuf;
 
840
  gint   i;
 
841
  gchar *rbcur = ri->rowbuf;
723
842
 
724
843
  for (i = 0; i < ri->xres; i++)
725
844
    {
727
846
      *(rbcur++) = ri->grn[*data];
728
847
      *(rbcur++) = ri->blu[*(data++)];
729
848
    }
730
 
  write(ri->fd, ri->rowbuf, ri->xres*3);
 
849
 
 
850
  write (ri->fd, ri->rowbuf, ri->xres * 3);
731
851
}
732
852
 
733
853
/* Writes out RGB and greyscale ascii rows */
734
854
static void
735
 
pnmsaverow_ascii (PNMRowInfo    *ri,
736
 
                  unsigned char *data)
 
855
pnmsaverow_ascii (PNMRowInfo *ri,
 
856
                  guchar     *data)
737
857
{
738
 
  int i;
739
 
  char *rbcur = ri->rowbuf;
 
858
  gint   i;
 
859
  gchar *rbcur = ri->rowbuf;
740
860
 
741
861
  for (i = 0; i < ri->xres*ri->np; i++)
742
862
    {
743
 
      sprintf((char *) rbcur,"%d\n", 0xff & *(data++));
744
 
      rbcur += strlen(rbcur);
 
863
      sprintf ((char *) rbcur,"%d\n", 0xff & *(data++));
 
864
      rbcur += strlen (rbcur);
745
865
    }
746
 
  write(ri->fd, ri->rowbuf, strlen((char *) ri->rowbuf));
 
866
 
 
867
  write (ri->fd, ri->rowbuf, strlen ((char *) ri->rowbuf));
747
868
}
748
869
 
749
870
/* Writes out RGB and greyscale ascii rows */
750
871
static void
751
 
pnmsaverow_ascii_indexed (PNMRowInfo    *ri,
752
 
                          unsigned char *data)
 
872
pnmsaverow_ascii_indexed (PNMRowInfo *ri,
 
873
                          guchar     *data)
753
874
{
754
 
  int i;
755
 
  char *rbcur = ri->rowbuf;
 
875
  gint   i;
 
876
  gchar *rbcur = ri->rowbuf;
756
877
 
757
878
  for (i = 0; i < ri->xres; i++)
758
879
    {
759
 
      sprintf((char *) rbcur,"%d\n", 0xff & ri->red[*(data)]);
760
 
      rbcur += strlen(rbcur);
761
 
      sprintf((char *) rbcur,"%d\n", 0xff & ri->grn[*(data)]);
762
 
      rbcur += strlen(rbcur);
763
 
      sprintf((char *) rbcur,"%d\n", 0xff & ri->blu[*(data++)]);
764
 
      rbcur += strlen(rbcur);
 
880
      sprintf ((char *) rbcur,"%d\n", 0xff & ri->red[*(data)]);
 
881
      rbcur += strlen (rbcur);
 
882
      sprintf ((char *) rbcur,"%d\n", 0xff & ri->grn[*(data)]);
 
883
      rbcur += strlen (rbcur);
 
884
      sprintf ((char *) rbcur,"%d\n", 0xff & ri->blu[*(data++)]);
 
885
      rbcur += strlen (rbcur);
765
886
    }
766
 
  write(ri->fd, ri->rowbuf, strlen((char *) ri->rowbuf));
 
887
 
 
888
  write (ri->fd, ri->rowbuf, strlen ((char *) ri->rowbuf));
767
889
}
768
890
 
769
 
static gint
 
891
static gboolean
770
892
save_image (const gchar *filename,
771
 
            gint32       image_ID,
772
 
            gint32       drawable_ID)
 
893
            gint32       image_ID,
 
894
            gint32       drawable_ID,
 
895
            gboolean     pbm)
773
896
{
774
 
  GimpPixelRgn pixel_rgn;
775
 
  GimpDrawable *drawable;
776
 
  GimpImageType drawable_type;
777
 
  PNMRowInfo rowinfo;
778
 
  void (*saverow) (PNMRowInfo *, unsigned char *) = NULL;
779
 
  unsigned char red[256];
780
 
  unsigned char grn[256];
781
 
  unsigned char blu[256];
782
 
  unsigned char *data, *d;
783
 
  char *rowbuf;
784
 
  char buf[BUFLEN];
785
 
  char *temp;
786
 
  int np = 0;
787
 
  int xres, yres;
788
 
  int ypos, yend;
789
 
  int rowbufsize = 0;
790
 
  int fd;
 
897
  GimpPixelRgn   pixel_rgn;
 
898
  GimpDrawable  *drawable;
 
899
  GimpImageType  drawable_type;
 
900
  PNMRowInfo     rowinfo;
 
901
  void (*saverow) (PNMRowInfo *, guchar *) = NULL;
 
902
  guchar         red[256];
 
903
  guchar         grn[256];
 
904
  guchar         blu[256];
 
905
  guchar        *data, *d;
 
906
  gchar         *rowbuf;
 
907
  gchar          buf[BUFLEN];
 
908
  gint           np = 0;
 
909
  gint           xres, yres;
 
910
  gint           ypos, yend;
 
911
  gint           rowbufsize = 0;
 
912
  gint           fd;
791
913
 
792
914
  drawable = gimp_drawable_get (drawable_ID);
793
915
  drawable_type = gimp_drawable_type (drawable_ID);
794
916
  gimp_pixel_rgn_init (&pixel_rgn, drawable,
795
 
                       0, 0, drawable->width, drawable->height, FALSE, FALSE);
 
917
                       0, 0, drawable->width, drawable->height, FALSE, FALSE);
796
918
 
797
919
  /*  Make sure we're not saving an image with an alpha channel  */
798
920
  if (gimp_drawable_has_alpha (drawable_ID))
799
921
    {
800
 
      g_message (_("PNM save cannot handle images with alpha channels."));
 
922
      g_message (_("Cannot save images with alpha channel."));
801
923
      return FALSE;
802
924
    }
803
925
 
804
926
  /* open the file */
805
 
  fd = open (filename, O_WRONLY | O_CREAT | O_TRUNC | _O_BINARY, 0644);
 
927
  fd = g_open (filename, O_WRONLY | O_CREAT | O_TRUNC | _O_BINARY, 0644);
806
928
 
807
929
  if (fd == -1)
808
930
    {
811
933
      return FALSE;
812
934
    }
813
935
 
814
 
  temp = g_strdup_printf (_("Saving '%s'..."),
815
 
                          gimp_filename_to_utf8 (filename));
816
 
  gimp_progress_init (temp);
817
 
  g_free (temp);
 
936
  gimp_progress_init_printf (_("Saving '%s'"),
 
937
                             gimp_filename_to_utf8 (filename));
818
938
 
819
939
  xres = drawable->width;
820
940
  yres = drawable->height;
821
941
 
822
942
  /* write out magic number */
823
943
  if (psvals.raw == FALSE)
824
 
    switch (drawable_type)
825
 
      {
826
 
      case GIMP_GRAY_IMAGE:
827
 
        write(fd, "P2\n", 3);
828
 
        np = 1;
829
 
        rowbufsize = xres * 4;
830
 
        saverow = pnmsaverow_ascii;
831
 
        break;
832
 
      case GIMP_RGB_IMAGE:
833
 
        write(fd, "P3\n", 3);
834
 
        np = 3;
835
 
        rowbufsize = xres * 12;
836
 
        saverow = pnmsaverow_ascii;
837
 
        break;
838
 
      case GIMP_INDEXED_IMAGE:
839
 
        write(fd, "P3\n", 3);
840
 
        np = 1;
841
 
        rowbufsize = xres * 12;
842
 
        saverow = pnmsaverow_ascii_indexed;
843
 
        break;
844
 
      default:
845
 
        g_warning ("pnm: unknown drawable_type\n");
846
 
        return FALSE;
847
 
      }
 
944
    {
 
945
      if (pbm)
 
946
        {
 
947
          write (fd, "P1\n", 3);
 
948
          np = 0;
 
949
          rowbufsize = xres + (int) (xres / 70) + 1;
 
950
          saverow = pnmsaverow_ascii_pbm;
 
951
        }
 
952
      else
 
953
        {
 
954
          switch (drawable_type)
 
955
            {
 
956
            case GIMP_GRAY_IMAGE:
 
957
              write (fd, "P2\n", 3);
 
958
              np = 1;
 
959
              rowbufsize = xres * 4;
 
960
              saverow = pnmsaverow_ascii;
 
961
              break;
 
962
 
 
963
            case GIMP_RGB_IMAGE:
 
964
              write (fd, "P3\n", 3);
 
965
              np = 3;
 
966
              rowbufsize = xres * 12;
 
967
              saverow = pnmsaverow_ascii;
 
968
              break;
 
969
 
 
970
            case GIMP_INDEXED_IMAGE:
 
971
              write (fd, "P3\n", 3);
 
972
              np = 1;
 
973
              rowbufsize = xres * 12;
 
974
              saverow = pnmsaverow_ascii_indexed;
 
975
              break;
 
976
 
 
977
            default:
 
978
              g_warning ("pnm: unknown drawable_type\n");
 
979
              return FALSE;
 
980
            }
 
981
        }
 
982
    }
848
983
  else if (psvals.raw == TRUE)
849
 
    switch (drawable_type)
850
 
      {
851
 
      case GIMP_GRAY_IMAGE:
852
 
        write(fd, "P5\n", 3);
853
 
        np = 1;
854
 
        rowbufsize = xres;
855
 
        saverow = pnmsaverow_raw;
856
 
        break;
857
 
      case GIMP_RGB_IMAGE:
858
 
        write(fd, "P6\n", 3);
859
 
        np = 3;
860
 
        rowbufsize = xres * 3;
861
 
        saverow = pnmsaverow_raw;
862
 
        break;
863
 
      case GIMP_INDEXED_IMAGE:
864
 
        write(fd, "P6\n", 3);
865
 
        np = 1;
866
 
        rowbufsize = xres * 3;
867
 
        saverow = pnmsaverow_raw_indexed;
868
 
        break;
869
 
      default:
870
 
        g_warning ("pnm: unknown drawable_type\n");
871
 
        return FALSE;
 
984
    {
 
985
      if (pbm)
 
986
        {
 
987
          write (fd, "P4\n", 3);
 
988
          np = 0;
 
989
          rowbufsize = (int)ceil ((double)(xres)/8.0);
 
990
          saverow = pnmsaverow_raw_pbm;
 
991
        }
 
992
      else
 
993
        {
 
994
          switch (drawable_type)
 
995
            {
 
996
            case GIMP_GRAY_IMAGE:
 
997
              write (fd, "P5\n", 3);
 
998
              np = 1;
 
999
              rowbufsize = xres;
 
1000
              saverow = pnmsaverow_raw;
 
1001
              break;
 
1002
 
 
1003
            case GIMP_RGB_IMAGE:
 
1004
              write (fd, "P6\n", 3);
 
1005
              np = 3;
 
1006
              rowbufsize = xres * 3;
 
1007
              saverow = pnmsaverow_raw;
 
1008
              break;
 
1009
 
 
1010
            case GIMP_INDEXED_IMAGE:
 
1011
              write (fd, "P6\n", 3);
 
1012
              np = 1;
 
1013
              rowbufsize = xres * 3;
 
1014
              saverow = pnmsaverow_raw_indexed;
 
1015
              break;
 
1016
 
 
1017
            default:
 
1018
              g_warning ("pnm: unknown drawable_type\n");
 
1019
              return FALSE;
 
1020
            }
 
1021
        }
872
1022
    }
873
1023
 
874
 
  if (drawable_type == GIMP_INDEXED_IMAGE)
 
1024
  if (drawable_type == GIMP_INDEXED_IMAGE && !pbm)
875
1025
    {
876
1026
      gint    i;
877
1027
      guchar *cmap;
880
1030
      cmap = gimp_image_get_colormap (image_ID, &colors);
881
1031
 
882
1032
      for (i = 0; i < colors; i++)
883
 
        {
884
 
          red[i] = *cmap++;
885
 
          grn[i] = *cmap++;
886
 
          blu[i] = *cmap++;
887
 
        }
 
1033
        {
 
1034
          red[i] = *cmap++;
 
1035
          grn[i] = *cmap++;
 
1036
          blu[i] = *cmap++;
 
1037
        }
888
1038
 
889
1039
      rowinfo.red = red;
890
1040
      rowinfo.grn = grn;
898
1048
  write (fd, SAVE_COMMENT_STRING, strlen (SAVE_COMMENT_STRING));
899
1049
 
900
1050
  /* write out resolution and maxval */
901
 
  sprintf (buf, "%d %d\n255\n", xres, yres);
 
1051
  if (pbm)
 
1052
    sprintf (buf, "%d %d\n", xres, yres);
 
1053
  else
 
1054
    sprintf (buf, "%d %d\n255\n", xres, yres);
 
1055
 
902
1056
  write (fd, buf, strlen(buf));
903
1057
 
904
 
  rowbuf = g_malloc (rowbufsize + 1);
 
1058
  rowbuf = g_new (gchar, rowbufsize + 1);
905
1059
  rowinfo.fd = fd;
906
1060
  rowinfo.rowbuf = rowbuf;
907
1061
  rowinfo.xres = xres;
913
1067
  for (ypos = 0; ypos < yres; ypos++)
914
1068
    {
915
1069
      if ((ypos % gimp_tile_height ()) == 0)
916
 
        {
917
 
          yend = ypos + gimp_tile_height ();
918
 
          yend = MIN (yend, yres);
919
 
          gimp_pixel_rgn_get_rect (&pixel_rgn, data,
920
 
                                   0, ypos, xres, (yend - ypos));
921
 
          d = data;
922
 
        }
 
1070
        {
 
1071
          yend = ypos + gimp_tile_height ();
 
1072
          yend = MIN (yend, yres);
 
1073
          gimp_pixel_rgn_get_rect (&pixel_rgn, data,
 
1074
                                   0, ypos, xres, (yend - ypos));
 
1075
          d = data;
 
1076
        }
923
1077
 
924
1078
      (*saverow)(&rowinfo, d);
925
 
      d += xres*np;
 
1079
      d += xres * (np ? np : 1);
926
1080
 
927
1081
      if ((ypos % 20) == 0)
928
 
        gimp_progress_update ((double) ypos / (double) yres);
 
1082
        gimp_progress_update ((double) ypos / (double) yres);
929
1083
    }
930
1084
 
 
1085
  gimp_progress_update (1.0);
 
1086
 
931
1087
  /* close the file */
932
1088
  close (fd);
933
1089
 
942
1098
static gint
943
1099
save_dialog (void)
944
1100
{
945
 
  GtkWidget *dlg;
 
1101
  GtkWidget *dialog;
946
1102
  GtkWidget *frame;
947
1103
  gboolean   run;
948
1104
 
949
 
  dlg = gimp_dialog_new (_("Save as PNM"), "pnm",
950
 
                         NULL, 0,
951
 
                         gimp_standard_help_func, "file-pnm-save",
952
 
 
953
 
                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
954
 
                         GTK_STOCK_OK,     GTK_RESPONSE_OK,
955
 
 
956
 
                         NULL);
 
1105
  dialog = gimp_dialog_new (_("Save as PNM"), PLUG_IN_BINARY,
 
1106
                            NULL, 0,
 
1107
                            gimp_standard_help_func, PNM_SAVE_PROC,
 
1108
 
 
1109
                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
1110
                            GTK_STOCK_SAVE,   GTK_RESPONSE_OK,
 
1111
 
 
1112
                            NULL);
 
1113
 
 
1114
  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
 
1115
                                           GTK_RESPONSE_OK,
 
1116
                                           GTK_RESPONSE_CANCEL,
 
1117
                                           -1);
 
1118
 
 
1119
  gimp_window_set_transient (GTK_WINDOW (dialog));
957
1120
 
958
1121
  /*  file save type  */
959
1122
  frame = gimp_int_radio_group_new (TRUE, _("Data formatting"),
960
 
                                    G_CALLBACK (gimp_radio_button_update),
961
 
                                    &psvals.raw, psvals.raw,
962
 
 
963
 
                                    _("Raw"),   TRUE,  NULL,
964
 
                                    _("Ascii"), FALSE, NULL,
965
 
 
966
 
                                    NULL);
 
1123
                                    G_CALLBACK (gimp_radio_button_update),
 
1124
                                    &psvals.raw, psvals.raw,
 
1125
 
 
1126
                                    _("Raw"),   TRUE,  NULL,
 
1127
                                    _("Ascii"), FALSE, NULL,
 
1128
 
 
1129
                                    NULL);
967
1130
  gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
968
 
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, FALSE, TRUE, 0);
969
 
 
 
1131
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
 
1132
                      frame, FALSE, TRUE, 0);
970
1133
  gtk_widget_show (frame);
971
1134
 
972
 
  gtk_widget_show (dlg);
973
 
 
974
 
  run = (gimp_dialog_run (GIMP_DIALOG (dlg)) == GTK_RESPONSE_OK);
975
 
 
976
 
  gtk_widget_destroy (dlg);
 
1135
  gtk_widget_show (dialog);
 
1136
 
 
1137
  run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
 
1138
 
 
1139
  gtk_widget_destroy (dialog);
977
1140
 
978
1141
  return run;
979
1142
}
993
1156
  s = g_new (PNMScanner, 1);
994
1157
  s->fd = fd;
995
1158
  s->inbuf = NULL;
996
 
  s->eof = !read(s->fd, &(s->cur), 1);
997
 
  return(s);
 
1159
  s->eof = !read (s->fd, &(s->cur), 1);
 
1160
  return s;
998
1161
}
999
1162
 
1000
1163
/* pnmscanner_destroy ---
1003
1166
static void
1004
1167
pnmscanner_destroy (PNMScanner *s)
1005
1168
{
1006
 
  if (s->inbuf) g_free(s->inbuf);
1007
 
  g_free(s);
 
1169
  if (s->inbuf)
 
1170
    g_free (s->inbuf);
 
1171
  g_free (s);
1008
1172
}
1009
1173
 
1010
1174
/* pnmscanner_createbuffer ---
1012
1176
 */
1013
1177
static void
1014
1178
pnmscanner_createbuffer (PNMScanner *s,
1015
 
                         gint        bufsize)
 
1179
                         gint        bufsize)
1016
1180
{
1017
 
  s->inbuf = g_new (char, bufsize);
 
1181
  s->inbuf = g_new (gchar, bufsize);
1018
1182
  s->inbufsize = bufsize;
1019
1183
  s->inbufpos = 0;
1020
 
  s->inbufvalidsize = read(s->fd, s->inbuf, bufsize);
 
1184
  s->inbufvalidsize = read (s->fd, s->inbuf, bufsize);
1021
1185
}
1022
1186
 
1023
1187
/* pnmscanner_gettoken ---
1025
1189
 */
1026
1190
static void
1027
1191
pnmscanner_gettoken (PNMScanner *s,
1028
 
                     gchar      *buf,
1029
 
                     gint        bufsize)
 
1192
                     gchar      *buf,
 
1193
                     gint        bufsize)
1030
1194
{
1031
1195
  int ctr=0;
1032
1196
 
1037
1201
         (ctr < bufsize))
1038
1202
    {
1039
1203
      buf[ctr++] = s->cur;
1040
 
      pnmscanner_getchar(s);
 
1204
      pnmscanner_getchar (s);
1041
1205
    }
1042
1206
  buf[ctr] = '\0';
1043
1207
}
1047
1211
 */
1048
1212
static void
1049
1213
pnmscanner_getsmalltoken (PNMScanner *s,
1050
 
                          gchar      *buf)
 
1214
                          gchar      *buf)
1051
1215
{
1052
 
  pnmscanner_eatwhitespace(s);
 
1216
  pnmscanner_eatwhitespace (s);
1053
1217
  if (!(s->eof) && !g_ascii_isspace (s->cur) && (s->cur != '#'))
1054
1218
    {
1055
1219
      *buf = s->cur;
1056
 
      pnmscanner_getchar(s);
 
1220
      pnmscanner_getchar (s);
1057
1221
    }
1058
1222
}
1059
1223
 
1067
1231
    {
1068
1232
      s->cur = s->inbuf[s->inbufpos++];
1069
1233
      if (s->inbufpos >= s->inbufvalidsize)
1070
 
        {
1071
 
          if (s->inbufsize > s->inbufvalidsize)
1072
 
            s->eof = 1;
1073
 
          else
1074
 
            s->inbufvalidsize = read(s->fd, s->inbuf, s->inbufsize);
1075
 
          s->inbufpos = 0;
1076
 
        }
 
1234
        {
 
1235
          if (s->inbufpos > s->inbufvalidsize)
 
1236
            s->eof = 1;
 
1237
          else
 
1238
            s->inbufvalidsize = read (s->fd, s->inbuf, s->inbufsize);
 
1239
          s->inbufpos = 0;
 
1240
        }
1077
1241
    }
1078
1242
  else
1079
 
    s->eof = !read(s->fd, &(s->cur), 1);
 
1243
    s->eof = !read (s->fd, &(s->cur), 1);
1080
1244
}
1081
1245
 
1082
1246
/* pnmscanner_eatwhitespace ---
1091
1255
  while (!(s->eof) && (state != -1))
1092
1256
    {
1093
1257
      switch (state)
1094
 
        {
1095
 
        case 0:  /* in whitespace */
1096
 
          if (s->cur == '#')
1097
 
            {
1098
 
              state = 1;  /* goto comment */
1099
 
              pnmscanner_getchar(s);
1100
 
            }
1101
 
          else if (!g_ascii_isspace (s->cur))
1102
 
            state = -1;
1103
 
          else
1104
 
            pnmscanner_getchar(s);
1105
 
          break;
 
1258
        {
 
1259
        case 0:  /* in whitespace */
 
1260
          if (s->cur == '#')
 
1261
            {
 
1262
              state = 1;  /* goto comment */
 
1263
              pnmscanner_getchar(s);
 
1264
            }
 
1265
          else if (!g_ascii_isspace (s->cur))
 
1266
            state = -1;
 
1267
          else
 
1268
            pnmscanner_getchar (s);
 
1269
          break;
1106
1270
 
1107
 
        case 1:  /* in comment */
1108
 
          if (s->cur == '\n')
1109
 
            state = 0;  /* goto whitespace */
1110
 
          pnmscanner_getchar(s);
1111
 
          break;
1112
 
        }
 
1271
        case 1:  /* in comment */
 
1272
          if (s->cur == '\n')
 
1273
            state = 0;  /* goto whitespace */
 
1274
          pnmscanner_getchar (s);
 
1275
          break;
 
1276
        }
1113
1277
    }
1114
1278
}