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

« back to all changes in this revision

Viewing changes to plug-ins/bmp/bmpwrite.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:
8
8
/* Alexander.Schulz@stud.uni-karlsruhe.de                        */
9
9
 
10
10
/*
11
 
 * The GIMP -- an image manipulation program
 
11
 * GIMP - The GNU Image Manipulation Program
12
12
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
13
13
 *
14
14
 * This program is free software; you can redistribute it and/or modify
30
30
#include "config.h"
31
31
 
32
32
#include <errno.h>
33
 
#include <stdio.h>
34
 
#include <stdlib.h>
35
33
#include <string.h>
36
 
#ifdef HAVE_UNISTD_H
37
 
#include <unistd.h>
38
 
#endif
39
34
 
40
 
#include <gtk/gtk.h>
 
35
#include <glib/gstdio.h>
41
36
 
42
37
#include <libgimp/gimp.h>
43
38
#include <libgimp/gimpui.h>
46
41
 
47
42
#include "libgimp/stdplugins-intl.h"
48
43
 
49
 
static gint cur_progress = 0;
50
 
static gint max_progress = 0;
51
 
static gint encoded      = 0;
52
 
 
53
 
 
54
 
static  void      WriteImage  (FILE   *f,
55
 
                               guchar *src,
56
 
                               gint    width,
57
 
                               gint    height,
58
 
                               gint    encoded,
59
 
                               gint    channels,
60
 
                               gint    bpp,
61
 
                               gint    spzeile,
62
 
                               gint    MapSize);
63
 
static  gboolean  save_dialog (void);
 
44
typedef enum
 
45
{
 
46
  RGB_565,
 
47
  RGBA_5551,
 
48
  RGB_555,
 
49
  RGB_888,
 
50
  RGBA_8888,
 
51
  RGBX_8888
 
52
} RGBMode;
 
53
 
 
54
static struct
 
55
{
 
56
  RGBMode rgb_format;
 
57
  gint    encoded;
 
58
} BMPSaveData;
 
59
 
 
60
static gint    cur_progress = 0;
 
61
static gint    max_progress = 0;
 
62
 
 
63
 
 
64
static  void      write_image     (FILE   *f,
 
65
                                   guchar *src,
 
66
                                   gint    width,
 
67
                                   gint    height,
 
68
                                   gint    encoded,
 
69
                                   gint    channels,
 
70
                                   gint    bpp,
 
71
                                   gint    spzeile,
 
72
                                   gint    MapSize,
 
73
                                   RGBMode rgb_format);
 
74
 
 
75
static  gboolean  save_dialog     (gint    channels);
64
76
 
65
77
 
66
78
static void
82
94
}
83
95
 
84
96
static void
85
 
WriteColorMap (FILE *f,
86
 
               gint  red[MAXCOLORS],
87
 
               gint  green[MAXCOLORS],
88
 
               gint  blue[MAXCOLORS],
89
 
               gint  size)
 
97
write_color_map (FILE *f,
 
98
                 gint  red[MAXCOLORS],
 
99
                 gint  green[MAXCOLORS],
 
100
                 gint  blue[MAXCOLORS],
 
101
                 gint  size)
90
102
{
91
103
  gchar trgb[4];
92
 
  gint i;
 
104
  gint  i;
93
105
 
94
106
  size /= 4;
95
107
  trgb[3] = 0;
102
114
    }
103
115
}
104
116
 
 
117
static gboolean
 
118
warning_dialog (const gchar *primary,
 
119
                const gchar *secondary)
 
120
{
 
121
  GtkWidget *dialog;
 
122
  gboolean   ok;
 
123
 
 
124
  dialog = gtk_message_dialog_new (NULL, 0,
 
125
                                   GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL,
 
126
                                   primary);
 
127
 
 
128
  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
 
129
                                            secondary);
 
130
 
 
131
  gimp_window_set_transient (GTK_WINDOW (dialog));
 
132
 
 
133
  ok = (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK);
 
134
 
 
135
  gtk_widget_destroy (dialog);
 
136
 
 
137
  return ok;
 
138
}
 
139
 
105
140
GimpPDBStatusType
106
141
WriteBMP (const gchar *filename,
107
142
          gint32       image,
108
143
          gint32       drawable_ID)
109
144
{
110
 
  FILE         *outfile;
111
 
  gint          Red[MAXCOLORS];
112
 
  gint          Green[MAXCOLORS];
113
 
  gint          Blue[MAXCOLORS];
114
 
  guchar       *cmap;
115
 
  gint          rows, cols, Spcols, channels, MapSize, SpZeile;
116
 
  glong         BitsPerPixel;
117
 
  gint          colors;
118
 
  gchar        *temp_buf;
119
 
  guchar       *pixels;
120
 
  GimpPixelRgn  pixel_rgn;
121
 
  GimpDrawable *drawable;
122
 
  GimpImageType drawable_type;
123
 
  guchar        puffer[50];
124
 
  gint          i;
125
 
 
126
 
  /* first: can we save this image? */
 
