From 5715968065256daa4c43d5365cf5e268d75e007a Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 26 Jul 2016 00:51:09 +0300 Subject: [PATCH] Implement a loader for BMP images --- source/graphics/bmploader.cpp | 109 ++++++++++++++++++++++++++++++++ source/graphics/bmploader.h | 27 ++++++++ source/graphics/imageloader.cpp | 2 + 3 files changed, 138 insertions(+) create mode 100644 source/graphics/bmploader.cpp create mode 100644 source/graphics/bmploader.h diff --git a/source/graphics/bmploader.cpp b/source/graphics/bmploader.cpp new file mode 100644 index 0000000..71de507 --- /dev/null +++ b/source/graphics/bmploader.cpp @@ -0,0 +1,109 @@ +#include +#include "bmploader.h" + +using namespace std; + +namespace { + +void read_full(Msp::IO::Base &io, char *buffer, unsigned size) +{ + unsigned len = io.read(buffer, size); + if(len +T decode(const char *data) +{ + const Msp::UInt8 *udata = reinterpret_cast(data); + T result = 0; + for(unsigned i=0; i10) + throw invalid_argument("BmpLoader::BmpLoader"); +} + +bool BmpLoader::detect(const std::string &sig) +{ + static const char bmp_sig[] = "BM"; + if(sig.size()(bm_header+10); + + char dib_header[124]; + read_full(io, dib_header, 12); + unsigned dib_length = min(decode(dib_header), sizeof(dib_header)); + if(dib_length<40) + throw bad_image_data("DIB header too short (very old bmp file?)"); + + read_full(io, dib_header+12, dib_length-12); + + data.width = decode(dib_header+4); + Int32 height = decode(dib_header+8); + data.height = abs(height); + + unsigned color_planes = decode(dib_header+12); + if(color_planes!=1) + throw bad_image_data("color_planes!=1"); + unsigned bits_per_pixel = decode(dib_header+14); + unsigned compression = decode(dib_header+16); + if(compression) + throw unsupported_image_format("compression not supported"); + + data.stride = (data.width*bits_per_pixel+31)/32*4; + switch(bits_per_pixel) + { + case 8: data.fmt = COLOR_INDEX; break; + case 24: data.fmt = BGR; break; + case 32: data.fmt = BGRX; break; // TODO is it BGRX or XBGR? + default: throw unsupported_image_format("bits per pixel value not supported"); + } + + unsigned skip = data_offset-sizeof(bm_header)-dib_length; + while(skip>0) + { + char buffer[1024]; + unsigned size = min(sizeof(buffer), skip); + read_full(io, buffer, size); + skip -= size; + } + + data.data = new char[data.stride*data.height]; + if(height<0) + { + for(unsigned y=0; y + +namespace Msp { +namespace Graphics { + +class BmpLoader: public RegisteredImageLoader +{ +private: + IO::Base &io; + unsigned sig_bytes; + +public: + BmpLoader(IO::Base &, unsigned = 0); + + static unsigned get_signature_size() { return 2; } + static bool detect(const std::string &); + + virtual void load(Image::Data &); +}; + +} // namespace Graphics +} // namespace Msp + +#endif diff --git a/source/graphics/imageloader.cpp b/source/graphics/imageloader.cpp index fbba25c..965c7b3 100644 --- a/source/graphics/imageloader.cpp +++ b/source/graphics/imageloader.cpp @@ -1,6 +1,7 @@ #include #include #include +#include "bmploader.h" #include "imageloader.h" #ifdef WITH_LIBPNG #include "png/pngloader.h" @@ -48,6 +49,7 @@ ImageLoader *ImageLoader::open_file(const string &fn) ImageLoader *ImageLoader::open_io(IO::Seekable &io) { + (void)RegisteredImageLoader::reg; #ifdef WITH_LIBPNG (void)RegisteredImageLoader::reg; #endif -- 2.45.2