Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 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 // BMP loader 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 // RLE8 = 1L; 00093 // RLE4 = 2L; 00094 // JPEG = 4L; 00095 // PNG = 5L; 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 // TODO: support bih.Compression() == BMP_Type_RLE8 e BMP_XRGB meglio 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 // 8 bit palettized 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 /*// set alpha to 0xFF 00176 for(int i=0; i<palette_bytes; i+=4) 00177 palette[i+3] = 0xFF;*/ 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 // 8bpp uncompressed 00189 00190 if ( bih.Compression() == BMP_NoCompression ) 00191 { 00192 br = (int)file->read(img->pixels(), datasize); 00193 if(br != datasize) 00194 { 00195 // fclose(fin); 00196 file->close(); 00197 Log::error( Say("file %s truncated.\n") << file->path() ); 00198 return NULL; 00199 } 00200 } 00201 // BMP_Type_RLE8 not supported yet 00202 else 00203 { 00204 // TODO 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 // usato solo se 24 bits. 00217 int pad_bytes = (4 - (img->width() * 3) % 4) % 4; 00218 // fa prima se lo si legge tutto insieme. 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 // convert the buffer from 24 to 32bpp running from the end to the begining. 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 // convert BGRA to RGBA 00245 img = img->convertFormat(IF_RGBA); 00246 00247 // set alpha channel to 0xFF 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 // flip the image 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 // check bit count 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 // check compression 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 //-----------------------------------------------------------------------------