145
  FILE          *outfile;
 
146
  gint           Red[MAXCOLORS];
 
147
  gint           Green[MAXCOLORS];
 
148
  gint           Blue[MAXCOLORS];
 
149
  guchar        *cmap;
 
150
  gint           rows, cols, Spcols, channels, MapSize, SpZeile;
 
151
  glong          BitsPerPixel;
 
152
  gint           colors;
 
153
  guchar        *pixels;
 
154
  GimpPixelRgn   pixel_rgn;
 
155
  GimpDrawable  *drawable;
 
156
  GimpImageType  drawable_type;
 
157
  guchar         puffer[50];
 
158
  gint           i;
 
159
  gint           mask_info_size;
 
160
  guint32        Mask[4];
127
161
 
128
162
  drawable = gimp_drawable_get (drawable_ID);
129
163
  drawable_type = gimp_drawable_type (drawable_ID);
131
165
  gimp_pixel_rgn_init (&pixel_rgn, drawable,
132
166
                       0, 0, drawable->width, drawable->height, FALSE, FALSE);
133
167
 
134
 
  if (gimp_drawable_has_alpha (drawable_ID))
135
 
    {
136
 
      g_message (_("Cannot save images with alpha channel."));
137
 
      return GIMP_PDB_EXECUTION_ERROR;
138
 
    }
139
 
 
140
 
  /* We can save it. So what colors do we use? */
141
 
 
142
168
  switch (drawable_type)
143
169
    {
 
170
    case GIMP_RGBA_IMAGE:
 
171
      colors       = 0;
 
172
      BitsPerPixel = 32;
 
173
      MapSize      = 0;
 
174
      channels     = 4;
 
175
      BMPSaveData.rgb_format = RGBA_8888;
 
176
      break;
 
177
 
144
178
    case GIMP_RGB_IMAGE:
145
179
      colors       = 0;
146
180
      BitsPerPixel = 24;
147
181
      MapSize      = 0;
148
182
      channels     = 3;
 
183
      BMPSaveData.rgb_format = RGB_888;
149
184
      break;
 
185
 
 
186
    case GIMP_GRAYA_IMAGE:
 
187
      if (interactive && !warning_dialog (_("Cannot save indexed image with "
 
188
                                            "transparency in BMP file format."),
 
189
                                          _("Alpha channel will be ignored.")))
 
190
          return GIMP_PDB_CANCEL;
 
191
 
 
192
     /* fallthrough */
 
193
 
150
194
    case GIMP_GRAY_IMAGE:
151
195
      colors       = 256;
152
196
      BitsPerPixel = 8;
153
197
      MapSize      = 1024;
154
 
      channels     = 1;
 
198
      if (drawable_type == GIMP_GRAY_IMAGE) channels = 1;
 
199
      else channels = 2;
155
200
      for (i = 0; i < colors; i++)
156
201
        {
157
202
          Red[i]   = i;
159
204
          Blue[i]  = i;
160
205
        }
161
206
      break;
 
207
 
 
208
    case GIMP_INDEXEDA_IMAGE:
 
209
      if (interactive && !warning_dialog (_("Cannot save indexed image with "
 
210
                                            "transparency in BMP file format."),
 
211
                                          _("Alpha channel will be ignored.")))
 
212
          return GIMP_PDB_CANCEL;
 
213
 
 
214
     /* fallthrough */
 
215
 
162
216
    case GIMP_INDEXED_IMAGE:
163
217
      cmap     = gimp_image_get_colormap (image, &colors);
164
218
      MapSize  = 4 * colors;
165
 
      channels = 1;
 
219
      if (drawable_type == GIMP_INDEXED_IMAGE) channels = 1;
 
220
      else channels = 2;
166
221
 
167
222
      if (colors > 16)
168
223
        BitsPerPixel = 8;
178
233
          Blue[i]  = *cmap++;
179
234
        }
180
235
      break;
 
236
 
181
237
    default:
182
 
      g_message (_("Cannot operate on unknown image types."));
183
 
      return GIMP_PDB_EXECUTION_ERROR;
 
238
      g_assert_not_reached ();
184
239
    }
185
240
 
186
241
  /* Perhaps someone wants RLE encoded Bitmaps */
187
 
  encoded = 0;
188
 
  if ((BitsPerPixel == 8 || BitsPerPixel == 4) && interactive_bmp)
