Download code
From LiteratePrograms
Back to BMP_decoder_(C)
Download for Windows: single file, zip
Download for UNIX: single file, zip, tar.gz, tar.bz2
bmp_decode.c
1 /* Copyright (c) 2010 the authors listed at the following URL, and/or 2 the authors of referenced articles or incorporated external code: 3 http://en.literateprograms.org/BMP_decoder_(C)?action=history&offset=20081217213412 4 5 Permission is hereby granted, free of charge, to any person obtaining 6 a copy of this software and associated documentation files (the 7 "Software"), to deal in the Software without restriction, including 8 without limitation the rights to use, copy, modify, merge, publish, 9 distribute, sublicense, and/or sell copies of the Software, and to 10 permit persons to whom the Software is furnished to do so, subject to 11 the following conditions: 12 13 The above copyright notice and this permission notice shall be 14 included in all copies or substantial portions of the Software. 15 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 24 Retrieved from: http://en.literateprograms.org/BMP_decoder_(C)?oldid=15641 25 */ 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 30 /* Reads up to size bytes into the buffer, returning number of bytes read */ 31 typedef int (*read_func)(void* buffer, int size); 32 33 enum color_component { 34 BLUE, 35 GREEN, 36 RED 37 }; 38 39 #define PALETTE_ENTRY_SIZE 4 40 #define MAX_PALETTE_SIZE 256 41 42 typedef unsigned char palette[MAX_PALETTE_SIZE][PALETTE_ENTRY_SIZE]; 43 44 typedef unsigned char raw_pixels[][3]; 45 46 #define HEADER_SIZE (2 + 6*4 + 2*2 + 6*4) 47 48 enum compression_values { 49 UNCOMPRESSED = 0, 50 51 }; 52 53 struct bmp_file_header { 54 unsigned short type; 55 unsigned long size; 56 unsigned long reserved; 57 unsigned long bitmap_offset; 58 unsigned long header_size; 59 signed long width; 60 signed long height; 61 unsigned short planes; 62 unsigned short bits_per_pixel; 63 unsigned long compression; 64 unsigned long bitmap_size; 65 signed long horizontal_resolution; 66 signed long vertical_resolution; 67 unsigned long num_colors; 68 unsigned long num_important_colors; 69 }; 70 71 72 void fix_endian_func(void* data, int size) { 73 int endian_test = 1; 74 unsigned char* endian_test_bytes = (unsigned char *)&endian_test; 75 if (endian_test_bytes[0] == '\0') 76 { 77 unsigned char* cdata = data; 78 int i; 79 for (i=0; i<size/2; i++) { 80 unsigned char temp = cdata[i]; 81 cdata[i] = cdata[size-1 - i]; 82 cdata[size-1 - i] = temp; 83 } 84 } 85 } 86 87 #define fix_endian(x) (fix_endian_func(&(x), sizeof(x))) 88 89 unsigned char read_u8(read_func read) { 90 unsigned char result; 91 if (read(&result, 1) < 1) { 92 printf("Unexpected end of file"); 93 exit(-1); 94 } 95 return result; 96 } 97 98 unsigned short read_u16(read_func read) { 99 unsigned short result = 0; 100 if (read(&result, 2) < 2) { 101 printf("Unexpected end of file"); 102 exit(-1); 103 } 104 fix_endian(result); 105 return result; 106 } 107 108 unsigned long read_u32(read_func read) { 109 unsigned long result = 0; 110 if (read(&result, 4) < 4) { 111 printf("Unexpected end of file"); 112 exit(-1); 113 } 114 fix_endian(result); 115 return result; 116 } 117 118 signed long read_s32(read_func read) { 119 unsigned long result = 0; 120 if (read(&result, 4) < 4) { 121 printf("Unexpected end of file"); 122 exit(-1); 123 } 124 fix_endian(result); 125 if ((result >> 31) & 1) { /* If it's negative... */ 126 result |= ((unsigned long)(-1)) << 32; 127 } 128 return (long)result; 129 } 130 131 void read_bitmap_header(read_func in, struct bmp_file_header* header) { 132 header->type = read_u16(in); 133 header->size = read_u32(in); 134 header->reserved = read_u32(in); 135 header->bitmap_offset = read_u32(in); 136 header->header_size = read_u32(in); 137 header->width = read_s32(in); 138 header->height = read_s32(in); 139 header->planes = read_u16(in); 140 header->bits_per_pixel = read_u16(in); 141 header->compression = read_u32(in); 142 header->bitmap_size = read_u32(in); 143 header->horizontal_resolution = read_s32(in); 144 header->vertical_resolution = read_u32(in); 145 header->num_colors = read_u32(in); 146 header->num_important_colors = read_u32(in); 147 } 148 149 int read_palette(read_func in, struct bmp_file_header* header, palette palette) { 150 int palette_size = header->bitmap_offset - HEADER_SIZE; 151 152 if (in(&palette[0][0], palette_size) < palette_size) { 153 printf("Unexpected end of file"); 154 exit(-1); 155 } 156 return palette_size/PALETTE_ENTRY_SIZE; 157 } 158 159
