1997-11-25 06:05:25 +08:00
|
|
|
/* bmpwrite.c Writes Bitmap files. Even RLE encoded ones. */
|
|
|
|
/* (Windows (TM) doesn't read all of those, but who */
|
|
|
|
/* cares? ;-) */
|
1998-04-07 11:41:22 +08:00
|
|
|
/* I changed a few things over the time, so perhaps */
|
|
|
|
/* it dos now, but now there's no Windows left on */
|
|
|
|
/* my computer... */
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Alexander.Schulz@stud.uni-karlsruhe.de */
|
|
|
|
|
1999-12-19 20:20:38 +08:00
|
|
|
/*
|
|
|
|
* The GIMP -- an image manipulation program
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
1999-05-29 09:28:24 +08:00
|
|
|
#include "config.h"
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
1999-05-29 09:28:24 +08:00
|
|
|
#ifdef HAVE_UNISTD_H
|
1998-04-11 13:07:52 +08:00
|
|
|
#include <unistd.h>
|
1999-05-29 09:28:24 +08:00
|
|
|
#endif
|
1999-12-19 20:20:38 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <gtk/gtk.h>
|
2000-02-13 01:39:21 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include <libgimp/gimp.h>
|
2000-02-13 01:39:21 +08:00
|
|
|
#include <libgimp/gimpui.h>
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
#include "bmp.h"
|
2000-02-13 01:39:21 +08:00
|
|
|
|
1999-05-30 00:35:47 +08:00
|
|
|
#include "libgimp/stdplugins-intl.h"
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
guchar *pixels;
|
2000-02-13 01:39:21 +08:00
|
|
|
gint cur_progress;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-02-13 01:39:21 +08:00
|
|
|
gint max_progress;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
gint run;
|
1999-11-04 02:47:35 +08:00
|
|
|
} BMPSaveInterface;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
1999-11-04 02:47:35 +08:00
|
|
|
static BMPSaveInterface gsint =
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
FALSE /* run */
|
|
|
|
};
|
|
|
|
|
2000-02-13 01:39:21 +08:00
|
|
|
gint encoded = 0;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
|
2000-02-13 01:39:21 +08:00
|
|
|
static gint save_dialog (void);
|
|
|
|
static void save_ok_callback (GtkWidget *widget,
|
|
|
|
gpointer data);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-08-22 11:27:14 +08:00
|
|
|
GimpPDBStatusType
|
2000-02-13 01:39:21 +08:00
|
|
|
WriteBMP (gchar *filename,
|
1999-12-19 20:20:38 +08:00
|
|
|
gint32 image,
|
|
|
|
gint32 drawable_ID)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
FILE *outfile;
|
2000-02-13 01:39:21 +08:00
|
|
|
gint Red[MAXCOLORS];
|
|
|
|
gint Green[MAXCOLORS];
|
|
|
|
gint Blue[MAXCOLORS];
|
|
|
|
guchar *cmap;
|
|
|
|
gint rows, cols, Spcols, channels, MapSize, SpZeile;
|
|
|
|
glong BitsPerPixel;
|
|
|
|
gint colors;
|
|
|
|
gchar *temp_buf;
|
gimp-joke-980321
* app/iscissors.c, app/tips_dialog.c, app/gradient.c,
libgimp/gimp.c, plug-ins/AlienMap/AlienMap.c,
plug-ins/bmp/bmp.c, plug-ins/fits/fitsrw.h,
plug-ins/fits/fitsrw.c, plug-ins/flarefx/flarefx.c,
plug-ins/gfig/gfig.c, plug-ins/gfli/gfli.c,
plug-ins/gicon/gicon.c, plug-ins/gqbist/gqbist.c,
plug-ins/gtm/gtm.c, plug-ins/hot/hot.c,
plug-ins/ifscompose/ifscompose.c,
plug-ins/ifscompose/ifscompose_utils.c
plug-ins/max_rgb/max_rgb.c, plug-ins/nlfilt/nlfilt.c,
plug-ins/pat/pat.c, plug-ins/pcx/pcx.c, plug-ins/rotate/rotate.c,
plug-ins/script-fu/script-fu-server.c, plug-ins/snoise/snoise.c,
plug-ins/threshold_alpha/threshold_alpha.c,
plug-ins/zealouscrop/zealouscrop.c :gimp-joke-980321
plug-ins/CML_explorer, plug-ins/autocrop,
plug-ins/align_layers, plug-ins/blinds,
plug-ins/bmp, plug-ins/megawidget: gimp-joke-980322
Applied gimp-joke-980322-0.patch and gimp-joke-980321-0.patch
from Yasuhiro SHIRASAKI <joke@awa.tohoku.ac.jp>. Mostly
portability for DEC osf1's cc. Lots of MAIN();'s, trailing
commas in enums, and guchar/gchar madness.
Gimp now sends mail, cleans vinyl records,
removes stubborn stains, julien fries, and more!
-adrian
1998-03-23 04:44:39 +08:00
|
|
|
guchar *pixels;
|
2000-08-22 11:27:14 +08:00
|
|
|
GimpPixelRgn pixel_rgn;
|
|
|
|
GimpDrawable *drawable;
|
|
|
|
GimpImageType drawable_type;
|
1998-03-17 17:39:40 +08:00
|
|
|
guchar puffer[50];
|
2000-02-13 01:39:21 +08:00
|
|
|
gint i;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* first: can we save this image? */
|
|
|
|
|
|
|
|
drawable = gimp_drawable_get(drawable_ID);
|
|
|
|
drawable_type = gimp_drawable_type(drawable_ID);
|
2000-02-13 01:39:21 +08:00
|
|
|
gimp_pixel_rgn_init (&pixel_rgn, drawable,
|
|
|
|
0, 0, drawable->width, drawable->height, FALSE, FALSE);
|
1997-11-25 06:05:25 +08:00
|
|
|
switch (drawable_type)
|
|
|
|
{
|
2000-08-22 11:27:14 +08:00
|
|
|
case GIMP_RGB_IMAGE:
|
|
|
|
case GIMP_GRAY_IMAGE:
|
|
|
|
case GIMP_INDEXED_IMAGE:
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
|
|
|
default:
|
2000-05-08 06:04:51 +08:00
|
|
|
g_message(_("BMP: cannot operate on unknown image types or alpha images"));
|
2000-08-22 11:27:14 +08:00
|
|
|
return GIMP_PDB_EXECUTION_ERROR;
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We can save it. So what colors do we use? */
|
|
|
|
|
|
|
|
switch (drawable_type)
|
|
|
|
{
|
2000-08-22 11:27:14 +08:00
|
|
|
case GIMP_RGB_IMAGE:
|
2000-02-13 01:39:21 +08:00
|
|
|
colors = 0;
|
1997-11-25 06:05:25 +08:00
|
|
|
BitsPerPixel = 24;
|
2000-02-13 01:39:21 +08:00
|
|
|
MapSize = 0;
|
|
|
|
channels = 3;
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
2000-08-22 11:27:14 +08:00
|
|
|
case GIMP_GRAY_IMAGE:
|
2000-02-13 01:39:21 +08:00
|
|
|
colors = 256;
|
|
|
|
BitsPerPixel = 8;
|
|
|
|
MapSize = 1024;
|
|
|
|
channels = 1;
|
1997-11-25 06:05:25 +08:00
|
|
|
for (i = 0; i < colors; i++)
|
|
|
|
{
|
2000-02-13 01:39:21 +08:00
|
|
|
Red[i] = i;
|
1997-11-25 06:05:25 +08:00
|
|
|
Green[i] = i;
|
2000-02-13 01:39:21 +08:00
|
|
|
Blue[i] = i;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
break;
|
2000-08-22 11:27:14 +08:00
|
|
|
case GIMP_INDEXED_IMAGE:
|
2000-02-13 01:39:21 +08:00
|
|
|
cmap = gimp_image_get_cmap (image, &colors);
|
|
|
|
MapSize = 4 * colors;
|
1997-11-25 06:05:25 +08:00
|
|
|
channels = 1;
|
2000-02-13 01:39:21 +08:00
|
|
|
|
|
|
|
if (colors > 16)
|
|
|
|
BitsPerPixel = 8;
|
|
|
|
else if (colors > 2)
|
|
|
|
BitsPerPixel = 4;
|
|
|
|
else
|
|
|
|
BitsPerPixel = 1;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
for (i = 0; i < colors; i++)
|
|
|
|
{
|
2000-02-13 01:39:21 +08:00
|
|
|
Red[i] = *cmap++;
|
1997-11-25 06:05:25 +08:00
|
|
|
Green[i] = *cmap++;
|
2000-02-13 01:39:21 +08:00
|
|
|
Blue[i] = *cmap++;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
1998-04-07 11:41:22 +08:00
|
|
|
fprintf (stderr, "%s: This should not happen\n", prog_name);
|
2000-08-22 11:27:14 +08:00
|
|
|
return GIMP_PDB_EXECUTION_ERROR;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Perhaps someone wants RLE encoded Bitmaps */
|
2000-02-13 01:39:21 +08:00
|
|
|
encoded = 0;
|
|
|
|
if ((BitsPerPixel == 8 || BitsPerPixel == 4) && interactive_bmp)
|
|
|
|
{
|
|
|
|
if (! save_dialog ())
|
2000-08-22 11:27:14 +08:00
|
|
|
return GIMP_PDB_CANCEL;
|
2000-02-13 01:39:21 +08:00
|
|
|
}
|
|
|
|
|
1999-12-19 20:20:38 +08:00
|
|
|
/* Let's take some file */
|
1997-11-25 06:05:25 +08:00
|
|
|
outfile = fopen (filename, "wb");
|
|
|
|
if (!outfile)
|
|
|
|
{
|
2000-05-08 06:04:51 +08:00
|
|
|
g_message (_("Can't open %s"), filename);
|
2000-08-22 11:27:14 +08:00
|
|
|
return GIMP_PDB_EXECUTION_ERROR;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
2000-02-13 01:39:21 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* fetch the image */
|
2000-02-13 01:39:21 +08:00
|
|
|
pixels = g_new (guchar, drawable->width * drawable->height * channels);
|
|
|
|
gimp_pixel_rgn_get_rect (&pixel_rgn, pixels,
|
|
|
|
0, 0, drawable->width, drawable->height);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* And let's begin the progress */
|
1998-03-17 17:39:40 +08:00
|
|
|
if (interactive_bmp)
|
|
|
|
{
|
1999-12-31 02:54:17 +08:00
|
|
|
temp_buf = g_strdup_printf (_("Saving %s:"), filename);
|
1998-03-17 17:39:40 +08:00
|
|
|
gimp_progress_init (temp_buf);
|
|
|
|
g_free (temp_buf);
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
cur_progress = 0;
|
|
|
|
max_progress = drawable->height;
|
2000-02-13 01:39:21 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* Now, we need some further information ... */
|
|
|
|
cols = drawable->width;
|
|
|
|
rows = drawable->height;
|
2000-02-13 01:39:21 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* ... that we write to our headers. */
|
2000-02-13 01:39:21 +08:00
|
|
|
if ((BitsPerPixel != 24) &&
|
|
|
|
(cols % (8/BitsPerPixel)))
|
|
|
|
Spcols = (((cols / (8 / BitsPerPixel)) + 1) * (8 / BitsPerPixel));
|
|
|
|
else
|
|
|
|
Spcols = cols;
|
|
|
|
|
|
|
|
if ((((Spcols * BitsPerPixel) / 8) % 4) == 0)
|
|
|
|
SpZeile = ((Spcols * BitsPerPixel) / 8);
|
|
|
|
else
|
|
|
|
SpZeile = ((gint) (((Spcols * BitsPerPixel) / 8) / 4) + 1) * 4;
|
|
|
|
|
|
|
|
Bitmap_File_Head.bfSize = 0x36 + MapSize + (rows * SpZeile);
|
2000-05-06 09:38:32 +08:00
|
|
|
Bitmap_File_Head.zzHotX = 0;
|
|
|
|
Bitmap_File_Head.zzHotY = 0;
|
2000-02-13 01:39:21 +08:00
|
|
|
Bitmap_File_Head.bfOffs = 0x36 + MapSize;
|
|
|
|
Bitmap_File_Head.biSize = 40;
|
|
|
|
|
|
|
|
Bitmap_Head.biWidth = cols;
|
|
|
|
Bitmap_Head.biHeight = rows;
|
2000-05-21 00:11:29 +08:00
|
|
|
Bitmap_Head.biPlanes = 1;
|
2000-02-13 01:39:21 +08:00
|
|
|
Bitmap_Head.biBitCnt = BitsPerPixel;
|
|
|
|
|
|
|
|
if (encoded == 0)
|
|
|
|
Bitmap_Head.biCompr = 0;
|
|
|
|
else if (BitsPerPixel == 8)
|
|
|
|
Bitmap_Head.biCompr = 1;
|
|
|
|
else if (BitsPerPixel == 4)
|
|
|
|
Bitmap_Head.biCompr = 2;
|
|
|
|
else
|
|
|
|
Bitmap_Head.biCompr = 0;
|
|
|
|
|
|
|
|
Bitmap_Head.biSizeIm = SpZeile * rows;
|
|
|
|
|
1999-12-19 20:20:38 +08:00
|
|
|
{
|
2000-02-13 01:39:21 +08:00
|
|
|
gdouble xresolution;
|
|
|
|
gdouble yresolution;
|
1999-12-19 20:20:38 +08:00
|
|
|
gimp_image_get_resolution (image, &xresolution, &yresolution);
|
|
|
|
|
2000-02-13 01:39:21 +08:00
|
|
|
if (xresolution > GIMP_MIN_RESOLUTION &&
|
|
|
|
yresolution > GIMP_MIN_RESOLUTION)
|
|
|
|
{
|
1999-12-19 20:20:38 +08:00
|
|
|
/*
|
|
|
|
* xresolution and yresolution are in dots per inch.
|
|
|
|
* the BMP spec says that biXPels and biYPels are in
|
|
|
|
* pixels per meter as long ints (actually, "DWORDS"),
|
|
|
|
* so...
|
|
|
|
* n dots inch 100 cm m dots
|
|
|
|
* ------ * ------- * ------ = ------
|
|
|
|
* inch 2.54 cm m inch
|
|
|
|
*/
|
|
|
|
Bitmap_Head.biXPels = (long int) xresolution * 100.0 / 2.54;
|
|
|
|
Bitmap_Head.biYPels = (long int) yresolution * 100.0 / 2.54;
|
|
|
|
}
|
|
|
|
}
|
2001-05-22 08:36:38 +08:00
|
|
|
|
2000-02-13 01:39:21 +08:00
|
|
|
if (BitsPerPixel < 24)
|
|
|
|
Bitmap_Head.biClrUsed = colors;
|
1999-12-19 20:20:38 +08:00
|
|
|
else
|
2000-02-13 01:39:21 +08:00
|
|
|
Bitmap_Head.biClrUsed = 0;
|
1999-12-19 20:20:38 +08:00
|
|
|
|
2000-02-13 01:39:21 +08:00
|
|
|
Bitmap_Head.biClrImp = Bitmap_Head.biClrUsed;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
printf("\nSize: %u, Colors: %u, Bits: %u, Width: %u, Height: %u, Comp: %u, Zeile: %u\n",
|
1998-04-07 11:41:22 +08:00
|
|
|
(int)Bitmap_File_Head.bfSize,(int)Bitmap_Head.biClrUsed,Bitmap_Head.biBitCnt,(int)Bitmap_Head.biWidth,
|
|
|
|
(int)Bitmap_Head.biHeight, (int)Bitmap_Head.biCompr,SpZeile);
|
1997-11-25 06:05:25 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* And now write the header and the colormap (if any) to disk */
|
2000-02-13 01:39:21 +08:00
|
|
|
|
|
|
|
Write (outfile, "BM", 2);
|
|
|
|
|
|
|
|
FromL (Bitmap_File_Head.bfSize, &puffer[0x00]);
|
2000-05-06 09:38:32 +08:00
|
|
|
FromS (Bitmap_File_Head.zzHotX, &puffer[0x04]);
|
|
|
|
FromS (Bitmap_File_Head.zzHotY, &puffer[0x06]);
|
2000-02-13 01:39:21 +08:00
|
|
|
FromL (Bitmap_File_Head.bfOffs, &puffer[0x08]);
|
|
|
|
FromL (Bitmap_File_Head.biSize, &puffer[0x0C]);
|
|
|
|
|
|
|
|
Write (outfile, puffer, 16);
|
|
|
|
|
|
|
|
FromL (Bitmap_Head.biWidth, &puffer[0x00]);
|
|
|
|
FromL (Bitmap_Head.biHeight, &puffer[0x04]);
|
|
|
|
FromS (Bitmap_Head.biPlanes, &puffer[0x08]);
|
|
|
|
FromS (Bitmap_Head.biBitCnt, &puffer[0x0A]);
|
|
|
|
FromL (Bitmap_Head.biCompr, &puffer[0x0C]);
|
|
|
|
FromL (Bitmap_Head.biSizeIm, &puffer[0x10]);
|
|
|
|
FromL (Bitmap_Head.biXPels, &puffer[0x14]);
|
|
|
|
FromL (Bitmap_Head.biYPels, &puffer[0x18]);
|
|
|
|
FromL (Bitmap_Head.biClrUsed, &puffer[0x1C]);
|
|
|
|
FromL (Bitmap_Head.biClrImp, &puffer[0x20]);
|
|
|
|
|
|
|
|
Write (outfile, puffer, 36);
|
|
|
|
WriteColorMap (outfile, Red, Green, Blue, MapSize);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* After that is done, we write the image ... */
|
|
|
|
|
2000-02-13 01:39:21 +08:00
|
|
|
WriteImage (outfile,
|
|
|
|
pixels, cols, rows,
|
|
|
|
encoded, channels, BitsPerPixel, SpZeile, MapSize);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
/* ... and exit normally */
|
2000-02-13 01:39:21 +08:00
|
|
|
|
|
|
|
fclose (outfile);
|
|
|
|
gimp_drawable_detach (drawable);
|
|
|
|
g_free (pixels);
|
|
|
|
|
2000-08-22 11:27:14 +08:00
|
|
|
return GIMP_PDB_SUCCESS;
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
1999-12-19 20:20:38 +08:00
|
|
|
void
|
|
|
|
WriteColorMap (FILE *f,
|
2000-02-13 01:39:21 +08:00
|
|
|
gint red[MAXCOLORS],
|
|
|
|
gint green[MAXCOLORS],
|
|
|
|
gint blue[MAXCOLORS],
|
|
|
|
gint size)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-02-13 01:39:21 +08:00
|
|
|
gchar trgb[4];
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
size /= 4;
|
|
|
|
trgb[3] = 0;
|
|
|
|
for (i = 0; i < size; i++)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-02-13 01:39:21 +08:00
|
|
|
trgb[0] = (guchar) blue[i];
|
|
|
|
trgb[1] = (guchar) green[i];
|
|
|
|
trgb[2] = (guchar) red[i];
|
|
|
|
Write (f, trgb, 4);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-12-19 20:20:38 +08:00
|
|
|
void
|
|
|
|
WriteImage (FILE *f,
|
|
|
|
guchar *src,
|
2000-02-13 01:39:21 +08:00
|
|
|
gint width,
|
|
|
|
gint height,
|
|
|
|
gint encoded,
|
|
|
|
gint channels,
|
|
|
|
gint bpp,
|
|
|
|
gint spzeile,
|
|
|
|
gint MapSize)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
1998-04-07 11:41:22 +08:00
|
|
|
guchar buf[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0};
|
|
|
|
guchar puffer[8];
|
2000-02-13 01:39:21 +08:00
|
|
|
guchar *temp, v;
|
|
|
|
guchar *Zeile, *ketten;
|
|
|
|
gint xpos, ypos, i, j, rowstride, laenge, thiswidth;
|
|
|
|
gint breite, n, k;
|
|
|
|
|
|
|
|
xpos = 0;
|
|
|
|
rowstride = width * channels;
|
1998-04-07 11:41:22 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* We'll begin with the 24 bit Bitmaps, they are easy :-) */
|
2000-02-13 01:39:21 +08:00
|
|
|
|
|
|
|
if (bpp == 24)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-02-13 01:39:21 +08:00
|
|
|
for (ypos = height - 1; ypos >= 0; ypos--) /* for each row */
|
1999-11-04 02:47:35 +08:00
|
|
|
{
|
2000-02-13 01:39:21 +08:00
|
|
|
for (i = 0; i < width; i++) /* for each pixel */
|
1999-11-04 02:47:35 +08:00
|
|
|
{
|
|
|
|
temp = src + (ypos * rowstride) + (xpos * channels);
|
2000-02-13 01:39:21 +08:00
|
|
|
buf[2] = (guchar) *temp;
|
1999-11-04 02:47:35 +08:00
|
|
|
temp++;
|
2000-02-13 01:39:21 +08:00
|
|
|
buf[1] = (guchar) *temp;
|
1999-11-04 02:47:35 +08:00
|
|
|
temp++;
|
2000-02-13 01:39:21 +08:00
|
|
|
buf[0] = (guchar) *temp;
|
1999-11-04 02:47:35 +08:00
|
|
|
xpos++;
|
2000-02-13 01:39:21 +08:00
|
|
|
Write (f, buf, 3);
|
1999-11-04 02:47:35 +08:00
|
|
|
}
|
2000-02-13 01:39:21 +08:00
|
|
|
Write (f, &buf[3], spzeile - (width * 3));
|
|
|
|
|
1999-11-04 02:47:35 +08:00
|
|
|
cur_progress++;
|
2000-02-13 01:39:21 +08:00
|
|
|
if ((interactive_bmp) &&
|
|
|
|
((cur_progress % 5) == 0))
|
|
|
|
gimp_progress_update ((gdouble) cur_progress /
|
|
|
|
(gdouble) max_progress);
|
|
|
|
|
|
|
|
xpos = 0;
|
1999-11-04 02:47:35 +08:00
|
|
|
}
|
2000-02-13 01:39:21 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (encoded) /* now it gets more difficult */
|
|
|
|
{ /* uncompressed 1,4 and 8 bit */
|
1999-11-04 02:47:35 +08:00
|
|
|
case 0:
|
|
|
|
{
|
2000-02-13 01:39:21 +08:00
|
|
|
thiswidth = (width / (8 / bpp));
|
|
|
|
if (width % (8 / bpp))
|
|
|
|
thiswidth++;
|
|
|
|
|
|
|
|
for (ypos = height - 1; ypos >= 0; ypos--) /* for each row */
|
1999-11-04 02:47:35 +08:00
|
|
|
{
|
2000-02-13 01:39:21 +08:00
|
|
|
for (xpos = 0; xpos < width;) /* for each _byte_ */
|
1999-11-04 02:47:35 +08:00
|
|
|
{
|
2000-02-13 01:39:21 +08:00
|
|
|
v = 0;
|
|
|
|
for (i = 1;
|
|
|
|
(i <= (8 / bpp)) && (xpos < width);
|
|
|
|
i++, xpos++) /* for each pixel */
|
1999-11-04 02:47:35 +08:00
|
|
|
{
|
|
|
|
temp = src + (ypos * rowstride) + (xpos * channels);
|
2000-02-13 01:39:21 +08:00
|
|
|
v=v | ((guchar) *temp << (8 - (i * bpp)));
|
1999-11-04 02:47:35 +08:00
|
|
|
}
|
2000-02-13 01:39:21 +08:00
|
|
|
Write (f, &v, 1);
|
1999-11-04 02:47:35 +08:00
|
|
|
}
|
2000-02-13 01:39:21 +08:00
|
|
|
Write (f, &buf[3], spzeile - thiswidth);
|
|
|
|
xpos = 0;
|
|
|
|
|
1999-11-04 02:47:35 +08:00
|
|
|
cur_progress++;
|
2000-02-13 01:39:21 +08:00
|
|
|
if ((interactive_bmp) &&
|
|
|
|
((cur_progress % 5) == 0))
|
|
|
|
gimp_progress_update ((gdouble) cur_progress /
|
|
|
|
(gdouble) max_progress);
|
1999-11-04 02:47:35 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
2000-02-13 01:39:21 +08:00
|
|
|
{ /* Save RLE encoded file, quite difficult */
|
1999-11-04 02:47:35 +08:00
|
|
|
laenge = 0;
|
|
|
|
buf[12] = 0;
|
|
|
|
buf[13] = 1;
|
|
|
|
buf[14] = 0;
|
|
|
|
buf[15] = 0;
|
|
|
|
Zeile = (guchar *) g_malloc (width / (8 / bpp) + 10);
|
|
|
|
ketten = (guchar *) g_malloc (width / (8 / bpp) + 10);
|
2000-02-13 01:39:21 +08:00
|
|
|
for (ypos = height - 1; ypos >= 0; ypos--)
|
|
|
|
{ /* each row separately */
|
|
|
|
/*printf("Line: %i\n",ypos); */
|
1999-11-04 02:47:35 +08:00
|
|
|
j = 0;
|
2000-02-13 01:39:21 +08:00
|
|
|
/* first copy the pixels to a buffer,
|
|
|
|
* making one byte from two 4bit pixels
|
|
|
|
*/
|
|
|
|
for (xpos = 0; xpos < width;)
|
|
|
|
{
|
|
|
|
v = 0;
|
|
|
|
for (i = 1;
|
|
|
|
(i <= (8 / bpp)) && (xpos < width);
|
|
|
|
i++, xpos++)
|
|
|
|
{ /* for each pixel */
|
|
|
|
temp = src + (ypos * rowstride) + (xpos * channels);
|
|
|
|
v = v | ((guchar) * temp << (8 - (i * bpp)));
|
|
|
|
}
|
|
|
|
Zeile[j++] = v;
|
|
|
|
}
|
|
|
|
breite = width / (8 / bpp);
|
|
|
|
if (width % (8 / bpp))
|
|
|
|
breite++;
|
|
|
|
/* then check for strings of equal bytes */
|
|
|
|
for (i = 0; i < breite;)
|
1999-11-04 02:47:35 +08:00
|
|
|
{
|
|
|
|
j = 0;
|
2000-02-13 01:39:21 +08:00
|
|
|
while ((i + j < breite) &&
|
|
|
|
(j < (255 / (8 / bpp))) &&
|
|
|
|
(Zeile[i + j] == Zeile[i]))
|
|
|
|
j++;
|
|
|
|
|
|
|
|
ketten[i] = j;
|
|
|
|
/*printf("%i:",ketten[i]); */
|
|
|
|
i += j;
|
|
|
|
}
|
|
|
|
/*printf("\n"); */
|
|
|
|
|
|
|
|
/* then write the strings and the other pixels to the file */
|
|
|
|
for (i = 0; i < breite;)
|
|
|
|
{
|
|
|
|
if (ketten[i] < 3)
|
|
|
|
/* strings of different pixels ... */
|
|
|
|
{
|
|
|
|
j = 0;
|
|
|
|
while ((i + j < breite) &&
|
|
|
|
(j < (255 / (8 / bpp))) &&
|
|
|
|
(ketten[i + j] < 3))
|
|
|
|
j += ketten[i + j];
|
|
|
|
|
|
|
|
/* this can only happen if j jumps over
|
|
|
|
* the end with a 2 in ketten[i+j]
|
|
|
|
*/
|
|
|
|
if (j > (255 / (8 / bpp)))
|
|
|
|
j -= 2;
|
|
|
|
/* 00 01 and 00 02 are reserved */
|
|
|
|
if (j > 2)
|
|
|
|
{
|
|
|
|
Write (f, &buf[12], 1);
|
|
|
|
n = j * (8 / bpp);
|
|
|
|
if (n + i * (8 / bpp) > width)
|
|
|
|
n--;
|
|
|
|
Write (f, &n, 1);
|
|
|
|
laenge += 2;
|
|
|
|
Write (f, &Zeile[i], j);
|
|
|
|
/*printf("0.%i.",n); */
|
|
|
|
/*for (k=j;k;k--) printf("#"); */
|
|
|
|
laenge += j;
|
|
|
|
if ((j) % 2)
|
|
|
|
{
|
|
|
|
Write (f, &buf[12], 1);
|
|
|
|
laenge++;
|
|
|
|
/*printf("0"); */
|
|
|
|
}
|
|
|
|
/*printf("|"); */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (k = i; k < i + j; k++)
|
|
|
|
{
|
|
|
|
n = (8 / bpp);
|
|
|
|
if (n + i * (8 / bpp) > width)
|
|
|
|
n--;
|
|
|
|
Write (f, &n, 1);
|
|
|
|
Write (f, &Zeile[k], 1);
|
|
|
|
/*printf("%i.#|",n); */
|
|
|
|
laenge += 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
i += j;
|
1999-11-04 02:47:35 +08:00
|
|
|
}
|
2000-02-13 01:39:21 +08:00
|
|
|
else
|
|
|
|
/* strings of equal pixels */
|
|
|
|
{
|
|
|
|
n = ketten[i] * (8 / bpp);
|
1999-11-04 02:47:35 +08:00
|
|
|
if (n + i * (8 / bpp) > width)
|
|
|
|
n--;
|
|
|
|
Write (f, &n, 1);
|
2000-02-13 01:39:21 +08:00
|
|
|
Write (f, &Zeile[i], 1);
|
1999-11-04 02:47:35 +08:00
|
|
|
/*printf("%i.#|",n); */
|
2000-02-13 01:39:21 +08:00
|
|
|
i += ketten[i];
|
1999-11-04 02:47:35 +08:00
|
|
|
laenge += 2;
|
|
|
|
}
|
2000-02-13 01:39:21 +08:00
|
|
|
}
|
|
|
|
/*printf("\n"); */
|
|
|
|
Write (f, &buf[14], 2); /* End of row */
|
|
|
|
laenge += 2;
|
|
|
|
|
|
|
|
cur_progress++;
|
|
|
|
if ((interactive_bmp) &&
|
|
|
|
((cur_progress % 5) == 0))
|
|
|
|
gimp_progress_update ((gdouble) cur_progress /
|
|
|
|
(gdouble) max_progress);
|
1999-11-04 02:47:35 +08:00
|
|
|
}
|
2000-02-13 01:39:21 +08:00
|
|
|
fseek (f, -2, SEEK_CUR); /* Overwrite last End of row ... */
|
|
|
|
Write (f, &buf[12], 2); /* ... with End of file */
|
1998-04-07 11:41:22 +08:00
|
|
|
|
2000-02-13 01:39:21 +08:00
|
|
|
fseek (f, 0x22, SEEK_SET); /* Write length of image */
|
1999-11-04 02:47:35 +08:00
|
|
|
FromL (laenge, puffer);
|
|
|
|
Write (f, puffer, 4);
|
2000-02-13 01:39:21 +08:00
|
|
|
fseek (f, 0x02, SEEK_SET); /* Write length of file */
|
1999-11-04 02:47:35 +08:00
|
|
|
laenge += (0x36 + MapSize);
|
|
|
|
FromL (laenge, puffer);
|
|
|
|
Write (f, puffer, 4);
|
|
|
|
g_free (ketten);
|
|
|
|
g_free (Zeile);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
2000-02-13 01:39:21 +08:00
|
|
|
if (interactive_bmp)
|
|
|
|
gimp_progress_update (1);
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2000-02-13 01:39:21 +08:00
|
|
|
save_dialog (void)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
|
|
|
GtkWidget *dlg;
|
|
|
|
GtkWidget *toggle;
|
|
|
|
GtkWidget *frame;
|
|
|
|
GtkWidget *vbox;
|
1998-04-07 11:41:22 +08:00
|
|
|
|
2000-02-13 01:39:21 +08:00
|
|
|
dlg = gimp_dialog_new (_("Save as BMP"), "bmp",
|
2000-05-23 01:10:28 +08:00
|
|
|
gimp_standard_help_func, "filters/bmp.html",
|
2000-02-13 01:39:21 +08:00
|
|
|
GTK_WIN_POS_MOUSE,
|
|
|
|
FALSE, TRUE, FALSE,
|
|
|
|
|
|
|
|
_("OK"), save_ok_callback,
|
|
|
|
NULL, NULL, NULL, TRUE, FALSE,
|
|
|
|
_("Cancel"), gtk_widget_destroy,
|
|
|
|
NULL, 1, NULL, FALSE, TRUE,
|
|
|
|
|
|
|
|
NULL);
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
|
2000-02-13 01:39:21 +08:00
|
|
|
GTK_SIGNAL_FUNC (gtk_main_quit),
|
1997-11-25 06:05:25 +08:00
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* parameter settings */
|
1999-05-30 00:35:47 +08:00
|
|
|
frame = gtk_frame_new (_("Save Options"));
|
2000-08-28 08:42:32 +08:00
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, TRUE, TRUE, 0);
|
2000-02-13 01:39:21 +08:00
|
|
|
|
|
|
|
vbox = gtk_vbox_new (FALSE, 2);
|
2000-08-28 08:42:32 +08:00
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (frame), vbox);
|
|
|
|
|
1999-05-30 00:35:47 +08:00
|
|
|
toggle = gtk_check_button_new_with_label (_("RLE encoded"));
|
2000-02-13 01:39:21 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
|
2000-02-13 01:39:21 +08:00
|
|
|
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
|
1997-11-25 06:05:25 +08:00
|
|
|
&encoded);
|
1999-01-16 01:35:04 +08:00
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), encoded);
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_widget_show (toggle);
|
|
|
|
|
|
|
|
gtk_widget_show (vbox);
|
|
|
|
gtk_widget_show (frame);
|
|
|
|
gtk_widget_show (dlg);
|
|
|
|
|
|
|
|
gtk_main ();
|
|
|
|
gdk_flush ();
|
2000-02-13 01:39:21 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
return gsint.run;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
save_ok_callback (GtkWidget *widget,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
gsint.run = TRUE;
|
2000-02-13 01:39:21 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
gtk_widget_destroy (GTK_WIDGET (data));
|
|
|
|
}
|