189
 
    {
190
 
      if (! save_dialog ())
191
 
        return GIMP_PDB_CANCEL;
192
 
    }
 
242
  BMPSaveData.encoded = 0;
 
243
  mask_info_size = 0;
 
244
 
 
245
  if (!interactive && lastvals)
 
246
    {
 
247
      gimp_get_data (SAVE_PROC, &BMPSaveData);
 
248
    }
 
249
 
 
250
  if ((BitsPerPixel == 8 || BitsPerPixel == 4) && interactive)
 
251
    {
 
252
      if (! save_dialog (1))
 
253
        return GIMP_PDB_CANCEL;
 
254
    }
 
255
  else if ((BitsPerPixel == 24 || BitsPerPixel == 32))
 
256
    {
 
257
      if (interactive && !save_dialog (channels))
 
258
        return GIMP_PDB_CANCEL;
 
259
 
 
260
      switch (BMPSaveData.rgb_format)
 
261
        {
 
262
        case RGB_888:
 
263
          BitsPerPixel = 24;
 
264
          break;
 
265
        case RGBA_8888:
 
266
          BitsPerPixel = 32;
 
267
          break;
 
268
        case RGBX_8888:
 
269
          BitsPerPixel = 32;
 
270
          mask_info_size = 16;
 
271
          break;
 
272
        case RGB_565:
 
273
          BitsPerPixel = 16;
 
274
          mask_info_size = 16;
 
275
          break;
 
276
        case RGBA_5551:
 
277
          BitsPerPixel = 16;
 
278
          mask_info_size = 16;
 
279
          break;
 
280
        case RGB_555:
 
281
          BitsPerPixel = 16;
 
282
          break;
 
283
        default:
 
284
          g_return_val_if_reached (GIMP_PDB_EXECUTION_ERROR);
 
285
        }
 
286
    }
 
287
 
 
288
  gimp_set_data (SAVE_PROC, &BMPSaveData, sizeof (BMPSaveData));
193
289
 
194
290
  /* Let's take some file */
195
 
  outfile = fopen (filename, "wb");
 
291
  outfile = g_fopen (filename, "wb");
196
292
  if (!outfile)
197
293
    {
198
294
      g_message (_("Could not open '%s' for writing: %s"),
206
302
                           0, 0, drawable->width, drawable->height);
207
303
 
208
304
  /* And let's begin the progress */
209
 
  temp_buf = g_strdup_printf (_("Saving '%s'..."),
210
 
                               gimp_filename_to_utf8 (filename));
211
 
  gimp_progress_init (temp_buf);
212
 
  g_free (temp_buf);
 
305
  gimp_progress_init_printf (_("Saving '%s'"),
 
306
                             gimp_filename_to_utf8 (filename));
213
307
 
214
308
  cur_progress = 0;
215
309
  max_progress = drawable->height;
219
313
  rows = drawable->height;
220
314
 
221
315
  /* ... that we write to our headers. */
222
 
  if ((BitsPerPixel != 24) &&
223
 
      (cols % (8/BitsPerPixel)))
 
316
  if ((BitsPerPixel <= 8) && (cols % (8 / BitsPerPixel)))
224
317
    Spcols = (((cols / (8 / BitsPerPixel)) + 1) * (8 / BitsPerPixel));
225
318
  else
226
319
    Spcols = cols;
230
323
  else
231
324
    SpZeile = ((gint) (((Spcols * BitsPerPixel) / 8) / 4) + 1) * 4;
232
325
 
233
 
  Bitmap_File_Head.bfSize    = 0x36 + MapSize + (rows * SpZeile);
 
326
  Bitmap_File_Head.bfSize    = 0x36 + MapSize + (rows * SpZeile) + mask_info_size;
234
327
  Bitmap_File_Head.zzHotX    = 0;
235
328
  Bitmap_File_Head.zzHotY    = 0;
236
 
  Bitmap_File_Head.bfOffs    = 0x36 + MapSize;
237
 
  Bitmap_File_Head.biSize    = 40;
 
329
  Bitmap_File_Head.bfOffs    = 0x36 + MapSize + mask_info_size;
 
330
  Bitmap_File_Head.biSize    = 40 + (mask_info_size > 12 ? mask_info_size : 0);
238
331
 
239
332
  Bitmap_Head.biWidth  = cols;
240
333
  Bitmap_Head.biHeight = rows;
241
334
  Bitmap_Head.biPlanes = 1;
242
335
  Bitmap_Head.biBitCnt = BitsPerPixel;
243
336
 
244
 
  if (encoded == 0)
245
 
    Bitmap_Head.biCompr = 0;
 
337
  if (BMPSaveData.encoded == 0)
 
338
  {
 
339
    if (!mask_info_size) Bitmap_Head.biCompr = 0;
 
340
    else Bitmap_Head.biCompr = 3;
 
341
  }
246
342
  else if (BitsPerPixel == 8)
247
343
    Bitmap_Head.biCompr = 1;
248
344
  else if (BitsPerPixel == 4)
276
372
      }
