22#define MFMT_BMPINFO_OFS_WIDTH 4
23#define MFMT_BMPINFO_OFS_HEIGHT 8
24#define MFMT_BMPINFO_OFS_COLOR_PLANES 12
25#define MFMT_BMPINFO_OFS_BPP 14
26#define MFMT_BMPINFO_OFS_COMPRESSION 16
27#define MFMT_BMPINFO_OFS_SZ 20
28#define MFMT_BMPINFO_OFS_HRES 24
29#define MFMT_BMPINFO_OFS_VRES 28
30#define MFMT_BMPINFO_OFS_PAL_SZ 32
31#define MFMT_BMPINFO_OFS_IMP_COLORS 36
34#define MFMT_BMP_COMPRESSION_NONE (0)
36#define MFMT_BMP_COMPRESSION_RLE8 (1)
38#define MFMT_BMP_COMPRESSION_RLE4 (2)
42#define MFMT_DECOMP_FLAG_4BIT 0x01
43#define MFMT_DECOMP_FLAG_8BIT 0x02
45#define MFMT_PX_FLAG_INVERT_Y 0x01
47#ifndef MFMT_TRACE_BMP_LVL
48# define MFMT_TRACE_BMP_LVL 0
51#ifndef MFMT_TRACE_RLE_LVL
52# define MFMT_TRACE_RLE_LVL 0
72#define mfmt_bmp_check_header() \
73 if( 40 == header->sz ) { \
74 header_bmp_info = (struct MFMT_STRUCT_BMPINFO*)header; \
75 } else if( 0x4d42 == *((uint16_t*)header) ) { \
76 debug_printf( MFMT_TRACE_BMP_LVL, "bmp file header detected" ); \
77 header_bmp_file = (struct MFMT_STRUCT_BMPFILE*)header; \
78 header_bmp_info = &(header_bmp_file->info); \
80 error_printf( "unable to select read header!" ); \
81 retval = MERROR_FILE; \
132 mfile_t* p_file_in, off_t file_offset, off_t file_sz,
size_t line_w,
133 MAUG_MHANDLE buffer_out, off_t buffer_out_sz, uint8_t flags );
140 uint32_t file_offset, off_t file_sz, uint8_t* p_flags );
146 struct MFMT_STRUCT* header, uint32_t* palette,
size_t palette_sz,
147 mfile_t* p_file_in, uint32_t file_offset, off_t file_sz,
154 struct MFMT_STRUCT* header, uint8_t SEG_FAR* px, off_t px_sz,
155 mfile_t* p_file_in, uint32_t file_offset, off_t file_sz,
162 mfile_t* p_file_in, off_t file_offset, off_t file_sz,
size_t line_w,
163 MAUG_MHANDLE buffer_out, off_t buffer_out_sz, uint8_t flags );
167 uint32_t file_offset, off_t file_sz, uint8_t* p_flags );
170 struct MFMT_STRUCT* header, uint32_t* palette,
size_t palette_sz,
171 mfile_t* p_file_in, uint32_t file_offset, off_t file_sz,
178 struct MFMT_STRUCT* header, uint8_t SEG_FAR* px, off_t px_sz,
179 mfile_t* p_file_in, uint32_t file_offset, off_t file_sz,
185 mfile_t* p_file_in, off_t file_offset, off_t file_sz,
size_t line_w,
186 MAUG_MHANDLE buffer_out_h, off_t buffer_out_sz, uint8_t flags
189 uint8_t* buffer_out = NULL;
190 off_t in_byte_cur = 0,
192 uint8_t out_mask_cur = 0xf0,
196 unpadded_written = 0,
201 #define MFMT_RLE_DECODE_RUN 0
202 #define MFMT_RLE_DECODE_CHAR 1
203 #define MFMT_RLE_DECODE_ABS_RIGHT 2
204 #define MFMT_RLE_DECODE_ABS_DOWN 3
205 #define MFMT_RLE_DECODE_ESC 4
206 #define MFMT_RLE_DECODE_LITERAL 5
207 #define MFMT_RLE_DECODE_LITERAL_PAD 6
209 assert( flags == MFMT_DECOMP_FLAG_4BIT );
211 #define mfmt_decode_rle_state( new_state ) \
212 debug_printf( MFMT_TRACE_RLE_LVL, "new state: %s", #new_state ); \
213 decode_state = new_state;
215 #define mfmt_decode_rle_check_eol() \
216 if( line_px_written >= line_w ) { \
217 debug_printf( MFMT_TRACE_RLE_LVL, \
218 "EOL: %u px written (between runs)", \
220 mfmt_decode_rle_reset_line(); \
224 #define mfmt_decode_rle_advance_mask() \
225 out_mask_cur >>= 4; \
226 if( 0 == out_mask_cur ) { \
228 if( out_byte_cur > buffer_out_sz ) { \
230 "out byte " OFF_T_FMT " outside of " OFF_T_FMT \
231 " pixel buffer!", out_byte_cur, buffer_out_sz ); \
232 retval = MERROR_OVERFLOW; \
234 } else if( out_byte_cur < buffer_out_sz ) { \
236 buffer_out[out_byte_cur] = 0; \
238 out_mask_cur = 0xf0; \
241 #define mfmt_decode_rle_reset_line() \
242 if( line_w != line_px_written ) { \
244 "line written pixels %u does not match line width " SIZE_T_FMT, \
245 line_px_written, line_w ); \
246 retval = MERROR_OVERFLOW; \
249 line_px_written = 0; \
250 out_mask_cur = 0xf0; \
252 debug_printf( MFMT_TRACE_RLE_LVL, "now on line: %u", lines_out );
254 #define mfmt_decode_rle_inc_line_w( incr ) \
255 line_px_written += incr; \
256 if( line_w < line_px_written ) { \
258 "line byte %u outside of " SIZE_T_FMT \
259 " line width!", line_px_written, line_w ); \
260 retval = MERROR_OVERFLOW; \
264 debug_printf( 1,
"decompressing RLE into temporary buffer..." );
266 maug_mlock( buffer_out_h, buffer_out );
271 retval = p_file_in->seek( p_file_in, file_offset + in_byte_cur++ );
272 maug_cleanup_if_not_ok();
273 retval = p_file_in->read_int( p_file_in, &byte_buffer, 1, 0 );
274 maug_cleanup_if_not_ok();
280 debug_printf( MFMT_TRACE_RLE_LVL,
"in byte " OFF_T_FMT
281 ": 0x%02x, out byte " OFF_T_FMT
", line px: %u",
282 in_byte_cur, byte_buffer, out_byte_cur, line_px_written );
284 switch( byte_buffer ) {
286 if( MFMT_RLE_DECODE_RUN == decode_state ) {
287 mfmt_decode_rle_state( MFMT_RLE_DECODE_ESC );
290 }
else if( MFMT_RLE_DECODE_LITERAL_PAD == decode_state ) {
292 assert( 0 == byte_buffer );
293 mfmt_decode_rle_state( MFMT_RLE_DECODE_RUN );
296 }
else if( MFMT_RLE_DECODE_ESC == decode_state ) {
298 debug_printf( MFMT_TRACE_RLE_LVL,
299 "EOL: %u px written", line_px_written );
300 while( line_px_written < line_w ) {
302 assert( 0 == line_px_written % 2 );
303 buffer_out[out_byte_cur++] = 0x00;
304 mfmt_decode_rle_inc_line_w( 2 );
305 debug_printf( MFMT_TRACE_RLE_LVL,
306 "padded line (%u written)", line_px_written );
308 mfmt_decode_rle_reset_line();
311 mfmt_decode_rle_state( MFMT_RLE_DECODE_RUN );
316 if( MFMT_RLE_DECODE_ESC == decode_state ) {
317 debug_printf( MFMT_TRACE_RLE_LVL,
"EOBM" );
320 while( out_byte_cur < buffer_out_sz ) {
322 assert( 0 == line_px_written % 2 );
323 mfmt_decode_rle_check_eol();
324 buffer_out[out_byte_cur++] = 0x00;
325 mfmt_decode_rle_inc_line_w( 2 );
326 debug_printf( MFMT_TRACE_RLE_LVL,
327 "padded file (%u written)", line_px_written );
330 mfmt_decode_rle_state( MFMT_RLE_DECODE_RUN );
335 if( MFMT_RLE_DECODE_ESC == decode_state ) {
336 debug_printf( MFMT_TRACE_RLE_LVL,
"absolute mode: right" );
339 mfmt_decode_rle_state( MFMT_RLE_DECODE_ABS_RIGHT );
344 switch( decode_state ) {
345 case MFMT_RLE_DECODE_LITERAL:
347 mfmt_decode_rle_check_eol();
350 unpadded_written += 2;
351 mfmt_decode_rle_inc_line_w( 2 );
352 debug_printf( MFMT_TRACE_RLE_LVL,
353 "writing literal: 0x%02x (%u left, unpadded run val: %u)",
354 byte_buffer, run_count, unpadded_written );
355 buffer_out[out_byte_cur++] = byte_buffer;
357 if( 0 == run_count ) {
358 if( 0 != unpadded_written % 4 ) {
361 debug_printf( MFMT_TRACE_RLE_LVL,
362 "unpadded: %u, next is pad byte", unpadded_written );
364 mfmt_decode_rle_state( MFMT_RLE_DECODE_LITERAL_PAD );
368 mfmt_decode_rle_state( MFMT_RLE_DECODE_RUN );
373 case MFMT_RLE_DECODE_ESC:
374 run_count = byte_buffer;
375 unpadded_written = 0;
376 debug_printf( MFMT_TRACE_RLE_LVL,
377 "literal mode: %u nibbles", run_count );
378 assert( 0 == run_count % 2 );
379 mfmt_decode_rle_state( MFMT_RLE_DECODE_LITERAL );
382 case MFMT_RLE_DECODE_ABS_RIGHT:
383 debug_printf( MFMT_TRACE_RLE_LVL,
"absolute mode: up" );
386 mfmt_decode_rle_state( MFMT_RLE_DECODE_ABS_DOWN );
389 case MFMT_RLE_DECODE_RUN:
391 mfmt_decode_rle_check_eol();
393 run_count = byte_buffer;
394 debug_printf( MFMT_TRACE_RLE_LVL,
395 "starting run: %u nibbles", run_count );
396 mfmt_decode_rle_state( MFMT_RLE_DECODE_CHAR );
399 case MFMT_RLE_DECODE_CHAR:
400 assert( 0 != run_count );
401 run_char = byte_buffer;
402 debug_printf( MFMT_TRACE_RLE_LVL,
403 "%u-long run of 0x%02x...", run_count, run_char );
406 debug_printf( MFMT_TRACE_RLE_LVL,
407 "writing 0x%02x & 0x%02x #%u (line px #%u)...",
408 run_char, out_mask_cur, run_count, line_px_written );
409 buffer_out[out_byte_cur] |= (run_char & out_mask_cur);
410 mfmt_decode_rle_advance_mask();
411 mfmt_decode_rle_inc_line_w( 1 );
414 }
while( 0 < run_count );
417 mfmt_decode_rle_state( MFMT_RLE_DECODE_RUN );
423 }
while( in_byte_cur < file_sz );
426 MFMT_TRACE_RLE_LVL,
"wrote " OFF_T_FMT
" bytes (%u lines)",
427 out_byte_cur, lines_out );
431 if( NULL != buffer_out ) {
432 maug_munlock( buffer_out_h, buffer_out );
440 uint32_t file_offset, off_t file_sz, uint8_t* p_flags
445 uint32_t file_hdr_sz = 0;
446 off_t header_offset = 0;
448 mfmt_bmp_check_header();
450 if( NULL != header_bmp_file ) {
454 retval = p_file_in->seek( p_file_in, file_offset + 2 );
455 maug_cleanup_if_not_ok();
456 retval = p_file_in->read_int( p_file_in,
457 (uint8_t*)&(header_bmp_file->file_sz), 4, MFILE_READ_FLAG_LSBF );
458 maug_cleanup_if_not_ok();
460 retval = p_file_in->seek( p_file_in, file_offset + 10 );
461 maug_cleanup_if_not_ok();
462 retval = p_file_in->read_int( p_file_in,
463 (uint8_t*)&(header_bmp_file->px_offset), 4, MFILE_READ_FLAG_LSBF );
464 maug_cleanup_if_not_ok();
466 debug_printf( MFMT_TRACE_BMP_LVL,
467 "bitmap file " UPRINTF_U32_FMT
" bytes long, px at "
468 UPRINTF_U32_FMT
" bytes",
469 header_bmp_file->file_sz, header_bmp_file->px_offset );
473 retval = p_file_in->seek( p_file_in, file_offset + header_offset );
474 maug_cleanup_if_not_ok();
475 retval = p_file_in->read_int( p_file_in,
476 (uint8_t*)&file_hdr_sz, 4, MFILE_READ_FLAG_LSBF );
477 maug_cleanup_if_not_ok();
478 if( 40 != file_hdr_sz ) {
479 error_printf(
"invalid header size: " UPRINTF_U32_FMT, file_hdr_sz );
480 retval = MERROR_FILE;
484 MFMT_TRACE_BMP_LVL,
"bitmap header is " UPRINTF_U32_FMT
" bytes",
487 if( 40 > file_sz - (file_offset + header_offset) ) {
489 "bitmap header overflow! (only " OFF_T_FMT
" bytes remain!)",
490 file_sz - (file_offset + header_offset) );
491 retval = MERROR_OVERFLOW;
496 retval = p_file_in->seek( p_file_in,
497 file_offset + header_offset + MFMT_BMPINFO_OFS_WIDTH );
498 maug_cleanup_if_not_ok();
499 retval = p_file_in->read_int( p_file_in,
500 (uint8_t*)&(header_bmp_info->
width), 4, MFILE_READ_FLAG_LSBF );
501 maug_cleanup_if_not_ok();
503 retval = p_file_in->seek( p_file_in,
504 file_offset + header_offset + MFMT_BMPINFO_OFS_HEIGHT );
505 maug_cleanup_if_not_ok();
506 retval = p_file_in->read_int( p_file_in,
507 (uint8_t*)&(header_bmp_info->
height), 4, MFILE_READ_FLAG_LSBF );
508 maug_cleanup_if_not_ok();
510 if( 0 > header_bmp_info->
height ) {
512 MFMT_TRACE_BMP_LVL,
"bitmap Y coordinate is inverted..." );
513 *p_flags |= MFMT_PX_FLAG_INVERT_Y;
516 retval = p_file_in->seek( p_file_in,
517 file_offset + header_offset + MFMT_BMPINFO_OFS_SZ );
518 maug_cleanup_if_not_ok();
519 retval = p_file_in->read_int( p_file_in,
520 (uint8_t*)&(header_bmp_info->
img_sz), 4, MFILE_READ_FLAG_LSBF );
521 maug_cleanup_if_not_ok();
524 retval = p_file_in->seek( p_file_in,
525 file_offset + header_offset + MFMT_BMPINFO_OFS_BPP );
526 maug_cleanup_if_not_ok();
527 retval = p_file_in->read_int( p_file_in,
528 (uint8_t*)&(header_bmp_info->
bpp), 2, MFILE_READ_FLAG_LSBF );
529 maug_cleanup_if_not_ok();
531 if( 8 < header_bmp_info->
bpp ) {
532 error_printf(
"invalid bitmap bpp: %u", header_bmp_info->
bpp );
533 retval = MERROR_FILE;
538 retval = p_file_in->seek( p_file_in,
539 file_offset + header_offset + MFMT_BMPINFO_OFS_COMPRESSION );
540 maug_cleanup_if_not_ok();
541 retval = p_file_in->read_int( p_file_in,
542 (uint8_t*)&(header_bmp_info->
compression), 4, MFILE_READ_FLAG_LSBF );
543 maug_cleanup_if_not_ok();
549 error_printf(
"invalid bitmap compression: " UPRINTF_U32_FMT,
551 retval = MERROR_FILE;
557 retval = p_file_in->seek( p_file_in,
558 file_offset + header_offset + MFMT_BMPINFO_OFS_PAL_SZ );
559 maug_cleanup_if_not_ok();
560 retval = p_file_in->read_int( p_file_in,
561 (uint8_t*)&(header_bmp_info->
palette_ncolors), 4, MFILE_READ_FLAG_LSBF );
562 maug_cleanup_if_not_ok();
564 debug_printf( 2,
"bitmap is " UPRINTF_S32_FMT
" x " UPRINTF_S32_FMT
565 ", %u bpp (palette has " UPRINTF_U32_FMT
" colors)",
575 struct MFMT_STRUCT* header, uint32_t* palette,
size_t palette_sz,
576 mfile_t* p_file_in, uint32_t file_offset, off_t file_sz, uint8_t flags
583 mfmt_bmp_check_header();
585 retval = p_file_in->seek( p_file_in, file_offset );
586 maug_cleanup_if_not_ok();
588 if( i * 4 > palette_sz ) {
589 error_printf(
"palette overflow!" );
590 retval = MERROR_OVERFLOW;
594 retval = p_file_in->read_int( p_file_in,
595 (uint8_t*)&(palette[i]), 4, MFILE_READ_FLAG_LSBF );
596 maug_cleanup_if_not_ok();
598 debug_printf( MFMT_TRACE_BMP_LVL,
599 "set palette entry " OFF_T_FMT
" to " UPRINTF_X32_FMT,
609 struct MFMT_STRUCT* header, uint8_t SEG_FAR* px, off_t px_sz,
610 mfile_t* p_file_in, uint32_t file_offset, off_t file_sz, uint8_t flags
621 uint8_t byte_buffer = 0,
624 MAUG_MHANDLE decomp_buffer_h = (MAUG_MHANDLE)NULL;
626 mfile_t *p_file_bmp = p_file_in;
630 mfmt_bmp_check_header();
632 if( 0 == header_bmp_info->
height ) {
633 error_printf(
"bitmap height is 0!" );
634 retval = MERROR_FILE;
638 if( 0 == header_bmp_info->
width ) {
639 error_printf(
"bitmap width is 0!" );
640 retval = MERROR_FILE;
644 if( 0 == header_bmp_info->
bpp ) {
645 error_printf(
"bitmap BPP is 0!" );
646 retval = MERROR_FILE;
650 if( 8 < header_bmp_info->
bpp ) {
651 error_printf(
">8BPP bitmaps not supported!" );
652 retval = MERROR_FILE;
658 debug_printf( 1,
"allocating decompression buffer..." );
661 decomp_buffer_h = maug_malloc(
663 maug_cleanup_if_null_alloc( MAUG_MHANDLE, decomp_buffer_h );
666 p_file_in, file_offset, header_bmp_info->
img_sz,
667 header_bmp_info->
width,
668 decomp_buffer_h, header_bmp_info->
width * header_bmp_info->
height,
669 MFMT_DECOMP_FLAG_4BIT );
670 maug_cleanup_if_not_ok();
673 decomp_buffer_h, header_bmp_info->
width * header_bmp_info->
height,
675 maug_cleanup_if_not_ok();
678 p_file_bmp = &file_decomp;
682 assert( 0 == header_bmp_info->
width % 4 );
684 #define mfmt_read_bmp_px_out_idx() \
685 (MFMT_PX_FLAG_INVERT_Y == (MFMT_PX_FLAG_INVERT_Y & flags) ? \
686 ((header_bmp_info->height - y - 1) * header_bmp_info->width) : \
687 ((y) * header_bmp_info->width))
689 y = header_bmp_info->
height - 1;
690 byte_out_idx = mfmt_read_bmp_px_out_idx();
691 if( p_file_bmp == p_file_in ) {
695 p_file_bmp->seek( p_file_bmp, file_offset );
701 debug_printf( MFMT_TRACE_BMP_LVL,
702 "byte in: " OFF_T_FMT
" (" OFF_T_FMT
703 "), bit " OFF_T_FMT
", y: " UPRINTF_U32_FMT
704 ", x: " UPRINTF_U32_FMT
"), byte out: " OFF_T_FMT,
705 byte_in_idx, file_sz, bit_idx, y, x, byte_out_idx );
708 if( px_sz <= byte_out_idx ) {
710 "byte " OFF_T_FMT
" outside of " OFF_T_FMT
711 " pixel buffer!", byte_out_idx, px_sz );
712 retval = MERROR_OVERFLOW;
718 if( byte_in_idx >= file_sz ) {
721 "input bitmap has insufficient size " OFF_T_FMT
" bytes)!",
729 retval = p_file_bmp->read_int( p_file_bmp, &byte_buffer, 1, 0 );
730 maug_cleanup_if_not_ok();
741 for( i = 0 ; header_bmp_info->
bpp > i ; i++ ) {
750 pixel_buffer |= byte_buffer & byte_mask;
757 (bit_idx - header_bmp_info->
bpp);
758 debug_printf( MFMT_TRACE_BMP_LVL,
759 "byte_mask: 0x%02x, bit_idx: " OFF_T_FMT
760 ", pixel_buffer: 0x%02x",
761 byte_mask, bit_idx, pixel_buffer );
764 debug_printf( MFMT_TRACE_BMP_LVL,
765 "writing byte " OFF_T_FMT
" (x: " UPRINTF_S32_FMT
766 ", y: " UPRINTF_S32_FMT
")",
767 byte_out_idx, x, y );
768 px[byte_out_idx] = pixel_buffer;
774 byte_mask >>= header_bmp_info->
bpp;
775 bit_idx -= header_bmp_info->
bpp;
779 if( x >= header_bmp_info->
width ) {
783 while( byte_in_idx % 4 != 0 ) {
785 p_file_bmp->seek( p_file_bmp, file_offset + byte_in_idx );
789 byte_out_idx = mfmt_read_bmp_px_out_idx();
793 debug_printf( MFMT_TRACE_BMP_LVL,
794 "new row starting at byte_out_idx: " OFF_T_FMT,
804 if( NULL != decomp_buffer_h ) {
805 debug_printf( 1,
"freeing decomp buffer %p...", decomp_buffer_h );
806 maug_mfree( decomp_buffer_h );
int MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition merror.h:19
#define MFMT_BMP_COMPRESSION_NONE
MFMT_STRUCT_BMPINFO::compression value indicating none.
Definition mfmt.h:34
#define MFMT_BMP_COMPRESSION_RLE4
MFMT_STRUCT_BMPINFO::compression value indicating 4-bit RLE.
Definition mfmt.h:38
MERROR_RETVAL mfmt_read_bmp_px(struct MFMT_STRUCT *header, uint8_t SEG_FAR *px, off_t px_sz, mfile_t *p_file_in, uint32_t file_offset, off_t file_sz, uint8_t flags)
Read mfmt_bitmap pixels into an 8-bit memory bitmap.
MERROR_RETVAL(* mfmt_read_header_cb)(struct MFMT_STRUCT *header, mfile_t *p_file_in, uint32_t file_offset, off_t file_sz, uint8_t *p_flags)
Callback to read image header and get properties.
Definition mfmt.h:138
MERROR_RETVAL mfmt_decode_rle(mfile_t *p_file_in, off_t file_offset, off_t file_sz, size_t line_w, MAUG_MHANDLE buffer_out, off_t buffer_out_sz, uint8_t flags)
Decode RLE-encoded data from an input file into a memory buffer.
MERROR_RETVAL(* mfmt_read_px_cb)(struct MFMT_STRUCT *header, uint8_t SEG_FAR *px, off_t px_sz, mfile_t *p_file_in, uint32_t file_offset, off_t file_sz, uint8_t flags)
Callback to read image pixels into 8-bit values.
Definition mfmt.h:153
MERROR_RETVAL(* mfmt_read_palette_cb)(struct MFMT_STRUCT *header, uint32_t *palette, size_t palette_sz, mfile_t *p_file_in, uint32_t file_offset, off_t file_sz, uint8_t flags)
Callback to read image palette into 24-bit RGB values.
Definition mfmt.h:145
MERROR_RETVAL(* mfmt_decode)(mfile_t *p_file_in, off_t file_offset, off_t file_sz, size_t line_w, MAUG_MHANDLE buffer_out, off_t buffer_out_sz, uint8_t flags)
Callback to decode compressed data.
Definition mfmt.h:131
#define maug_mzero(ptr, sz)
Zero the block of memory pointed to by ptr.
Definition mmem.h:62
void mfile_close(mfile_t *p_file)
Close a file opened with mfile_open_read().
MERROR_RETVAL mfile_lock_buffer(MAUG_MHANDLE, off_t, mfile_t *p_file)
Lock a buffer and assign it to an mfile_t to read/write.
BITMAPINFO struct that comes before Windows bitmap data.
Definition mfmt.h:86
uint32_t compression
Type of compression used.
Definition mfmt.h:98
uint32_t vres
Vertical resolution in pixels per inch (unsupported).
Definition mfmt.h:104
uint16_t bpp
Number of bits per pixel (only =<8 are supported).
Definition mfmt.h:96
uint16_t color_planes
Number of color planes (only 0 or 1 are supported).
Definition mfmt.h:94
uint32_t sz
Size of this struct in bytes (only 40 is supported).
Definition mfmt.h:88
uint32_t imp_colors
Definition mfmt.h:108
uint32_t img_sz
Size of pixel data in bytes.
Definition mfmt.h:100
uint32_t hres
Horizontal resolution in pixels per inch (unsupported).
Definition mfmt.h:102
uint32_t palette_ncolors
Number of palette colors in this bitmap (<256 supported).
Definition mfmt.h:106
int32_t width
Width of the bitmap in pixels.
Definition mfmt.h:90
int32_t height
Height of the bitmap in pixels.
Definition mfmt.h:92
Generic image description struct.
Definition mfmt.h:62
uint32_t sz
Size of this struct (use to tell apart).
Definition mfmt.h:64