1
/* bmpread.c reads any bitmap I could get for testing */
2
/* Alexander.Schulz@stud.uni-karlsruhe.de */
5
* GIMP - The GNU Image Manipulation Program
6
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
* ----------------------------------------------------------------------------
29
#include <glib/gstdio.h>
31
#include <libgimp/gimp.h>
35
#include "libgimp/stdplugins-intl.h"
38
#if !defined(WIN32) || defined(__MINGW32__)
42
#define BI_BITFIELDS 3
45
static gint32 ReadImage (FILE *fd,
54
const Bitmap_Channel *masks);
58
ToL (const guchar *puffer)
60
return (puffer[0] | puffer[1] << 8 | puffer[2] << 16 | puffer[3] << 24);
64
ToS (const guchar *puffer)
66
return (puffer[0] | puffer[1] << 8);
70
ReadColorMap (FILE *fd,
71
guchar buffer[256][3],
81
for (i = 0; i < number ; i++)
83
if (!ReadOK (fd, rgb, size))
85
g_message (_("Bad colormap"));
89
/* Bitmap save the colors in another order! But change only once! */
91
buffer[i][0] = rgb[2];
92
buffer[i][1] = rgb[1];
93
buffer[i][2] = rgb[0];
94
*grey = ((*grey) && (rgb[0]==rgb[1]) && (rgb[1]==rgb[2]));
100
ReadChannelMasks (guint32 *tmp, Bitmap_Channel *masks, guint channels)
103
gint i, nbits, offset, bit;
105
for (i = 0; i < channels; i++)
108
masks[i].mask = mask;
111
for (bit = 0; bit < 32; bit++)
121
masks[i].shiftin = offset;
122
masks[i].max_value = (gfloat)((1<<(nbits))-1);
125
g_print ("Channel %d mask %08x in %d max_val %d\n",
126
i, masks[i].mask, masks[i].shiftin, (gint)masks[i].max_value);
133
ReadBMP (const gchar *name)
137
gint ColormapSize, rowbytes, Maps;
138
gboolean Grey = FALSE;
139
guchar ColorMap[256][3];
142
Bitmap_Channel masks[4];
145
fd = g_fopen (filename, "rb");
149
g_message (_("Could not open '%s' for reading: %s"),
150
gimp_filename_to_utf8 (filename), g_strerror (errno));
154
gimp_progress_init_printf (_("Opening '%s'"),
155
gimp_filename_to_utf8 (name));
157
/* It is a File. Now is it a Bitmap? Read the shortest possible header */
159
if (!ReadOK (fd, magick, 2) || !(!strncmp (magick, "BA", 2) ||
160
!strncmp (magick, "BM", 2) || !strncmp (magick, "IC", 2) ||
161
!strncmp (magick, "PI", 2) || !strncmp (magick, "CI", 2) ||
162
!strncmp (magick, "CP", 2)))
164
g_message (_("'%s' is not a valid BMP file"),
165
gimp_filename_to_utf8 (filename));
169
while (!strncmp (magick, "BA", 2))
171
if (!ReadOK (fd, buffer, 12))
173
g_message (_("'%s' is not a valid BMP file"),
174
gimp_filename_to_utf8 (filename));
177
if (!ReadOK (fd, magick, 2))
179
g_message (_("'%s' is not a valid BMP file"),
180
gimp_filename_to_utf8 (filename));
185
if (!ReadOK (fd, buffer, 12))
187
g_message (_("'%s' is not a valid BMP file"),
188
gimp_filename_to_utf8 (filename));
192
/* bring them to the right byteorder. Not too nice, but it should work */
194
Bitmap_File_Head.bfSize = ToL (&buffer[0x00]);
195
Bitmap_File_Head.zzHotX = ToS (&buffer[0x04]);
196
Bitmap_File_Head.zzHotY = ToS (&buffer[0x06]);
197
Bitmap_File_Head.bfOffs = ToL (&buffer[0x08]);
199
if (!ReadOK (fd, buffer, 4))
201
g_message (_("'%s' is not a valid BMP file"),
202
gimp_filename_to_utf8 (filename));
206
Bitmap_File_Head.biSize = ToL (&buffer[0x00]);
208
/* What kind of bitmap is it? */
210
if (Bitmap_File_Head.biSize == 12) /* OS/2 1.x ? */
212
if (!ReadOK (fd, buffer, 8))
214
g_message (_("Error reading BMP file header from '%s'"),
215
gimp_filename_to_utf8 (filename));
219
Bitmap_Head.biWidth = ToS (&buffer[0x00]); /* 12 */
220
Bitmap_Head.biHeight = ToS (&buffer[0x02]); /* 14 */
221
Bitmap_Head.biPlanes = ToS (&buffer[0x04]); /* 16 */
222
Bitmap_Head.biBitCnt = ToS (&buffer[0x06]); /* 18 */
223
Bitmap_Head.biCompr = 0;
224
Bitmap_Head.biSizeIm = 0;
225
Bitmap_Head.biXPels = Bitmap_Head.biYPels = 0;
226
Bitmap_Head.biClrUsed = 0;
227
Bitmap_Head.biClrImp = 0;
228
Bitmap_Head.masks[0] = 0;
229
Bitmap_Head.masks[1] = 0;
230
Bitmap_Head.masks[2] = 0;
231
Bitmap_Head.masks[3] = 0;
233
memset(masks, 0, sizeof(masks));
236
else if (Bitmap_File_Head.biSize == 40) /* Windows 3.x */
238
if (!ReadOK (fd, buffer, 36))
240
g_message (_("Error reading BMP file header from '%s'"),
241
gimp_filename_to_utf8 (filename));
244
Bitmap_Head.biWidth = ToL (&buffer[0x00]); /* 12 */
245
Bitmap_Head.biHeight = ToL (&buffer[0x04]); /* 16 */
246
Bitmap_Head.biPlanes = ToS (&buffer[0x08]); /* 1A */
247
Bitmap_Head.biBitCnt = ToS (&buffer[0x0A]); /* 1C */
248
Bitmap_Head.biCompr = ToL (&buffer[0x0C]); /* 1E */
249
Bitmap_Head.biSizeIm = ToL (&buffer[0x10]); /* 22 */
250
Bitmap_Head.biXPels = ToL (&buffer[0x14]); /* 26 */
251
Bitmap_Head.biYPels = ToL (&buffer[0x18]); /* 2A */
252
Bitmap_Head.biClrUsed = ToL (&buffer[0x1C]); /* 2E */
253
Bitmap_Head.biClrImp = ToL (&buffer[0x20]); /* 32 */
254
Bitmap_Head.masks[0] = 0;
255
Bitmap_Head.masks[1] = 0;
256
Bitmap_Head.masks[2] = 0;
257
Bitmap_Head.masks[3] = 0;
260
memset(masks, 0, sizeof(masks));
262
if (Bitmap_Head.biCompr == BI_BITFIELDS)
264
if (!ReadOK (fd, buffer, 3 * sizeof (guint32)))
266
g_message (_("Error reading BMP file header from '%s'"),
267
gimp_filename_to_utf8 (filename));
270
Bitmap_Head.masks[0] = ToL(&buffer[0x00]);
271
Bitmap_Head.masks[1] = ToL(&buffer[0x04]);
272
Bitmap_Head.masks[2] = ToL(&buffer[0x08]);
273
ReadChannelMasks (&Bitmap_Head.masks[0], masks, 3);
276
switch (Bitmap_Head.biBitCnt)
279
masks[0].mask = 0x00ff0000;
280
masks[0].shiftin = 16;
281
masks[0].max_value= (gfloat)255.0;
282
masks[1].mask = 0x0000ff00;
283
masks[1].shiftin = 8;
284
masks[1].max_value= (gfloat)255.0;
285
masks[2].mask = 0x000000ff;
286
masks[2].shiftin = 0;
287
masks[2].max_value= (gfloat)255.0;
288
masks[3].mask = 0xff000000;
289
masks[3].shiftin = 24;
290
masks[3].max_value= (gfloat)255.0;
293
masks[0].mask = 0xff0000;
294
masks[0].shiftin = 16;
295
masks[0].max_value= (gfloat)255.0;
296
masks[1].mask = 0x00ff00;
297
masks[1].shiftin = 8;
298
masks[1].max_value= (gfloat)255.0;
299
masks[2].mask = 0x0000ff;
300
masks[2].shiftin = 0;
301
masks[2].max_value= (gfloat)255.0;
303
masks[3].shiftin = 0;
304
masks[3].max_value= (gfloat)0.0;
307
masks[0].mask = 0x7c00;
308
masks[0].shiftin = 10;
309
masks[0].max_value= (gfloat)31.0;
310
masks[1].mask = 0x03e0;
311
masks[1].shiftin = 5;
312
masks[1].max_value= (gfloat)31.0;
313
masks[2].mask = 0x001f;
314
masks[2].shiftin = 0;
315
masks[2].max_value= (gfloat)31.0;
317
masks[3].shiftin = 0;
318
masks[3].max_value= (gfloat)0.0;
324
else if (Bitmap_File_Head.biSize >= 56 && Bitmap_File_Head.biSize <= 64)
325
/* enhanced Windows format with bit masks */
327
if (!ReadOK (fd, buffer, Bitmap_File_Head.biSize - 4))
329
g_message (_("Error reading BMP file header from '%s'"),
330
gimp_filename_to_utf8 (filename));
333
Bitmap_Head.biWidth =ToL (&buffer[0x00]); /* 12 */
334
Bitmap_Head.biHeight =ToL (&buffer[0x04]); /* 16 */
335
Bitmap_Head.biPlanes =ToS (&buffer[0x08]); /* 1A */
336
Bitmap_Head.biBitCnt =ToS (&buffer[0x0A]); /* 1C */
337
Bitmap_Head.biCompr =ToL (&buffer[0x0C]); /* 1E */
338
Bitmap_Head.biSizeIm =ToL (&buffer[0x10]); /* 22 */
339
Bitmap_Head.biXPels =ToL (&buffer[0x14]); /* 26 */
340
Bitmap_Head.biYPels =ToL (&buffer[0x18]); /* 2A */
341
Bitmap_Head.biClrUsed =ToL (&buffer[0x1C]); /* 2E */
342
Bitmap_Head.biClrImp =ToL (&buffer[0x20]); /* 32 */
343
Bitmap_Head.masks[0] =ToL (&buffer[0x24]); /* 36 */
344
Bitmap_Head.masks[1] =ToL (&buffer[0x28]); /* 3A */
345
Bitmap_Head.masks[2] =ToL (&buffer[0x2C]); /* 3E */
346
Bitmap_Head.masks[3] =ToL (&buffer[0x30]); /* 42 */
349
ReadChannelMasks (&Bitmap_Head.masks[0], masks, 4);
353
g_message (_("Error reading BMP file header from '%s'"),
354
gimp_filename_to_utf8 (filename));
358
/* Valid bitpdepthis 1, 4, 8, 16, 24, 32 */
359
/* 16 is awful, we should probably shoot whoever invented it */
361
/* There should be some colors used! */
364
(Bitmap_File_Head.bfOffs - Bitmap_File_Head.biSize - 14) / Maps;
366
if ((Bitmap_Head.biClrUsed == 0) && (Bitmap_Head.biBitCnt <= 8))
367
ColormapSize = Bitmap_Head.biClrUsed = 1 << Bitmap_Head.biBitCnt;
369
if (ColormapSize > 256)
374
if (Bitmap_Head.biHeight == 0 || Bitmap_Head.biWidth == 0) {
375
g_message (_("Error reading BMP file header from '%s'"),
376
gimp_filename_to_utf8 (filename));
380
if (Bitmap_Head.biWidth < 0)
382
g_message (_("'%s' is not a valid BMP file"),
383
gimp_filename_to_utf8 (filename));
387
if (Bitmap_Head.biPlanes != 1) {
388
g_message (_("Error reading BMP file header from '%s'"),
389
gimp_filename_to_utf8 (filename));
393
if (Bitmap_Head.biClrUsed > 256) {
394
g_message (_("Error reading BMP file header from '%s'"),
395
gimp_filename_to_utf8 (filename));
399
/* Windows and OS/2 declare filler so that rows are a multiple of
400
* word length (32 bits == 4 bytes)
403
rowbytes= ((Bitmap_Head.biWidth * Bitmap_Head.biBitCnt - 1) / 32) * 4 + 4;
406
printf ("\nSize: %u, Colors: %u, Bits: %u, Width: %u, Height: %u, "
407
"Comp: %u, Zeile: %u\n",
408
Bitmap_File_Head.bfSize,
409
Bitmap_Head.biClrUsed,
410
Bitmap_Head.biBitCnt,
412
Bitmap_Head.biHeight,
417
if (Bitmap_Head.biBitCnt <= 8)
420
printf ("Colormap read\n");
422
/* Get the Colormap */
423
if (!ReadColorMap (fd, ColorMap, ColormapSize, Maps, &Grey))
427
fseek (fd, Bitmap_File_Head.bfOffs, SEEK_SET);
429
/* Get the Image and return the ID or -1 on error*/
430
image_ID = ReadImage (fd,
432
ABS (Bitmap_Head.biHeight),
434
Bitmap_Head.biClrUsed,
435
Bitmap_Head.biBitCnt,
444
if (Bitmap_Head.biXPels > 0 && Bitmap_Head.biYPels > 0)
446
/* Fixed up from scott@asofyet's changes last year, njl195 */
450
/* I don't agree with scott's feeling that Gimp should be
451
* trying to "fix" metric resolution translations, in the
452
* long term Gimp should be SI (metric) anyway, but we
453
* haven't told the Americans that yet */
455
xresolution = Bitmap_Head.biXPels * 0.0254;
456
yresolution = Bitmap_Head.biYPels * 0.0254;
458
gimp_image_set_resolution (image_ID, xresolution, yresolution);
461
if (Bitmap_Head.biHeight < 0)
462
gimp_image_flip (image_ID, GIMP_ORIENTATION_VERTICAL);
477
const Bitmap_Channel *masks)
480
GimpPixelRgn pixel_rgn;
485
GimpDrawable *drawable;
486
guchar *dest, *temp, *buffer;
487
guchar gimp_cmap[768];
489
glong rowstride, channels;
490
gint i, i_max, j, cur_progress, max_progress;
491
gint total_bytes_read;
492
GimpImageBaseType base_type;
493
GimpImageType image_type;
496
if (! (compression == BI_RGB ||
497
(bpp == 8 && compression == BI_RLE8) ||
498
(bpp == 4 && compression == BI_RLE4) ||
499
(bpp == 16 && compression == BI_BITFIELDS) ||
500
(bpp == 32 && compression == BI_BITFIELDS)))
502
g_message (_("Unrecognized or invalid BMP compression format."));
506
/* Make a new image in GIMP */
513
base_type = GIMP_RGB;
514
if (masks[3].mask != 0)
516
image_type = GIMP_RGBA_IMAGE;
521
image_type = GIMP_RGB_IMAGE;
531
base_type = GIMP_GRAY;
532
image_type = GIMP_GRAY_IMAGE;
536
base_type = GIMP_INDEXED;
537
image_type = GIMP_INDEXED_IMAGE;
544
g_message (_("Unsupported or invalid bitdepth."));
548
if ((width < 0) || (width > GIMP_MAX_IMAGE_SIZE))
550
g_message (_("Unsupported or invalid image width: %d"), width);
553
if ((height < 0) || (height > GIMP_MAX_IMAGE_SIZE))
555
g_message (_("Unsupported or invalid image height: %d"), height);
558
image = gimp_image_new (width, height, base_type);
559
layer = gimp_layer_new (image, _("Background"),
561
image_type, 100, GIMP_NORMAL_MODE);
563
gimp_image_set_filename (image, filename);
565
gimp_image_add_layer (image, layer, 0);
566
drawable = gimp_drawable_get (layer);
568
/* use g_malloc0 to initialize the dest buffer so that unspecified
569
pixels in RLE bitmaps show up as the zeroth element in the palette.
571
dest = g_malloc0 (drawable->width * drawable->height * channels);
572
buffer = g_malloc (rowbytes);
573
rowstride = drawable->width * channels;
575
ypos = height - 1; /* Bitmaps begin in the lower left corner */
577
max_progress = height;
583
while (ReadOK (fd, buffer, rowbytes))
585
temp = dest + (ypos * rowstride);
586
for (xpos= 0; xpos < width; ++xpos)
588
px32 = ToL(&buffer[xpos*4]);
589
*(temp++)= (guchar)((px32 & masks[0].mask) >> masks[0].shiftin);
590
*(temp++)= (guchar)((px32 & masks[1].mask) >> masks[1].shiftin);
591
*(temp++)= (guchar)((px32 & masks[2].mask) >> masks[2].shiftin);
593
*(temp++)= (guchar)((px32 & masks[3].mask) >> masks[3].shiftin);
597
--ypos; /* next line */
599
if ((cur_progress % 5) == 0)
600
gimp_progress_update ((gdouble) cur_progress /
601
(gdouble) max_progress);
606
gboolean has_alpha = FALSE;
608
/* at least one pixel should have nonzero alpha */
609
for (ypos = 0; ypos < height; ypos++)
611
temp = dest + (ypos * rowstride);
612
for (xpos = 0; xpos < width; xpos++)
625
/* workaround unwanted behaviour when all alpha pixels are zero */
628
for (ypos = 0; ypos < height; ypos++)
630
temp = dest + (ypos * rowstride);
631
for (xpos = 0; xpos < width; xpos++)
644
while (ReadOK (fd, buffer, rowbytes))
646
temp = dest + (ypos * rowstride);
647
for (xpos= 0; xpos < width; ++xpos)
649
*(temp++)= buffer[xpos * 3 + 2];
650
*(temp++)= buffer[xpos * 3 + 1];
651
*(temp++)= buffer[xpos * 3];
655
--ypos; /* next line */
657
if ((cur_progress % 5) == 0)
658
gimp_progress_update ((gdouble) cur_progress /
659
(gdouble) max_progress);
666
while (ReadOK (fd, buffer, rowbytes))
668
temp = dest + (ypos * rowstride);
669
for (xpos= 0; xpos < width; ++xpos)
671
rgb= ToS(&buffer[xpos * 2]);
672
*(temp++) = (guchar)(((rgb & masks[0].mask) >> masks[0].shiftin) * 255.0 / masks[0].max_value + 0.5);
673
*(temp++) = (guchar)(((rgb & masks[1].mask) >> masks[1].shiftin) * 255.0 / masks[1].max_value + 0.5);
674
*(temp++) = (guchar)(((rgb & masks[2].mask) >> masks[2].shiftin) * 255.0 / masks[2].max_value + 0.5);
676
*(temp++) = (guchar)(((rgb & masks[3].mask) >> masks[3].shiftin) * 255.0 / masks[3].max_value + 0.5);
680
--ypos; /* next line */
682
if ((cur_progress % 5) == 0)
683
gimp_progress_update ((gdouble) cur_progress /
684
(gdouble) max_progress);
693
if (compression == 0)
696
while (ReadOK (fd, &v, 1))
698
for (i = 1; (i <= (8 / bpp)) && (xpos < width); i++, xpos++)
700
temp = dest + (ypos * rowstride) + (xpos * channels);
701
*temp=( v & ( ((1<<bpp)-1) << (8-(i*bpp)) ) ) >> (8-(i*bpp));
703
*temp = cmap[*temp][0];
707
fread(buffer, rowbytes - 1 - (width * bpp - 1) / 8, 1, fd);
714
if ((cur_progress % 5) == 0)
715
gimp_progress_update ((gdouble) cur_progress /
716
(gdouble) max_progress);
725
/* compressed image (either RLE8 or RLE4) */
726
while (ypos >= 0 && xpos <= width)
728
if (!ReadOK (fd, buffer, 2))
730
g_message (_("The bitmap ends unexpectedly."));
734
if ((guchar) buffer[0] != 0)
735
/* Count + Color - record */
737
/* encoded mode run -
738
buffer[0] == run_length
739
buffer[1] == pixel data
742
((guchar) j < (guchar) buffer[0]) && (xpos < width);)
745
printf("%u %u | ",xpos,width);
750
((guchar) j < (unsigned char) buffer[0]));
753
temp = dest + (ypos * rowstride) + (xpos * channels);
755
(((1<<bpp)-1) << (8 - (i * bpp)))) >> (8 - (i * bpp));
757
*temp = cmap[*temp][0];
761
if (((guchar) buffer[0] == 0) && ((guchar) buffer[1] > 2))
762
/* uncompressed record */
765
total_bytes_read = 0;
766
for (j = 0; j < n; j += (8 / bpp))
768
/* read the next byte in the record */
769
if (!ReadOK (fd, &v, 1))
771
g_message (_("The bitmap ends unexpectedly."));
776
/* read all pixels from that byte */
784
while ((i <= i_max) && (xpos < width))
787
dest + (ypos * rowstride) + (xpos * channels);
788
*temp = (v >> (8-(i*bpp))) & ((1<<bpp)-1);
790
*temp = cmap[*temp][0];
796
/* absolute mode runs are padded to 16-bit alignment */
797
if (total_bytes_read % 2)
800
if (((guchar) buffer[0] == 0) && ((guchar) buffer[1]==0))
807
if ((cur_progress % 5) == 0)
808
gimp_progress_update ((gdouble) cur_progress /
809
(gdouble) max_progress);
811
if (((guchar) buffer[0]==0) && ((guchar) buffer[1]==1))
816
if (((guchar) buffer[0]==0) && ((guchar) buffer[1]==2))
819
if (!ReadOK (fd, buffer, 2))
821
g_message (_("The bitmap ends unexpectedly."));
824
xpos += (guchar) buffer[0];
825
ypos -= (guchar) buffer[1];
834
g_assert_not_reached ();
840
for (i = 0, j = 0; i < ncols; i++)
842
gimp_cmap[j++] = cmap[i][0];
843
gimp_cmap[j++] = cmap[i][1];
844
gimp_cmap[j++] = cmap[i][2];
847
gimp_progress_update (1);
849
gimp_pixel_rgn_init (&pixel_rgn, drawable,
850
0, 0, drawable->width, drawable->height, TRUE, FALSE);
851
gimp_pixel_rgn_set_rect (&pixel_rgn, dest,
852
0, 0, drawable->width, drawable->height);
854
if ((!grey) && (bpp<= 8))
855
gimp_image_set_colormap (image, gimp_cmap, ncols);
857
gimp_drawable_flush (drawable);
858
gimp_drawable_detach (drawable);