277
373
  }
278
374
 
279
 
  if (BitsPerPixel < 24)
 
375
  if (BitsPerPixel <= 8)
280
376
    Bitmap_Head.biClrUsed = colors;
281
377
  else
282
378
    Bitmap_Head.biClrUsed = 0;
313
409
  FromL (Bitmap_Head.biClrImp, &puffer[0x20]);
314
410
 
315
411
  Write (outfile, puffer, 36);
316
 
  WriteColorMap (outfile, Red, Green, Blue, MapSize);
 
412
  write_color_map (outfile, Red, Green, Blue, MapSize);
 
413
 
 
414
  if (mask_info_size)
 
415
    {
 
416
      switch (BMPSaveData.rgb_format)
 
417
        {
 
418
        default:
 
419
        case RGB_888:
 
420
        case RGBX_8888:
 
421
          Mask[0] = 0xff000000;
 
422
          Mask[1] = 0x00ff0000;
 
423
          Mask[2] = 0x0000ff00;
 
424
          Mask[3] = 0x00000000;
 
425
          break;
 
426
 
 
427
        case RGBA_8888:
 
428
          Mask[0] = 0xff000000;
 
429
          Mask[1] = 0x00ff0000;
 
430
          Mask[2] = 0x0000ff00;
 
431
          Mask[3] = 0x000000ff;
 
432
          break;
 
433
 
 
434
        case RGB_565:
 
435
          Mask[0] = 0xf800;
 
436
          Mask[1] = 0x7e0;
 
437
          Mask[2] = 0x1f;
 
438
          Mask[3] = 0x0;
 
439
          break;
 
440
 
 
441
        case RGBA_5551:
 
442
          Mask[0] = 0x7c00;
 
443
          Mask[1] = 0x3e0;
 
444
          Mask[2] = 0x1f;
 
445
          Mask[3] = 0x8000;
 
446
          break;
 
447
 
 
448
        case RGB_555:
 
449
          Mask[0] = 0x7c00;
 
450
          Mask[1] = 0x3e0;
 
451
          Mask[2] = 0x1f;
 
452
          Mask[3] = 0x0;
 
453
          break;
 
454
        }
 
455
 
 
456
      FromL (Mask[0], &puffer[0x00]);
 
457
      FromL (Mask[1], &puffer[0x04]);
 
458
      FromL (Mask[2], &puffer[0x08]);
 
459
      FromL (Mask[3], &puffer[0x0C]);
 
460
      Write (outfile, puffer, mask_info_size);
 
461
    }
317
462
 
318
463
  /* After that is done, we write the image ... */
319
464
 
320
 
  WriteImage (outfile,
321
 
              pixels, cols, rows,
322
 
              encoded, channels, BitsPerPixel, SpZeile, MapSize);
 
465
  write_image (outfile,
 
466
               pixels, cols, rows,
 
467
               BMPSaveData.encoded, channels, BitsPerPixel, SpZeile, MapSize,
 
468
               BMPSaveData.rgb_format);
323
469
 
324
470
  /* ... and exit normally */
325
471
 
330
476
  return GIMP_PDB_SUCCESS;
331
477
}
332
478
 
 
479
static inline void Make565(guchar r, guchar g, guchar b, guchar *buf)
 
480
{
 
481
    gint p;
 
482
    p = (((gint)(r / 255.0 * 31.0 + 0.5))<<11) |
 
483
        (((gint)(g / 255.0 * 63.0 + 0.5))<<5)  |
 
484
         ((gint)(b / 255.0 * 31.0 + 0.5));
 
485
    buf[0] = (guchar)(p & 0xff);
 
486
    buf[1] = (guchar)(p>>8);
 
487
}
 
488
 
 
489
static inline void Make5551(guchar r, guchar g, guchar b, guchar a, guchar *buf)
 
490
{
 
491
    gint p;
 
492
    p = (((gint)(r / 255.0 * 31.0 + 0.5))<<10) |
 
493
        (((gint)(g / 255.0 * 31.0 + 0.5))<<5)  |
 
494
         ((gint)(b / 255.0 * 31.0 + 0.5))      |
 
495
         ((gint)(a / 255.0 + 0.5)<<15);
 
496
    buf[0] = (guchar)(p & 0xff);
 
497
    buf[1] = (guchar)(p>>8);
 
498
}
 
