ImageBMP.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                              SOFA :: Framework                              *
00020 *                                                                             *
00021 * Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
00022 * H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
00023 * M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
00024 *                                                                             *
00025 * Contact information: contact@sofa-framework.org                             *
00026 ******************************************************************************/
00027 #include <sofa/helper/io/ImageBMP.h>
00028 #include <sofa/helper/system/FileRepository.h>
00029 #include <cstdio>
00030 #include <iostream>
00031 
00032 namespace sofa
00033 {
00034 
00035 namespace helper
00036 {
00037 
00038 namespace io
00039 {
00040 
00041 //using namespace sofa::defaulttype;
00042 
00043 SOFA_DECL_CLASS(ImageBMP)
00044 
00045 Creator<Image::FactoryImage,ImageBMP> ImageBMPClass("bmp");
00046 
00047 bool ImageBMP::load(std::string filename)
00048 {
00049     if (!sofa::helper::system::DataRepository.findFile(filename))
00050     {
00051     std::cerr << "File " << filename << " not found " << std::endl;
00052     return false;
00053     }
00054     unsigned short int bfType;
00055     long int bfOffBits;
00056     short int biPlanes;
00057     short int biBitCount;
00058     long int biSizeImage;
00059     FILE *file;
00060     /* make sure the file is there and open it read-only (binary) */
00061     if ((file = fopen(filename.c_str(), "rb")) == NULL)
00062     {
00063         std::cerr << "File not found : " << filename << std::endl;
00064         return false;
00065     }
00066     
00067     if(!fread(&bfType, sizeof(short int), 1, file))
00068     {
00069         std::cerr << "Error reading file!" << std::endl;
00070         return false;
00071     }
00072     
00073     /* check if file is a bitmap */
00074     if (bfType != 19778)
00075     {
00076         std::cerr << "Not a Bitmap-File!\n";
00077         return false;
00078     }        
00079     /* get the file size */
00080     /* skip file size and reserved fields of bitmap file header */
00081     fseek(file, 8, SEEK_CUR);
00082     /* get the position of the actual bitmap data */
00083     if (!fread(&bfOffBits, sizeof(long int), 1, file))
00084     {
00085         std::cerr << "Error reading file!\n";
00086         return false;
00087     }
00088     // printf("Data at Offset: %ld\n", bfOffBits);
00089     /* skip size of bitmap info header */
00090     fseek(file, 4, SEEK_CUR);
00091     /* get the width of the bitmap */
00092     fread(&width, sizeof(int), 1, file);
00093     if (width < 0) width = -width;
00094     //printf("Width of Bitmap: %d\n", texture->width);
00095     /* get the height of the bitmap */
00096     fread(&height, sizeof(int), 1, file);
00097     bool upsidedown = false;
00098     if (height < 0) { height = -height; upsidedown = true; }
00099     //printf("Height of Bitmap: %d\n", texture->height);
00100     /* get the number of planes (must be set to 1) */
00101     fread(&biPlanes, sizeof(short int), 1, file);
00102     if (biPlanes != 1)
00103     {
00104         std::cerr << "Error: number of Planes not 1!\n";
00105         return false;
00106     }
00107     /* get the number of bits per pixel */
00108     if (!fread(&biBitCount, sizeof(short int), 1, file))
00109     {
00110         std::cerr << "Error reading file!\n";
00111         return false;
00112     }
00113     //printf("Bits per Pixel: %d\n", biBitCount);
00114     if (biBitCount != 24 && biBitCount != 32 && biBitCount != 8)
00115     {
00116         std::cerr << "Bits per Pixel not supported\n";
00117         return false;
00118     }
00119     nbBits = biBitCount;
00120     int nc = ((nbBits+7)/8);
00121     /* calculate the size of the image in bytes */
00122     biSizeImage = width * height * nc;
00123     // std::cout << "Size of the image data: " << biSizeImage << std::endl;
00124 //     std::cout << "ImageBMP "<<filename<<" "<<width<<"x"<<height<<"x"<<nbBits<<" = "<<biSizeImage<<" bytes"<<std::endl;
00125     data = (unsigned char*) malloc(biSizeImage);
00126     /* seek to the actual data */
00127     fseek(file, bfOffBits, SEEK_SET);
00128     
00129     if (((width*nc)%4)==0 && !upsidedown)
00130     {
00131         if (!fread(data, biSizeImage, 1, file))
00132         {
00133             std::cerr << "Error loading file!\n";
00134             return false;
00135         }
00136     }
00137     else
00138     {
00139             int pad = (4-((width*nc)%4))%4;
00140             char buf[3];
00141             for (int y=0;y<height;y++)
00142             {
00143                 if (!fread(data+(upsidedown?height-1-y:y)*width*nc, width*nc, 1, file))
00144             {
00145                 std::cerr << "Error loading file!\n";
00146                 return false;
00147             }
00148             if (pad && !fread(buf, 4-((width*nc)%4), 1, file))
00149             {
00150                 std::cerr << "Error loading file!\n";
00151                 return false;
00152             }
00153         }
00154     }
00155 
00156     if (nc == 3 || nc == 4)
00157     {
00158     int i;
00159     unsigned char temp;
00160         // swap red and blue (bgr -> rgb)
00161         for (i = 0; i < width*height*nc; i += nc)
00162         {
00163                 temp = data[i];
00164                 data[i] = data[i + 2];
00165                 data[i + 2] = temp;
00166         }
00167     }
00168 
00169     fclose(file);
00170     return true;
00171 }
00172 
00173 static bool fwriteW(FILE* file, unsigned short data)
00174 {
00175   return fwrite(&data,sizeof(data),1,file)!=0;
00176 }
00177 
00178 static bool fwriteDW(FILE* file, unsigned long data)
00179 {
00180   return fwrite(&data,sizeof(data),1,file)!=0;
00181 }
00182 
00183 bool ImageBMP::save(std::string filename, int)
00184 {
00185     FILE *file;
00186     /* make sure the file is there and open it read-only (binary) */
00187     if ((file = fopen(filename.c_str(), "wb")) == NULL)
00188     {
00189         std::cerr << "File write access failed : " << filename << std::endl;
00190         return false;
00191     }
00192 
00193     unsigned long lineSizeIn = ((nbBits+7)/8)*width;
00194     unsigned long lineSizeOut = ((lineSizeIn+3)/4)*4;
00195     unsigned long biSizeImage = lineSizeOut*height;
00196 
00197     // BITMAPFILEHEADER
00198     if (!fwriteW(file, (unsigned short)'B' | ((unsigned short)'M' << 8))) return false; // Type
00199     if (!fwriteDW(file, 14+40+biSizeImage)) return false; // Size
00200     if (!fwriteW(file, 0)) return false; // Reserved1
00201     if (!fwriteW(file, 0)) return false; // Reserved2
00202     if (!fwriteDW(file, 14+40)) return false; // OffBits
00203 
00204     // BITMAPINFOHEADER
00205     if (!fwriteDW(file, 40)) return false; // Size
00206     if (!fwriteDW(file, width)) return false; // Width
00207     if (!fwriteDW(file, height)) return false; // Height
00208     if (!fwriteW(file, 1)) return false; // Planes
00209     if (!fwriteW(file, nbBits)) return false; // BitCount
00210     if (!fwriteDW(file, 0)) return false; // Compression
00211     if (!fwriteDW(file, biSizeImage)) return false; // SizeImage
00212     if (!fwriteDW(file, 2825)) return false; // XPelsPerMeter
00213     if (!fwriteDW(file, 2825)) return false; // YPelsPerMeter
00214     if (!fwriteDW(file, 0)) return false; // ClrUsed
00215     if (!fwriteDW(file, 0)) return false; // ClrImportant
00216 
00217     if(nbBits==24)
00218     {
00219         unsigned char temp;
00220         /* swap red and blue (rgb -> bgr) */
00221         for (int i = 0; i < width*height*3; i += 3)
00222         {
00223             temp = data[i];
00224             data[i] = data[i + 2];
00225             data[i + 2] = temp;
00226         }
00227     }
00228     if (lineSizeIn == lineSizeOut)
00229     {
00230         if (!fwrite(data, biSizeImage, 1, file)) return false;
00231     }
00232     else
00233     {
00234         for (int y=0;y<height;y++)
00235         {
00236             if (!fwrite(data+y*lineSizeIn, lineSizeIn, 1, file)) return false;
00237             char buf[3]={0,0,0};
00238             if (!fwrite(buf, lineSizeOut-lineSizeIn, 1, file)) return false;
00239         }
00240     }
00241     if(nbBits==24)
00242     {
00243         int i;
00244         unsigned char temp;
00245         /* swap red and blue (bgr -> rgb) */
00246         for (i = 0; i < width*height*3; i += 3)
00247         {
00248             temp = data[i];
00249             data[i] = data[i + 2];
00250             data[i + 2] = temp;
00251         }
00252     }
00253 
00254     fclose(file);
00255     return true;
00256 }
00257 
00258 } // namespace io
00259 
00260 } // namespace helper
00261 
00262 } // namespace sofa
00263 

Generated on Sun Nov 23 02:29:30 2008 for Sofa by  doxygen 1.5.7.1