Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "ioBMP.hpp"
00033 #include <vlCore/LoadWriterManager.hpp>
00034 #include <vlCore/VisualizationLibrary.hpp>
00035 #include <vlCore/FileSystem.hpp>
00036 #include <vlCore/VirtualFile.hpp>
00037 #include <vlCore/Image.hpp>
00038
00039 using namespace vl;
00040
00041 #include <vlCore/ImageTools.hpp>
00042
00043
00044
00045
00046 namespace
00047 {
00048 typedef struct
00049 {
00050 char mType[2];
00051 char mSize[4];
00052 char mReserved1[2];
00053 char mReserved2[2];
00054 char mOffBits[4];
00055
00056 unsigned short Type() const { return *(const unsigned short*)mType; }
00057 unsigned int Size() const { return *(const unsigned int*)mSize; }
00058 unsigned short Reserved1() const { return *(const unsigned short*)mReserved1; }
00059 unsigned short Reserved2() const { return *(const unsigned short*)mReserved2; }
00060 unsigned int OffBits() const { return *(const unsigned int*)mOffBits; }
00061 } BitmapFileHeader;
00062
00063 typedef struct
00064 {
00065 unsigned int Size() { return *(unsigned int*)mSize; }
00066 int Width() { return *(int*)mWidth; }
00067 int Height() { return *(int*)mHeight; }
00068 unsigned short Planes() { return *(unsigned short*)mPlanes; }
00069 unsigned short BitCount() { return *(unsigned short*)mBitCount; }
00070 unsigned int Compression() { return *(unsigned int*)mCompression; }
00071 unsigned int SizeImage() { return *(unsigned int*)mSizeImage; }
00072 int XPelsPerMeter() { return *(int*)mXPelsPerMeter; }
00073 int YPelsPerMeter() { return *(int*)mYPelsPerMeter; }
00074 unsigned int ClrUsed() { return *(unsigned int*)mClrUsed; }
00075 unsigned int ClrImportant() { return *(unsigned int*)mClrImportant; }
00076
00077 char mSize[4];
00078 char mWidth[4];
00079 char mHeight[4];
00080 char mPlanes[2];
00081 char mBitCount[2];
00082 char mCompression[4];
00083 char mSizeImage[4];
00084 char mXPelsPerMeter[4];
00085 char mYPelsPerMeter[4];
00086 char mClrUsed[4];
00087 char mClrImportant[4];
00088 } BitmapInfoHeader;
00089
00090 const unsigned int BMP_NoCompression = 0;
00091 const unsigned int BMP_XRGB = 3;
00092
00093
00094
00095
00096 }
00097
00104 ref<Image> vl::loadBMP( const String& path )
00105 {
00106 ref<VirtualFile> file = defFileSystem()->locateFile(path);
00107 if ( !file )
00108 {
00109 Log::error( Say("File '%s' not found.\n") << path );
00110 return NULL;
00111 }
00112
00113 return loadBMP(file.get());
00114 }
00115
00116 ref<Image> vl::loadBMP( VirtualFile* file )
00117 {
00118 if ( !file->open(OM_ReadOnly) )
00119 {
00120 Log::error( Say("loadBMP: error opening file: '%s'\n") << file->path() );
00121 return NULL;
00122 }
00123
00124 ref<Image> img = new Image;
00125 img->setObjectName(file->path().toStdString().c_str());
00126
00127 BitmapFileHeader bfh;
00128 memset(&bfh, 0, sizeof(bfh));
00129 BitmapInfoHeader bih;
00130 memset(&bih, 0, sizeof(bih));
00131
00132 file->read(&bfh, sizeof(bfh));
00133 if (bfh.Type() != 0x4D42)
00134 {
00135 file->close();
00136 Log::error( Say("The file '%s' is not a BMP file.\n") << file->path() );
00137 return NULL;
00138 }
00139
00140 int head = (int)file->position();
00141
00142 file->read(&bih, sizeof(bih));
00143
00144 bool flip = false;
00145 if ( bih.Height() < 0 )
00146 {
00147 int *h = (int*)bih.mHeight;
00148 *h = -*h;
00149 flip = true;
00150 }
00151 VL_CHECK( bih.Height() * bih.Width() );
00152
00153
00154 if ( bih.Compression() != BMP_NoCompression && bih.Compression() != BMP_XRGB )
00155 {
00156 Log::error( Say("Compression %n unsupported for %s\n") << bih.Compression() << file->path() );
00157 file->close();
00158 return NULL;
00159 }
00160
00161 switch( bih.BitCount() )
00162 {
00163
00164 case 8:
00165 {
00166 img->allocate2D(bih.Width(), bih.Height(), 4, IF_BGRA, IT_UNSIGNED_BYTE);
00167
00168 TPalette4x256 palette;
00169 memset(palette, 0, 256*4);
00170
00171 int br;
00172 file->seekSet( (int)head + bih.Size() );
00173 int palette_bytes = (bih.ClrUsed() ? bih.ClrUsed() : 256)*4;
00174 br = (int)file->read(palette, palette_bytes);
00175
00176
00177
00178 if(br != palette_bytes)
00179 {
00180 file->close();
00181 Log::error( Say("File %s truncated: %n < %n.\n") << file->path() << br << palette_bytes );
00182 return NULL;
00183 }
00184
00185 int pad_bytes = (4 - (img->width() * 1) % 4) % 4;
00186 int datasize = (img->width() * 1 + pad_bytes) * img->height();
00187
00188
00189
00190 if ( bih.Compression() == BMP_NoCompression )
00191 {
00192 br = (int)file->read(img->pixels(), datasize);
00193 if(br != datasize)
00194 {
00195
00196 file->close();
00197 Log::error( Say("file %s truncated.\n") << file->path() );
00198 return NULL;
00199 }
00200 }
00201
00202 else
00203 {
00204
00205 }
00206
00207 convert8ToRGBA( palette, img->pixels(), img->width(), img->height(), 4 );
00208 } break;
00209
00210 case 32:
00211 case 24:
00212 {
00213 img->allocate2D(bih.Width(), bih.Height(), 4, IF_BGRA, IT_UNSIGNED_BYTE);
00214 file->seekSet(bfh.OffBits());
00215
00216
00217 int pad_bytes = (4 - (img->width() * 3) % 4) % 4;
00218
00219 int datasize = bih.BitCount() == 32 ? img->width() * img->height() * 4 : (img->width() * 3 + pad_bytes) * img->height();
00220 int rd = (int)file->read(img->pixels(), datasize);
00221 if( rd < datasize )
00222 {
00223 file->close();
00224 Log::error( Say("File %s truncated.\n") << file->path() );
00225 return NULL;
00226 }
00227
00228
00229 if (bih.BitCount() == 24)
00230 convertRGBToRGBA(img->pixels(), img->width(), img->height(), 0xFF, 4);
00231
00232 } break;
00233
00234 default:
00235 {
00236 file->close();
00237 Log::error( Say("BitCount %n unsupported for %s\n") << (int)bih.BitCount() << file->path() );
00238 return NULL;
00239 }
00240 }
00241
00242 file->close();
00243
00244
00245 img = img->convertFormat(IF_RGBA);
00246
00247
00248 for(int h=0; h<img->height(); ++h)
00249 {
00250 unsigned char* px = img->pixels() + img->pitch()*h;
00251 for(int x=0; x<img->width()*4; x+=4)
00252 px[x+3] = 0xFF;
00253 }
00254
00255
00256 if (flip)
00257 img->flipVertically();
00258
00259 return img;
00260 }
00261
00262 bool vl::isBMP(VirtualFile* file)
00263 {
00264 if (!file->open(OM_ReadOnly))
00265 return false;
00266
00267 BitmapFileHeader bfh;
00268 memset(&bfh, 0, sizeof(bfh));
00269 BitmapInfoHeader bih;
00270 memset(&bih, 0, sizeof(bih));
00271
00272 file->read(&bfh, sizeof(bfh));
00273 file->read(&bih, sizeof(bih));
00274 file->close();
00275
00276 if (bfh.Type() != 0x4D42)
00277 {
00278 return false;
00279 }
00280
00281
00282 switch( bih.BitCount() )
00283 {
00284 case 1:
00285 case 4:
00286 case 8:
00287 case 16:
00288 case 24:
00289 case 32:
00290 break;
00291 default:
00292 return false;
00293 }
00294
00295
00296 switch( bih.Compression() )
00297 {
00298 case 0:
00299 case 1:
00300 case 2:
00301 case 3:
00302 case 4:
00303 case 5:
00304 break;
00305 default:
00306 return false;
00307 }
00308
00309 return true;
00310 }
00311