499
 
333
500
static void
334
 
WriteImage (FILE   *f,
335
 
            guchar *src,
336
 
            gint    width,
337
 
            gint    height,
338
 
            gint    encoded,
339
 
            gint    channels,
340
 
            gint    bpp,
341
 
            gint    spzeile,
342
 
            gint    MapSize)
 
501
write_image (FILE   *f,
 
502
             guchar *src,
 
503
             gint    width,
 
504
             gint    height,
 
505
             gint    encoded,
 
506
             gint    channels,
 
507
             gint    bpp,
 
508
             gint    spzeile,
 
509
             gint    MapSize,
 
510
             RGBMode rgb_format)
343
511
{
344
 
  guchar buf[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0};
345
 
  guchar puffer[8];
 
512
  guchar  buf[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0 };
 
513
  guchar  puffer[8];
346
514
  guchar *temp, v;
347
 
  guchar *Zeile, *ketten;
348
 
  gint xpos, ypos, i, j, rowstride, laenge, thiswidth;
349
 
  gint breite, k;
350
 
  guchar n;
 
515
  guchar *row, *ketten;
 
516
  gint    xpos, ypos, i, j, rowstride, length, thiswidth;
 
517
  gint    breite, k;
 
518
  guchar  n, r, g, b, a;
351
519
 
352
520
  xpos = 0;
353
521
  rowstride = width * channels;
354
522
 
355
 
  /* We'll begin with the 24 bit Bitmaps, they are easy :-) */
 
523
  /* We'll begin with the 16/24/32 bit Bitmaps, they are easy :-) */
356
524
 
357
 
  if (bpp == 24)
 
525
  if (bpp > 8)
358
526
    {
359
527
      for (ypos = height - 1; ypos >= 0; ypos--)  /* for each row   */
360
528
        {
361
529
          for (i = 0; i < width; i++)  /* for each pixel */
362
530
            {
363
531
              temp = src + (ypos * rowstride) + (xpos * channels);
364
 
              buf[2] = (guchar) *temp;
365
 
              temp++;
366
 
              buf[1] = (guchar) *temp;
367
 
              temp++;
368
 
              buf[0] = (guchar) *temp;
369
 
              xpos++;
370
 
              Write (f, buf, 3);
 
532
              switch (rgb_format)
 
533
                {
 
534
                default:
 
535
                case RGB_888:
 
536
                  buf[2] = *temp++;
 
537
                  buf[1] = *temp++;
 
538
                  buf[0] = *temp++;
 
539
                  xpos++;
 
540
                  if (channels > 3 && (guchar) *temp == 0)
 
541
                    buf[0] = buf[1] = buf[2] = 0xff;
 
542
                  Write (f, buf, 3);
 
543
                  break;
 
544
                case RGBX_8888:
 
545
                  buf[0] = 0;
 
546
                  buf[3] = *temp++;
 
547
                  buf[2] = *temp++;
 
548
                  buf[1] = *temp++;
 
549
                  xpos++;
 
550
                  if (channels > 3 && (guchar) *temp == 0)
 
551
                    buf[0] = buf[1] = buf[2] = 0xff;
 
552
                  Write (f, buf, 4);
 
553
                  break;
 
554
                case RGBA_8888:
 
555
                  buf[2] = *temp++;
 
556
                  buf[1] = *temp++;
 
557
                  buf[0] = *temp++;
 
558
                  buf[3] = *temp;
 
559
                  xpos++;
 
560
                  Write (f, buf, 4);
 
561
                  break;
 
562
                case RGB_565:
 
563
                  r = *temp++;
 
564
                  g = *temp++;
 
565
                  b = *temp++;
 
566
                  if (channels > 3 && (guchar) *temp == 0)
 
567
                    r = g = b = 0xff;
 
568
                  Make565 (r, g, b, buf);
 
569
                  xpos++;
 
570
                  Write (f, buf, 2);
 
571
                  break;
 
572
                case RGB_555:
 
573
                  r = *temp++;
 
574
                  g = *temp++;
 
575
                  b = *temp++;
 
576
                  if (channels > 3 && (guchar) *temp == 0)
 
577
                    r = g = b = 0xff;
 
578
                  Make5551 (r, g, b, 0x0, buf);
 
579
                  xpos++;
 
580
                  Write (f, buf, 2);
 
581
                  break;
 
582
                case RGBA_5551:
 
583
                  r = *temp++;
 
584
                  g = *temp++;
 
585
                  b = *temp++;
 
586
                  a = *temp;
 
587
                  Make5551 (r, g, b, a, buf);
 
588
                  xpos++;
 
589
                  Write (f, buf, 2);
 
590
                  break;
 
591
                }
371
592
            }
372
 
          Write (f, &buf[3], spzeile - (width * 3));
 
593
 
 
594
          Write (f, &buf[4], spzeile - (width * (bpp/8)));
373
595
 
374
596
          cur_progress++;
375
597
          if ((cur_progress % 5) == 0)
399
621
                         i++, xpos++)  /* for each pixel */
400
622
                      {
401
623
                        temp = src + (ypos * rowstride) + (xpos * channels);
 
624
                        if (channels > 1 && *(temp+1) == 0) *temp = 0x0;
402
625
                        v=v | ((guchar) *temp << (8 - (i * bpp)));
403
626
                      }
404
627
                    Write (f, &v, 1);
415
638
          }
416
639
        default:
417
640
          {              /* Save RLE encoded file, quite difficult */
418
 
            laenge = 0;
 
641
            length = 0;
419
642
            buf[12] = 0;
420
643
            buf[13] = 1;
421
644
            buf[14] = 0;
422
645
            buf[15] = 0;
423
 
            Zeile = (guchar *) g_malloc (width / (8 / bpp) + 10);
424
 
            ketten = (guchar *) g_malloc (width / (8 / bpp) + 10);
 
646
            row = g_new (guchar, width / (8 / bpp) + 10);
 
647
            ketten = g_new (guchar, width / (8 / bpp) + 10);
425
648
            for (ypos = height - 1; ypos >= 0; ypos--)
426
649
              { /* each row separately */
427
650
                j = 0;
436
659
                         i++, xpos++)
437
660
                      { /* for each pixel */
438
661
                        temp = src + (ypos * rowstride) + (xpos * channels);
 
662
                        if (channels > 1 && *(temp+1) == 0) *temp = 0x0;
439
663
                        v = v | ((guchar) * temp << (8 - (i * bpp)));
440
664
                      }
441
 
                    Zeile[j++] = v;
 
665
                    row[j++] = v;
442
666
                  }
443
667
                breite = width / (8 / bpp);
444
668
                if (width % (8 / bpp))
445
669
                  breite++;
446
670
                /* then check for strings of equal bytes */
447
 
                for (i = 0; i < breite;)
 
671
                for (i = 0; i < breite; i += j)
448
672
                  {
449
673
                    j = 0;
450
674
                    while ((i + j < breite) &&
451
675
                           (j < (255 / (8 / bpp))) &&
452
 
                           (Zeile[i + j] == Zeile[i]))
 
676
                           (row[i + j] == row[i]))
453
677
                      j++;
454
678
 
455
679
                    ketten[i] = j;
456
 
                    i += j;
457
680
                  }
