plug-ins/bmp/bmp.[ch] plug-ins/bmp/bmpread.c return STATUS_CANCEL if

2000-02-12  Michael Natterer  <mitch@gimp.org>

	* plug-ins/bmp/bmp.[ch]
	* plug-ins/bmp/bmpread.c
	* plug-ins/bmp/bmpwrite.c: return STATUS_CANCEL if "Cancel" was
	pressed, code & ui cleanups.
This commit is contained in:
Michael Natterer
2000-02-12 17:39:21 +00:00
committed by Michael Natterer
parent 80acd3bf67
commit 6ff6f358d9
5 changed files with 650 additions and 536 deletions

View File

@ -1,3 +1,10 @@
2000-02-12 Michael Natterer <mitch@gimp.org>
* plug-ins/bmp/bmp.[ch]
* plug-ins/bmp/bmpread.c
* plug-ins/bmp/bmpwrite.c: return STATUS_CANCEL if "Cancel" was
pressed, code & ui cleanups.
Sat Feb 12 16:02:12 CET 2000 Sven Neumann <sven@gimp.org>
* app/menus.c: ooops, must have been late

View File

@ -259,10 +259,7 @@ run (gchar *name,
if (status == STATUS_SUCCESS)
{
if (! WriteBMP (param[3].data.d_string, image_ID, drawable_ID))
{
status = STATUS_EXECUTION_ERROR;
}
status = WriteBMP (param[3].data.d_string, image_ID, drawable_ID);
}
if (export == EXPORT_EXPORT)
@ -319,5 +316,3 @@ init_gtk (void)
gtk_init (&argc, &argv);
gtk_rc_parse (gimp_gtkrc ());
}

View File

@ -10,49 +10,77 @@
#define WriteOK(file,buffer,len) (Write(buffer, len, file) != 0)
extern gint32 ToL (guchar *);
extern void FromL(gint32, guchar *);
extern void FromL (gint32,
guchar *);
extern gint16 ToS (guchar *);
extern void FromS(gint16, guchar *);
extern gint32 ReadBMP (char *);
extern gint WriteBMP (char *,gint32,gint32);
extern gint ReadColorMap(FILE *, unsigned char[256][3], int, int, int *);
extern Image ReadImage(FILE *, int, int, unsigned char[256][3], int, int, int, int, int);
extern void WriteColorMap(FILE *, int *, int *, int *, int);
extern void WriteImage(FILE *,guchar *,int,int,int,int,int,int,int);
extern void FromS (gint16,
guchar *);
extern gint32 ReadBMP (gchar *);
extern GStatusType WriteBMP (gchar *,
gint32,
gint32);
extern gint ReadColorMap (FILE *,
guchar[256][3],
gint,
gint,
gint *);
extern Image ReadImage (FILE *,
gint,
gint,
guchar[256][3],
gint,
gint,
gint,
gint,
gint);
extern void WriteColorMap (FILE *,
gint *,
gint *,
gint *,
gint);
extern void WriteImage (FILE *,
guchar *,
gint,
gint,
gint,
gint,
gint,
gint,
gint);
extern int interactive_bmp;
extern char *prog_name;
extern char *filename;
extern gint interactive_bmp;
extern gchar *prog_name;
extern gchar *filename;
extern FILE *errorfile;
extern struct Bitmap_File_Head_Struct
{
unsigned long bfSize; /* 02 */
unsigned long reserverd; /* 06 */
unsigned long bfOffs; /* 0A */
unsigned long biSize; /* 0E */
gulong bfSize; /* 02 */
gulong reserverd; /* 06 */
gulong bfOffs; /* 0A */
gulong biSize; /* 0E */
} Bitmap_File_Head;
extern struct Bitmap_Head_Struct
{
unsigned long biWidth; /* 12 */
unsigned long biHeight; /* 16 */
unsigned short biPlanes; /* 1A */
unsigned short biBitCnt; /* 1C */
unsigned long biCompr; /* 1E */
unsigned long biSizeIm; /* 22 */
unsigned long biXPels; /* 26 */
unsigned long biYPels; /* 2A */
unsigned long biClrUsed; /* 2E */
unsigned long biClrImp; /* 32 */
gulong biWidth; /* 12 */
gulong biHeight; /* 16 */
gushort biPlanes; /* 1A */
gushort biBitCnt; /* 1C */
gulong biCompr; /* 1E */
gulong biSizeIm; /* 22 */
gulong biXPels; /* 26 */
gulong biYPels; /* 2A */
gulong biClrUsed; /* 2E */
gulong biClrImp; /* 32 */
/* 36 */
} Bitmap_Head;
extern struct Bitmap_OS2_Head_Struct
{
unsigned short bcWidth; /* 12 */
unsigned short bcHeight; /* 14 */
unsigned short bcPlanes; /* 16 */
unsigned short bcBitCnt; /* 18 */
gushort bcWidth; /* 12 */
gushort bcHeight; /* 14 */
gushort bcPlanes; /* 16 */
gushort bcBitCnt; /* 18 */
} Bitmap_OS2_Head;

