3 * libneuro, a light weight abstraction of high or lower libraries
4 * and toolkit for applications.
5 * Copyright (C) 2005-2006 Nicholas Niro, Robert Lemay
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 /* bitmap process module */
32 /* this is used to open the bitmaps,
33 * the beauty of this is it works
34 * for compressed and uncompressed
35 * transparently, meaning no extra code
40 #else /* NOT USE_ZLIB */
46 #include <extlib.h> /* Lib_GetDefaultDepth() */
48 #include <graphics.h> /* Neuro_PutPixel */
51 typedef struct BITMAP_HEADER
53 u16 type
__attribute__((packed
)); /* Magic identifier */
54 u32 size
__attribute__((packed
)); /* File size in bytes */
55 u16 reserved1
, reserved2
; /* reserved */
56 u32 offset
__attribute__((packed
)); /* Offset to image data, bytes */
59 typedef struct BITMAP_INFOHEADER
61 u32 size
; /* Header size in bytes */
62 i32 width
, height
; /* Width and height of image */
63 u16 planes
; /* Number of colour planes */
64 u16 bits
; /* Bits per pixel */
65 u32 compression
; /* Compression type */
66 u32 imagesize
; /* Image size in bytes */
67 i32 xresolution
, yresolution
; /* Pixels per meter */
68 u32 ncolors
; /* Number of colours */
69 u32 importantcolours
; /* Important colours */
72 typedef struct BITMAP_HDATA
74 BITMAP_HEADER header
__attribute__((packed
));
75 BITMAP_INFOHEADER infoheader
__attribute__((packed
));
78 typedef struct BITMAP_COLOR
80 u8 r
, g
, b
/*, a*/ ; /* red green blue */
81 u8
*symbol
; /* unique symbol associated with this color */
84 typedef struct BITMAP_MAP
89 static u32 color_key
= 0; /* this is the pixel we will make it so it is transparent */
91 /* static function prototypes */
92 static void print_bitmap_infos(BITMAP_HDATA
*bmap
) __attribute__((unused
));
93 static int fpdata8(nFILE
*input
, u8
*output
) __attribute__((unused
));
94 static int fpdata16(nFILE
*input
, u16
*output
) __attribute__((unused
));
95 static int fpdata32(nFILE
*input
, u32
*output
) __attribute__((unused
));
99 /* static functions */
102 clean_bmap_color(void *eng
)
106 buf
= (BITMAP_COLOR
*)eng
;
113 /* returns 0 on success and puts the data in *output
114 * 1 on error dont touch output
117 fpdata8(nFILE
*input
, u8
*output
)
119 if (input
== NULL
|| output
== NULL
)
122 *output
= gzgetc(input
);
123 #else /* NOT USE_ZLIB */
124 *output
= fgetc(input
);
125 #endif /* NOT USE_ZLIB */
131 /* returns 0 on success and puts the data in *output
132 * 1 on error dont touch output
135 fpdata16(nFILE
*input
, u16
*output
)
140 if (input
== NULL
|| output
== NULL
)
144 feed
[0] = gzgetc(input
);
145 feed
[1] = gzgetc(input
);
146 #else /* NOT USE_ZLIB */
147 feed
[0] = fgetc(input
);
148 feed
[1] = fgetc(input
);
149 #endif /* NOT USE_ZLIB */
158 /* returns 0 on success and puts the data in *output
159 * 1 on error dont touch output
162 fpdata32(nFILE
*input
, u32
*output
)
164 /* register int feed; */
169 if (input
== NULL
|| output
== NULL
)
173 feed
[0] = gzgetc(input
);
174 feed
[1] = gzgetc(input
);
175 feed
[2] = gzgetc(input
);
176 feed
[3] = gzgetc(input
);
177 #else /* NOT USE_ZLIB */
178 feed
[0] = fgetc(input
);
179 feed
[1] = fgetc(input
);
180 feed
[2] = fgetc(input
);
181 feed
[3] = fgetc(input
);
182 #endif /* NOT USE_ZLIB */
191 static BITMAP_HDATA
*
192 parse_bitmap_header(nFILE
*input
)
195 BITMAP_INFOHEADER
*tmp
;
200 buf
= calloc(1, sizeof(BITMAP_HDATA
));
202 tmp
= &buf
->infoheader
;
204 fpdata16(input
, &buf
->header
.type
);
205 fpdata32(input
, &buf
->header
.size
);
206 fpdata16(input
, &buf
->header
.reserved1
);
207 fpdata16(input
, &buf
->header
.reserved2
);
208 fpdata32(input
, &buf
->header
.offset
);
210 fpdata32(input
, &tmp
->size
);
211 fpdata32(input
, (u32
*)&tmp
->width
);
212 fpdata32(input
, (u32
*)&tmp
->height
);
213 fpdata16(input
, &tmp
->planes
);
214 fpdata16(input
, &tmp
->bits
);
215 fpdata32(input
, &tmp
->compression
);
216 fpdata32(input
, &tmp
->imagesize
);
217 fpdata32(input
, (u32
*)&tmp
->xresolution
);
218 fpdata32(input
, (u32
*)&tmp
->yresolution
);
219 fpdata32(input
, &tmp
->ncolors
);
220 fpdata32(input
, &tmp
->importantcolours
);
225 /* the magic number will probably not show correctly if big endian */
227 print_bitmap_infos(BITMAP_HDATA
*bmap
)
229 printf("[%c%c] header data :\nsize %d\noffset %d\ninfoheader data :\nsize %d\nwidth %d\nheight %d\nplanes %d\nbits %d\ncompression %d\nimagesize %d\nxres %d\nyres %d\nncolors %d\nimportantcolors %d\n",
230 bmap
->header
.type
& 0x00FF,
231 (bmap
->header
.type
& 0xFF00) >> 8,
234 bmap
->infoheader
.size
,
235 bmap
->infoheader
.width
,
236 bmap
->infoheader
.height
,
237 bmap
->infoheader
.planes
,
238 bmap
->infoheader
.bits
,
239 bmap
->infoheader
.compression
,
240 bmap
->infoheader
.imagesize
,
241 bmap
->infoheader
.xresolution
,
242 bmap
->infoheader
.yresolution
,
243 bmap
->infoheader
.ncolors
,
244 bmap
->infoheader
.importantcolours
);
249 process_palette(nFILE
*input
, BITMAP_HDATA
*bmap
, EBUF
*bcolors
)
254 while (i
< bmap
->infoheader
.ncolors
)
256 Neuro_AllocEBuf(bcolors
, sizeof(BITMAP_COLOR
*), sizeof(BITMAP_COLOR
));
258 buf
= Neuro_GiveCurEBuf(bcolors
);
260 /*buf->r = palette[(i * 4) + 2];
261 buf->g = palette[(i * 4) + 1];
262 buf->b = palette[(i * 4)];
266 fpdata8(input, &buf->b);
267 fpdata8(input, &buf->g);
268 fpdata8(input, &buf->r);
269 fpdata8(input, &buf->a);
272 buf
->b
= gzgetc(input
);
273 buf
->g
= gzgetc(input
);
274 buf
->r
= gzgetc(input
);
276 /* I leave this just in case */
277 /* buf->a = fgetc(input); */
279 /* skip the alpha color */
281 #else /* NOT USE_ZLIB */
282 buf
->b
= fgetc(input
);
283 buf
->g
= fgetc(input
);
284 buf
->r
= fgetc(input
);
286 /* I leave this just in case */
287 /* buf->a = fgetc(input); */
289 /* skip the alpha color */
291 #endif /* NOT USE_ZLIB */
296 /* input the bits per pixel of the image
297 * input a 1 byte of data to process
300 process_bitmap2(BITMAP_HDATA
*bmap
, v_object
*image
, u8
*palette
, u8
*data
, EBUF
*bcolors
, u32
*x
, u32
*y
, int *aux
, char **buf
)
303 /* we will call functions depending on the bpp of the image */
304 switch (bmap
->infoheader
.bits
)
308 /* will do a loop to get each 8 pixels from the data */
310 /* this is pretty much for little endian
311 * the minimum data size we can have for a certain width is
312 * 32 bits (4 bytes increments). Those 32 bits will be able
313 * to hold up to 32 pixels. In case the width is higher than
314 * 32 pixels, it will put 32 bits until the whole width
317 /* we will need to have the width value because we will need
318 * to know how many bits we have to read from 32 bits (4 bytes).
320 /* aux will keep how many 32 bits still need to be done in a
324 /* double calc = 0; */
328 const u8 values
[8] = {
343 *buf
= calloc(1, sizeof(char));
348 /* set up aux for remaining pixels */
350 *aux
= bmap
->infoheader
.width
;
352 /* set up the number of pixels we need to process in this cycle */
368 BITMAP_COLOR
*cbuf
= NULL
;
370 if (IsLittleEndian())
371 temp
= *data
& values
[i
];
373 temp
= *data
& values
[7 - i
];
379 cbuf
= Neuro_GiveEBuf(bcolors
, temp
);
381 Neuro_PutPixel(image
, *x
, (bmap
->infoheader
.height
- 1) - *y
, Neuro_MapRGB(cbuf
->r
, cbuf
->g
, cbuf
->b
));
387 if (*x
> bmap
->infoheader
.width
- 1)
397 /* will do a loop to get each 2 pixels from the data */
399 /* double calc = 0; */
403 const u8 values
[2] = {
412 *buf
= calloc(1, sizeof(char));
417 /* set up aux for remaining pixels */
419 *aux
= bmap
->infoheader
.width
;
421 /* set up the number of pixels we need to process in this cycle */
437 BITMAP_COLOR
*cbuf
= NULL
;
439 if (IsLittleEndian())
441 temp
= *data
& values
[i
];
443 if (temp
> values
[1])
448 temp
= *data
& values
[1 - i
];
450 if (temp
> values
[0])
454 cbuf
= Neuro_GiveEBuf(bcolors
, temp
);
456 Neuro_PutPixel(image
, *x
, (bmap
->infoheader
.height
- 1) - *y
, Neuro_MapRGB(cbuf
->r
, cbuf
->g
, cbuf
->b
));
462 if (*x
> bmap
->infoheader
.width
- 1)
473 /* will get the single pixel from the data */
475 /* double calc = 0; */
484 *buf
= calloc(1, sizeof(char));
489 /* set up aux for remaining pixels */
491 *aux
= bmap
->infoheader
.width
;
493 /* set up the number of pixels we need to process in this cycle */
509 BITMAP_COLOR
*cbuf
= NULL
;
513 cbuf
= Neuro_GiveEBuf(bcolors
, temp
);
515 Neuro_PutPixel(image
, *x
, (bmap
->infoheader
.height
- 1) - *y
, Neuro_MapRGB(cbuf
->r
, cbuf
->g
, cbuf
->b
));
521 if (*x
> bmap
->infoheader
.width
- 1)
532 /* we do not support 16 bit because I think they
533 * use 24 bit for those. we'll see through use.
534 * if not, I really think this depth is pointless...
541 /* will need to gather the data for 2 other bytes to get a
542 * single pixel. We will use the auxiliary variable to keep
543 * track of where we are at in the gathering.
548 *buf
= calloc(3, sizeof(u8
));
552 (*buf
)[*aux
] = *data
;
559 Neuro_PutPixel(image
, *x
, (bmap
->infoheader
.height
- 1) - *y
, Neuro_MapRGB((*buf
)[2], (*buf
)[1], (*buf
)[0]));
564 if (*x
> bmap
->infoheader
.width
- 1)
574 /* we do not support 32 bit because it is Very uncommon if it
575 * actually exist. Pretty much the same as 16 bpp.
582 /* an error occured */
590 processFD_BMP(nFILE
*f_bitmap
)
592 /* major (buffers) */
593 EBUF
*bmap_colors
= NULL
; /* the colors */
594 u8
*buf
= NULL
; /* the buffer that will contain the content of the file */
596 /* minor (mostly pointers and temporary variables) */
597 register i32 i
= 0; /* incremental variable */
598 u32 skip_i
= 0, x
= 0, y
= 0;
600 u32 psize
= 0; /* the full size of the pixels data */
601 u8
*palette
= NULL
; /* the pointer to the palette if theres one */
602 BITMAP_HDATA
*bmap
; /* this is how we will get informations about the bitmap */
603 int aux_var
= 0; /* auxiliary variable that can be used by external functions */
604 char *aux_buf
= NULL
; /* same as aux_var but a buffer */
612 v_object
*output
; /* the image into which we will load the bitmap */
614 if (f_bitmap
== NULL
)
617 bmap
= parse_bitmap_header(f_bitmap
);
619 /* TODO TODO XXX check here if the bitmap is valid or not
620 * first check for the BM word
621 * then we check for the size of the file in header and size
622 * we got when reading the file
628 /* if it is valid, we create the buffers */
629 Neuro_CreateEBuf(&bmap_colors
);
630 Neuro_SetcallbEBuf(bmap_colors
, &clean_bmap_color
);
633 /* print_bitmap_infos(bmap); */
635 /* process the bitmap(load it in memory) */
637 psize
= bmap
->header
.size
- (sizeof(BITMAP_HEADER
) + sizeof(BITMAP_INFOHEADER
));
638 psize
= psize
- (bmap
->infoheader
.ncolors
* 4);
639 /* printf("data size %d\n", psize); */
641 if (bmap
->infoheader
.ncolors
)
643 process_palette(f_bitmap
, bmap
, bmap_colors
);
646 /* we create the v_object
648 * will need to put better values for the masks to support SDL.
651 u32 rmask
= 0, gmask
= 0, bmask
= 0, amask
= 0;
653 if (IsLittleEndian())
655 switch (Lib_GetDefaultDepth())
682 switch (Lib_GetDefaultDepth())
707 if (IsLittleEndian())
723 output
= Neuro_CreateVObject(0, bmap
->infoheader
.width
, bmap
->infoheader
.height
, bmap
->infoheader
.bits
, rmask
, gmask
, bmask
, amask
);
729 /* semi static values to skip bytes that form 32 bit chunks in the data */
731 pixellen
= (8 / (double)bmap
->infoheader
.bits
);
732 msize
= pixellen
* 4;
734 /* we calculate the number of bytes there is per rows
735 * this is mainly so we can know how much "alignment"
736 * bytes there is (which need to be skipped)
739 wmult
= (u32
)bmap
->infoheader
.bits
/ 8;
744 wmult
= wmult
* bmap
->infoheader
.width
;
747 increm
= (u32
)pixellen
;
752 x
= (u32
)(bmap
->infoheader
.width
/ msize
);
754 tmp
= (double)bmap
->infoheader
.width
- tmp
;
755 tmp
= tmp
- 0.000001; /* to avoid bugs */
759 gzseek(f_bitmap
, bmap
->header
.offset
, SEEK_SET
);
760 #else /* NOT USE_ZLIB */
761 fseek(f_bitmap
, bmap
->header
.offset
, SEEK_SET
);
762 #endif /* NOT USE_ZLIB */
764 Lib_LockVObject(output
);
766 /* Debug_Val(0, "Image bits depth %d tmp %f\n", bmap->infoheader.bits, tmp); */
772 /* skip bytes that are inside the bitmap for
773 * filling purpose. (the data is purposely filled
774 * with 0 bits so the data is 32bits aligned)
778 calc
= tmp
/ pixellen
;
784 skip_i
= (4 - skip_i
);
788 gzseek(f_bitmap
, bmap
->header
.offset
+ i
, SEEK_SET
);
789 #else /* NOT USE_ZLIB */
790 fseek(f_bitmap
, bmap
->header
.offset
+ i
, SEEK_SET
);
791 #endif /* NOT USE_ZLIB */
794 printf("skipping %d bytes wmult %d width %d tmp %f plen %f calc %f\n",
797 bmap->infoheader.width,
812 fpdata8(f_bitmap
, &DATA
);
814 process_bitmap2(bmap
, output
, palette
, &DATA
,
815 bmap_colors
, &x
, &y
, &aux_var
, &aux_buf
);
818 /* process_bitmap2(bmap, output, palette, &DATA,
819 bmap_colors, x, y, &aux_var, &aux_buf); */
822 /* printf("i %d psize %d\n", i, psize); */
823 /* Debug_Val(0, "current coord : %d,%d %d\n", x, y, wmult); */
829 if (t == 0 || x > bmap->infoheader.width - 1)
831 if (x < bmap->infoheader.width - 1)
849 Lib_UnlockVObject(output
);
858 Neuro_CleanEBuf(&bmap_colors
);
863 #else /* NOT USE_ZLIB */
866 #endif /* NOT USE_ZLIB */
871 /* Global functions */
874 cleanPixmapEbuf(EBUF
**pixmap
)
876 Neuro_CleanEBuf(pixmap
);
880 setBitmapColorKey(u32 key
)
886 readBitmapBufferToPixmap(char *data
, EBUF
**output_pixmap
)
891 readBitmapFileToPixmap(const char *bitmap
, EBUF
**output_pixmap
)
896 readBitmapFile(const char *bitmap
)
901 f_bitmap
= gzopen(bitmap
, "r"); /* can also be used for non compressed files */
902 #else /* NOT USE_ZLIB */
903 f_bitmap
= fopen(bitmap
, "r");
904 #endif /* NOT USE_ZLIB */
906 return processFD_BMP(f_bitmap
);