458
681
 
459
682
                /* then write the strings and the other pixels to the file */
481
704
                            if (n + i * (8 / bpp) > width)
482
705
                              n--;
483
706
                            Write (f, &n, 1);
484
 
                            laenge += 2;
485
 
                            Write (f, &Zeile[i], j);
486
 
                            laenge += j;
 
707
                            length += 2;
 
708
                            Write (f, &row[i], j);
 
709
                            length += j;
487
710
                            if ((j) % 2)
488
711
                              {
489
712
                                Write (f, &buf[12], 1);
490
 
                                laenge++;
 
713
                                length++;
491
714
                              }
492
715
                          }
493
716
                        else
498
721
                                if (n + i * (8 / bpp) > width)
499
722
                                  n--;
500
723
                                Write (f, &n, 1);
501
 
                                Write (f, &Zeile[k], 1);
 
724
                                Write (f, &row[k], 1);
502
725
                                /*printf("%i.#|",n); */
503
 
                                laenge += 2;
 
726
                                length += 2;
504
727
                              }
505
728
                          }
506
729
                        i += j;
512
735
                        if (n + i * (8 / bpp) > width)
513
736
                          n--;
514
737
                        Write (f, &n, 1);
515
 
                        Write (f, &Zeile[i], 1);
 
738
                        Write (f, &row[i], 1);
516
739
                        i += ketten[i];
517
 
                        laenge += 2;
 
740
                        length += 2;
518
741
                      }
519
742
                  }
520
743
                Write (f, &buf[14], 2);          /* End of row */
521
 
                laenge += 2;
 
744
                length += 2;
522
745
 
523
746
                cur_progress++;
524
747
                if ((cur_progress % 5) == 0)
529
752
            Write (f, &buf[12], 2);      /* ... with End of file */
530
753
 
531
754
            fseek (f, 0x22, SEEK_SET);            /* Write length of image */
532
 
            FromL (laenge, puffer);
 
755
            FromL (length, puffer);
533
756
            Write (f, puffer, 4);