View File

@ -23,23 +23,28 @@
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include "bmp.h"
#include <libgimp/gimp.h>
#include "bmp.h"
#include "libgimp/stdplugins-intl.h"
gint32
ReadBMP (char *name)
ReadBMP (gchar *name)
{
FILE *fd;
char *temp_buf;
char buf[5];
int ColormapSize, SpeicherZeile, Maps, Grey;
unsigned char ColorMap[256][3];
gchar *temp_buf;
gchar buf[5];
gint ColormapSize, SpeicherZeile, Maps, Grey;
guchar ColorMap[256][3];
guchar puffer[50];
gint32 image_ID;
@ -102,7 +107,8 @@ ReadBMP (char *name)
Bitmap_Head.biPlanes = Bitmap_OS2_Head.bcPlanes;
Bitmap_Head.biBitCnt = Bitmap_OS2_Head.bcBitCnt;
Bitmap_File_Head.bfSize=(Bitmap_File_Head.bfSize*4)-(Bitmap_File_Head.bfOffs*3);
Bitmap_File_Head.bfSize = ((Bitmap_File_Head.bfSize * 4) -
(Bitmap_File_Head.bfOffs * 3));
Bitmap_Head.biHeight = Bitmap_OS2_Head.bcHeight;
Bitmap_Head.biWidth = Bitmap_OS2_Head.bcWidth;
Bitmap_Head.biClrUsed = 0;
@ -130,22 +136,31 @@ ReadBMP (char *name)
Maps = 4;
}
/* This means wrong file Format. I test this because it could crash the */
/* entire gimp. */
/* This means wrong file Format. I test this because it could crash the
* entire gimp.
*/
if (Bitmap_Head.biBitCnt > 24)
{
g_message (_("%s: too many colors: %u\n"), prog_name,
(unsigned int) Bitmap_Head.biBitCnt);
(guint) Bitmap_Head.biBitCnt);
return -1;
}
/* There should be some colors used! */
ColormapSize = (Bitmap_File_Head.bfOffs - Bitmap_File_Head.biSize - 14) / Maps;
if ((Bitmap_Head.biClrUsed==0) && (Bitmap_Head.biBitCnt<24)) Bitmap_Head.biClrUsed=ColormapSize;
if (Bitmap_Head.biBitCnt==24) SpeicherZeile=((Bitmap_File_Head.bfSize-Bitmap_File_Head.bfOffs)/Bitmap_Head.biHeight);
else SpeicherZeile=((Bitmap_File_Head.bfSize-Bitmap_File_Head.bfOffs)/Bitmap_Head.biHeight)*(8/Bitmap_Head.biBitCnt);
if ((Bitmap_Head.biClrUsed == 0) &&
(Bitmap_Head.biBitCnt < 24))
Bitmap_Head.biClrUsed = ColormapSize;
if (Bitmap_Head.biBitCnt == 24)
SpeicherZeile = ((Bitmap_File_Head.bfSize - Bitmap_File_Head.bfOffs) /
Bitmap_Head.biHeight);
else
SpeicherZeile = ((Bitmap_File_Head.bfSize - Bitmap_File_Head.bfOffs) /
Bitmap_Head.biHeight) * (8 / Bitmap_Head.biBitCnt);
#ifdef DEBUG
printf("\nSize: %u, Colors: %u, Bits: %u, Width: %u, Height: %u, Comp: %u, Zeile: %u\n",
@ -155,7 +170,8 @@ ReadBMP (char *name)
/* Get the Colormap */
if (ReadColorMap(fd, ColorMap, ColormapSize, Maps, &Grey) == -1) return -1;
if (ReadColorMap (fd, ColorMap, ColormapSize, Maps, &Grey) == -1)
return -1;
#ifdef DEBUG
printf("Colormap read\n");
@ -175,8 +191,8 @@ ReadBMP (char *name)
#ifdef GIMP_HAVE_RESOLUTION_INFO
{
/* quick hack by the muppet, scott@asofyet.org, 19 dec 1999 */
double xresolution;
double yresolution;
gdouble xresolution;
gdouble yresolution;
/*
* xresolution and yresolution are in dots per inch.
@ -203,13 +219,13 @@ ReadBMP (char *name)
gint
ReadColorMap (FILE *fd,
unsigned char buffer[256][3],
int number,
int size,
int *grey)
guchar buffer[256][3],
gint number,
gint size,
gint *grey)
{
int i;
unsigned char rgb[4];
gint i;
guchar rgb[4];
*grey=(number>2);
for (i = 0; i < number ; i++)
@ -222,11 +238,14 @@ ReadColorMap (FILE *fd,
/* Bitmap save the colors in another order! But change only once! */
if (size==4) {
if (size == 4)
{
buffer[i][0] = rgb[2];
buffer[i][1] = rgb[1];
buffer[i][2] = rgb[0];
} else {
}
else
{
/* this one is for old os2 Bitmaps, but it dosn't work well */
buffer[i][0] = rgb[1];
buffer[i][1] = rgb[0];
@ -234,39 +253,40 @@ ReadColorMap (FILE *fd,
}
*grey = ((*grey) && (rgb[0]==rgb[1]) && (rgb[1]==rgb[2]));
}
return(0);
return 0;
}
Image
ReadImage (FILE *fd,
int len,
int height,
unsigned char cmap[256][3],
int ncols,
int bpp,
int compression,
int spzeile,
int grey)
gint len,
gint height,
guchar cmap[256][3],
gint ncols,
gint bpp,
gint compression,
gint spzeile,
gint grey)
{
char *name_buf;
unsigned char v,wieviel;
gchar *name_buf;
guchar v,wieviel;
GPixelRgn pixel_rgn;
char buf[16];
int xpos = 0, ypos = 0;
gchar buf[16];
gint xpos = 0, ypos = 0;
Image image;
gint32 layer;
GDrawable *drawable;
guchar *dest, *temp;
guchar gimp_cmap[768];
long rowstride, channels;
int i, j, cur_progress, max_progress, egal;
gint i, j, cur_progress, max_progress, egal;
/* Make a new image in the gimp */
if (grey)
{
image = gimp_image_new (len, height, GRAY);
layer = gimp_layer_new (image, _("Background"), len, height, GRAY_IMAGE, 100, NORMAL_MODE);
layer = gimp_layer_new (image, _("Background"),
len, height, GRAY_IMAGE, 100, NORMAL_MODE);
channels = 1;
}
else
@ -274,13 +294,15 @@ ReadImage (FILE *fd,
if (bpp<24)
{
image = gimp_image_new (len, height, INDEXED);
layer = gimp_layer_new (image, _("Background"), len, height, INDEXED_IMAGE, 100, NORMAL_MODE);
layer = gimp_layer_new (image, _("Background"),
len, height, INDEXED_IMAGE, 100, NORMAL_MODE);
channels = 1;
}
else
{
image = gimp_image_new (len, height, RGB);
layer = gimp_layer_new (image, _("Background"), len, height, RGB_IMAGE, 100, NORMAL_MODE);
layer = gimp_layer_new (image, _("Background"),
len, height, RGB_IMAGE, 100, NORMAL_MODE);
channels = 3;
}
}
@ -316,14 +338,20 @@ ReadImage (FILE *fd,
egal=ReadOK (fd, buf, spzeile - (len * 3));
ypos--;
xpos = 0;
cur_progress++;
if ((interactive_bmp) &&((cur_progress % 5) == 0))
gimp_progress_update ((double) cur_progress / (double) max_progress);
if ((interactive_bmp) &&
((cur_progress % 5) == 0))
gimp_progress_update ((gdouble) cur_progress /
(gdouble) max_progress);
}
if (ypos < 0) break;
if (ypos < 0)
break;
}
}
else { switch(compression)
else
{
switch(compression)
{
case 0: /* uncompressed */
{
@ -333,18 +361,23 @@ ReadImage (FILE *fd,
{
temp = dest + (ypos * rowstride) + (xpos * channels);
*temp=( v & ( ((1<<bpp)-1) << (8-(i*bpp)) ) ) >> (8-(i*bpp));
if (grey) *temp=cmap[*temp][0];
if (grey)
*temp = cmap[*temp][0];
}
if (xpos == len)
{
egal = ReadOK (fd, buf, (spzeile - len) / (8 / bpp));
ypos--;
xpos = 0;
cur_progress++;
if ((interactive_bmp) && ((cur_progress % 5) == 0))
gimp_progress_update ((double) cur_progress / (double) max_progress);
if ((interactive_bmp) &&
((cur_progress % 5) == 0))
gimp_progress_update ((gdouble) cur_progress /
(gdouble) max_progress);
}
if (ypos < 0) break;
if (ypos < 0)
break;
}
break;
}
@ -353,23 +386,28 @@ ReadImage (FILE *fd,
while (TRUE)
{
egal = ReadOK (fd, buf, 2);
if ((unsigned char) buf[0]!=0)
if ((guchar) buf[0] != 0)
/* Count + Color - record */
{
for (j=0;((unsigned char) j < (unsigned char) buf[0]) && (xpos<len);)
for (j = 0; ((guchar) j < (guchar) buf[0]) && (xpos < len);)
{
#ifdef DEBUG2
printf("%u %u | ",xpos,len);
#endif
for (i=1;((i<=(8/bpp)) && (xpos<len) && ((unsigned char) j < (unsigned char) buf[0]));i++,xpos++,j++)
for (i = 1;
((i <= (8 / bpp)) &&
(xpos < len) &&
((guchar) j < (unsigned char) buf[0]));
i++, xpos++, j++)
{
temp = dest + (ypos * rowstride) + (xpos * channels);
*temp = (buf[1] & (((1<<bpp)-1) << (8 - (i * bpp)))) >> (8 - (i * bpp));
if (grey) *temp=cmap[*temp][0];
if (grey)
*temp = cmap[*temp][0];
}
}
}
if (((unsigned char) buf[0]==0) && ((unsigned char) buf[1]>2))
if (((guchar) buf[0] == 0) && ((guchar) buf[1] > 2))
/* uncompressed record */
{
wieviel = buf[1];
@ -381,34 +419,42 @@ ReadImage (FILE *fd,
{
temp = dest + (ypos * rowstride) + (xpos * channels);
*temp = (v & (((1<<bpp)-1) << (8-(i*bpp)))) >> (8-(i*bpp));
if (grey) *temp=cmap[*temp][0];
if (grey)
*temp = cmap[*temp][0];
i++;
xpos++;
}
}
if ((wieviel % 2) && (bpp==4)) wieviel++;
if ( (wieviel / (8/bpp)) % 2) egal=ReadOK(fd,&v,1);
if ((wieviel % 2) && (bpp==4))
wieviel++;
if ((wieviel / (8 / bpp)) % 2)
egal = ReadOK (fd, &v, 1);
/*if odd(x div (8 div bpp )) then blockread(f,z^,1);*/
}
if (((unsigned char) buf[0]==0) && ((unsigned char) buf[1]==0))
if (((guchar) buf[0] == 0) && ((guchar) buf[1]==0))
/* Zeilenende */
{
ypos--;
xpos = 0;
cur_progress++;
if ((interactive_bmp) && ((cur_progress % 5) == 0))
gimp_progress_update ((double) cur_progress / (double) max_progress);
if ((interactive_bmp) &&
((cur_progress % 5) == 0))
gimp_progress_update ((gdouble) cur_progress /
(gdouble) max_progress);
}
if (((unsigned char) buf[0]==0) && ((unsigned char) buf[1]==1))
if (((guchar) buf[0]==0) && ((guchar) buf[1]==1))
/* Bitmapende */
{
break;
}
if (((unsigned char) buf[0]==0) && ((unsigned char) buf[1]==2))
if (((guchar) buf[0]==0) && ((guchar) buf[1]==2))
/* Deltarecord */
{
xpos+=(unsigned char) buf[2];
ypos+=(unsigned char) buf[3];
xpos += (guchar) buf[2];
ypos += (guchar) buf[3];
}
}
break;
@ -417,20 +463,28 @@ ReadImage (FILE *fd,
}
fclose (fd);
if (bpp<24) for (i = 0, j = 0; i < ncols; i++)
if (bpp < 24)
for (i = 0, j = 0; i < ncols; i++)
{
gimp_cmap[j++] = cmap[i][0];
gimp_cmap[j++] = cmap[i][1];
gimp_cmap[j++] = cmap[i][2];
}
if (interactive_bmp) gimp_progress_update (1);
gimp_pixel_rgn_init(&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, TRUE, FALSE);
gimp_pixel_rgn_set_rect(&pixel_rgn, dest, 0, 0, drawable->width, drawable->height);
if ((!grey) && (bpp<24)) gimp_image_set_cmap(image, gimp_cmap, ncols);
if (interactive_bmp)
gimp_progress_update (1);
gimp_pixel_rgn_init (&pixel_rgn, drawable,
0, 0, drawable->width, drawable->height, TRUE, FALSE);
gimp_pixel_rgn_set_rect (&pixel_rgn, dest,
0, 0, drawable->width, drawable->height);
if ((!grey) && (bpp<24))
gimp_image_set_cmap (image, gimp_cmap, ncols);
gimp_drawable_flush (drawable);
gimp_drawable_detach (drawable);
g_free (dest);
return (image);
return image;
}

View File

@ -37,14 +37,18 @@
#endif
#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "bmp.h"
#include "libgimp/stdplugins-intl.h"
guchar *pixels;
int cur_progress;
gint cur_progress;
int max_progress;
gint max_progress;
typedef struct
{
@ -56,40 +60,40 @@ static BMPSaveInterface gsint =
FALSE /* run */
};
int encoded = 0;
gint encoded = 0;
static gint save_dialog (void);
static void save_close_callback (GtkWidget *widget, gpointer data);
static void save_ok_callback (GtkWidget *widget, gpointer data);
static void save_toggle_update (GtkWidget *widget, gpointer data);
static void save_ok_callback (GtkWidget *widget,
gpointer data);
gint
WriteBMP (char *filename,
GStatusType
WriteBMP (gchar *filename,
gint32 image,
gint32 drawable_ID)
{
FILE *outfile;
int Red[MAXCOLORS];
int Green[MAXCOLORS];
int Blue[MAXCOLORS];
unsigned char *cmap;
int rows, cols, Spcols, channels, MapSize, SpZeile;
long BitsPerPixel;
int colors;
char *temp_buf;
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;
guchar *pixels;
GPixelRgn pixel_rgn;
GDrawable *drawable;
GDrawableType drawable_type;
guchar puffer[50];
int i;
gint i;
/* first: can we save this image? */
drawable = gimp_drawable_get(drawable_ID);
drawable_type = gimp_drawable_type(drawable_ID);
gimp_pixel_rgn_init(&pixel_rgn, drawable, 0, 0, drawable->width, drawable->height, FALSE, FALSE);
gimp_pixel_rgn_init (&pixel_rgn, drawable,
0, 0, drawable->width, drawable->height, FALSE, FALSE);
switch (drawable_type)
{
case RGB_IMAGE:
@ -98,7 +102,7 @@ WriteBMP (char *filename,
break;
default:
g_message(_("bmp: cannot operate on unknown image types or alpha images"));
gimp_quit ();
return STATUS_EXECUTION_ERROR;
break;
}
@ -128,8 +132,13 @@ WriteBMP (char *filename,
cmap = gimp_image_get_cmap (image, &colors);
MapSize = 4 * colors;
channels = 1;
if (colors>16) BitsPerPixel=8; else if (colors>2) BitsPerPixel=4;
else BitsPerPixel=1;
if (colors > 16)
BitsPerPixel = 8;
else if (colors > 2)
BitsPerPixel = 4;
else
BitsPerPixel = 1;
for (i = 0; i < colors; i++)
{
@ -140,7 +149,7 @@ WriteBMP (char *filename,
break;
default:
fprintf (stderr, "%s: This should not happen\n", prog_name);
return FALSE;
return STATUS_EXECUTION_ERROR;
}
/* Perhaps someone wants RLE encoded Bitmaps */
@ -148,7 +157,7 @@ WriteBMP (char *filename,
if ((BitsPerPixel == 8 || BitsPerPixel == 4) && interactive_bmp)
{
if (! save_dialog ())
return -1;
return STATUS_CANCEL;
}
/* Let's take some file */
@ -156,16 +165,15 @@ WriteBMP (char *filename,
if (!outfile)
{
g_message (_("can't open %s\n"), filename);
return -1;
return STATUS_EXECUTION_ERROR;
}
/* fetch the image */
pixels = (guchar *) g_malloc(drawable->width*drawable->height*channels);
gimp_pixel_rgn_get_rect(&pixel_rgn, pixels, 0, 0, drawable->width, drawable->height);
pixels = g_new (guchar, drawable->width * drawable->height * channels);
gimp_pixel_rgn_get_rect (&pixel_rgn, pixels,
0, 0, drawable->width, drawable->height);
/* And let's begin the progress */
if (interactive_bmp)
{
temp_buf = g_strdup_printf (_("Saving %s:"), filename);
@ -176,35 +184,51 @@ WriteBMP (char *filename,
max_progress = drawable->height;
/* Now, we need some further information ... */
cols = drawable->width;
rows = drawable->height;
/* ... that we write to our headers. */
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;
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=((int)(((Spcols*BitsPerPixel)/8)/4)+1)*4;
Bitmap_File_Head.bfSize = 0x36 + MapSize + (rows * SpZeile);
Bitmap_File_Head.reserverd = 0;
Bitmap_File_Head.bfOffs = 0x36 + MapSize;
Bitmap_File_Head.biSize = 40;
Bitmap_Head.biWidth = cols;
Bitmap_Head.biHeight = rows;
Bitmap_Head.biPlanes = 1;
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;
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;
#ifdef GIMP_HAVE_RESOLUTION_INFO
{
double xresolution;
double yresolution;
gdouble xresolution;
gdouble yresolution;
gimp_image_get_resolution (image, &xresolution, &yresolution);
if (xresolution > 1e-5 && yresolution > 1e-5) {
if (xresolution > GIMP_MIN_RESOLUTION &&
yresolution > GIMP_MIN_RESOLUTION)
{
/*
* xresolution and yresolution are in dots per inch.
* the BMP spec says that biXPels and biYPels are in
@ -262,33 +286,36 @@ WriteBMP (char *filename,
/* After that is done, we write the image ... */
WriteImage(outfile, pixels, cols, rows, encoded, channels, BitsPerPixel, SpZeile, MapSize);
WriteImage (outfile,
pixels, cols, rows,
encoded, channels, BitsPerPixel, SpZeile, MapSize);
/* ... and exit normally */
fclose (outfile);
gimp_drawable_detach (drawable);
g_free (pixels);
return TRUE;
return STATUS_SUCCESS;
}
void
WriteColorMap (FILE *f,
int red[MAXCOLORS],
int green[MAXCOLORS],
int blue[MAXCOLORS],
int size)
gint red[MAXCOLORS],
gint green[MAXCOLORS],
gint blue[MAXCOLORS],
gint size)
{
char trgb[4];
int i;
gchar trgb[4];
gint i;
size=size/4;
size /= 4;
trgb[3] = 0;
for (i = 0; i < size; i++)
{
trgb[0]=(unsigned char) blue[i];
trgb[1]=(unsigned char) green[i];
trgb[2]=(unsigned char) red[i];
trgb[0] = (guchar) blue[i];
trgb[1] = (guchar) green[i];
trgb[2] = (guchar) red[i];
Write (f, trgb, 4);
}
}
@ -296,20 +323,20 @@ WriteColorMap (FILE *f,
void
WriteImage (FILE *f,
guchar *src,
int width,
int height,
int encoded,
int channels,
int bpp,
int spzeile,
int MapSize)
gint width,
gint height,
gint encoded,
gint channels,
gint bpp,
gint spzeile,
gint MapSize)
{
guchar buf[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0};
guchar puffer[8];
guchar *temp, v;
guchar *Zeile, *ketten;
int xpos,ypos,i,j,rowstride,laenge,thiswidth;
int breite, n, k;
gint xpos, ypos, i, j, rowstride, laenge, thiswidth;
gint breite, n, k;
xpos = 0;
rowstride = width * channels;
@ -323,43 +350,57 @@ WriteImage (FILE *f,
for (i = 0; i < width; i++) /* for each pixel */
{
temp = src + (ypos * rowstride) + (xpos * channels);
buf[2]=(unsigned char) *temp;
buf[2] = (guchar) *temp;
temp++;
buf[1]=(unsigned char) *temp;
buf[1] = (guchar) *temp;
temp++;
buf[0]=(unsigned char) *temp;
buf[0] = (guchar) *temp;
xpos++;
Write (f, buf, 3);
}
Write (f, &buf[3], spzeile - (width * 3));
cur_progress++;
if ((interactive_bmp) && ((cur_progress % 5) == 0)) gimp_progress_update ((double) cur_progress / (double) max_progress);
if ((interactive_bmp) &&
((cur_progress % 5) == 0))
gimp_progress_update ((gdouble) cur_progress /
(gdouble) max_progress);
xpos = 0;
}
} else {
}
else
{
switch (encoded) /* now it gets more difficult */
{ /* uncompressed 1,4 and 8 bit */
case 0:
{
thiswidth = (width / (8 / bpp));
if (width % (8/bpp)) thiswidth++;
if (width % (8 / bpp))
thiswidth++;
for (ypos = height - 1; ypos >= 0; ypos--) /* for each row */
{
for (xpos = 0; xpos < width;) /* for each _byte_ */
{
v = 0;
for (i=1;(i<=(8/bpp)) && (xpos<width);i++,xpos++) /* for each pixel */
for (i = 1;
(i <= (8 / bpp)) && (xpos < width);
i++, xpos++) /* for each pixel */
{
temp = src + (ypos * rowstride) + (xpos * channels);
v=v | ((unsigned char) *temp << (8-(i*bpp)));
v=v | ((guchar) *temp << (8 - (i * bpp)));
}
Write (f, &v, 1);
}
Write (f, &buf[3], spzeile - thiswidth);
xpos = 0;
cur_progress++;
if ((interactive_bmp) && ((cur_progress % 5) == 0))
gimp_progress_update ((double) cur_progress / (double) max_progress);
if ((interactive_bmp) &&
((cur_progress % 5) == 0))
gimp_progress_update ((gdouble) cur_progress /
(gdouble) max_progress);
}
break;
}
@ -372,13 +413,20 @@ WriteImage (FILE *f,
buf[15] = 0;
Zeile = (guchar *) g_malloc (width / (8 / bpp) + 10);
ketten = (guchar *) g_malloc (width / (8 / bpp) + 10);
for (ypos = height - 1; ypos >= 0; ypos--) { /* each row separately */
for (ypos = height - 1; ypos >= 0; ypos--)
{ /* each row separately */
/*printf("Line: %i\n",ypos); */
j = 0;
/* first copy the pixels to a buffer, making one byte from two 4bit pixels */
for (xpos = 0; xpos < width;) {
/* 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 */
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)));
}
@ -388,28 +436,40 @@ WriteImage (FILE *f,
if (width % (8 / bpp))
breite++;
/* then check for strings of equal bytes */
for (i = 0; i < breite;) {
for (i = 0; i < breite;)
{
j = 0;
while ((i + j < breite) && (j < (255 / (8 / bpp))) && (Zeile[i + j] == Zeile[i]))
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;) {
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))
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] */
/* 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) {
if (j > 2)
{
Write (f, &buf[12], 1);
n = j * (8 / bpp);
if (n + i * (8 / bpp) > width)
@ -420,13 +480,18 @@ WriteImage (FILE *f,
/*printf("0.%i.",n); */
/*for (k=j;k;k--) printf("#"); */
laenge += j;
if ((j) % 2) {
if ((j) % 2)
{
Write (f, &buf[12], 1);
laenge++; /*printf("0"); */
laenge++;
/*printf("0"); */
}
/*printf("|"); */
} else {
for (k = i; k < i + j; k++) {
}
else
{
for (k = i; k < i + j; k++)
{
n = (8 / bpp);
if (n + i * (8 / bpp) > width)
n--;
@ -437,7 +502,8 @@ WriteImage (FILE *f,
}
}
i += j;
} else
}
else
/* strings of equal pixels */
{
n = ketten[i] * (8 / bpp);
@ -453,9 +519,12 @@ WriteImage (FILE *f,
/*printf("\n"); */
Write (f, &buf[14], 2); /* End of row */
laenge += 2;
cur_progress++;
if ((interactive_bmp) && ((cur_progress % 5) == 0))
gimp_progress_update ((double)cur_progress / max_progress);
if ((interactive_bmp) &&
((cur_progress % 5) == 0))
gimp_progress_update ((gdouble) cur_progress /
(gdouble) max_progress);
}
fseek (f, -2, SEEK_CUR); /* Overwrite last End of row ... */
Write (f, &buf[12], 2); /* ... with End of file */
@ -473,67 +542,47 @@ WriteImage (FILE *f,
}
}
}
if (interactive_bmp) gimp_progress_update(1);
if (interactive_bmp)
gimp_progress_update (1);
}
/* These ones are just copied from the GIF-plugin */
static gint
save_dialog ()
save_dialog (void)
{
GtkWidget *dlg;
GtkWidget *button;
GtkWidget *hbbox;
GtkWidget *toggle;
GtkWidget *frame;
GtkWidget *vbox;
dlg = gtk_dialog_new ();
gtk_window_set_title (GTK_WINDOW (dlg), _("Save as BMP"));
gtk_window_position (GTK_WINDOW (dlg), GTK_WIN_POS_MOUSE);
gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
(GtkSignalFunc) save_close_callback,
dlg = gimp_dialog_new (_("Save as BMP"), "bmp",
gimp_plugin_help_func, "filters/bmp.html",
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);
/* Action area */
gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dlg)->action_area), 2);
gtk_box_set_homogeneous (GTK_BOX (GTK_DIALOG (dlg)->action_area), FALSE);
hbbox = gtk_hbutton_box_new ();
gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbbox), 4);
gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dlg)->action_area), hbbox, FALSE, FALSE, 0);
gtk_widget_show (hbbox);
button = gtk_button_new_with_label (_("OK"));
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_signal_connect (GTK_OBJECT (button), "clicked",
(GtkSignalFunc) save_ok_callback,
dlg);
gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0);
gtk_widget_grab_default (button);
gtk_widget_show (button);
button = gtk_button_new_with_label (_("Cancel"));
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
(GtkSignalFunc) gtk_widget_destroy,
GTK_OBJECT (dlg));
gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0);
gtk_widget_show (button);
gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
GTK_SIGNAL_FUNC (gtk_main_quit),
NULL);
/* parameter settings */
frame = gtk_frame_new (_("Save Options"));
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
gtk_container_border_width (GTK_CONTAINER (frame), 4);
gtk_container_border_width (GTK_CONTAINER (frame), 6);
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, TRUE, TRUE, 0);
vbox = gtk_vbox_new (FALSE, 4);
vbox = gtk_vbox_new (FALSE, 2);
gtk_container_border_width (GTK_CONTAINER (vbox), 4);
gtk_container_add (GTK_CONTAINER (frame), vbox);
toggle = gtk_check_button_new_with_label (_("RLE encoded"));
gtk_box_pack_start (GTK_BOX (vbox), toggle, TRUE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
(GtkSignalFunc) save_toggle_update,
GTK_SIGNAL_FUNC (gimp_toggle_button_update),
&encoded);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), encoded);
gtk_widget_show (toggle);
@ -544,14 +593,8 @@ save_dialog ()
gtk_main ();
gdk_flush ();
return gsint.run;
}
static void
save_close_callback (GtkWidget *widget,
gpointer data)
{
gtk_main_quit ();
return gsint.run;
}
static void
@ -559,19 +602,6 @@ save_ok_callback (GtkWidget *widget,
gpointer data)
{
gsint.run = TRUE;
gtk_widget_destroy (GTK_WIDGET (data));
}
static void
save_toggle_update (GtkWidget *widget,
gpointer data)
{
int *toggle_val;
toggle_val = (int *) data;
if (GTK_TOGGLE_BUTTON (widget)->active)
*toggle_val = TRUE;
else
*toggle_val = FALSE;
}