Download code

From LiteratePrograms

Jump to: navigation, search

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 


Views
Personal tools