534
757
            fseek (f, 0x02, SEEK_SET);            /* Write length of file */
535
 
            laenge += (0x36 + MapSize);
536
 
            FromL (laenge, puffer);
 
758
            length += (0x36 + MapSize);
 
759
            FromL (length, puffer);
537
760
            Write (f, puffer, 4);
538
761
            g_free (ketten);
539
 
            g_free (Zeile);
 
762
            g_free (row);
540
763
            break;
541
764
          }
542
765
        }
545
768
  gimp_progress_update (1);
546
769
}
547
770
 
 
771
static void
 
772
format_callback (GtkWidget *widget,
 
773
                 gpointer  *data)
 
774
{
 
775
  BMPSaveData.rgb_format = GPOINTER_TO_INT (data);
 
776
}
 
777
 
548
778
static gboolean
549
 
save_dialog (void)
 
779
save_dialog (gint channels)
550
780
{
551
 
  GtkWidget *dlg;
 
781
  GtkWidget *dialog;
552
782
  GtkWidget *toggle;
 
783
  GtkWidget *vbox_main;
553
784
  GtkWidget *vbox;
 
785
  GtkWidget *vbox2;
 
786
  GtkWidget *expander;
 
787
  GtkWidget *frame;
 
788
  GSList    *group;
554
789
  gboolean   run;
555
790
 
556
 
  dlg = gimp_dialog_new (_("Save as BMP"), "bmp",
557
 
                         NULL, 0,
558
 
                         gimp_standard_help_func, "file-bmp-save",
559
 
 
560
 
                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
561
 
                         GTK_STOCK_OK,     GTK_RESPONSE_OK,
562
 
 
563
 
                         NULL);
564
 
 
565
 
  vbox = gtk_vbox_new (FALSE, 12);
566
 
  gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
567
 
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), vbox, TRUE, TRUE, 0);
568
 
  gtk_widget_show (vbox);
569
 
 
570
 
  toggle = gtk_check_button_new_with_mnemonic (_("_RLE encoded"));
571
 
  gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
572
 
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), encoded);
 
791
  dialog = gimp_dialog_new (_("Save as BMP"), "bmp",
 
792
                            NULL, 0,
 
793
                            gimp_standard_help_func, SAVE_PROC,
 
794
 
 
795
                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
 
796
                            GTK_STOCK_SAVE,   GTK_RESPONSE_OK,
 
797
 
 
798
                            NULL);
 
799
 
 
800
  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
 
801
                                           GTK_RESPONSE_OK,
 
802
                                           GTK_RESPONSE_CANCEL,
 
803
                                           -1);
 
804
 
 
805
  gimp_window_set_transient (GTK_WINDOW (dialog));
 
806
 
 
807
  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
 
808
 
 
809
  vbox_main = gtk_vbox_new (FALSE, 12);
 
810
  gtk_container_set_border_width (GTK_CONTAINER (vbox_main), 12);
 
811
  gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), vbox_main);
 
812
  gtk_widget_show (vbox_main);
 
813
 
 
814
  toggle = gtk_check_button_new_with_mnemonic (_("_Run-Length Encoded"));
 
815
  gtk_box_pack_start (GTK_BOX (vbox_main), toggle, FALSE, FALSE, 0);
 
816
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle),
 
817
                                BMPSaveData.encoded);
573
818
  gtk_widget_show (toggle);
 
819
  if (channels > 1)
 
820
    gtk_widget_set_sensitive (toggle, FALSE);
574
821
 
575
822
  g_signal_connect (toggle, "toggled",
576
823
                    G_CALLBACK (gimp_toggle_button_update),
577
 
                    &encoded);
578
 
 
579
 
  gtk_widget_show (dlg);
580
 
 
581
 
  run = (gimp_dialog_run (GIMP_DIALOG (dlg)) == GTK_RESPONSE_OK);
582
 
 
583
 
  gtk_widget_destroy (dlg);
 
824
                    &BMPSaveData.encoded);
 
825
 
 
826
  expander = gtk_expander_new_with_mnemonic (_("_Advanced Options"));
 
827
 
 
828
  gtk_box_pack_start (GTK_BOX (vbox_main), expander, TRUE, TRUE, 0);
 
829
  gtk_widget_show (expander);
 
830
 
 
831
  if (channels < 3)
 
832
    gtk_widget_set_sensitive (expander, FALSE);
 
833
 
 
834
  vbox2 = gtk_vbox_new (FALSE, 12);
 
835
  gtk_container_set_border_width (GTK_CONTAINER (vbox2), 12);
 
836
  gtk_container_add (GTK_CONTAINER (expander), vbox2);
 
