Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlCore/plugins/ioBMP.cpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.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 //-----------------------------------------------------------------------------

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:30.
Permission is granted to use this page to write and publish articles regarding Visualization Library.