1 #include <msp/core/inttypes.h>
8 void read_full(Msp::IO::Base &io, char *buffer, unsigned size)
10 unsigned len = io.read(buffer, size);
12 throw Msp::Graphics::bad_image_data("premature end of file");
16 T decode(const char *data)
18 const Msp::UInt8 *udata = reinterpret_cast<const Msp::UInt8 *>(data);
20 for(unsigned i=0; i<sizeof(T); ++i)
21 result |= udata[i]<<(i*8);
30 BmpLoader::BmpLoader(IO::Base &i, unsigned sb):
34 // Image data location is stored at offset 10 and can't be skipped
36 throw invalid_argument("BmpLoader::BmpLoader");
39 bool BmpLoader::detect(const std::string &sig)
41 static const char bmp_sig[] = "BM";
42 if(sig.size()<sizeof(bmp_sig))
44 return !sig.compare(0, 2, bmp_sig);
47 void BmpLoader::load(Image::Data &data)
50 read_full(io, bm_header+sig_bytes, sizeof(bm_header)-sig_bytes);
52 if(!sig_bytes && (bm_header[0]!='B' || bm_header[1]!='M'))
53 throw bad_image_data("bitmap header mismatch");
55 unsigned data_offset = decode<UInt32>(bm_header+10);
58 read_full(io, dib_header, 12);
59 unsigned dib_length = min<unsigned>(decode<UInt32>(dib_header), sizeof(dib_header));
61 throw bad_image_data("DIB header too short (very old bmp file?)");
63 read_full(io, dib_header+12, dib_length-12);
65 data.width = decode<UInt32>(dib_header+4);
66 Int32 height = decode<UInt32>(dib_header+8);
67 data.height = abs(height);
69 unsigned color_planes = decode<UInt16>(dib_header+12);
71 throw bad_image_data("color_planes!=1");
72 unsigned bits_per_pixel = decode<UInt16>(dib_header+14);
73 unsigned compression = decode<UInt32>(dib_header+16);
75 throw unsupported_image_format("compression not supported");
77 data.stride = (data.width*bits_per_pixel+31)/32*4;
78 switch(bits_per_pixel)
80 case 8: data.fmt = COLOR_INDEX; break;
81 case 24: data.fmt = BGR; break;
82 case 32: data.fmt = BGRX; break; // TODO is it BGRX or XBGR?
83 default: throw unsupported_image_format("bits per pixel value not supported");
86 unsigned skip = data_offset-sizeof(bm_header)-dib_length;
90 unsigned size = min<unsigned>(sizeof(buffer), skip);
91 read_full(io, buffer, size);
95 data.data = new char[data.stride*data.height];
98 for(unsigned y=0; y<data.height; ++y)
99 read_full(io, data.data+(data.height-1-y)*data.stride, data.stride);
103 for(unsigned y=0; y<data.height; ++y)
104 read_full(io, data.data+y*data.stride, data.stride);
108 } // namespace Graphics