837
  gtk_widget_show (vbox2);
 
838
 
 
839
  group = NULL;
 
840
 
 
841
  frame = gimp_frame_new (_("16 bits"));
 
842
  gtk_box_pack_start (GTK_BOX (vbox2), frame, TRUE, TRUE, 0);
 
843
  gtk_widget_show (frame);
 
844
 
 
845
  vbox = gtk_vbox_new (FALSE, 6);
 
846
  gtk_container_add (GTK_CONTAINER (frame), vbox);
 
847
  gtk_widget_show (vbox);
 
848
 
 
849
  toggle = gtk_radio_button_new_with_label (group, "R5 G6 B5");
 
850
  group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (toggle));
 
851
  gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
 
852
  gtk_widget_show (toggle);
 
853
  g_signal_connect (toggle, "pressed",
 
854
                    G_CALLBACK (format_callback),
 
855
                    GINT_TO_POINTER (RGB_565));
 
856
 
 
857
  toggle = gtk_radio_button_new_with_label (group, "A1 R5 G5 B5");
 
858
  group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (toggle));
 
859
  gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
 
860
 
 
861
  if (channels < 4)
 
862
    gtk_widget_set_sensitive (toggle, FALSE);
 
863
 
 
864
  gtk_widget_show (toggle);
 
865
 
 
866
  g_signal_connect (toggle, "pressed",
 
867
                    G_CALLBACK (format_callback),
 
868
                    GINT_TO_POINTER (RGBA_5551));
 
869
  toggle = gtk_radio_button_new_with_label (group, "X1 R5 G5 B5");
 
870
  group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (toggle));
 
871
  gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
 
872
  gtk_widget_show (toggle);
 
873
  g_signal_connect (toggle, "pressed",
 
874
                    G_CALLBACK (format_callback),
 
875
                    GINT_TO_POINTER (RGB_555));
 
876
 
 
877
  frame = gimp_frame_new (_("24 bits"));
 
878
  gtk_box_pack_start (GTK_BOX (vbox2), frame, FALSE, FALSE, 0);
 
879
  gtk_widget_show (frame);
 
880
 
 
881
  toggle = gtk_radio_button_new_with_label (group, "R8 G8 B8");
 
882
  group = gtk_radio_button_get_group (GTK_RADIO_BUTTON(toggle));
 
883
  gtk_container_add (GTK_CONTAINER (frame), toggle);
 
884
  gtk_widget_show (toggle);
 
885
  g_signal_connect (toggle, "pressed",
 
886
                    G_CALLBACK (format_callback),
 
887
                    GINT_TO_POINTER (RGB_888));
 
888
  if (channels < 4)
 
889
    {
 
890
      BMPSaveData.rgb_format = RGB_888;
 
891
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), TRUE);
 
892
    }
 
893
 
 
894
  frame = gimp_frame_new (_("32 bits"));
 
895
  gtk_box_pack_start (GTK_BOX (vbox2), frame, FALSE, FALSE, 0);
 
896
  gtk_widget_show (frame);
 
897
 
 
898
  vbox = gtk_vbox_new (FALSE, 6);
 
899
  gtk_container_add (GTK_CONTAINER (frame), vbox);
 
900
  gtk_widget_show (vbox);
 
901
 
 
902
  toggle = gtk_radio_button_new_with_label (group, "A8 R8 G8 B8");
 
903
  group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (toggle));
 
904
  gtk_container_add (GTK_CONTAINER (vbox), toggle);
 
905
 
 
906
  if (channels < 4)
 
907
    {
 
908
      gtk_widget_set_sensitive (toggle, FALSE);
 
909
    }
 
910
  else
 
911
    {
 
912
      BMPSaveData.rgb_format = RGBA_8888;
 
913
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), TRUE);
 
914
    }
 
915
 
 
916
  gtk_widget_show (toggle);
 
917
  g_signal_connect (toggle, "pressed",
 
918
                    G_CALLBACK (format_callback),
 
919
                    GINT_TO_POINTER (RGBA_8888));
 
920
 
 
921
  toggle = gtk_radio_button_new_with_label (group, "X8 R8 G8 B8");
 
922
  group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (toggle));
 
923
  gtk_container_add (GTK_CONTAINER (vbox), toggle);
 
924
  gtk_widget_show (toggle);
 
925
  g_signal_connect (toggle, "pressed",
 
926
                    G_CALLBACK (format_callback),
 
927
                    GINT_TO_POINTER (RGBX_8888));
 
928
 
 
929
  gtk_widget_show (dialog);
 
930
 
 
931
  run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
 
932
 
 
933
  gtk_widget_destroy (dialog);
584
934
 
585
935
  return run;
586
936
}