IVT
ByteImage.cpp
Go to the documentation of this file.
00001 // ****************************************************************************
00002 // This file is part of the Integrating Vision Toolkit (IVT).
00003 //
00004 // The IVT is maintained by the Karlsruhe Institute of Technology (KIT)
00005 // (www.kit.edu) in cooperation with the company Keyetech (www.keyetech.de).
00006 //
00007 // Copyright (C) 2013 Karlsruhe Institute of Technology (KIT).
00008 // All rights reserved.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are met:
00012 //
00013 // 1. Redistributions of source code must retain the above copyright
00014 //    notice, this list of conditions and the following disclaimer.
00015 //
00016 // 2. Redistributions in binary form must reproduce the above copyright
00017 //    notice, this list of conditions and the following disclaimer in the
00018 //    documentation and/or other materials provided with the distribution.
00019 //
00020 // 3. Neither the name of the KIT nor the names of its contributors may be
00021 //    used to endorse or promote products derived from this software
00022 //    without specific prior written permission.
00023 //
00024 // THIS SOFTWARE IS PROVIDED BY THE KIT AND CONTRIBUTORS “AS IS” AND ANY
00025 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00026 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027 // DISCLAIMED. IN NO EVENT SHALL THE KIT OR CONTRIBUTORS BE LIABLE FOR ANY
00028 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00029 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00031 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00033 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 // ****************************************************************************
00035 // ****************************************************************************
00036 // Filename:  ByteImage.cpp
00037 // Author:    Pedram Azad
00038 // Date:      2004
00039 // ****************************************************************************
00040 // Changes:   24.07.2008, Miguel Bernal Marin
00041 //            * Added methods LoadFromFilePNM and SaveToFilePNM
00042 // ****************************************************************************
00043 
00044 
00045 // ****************************************************************************
00046 // Includes
00047 // ****************************************************************************
00048 
00049 #include <new> // for explicitly using correct new/delete operators on VC DSPs
00050 
00051 #include "ByteImage.h"
00052 
00053 #include "Helpers/helpers.h"
00054 
00055 #include <string.h>
00056 #include <stdio.h>
00057 #include <stdlib.h>
00058 #include <ctype.h>
00059 
00060 
00061 
00062 
00063 // ****************************************************************************
00064 // Defines
00065 // ****************************************************************************
00066 
00067 // this is a workaround for a bug in OpenCV:
00068 // on Mac, if not one byte extra is allocated for the pixel memory
00069 // most of the OpenCV functions crash (segmentation fault), such as
00070 // cvErode, cvDilate, cvSmooth, ... (after cvCreateImageHeader and
00071 // cvSetImageData)
00072 #define EXTRA_BYTES             1
00073 
00074 
00075 
00076 // ****************************************************************************
00077 // Constructors / Destructor
00078 // ****************************************************************************
00079 
00080 CByteImage::CByteImage()
00081 {
00082         width = 0;
00083         height = 0;
00084         bytesPerPixel = 0;
00085         pixels = 0;
00086         type = eGrayScale;
00087         m_bOwnMemory = false;
00088 }
00089 
00090 CByteImage::CByteImage(int nImageWidth, int nImageHeight, ImageType imageType, bool bHeaderOnly)
00091 {
00092         switch (imageType)
00093         {
00094                 case eGrayScale:
00095                         bytesPerPixel = 1;
00096                 break;
00097 
00098                 case eRGB24:
00099                 case eRGB24Split:
00100                         bytesPerPixel = 3;
00101                 break;
00102         }
00103 
00104         width = nImageWidth;
00105         height = nImageHeight;
00106         type = imageType;
00107 
00108         if (bHeaderOnly)
00109         {
00110                 pixels = 0;
00111                 m_bOwnMemory = false;
00112         }
00113         else
00114         {
00115                 pixels = new unsigned char[width * height * bytesPerPixel + EXTRA_BYTES];
00116                 m_bOwnMemory = true;
00117         }
00118 }
00119 
00120 CByteImage::CByteImage(const CByteImage &image, bool bHeaderOnly)
00121 {
00122         width = image.width;
00123         height = image.height;
00124         bytesPerPixel = image.bytesPerPixel;
00125         type = image.type;
00126         
00127         if (bHeaderOnly)
00128         {
00129                 pixels = 0;
00130                 m_bOwnMemory = false;
00131         }
00132         else
00133         {
00134                 pixels = new unsigned char[width * height * bytesPerPixel + EXTRA_BYTES];
00135                 m_bOwnMemory = true;
00136         }
00137 }
00138 
00139 CByteImage::CByteImage(const CByteImage *pImage, bool bHeaderOnly)
00140 {
00141         width = pImage->width;
00142         height = pImage->height;
00143         bytesPerPixel = pImage->bytesPerPixel;
00144         type = pImage->type;
00145         
00146         if (bHeaderOnly)
00147         {
00148                 pixels = 0;
00149                 m_bOwnMemory = false;
00150         }
00151         else
00152         {
00153                 pixels = new unsigned char[width * height * bytesPerPixel + EXTRA_BYTES];
00154                 m_bOwnMemory = true;
00155         }
00156 }
00157 
00158 CByteImage::~CByteImage()
00159 {
00160     FreeMemory();
00161 }
00162 
00163 
00164 // ****************************************************************************
00165 // Methods
00166 // ****************************************************************************
00167 
00168 void CByteImage::Set(int nImageWidth, int nImageHeight, ImageType imageType, bool bHeaderOnly)
00169 {
00170         FreeMemory();
00171 
00172         switch (imageType)
00173         {
00174                 case eGrayScale:
00175                         bytesPerPixel = 1;
00176                 break;
00177 
00178                 case eRGB24:
00179                 case eRGB24Split:
00180                         bytesPerPixel = 3;
00181                 break;
00182         }
00183 
00184         width = nImageWidth;
00185         height = nImageHeight;
00186         type = imageType;
00187 
00188         if (bHeaderOnly)
00189         {
00190                 pixels = 0;
00191                 m_bOwnMemory = false;
00192         }
00193         else
00194         {
00195                 pixels = new unsigned char[width * height * bytesPerPixel + EXTRA_BYTES];
00196                 m_bOwnMemory = true;
00197         }
00198 }
00199 
00200 void CByteImage::FreeMemory()
00201 {
00202         if (pixels)
00203         {
00204                 if (m_bOwnMemory)
00205                         delete [] pixels;
00206 
00207                 pixels = 0;
00208                 m_bOwnMemory = false;
00209         }
00210 }
00211 
00212 bool CByteImage::IsCompatible(const CByteImage *pImage) const
00213 {
00214         return width == pImage->width && height == pImage->height && type == pImage->type;
00215 }
00216 
00217 
00218 bool CByteImage::LoadFromFile(const char *pFileName)
00219 {
00220         const char *pBeginEnding = pFileName + strlen(pFileName) - 4;
00221         if (strcmp(pBeginEnding, ".bmp") ==  0 || strcmp(pBeginEnding, ".BMP") == 0)
00222                 return LoadFromFileBMP(pFileName);
00223         else if (strcmp(pBeginEnding, ".pgm") ==  0 || strcmp(pBeginEnding, ".PGM") == 0 ||
00224                         strcmp(pBeginEnding, ".ppm") ==  0 || strcmp(pBeginEnding, ".PPM") == 0)
00225                 return LoadFromFilePNM(pFileName);
00226                 
00227         return false;
00228 }
00229 
00230 bool CByteImage::SaveToFile(const char *pFileName) const
00231 {
00232         const char *pBeginEnding = pFileName + strlen(pFileName) - 4;
00233         if (strcmp(pBeginEnding, ".bmp") ==  0 || strcmp(pBeginEnding, ".BMP") == 0)
00234                 return SaveToFileBMP(pFileName);
00235         else if (strcmp(pBeginEnding, ".pgm") ==  0 || strcmp(pBeginEnding, ".PGM") == 0 ||
00236                         strcmp(pBeginEnding, ".ppm") ==  0 || strcmp(pBeginEnding, ".PPM") == 0)
00237                 return SaveToFilePNM(pFileName);
00238                 
00239         return false;
00240 }
00241 
00242 
00243 bool CByteImage::LoadFromFileBMP(const char *pFileName)
00244 {
00245         const unsigned short MB = 0x4d42;
00246 
00247         // first free memory, in any case
00248         FreeMemory();
00249 
00250         FILE *f = fopen(pFileName, "rb");
00251         if (!f)
00252                 return false;
00253 
00254         unsigned char szHeader[14 + 40];
00255 
00256         if (fread(szHeader, 14 + 40, 1, f) != 1)
00257         {
00258                 fclose(f);
00259                 return false;
00260         }
00261         
00262         myBITMAPFILEHEADER bitmapFileHeader;
00263         myBITMAPINFOHEADER bitmapInfoHeader;
00264         unsigned char *pBitmapInfoHeaderPosition = szHeader + 14;
00265         
00266 #ifdef IVT_BIG_ENDIAN
00267         bitmapFileHeader.bfType = invert_byte_order_short(*((unsigned short *) (szHeader)));
00268         bitmapFileHeader.bfSize = invert_byte_order_int(*((unsigned int *) (szHeader + 2)));
00269         bitmapFileHeader.bfReserved1 = invert_byte_order_short(*((unsigned short *) (szHeader + 6)));
00270         bitmapFileHeader.bfReserved2 = invert_byte_order_short(*((unsigned short *) (szHeader + 8)));
00271         bitmapFileHeader.bfOffBits = invert_byte_order_int(*((unsigned int *) (szHeader + 10)));
00272 
00273         if (bitmapFileHeader.bfType != MB || bitmapFileHeader.bfReserved1 != 0 || bitmapFileHeader.bfReserved2 != 0)
00274         {
00275                 fclose(f);
00276                 return false;
00277         }
00278 
00279         bitmapInfoHeader.biSize = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition)));
00280         bitmapInfoHeader.biWidth = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition + 4)));
00281         bitmapInfoHeader.biHeight = invert_byte_order_int(*((int *) (pBitmapInfoHeaderPosition + 8)));
00282         bitmapInfoHeader.biPlanes = invert_byte_order_short(*((unsigned short *) (pBitmapInfoHeaderPosition + 12)));
00283         bitmapInfoHeader.biBitCount = invert_byte_order_short(*((unsigned short *) (pBitmapInfoHeaderPosition + 14)));
00284         bitmapInfoHeader.biCompression = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition + 16)));
00285         bitmapInfoHeader.biSizeImage = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition + 20)));
00286         bitmapInfoHeader.biXPelsPerMeter = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition + 24)));
00287         bitmapInfoHeader.biYPelsPerMeter = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition + 28)));
00288         bitmapInfoHeader.biClrUsed = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition + 32)));
00289         bitmapInfoHeader.biClrImportant = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition + 36)));
00290 #else
00291         bitmapFileHeader.bfType = *((unsigned short *) (szHeader));
00292         bitmapFileHeader.bfSize = *((unsigned int *) (szHeader + 2));
00293         bitmapFileHeader.bfReserved1 = *((unsigned short *) (szHeader + 6));
00294         bitmapFileHeader.bfReserved2 = *((unsigned short *) (szHeader + 8));
00295         bitmapFileHeader.bfOffBits = *((unsigned int *) (szHeader + 10));
00296 
00297         if (bitmapFileHeader.bfType != MB || bitmapFileHeader.bfReserved1 != 0 || bitmapFileHeader.bfReserved2 != 0)
00298         {
00299                 fclose(f);
00300                 return false;
00301         }
00302 
00303         bitmapInfoHeader.biSize = *((unsigned int *) (pBitmapInfoHeaderPosition));
00304         bitmapInfoHeader.biWidth = *((unsigned int *) (pBitmapInfoHeaderPosition + 4));
00305         bitmapInfoHeader.biHeight = *((int *) (pBitmapInfoHeaderPosition + 8));
00306         bitmapInfoHeader.biPlanes = *((unsigned short *) (pBitmapInfoHeaderPosition + 12));
00307         bitmapInfoHeader.biBitCount = *((unsigned short *) (pBitmapInfoHeaderPosition + 14));
00308         bitmapInfoHeader.biCompression = *((unsigned int *) (pBitmapInfoHeaderPosition + 16));
00309         bitmapInfoHeader.biSizeImage = *((unsigned int *) (pBitmapInfoHeaderPosition + 20));
00310         bitmapInfoHeader.biXPelsPerMeter = *((unsigned int *) (pBitmapInfoHeaderPosition + 24));
00311         bitmapInfoHeader.biYPelsPerMeter = *((unsigned int *) (pBitmapInfoHeaderPosition + 28));
00312         bitmapInfoHeader.biClrUsed = *((unsigned int *) (pBitmapInfoHeaderPosition + 32));
00313         bitmapInfoHeader.biClrImportant = *((unsigned int *) (pBitmapInfoHeaderPosition + 36));
00314 #endif
00315 
00316         if (bitmapInfoHeader.biBitCount != 8 && bitmapInfoHeader.biBitCount != 24 && bitmapInfoHeader.biBitCount != 32 || bitmapInfoHeader.biWidth <= 0)
00317         {
00318                 fclose(f);
00319                 return false;
00320         }
00321 
00322         if (bitmapInfoHeader.biCompression != 0)
00323         {
00324                 fclose(f);
00325                 return false;
00326         }
00327 
00328         // allocate image
00329         width = bitmapInfoHeader.biWidth;
00330         height = abs(bitmapInfoHeader.biHeight);
00331 
00332         int nReadBytesPerPixel;
00333 
00334         unsigned char index_table[1024];
00335         bool bIndexed = false;
00336 
00337         if (bitmapInfoHeader.biBitCount == 8)
00338         {
00339                 bIndexed = false;
00340 
00341                 if (fread(index_table, 1024, 1, f) != 1)
00342                 {
00343                         fclose(f);
00344                         return false;
00345                 }
00346 
00347                 bool bGrayScale = true;
00348 
00349                 for (int i = 0; i < 1024; i += 4)
00350                 {
00351                         if (index_table[i] != index_table[i + 1] || index_table[i] != index_table[i + 2])
00352                         {
00353                                 // contains non grayscale data
00354                                 bIndexed = true;
00355                                 bGrayScale = false;
00356                                 break;
00357                         }
00358 
00359                         if (index_table[i] != (i >> 2))
00360                                 bIndexed = true;
00361                 }
00362 
00363                 if (bGrayScale)
00364                 {
00365                         type = eGrayScale;
00366                         bytesPerPixel = 1;
00367                         nReadBytesPerPixel = 1;
00368                 }
00369                 else
00370                 {
00371                         type = eRGB24;
00372                         bytesPerPixel = 3;
00373                         nReadBytesPerPixel = 1;
00374                 }
00375         }
00376         else
00377         {
00378                 switch (bitmapInfoHeader.biBitCount)
00379                 {
00380                         case 24:
00381                                 type = eRGB24;
00382                                 bytesPerPixel = 3;
00383                                 nReadBytesPerPixel = 3;
00384                         break;
00385 
00386                         case 32:
00387                                 type = eRGB24;
00388                                 bytesPerPixel = 3;
00389                                 nReadBytesPerPixel = 4;
00390                         break;
00391 
00392                         default:
00393                                 fclose(f);
00394                                 return false;
00395                         break;
00396                 }
00397         }
00398 
00399         const int padding_bytes = ((width * nReadBytesPerPixel) % 4 == 0) ? 0 : 4 - ((width * nReadBytesPerPixel) % 4);
00400 
00401         const int nPixels = width * height;
00402 
00403         // allocate memory
00404         pixels = new unsigned char[nPixels * bytesPerPixel + EXTRA_BYTES];
00405         unsigned char *pTempBuffer = new unsigned char[(width * nReadBytesPerPixel + padding_bytes) * height + EXTRA_BYTES];
00406         m_bOwnMemory = true;
00407 
00408         // fill pixels from file
00409         if (fread(pTempBuffer, (width * nReadBytesPerPixel + padding_bytes) * height, 1, f) != 1)
00410         {
00411                 FreeMemory();
00412                 fclose(f);
00413                 delete [] pTempBuffer;
00414                 return false;
00415         }
00416 
00417         if (bitmapInfoHeader.biHeight < 0)
00418         {
00419                 if (type == eRGB24)
00420                 {
00421                         const int write_width_bytes = 3 * width;
00422                         const int width_bytes = nReadBytesPerPixel * width;
00423                         const int aligned_width_bytes = width_bytes + padding_bytes;
00424                                                 
00425                         unsigned char *pHelper1 = pixels;
00426                         unsigned char *pHelper2 = pTempBuffer;
00427 
00428                         if (nReadBytesPerPixel == 1)
00429                         {
00430                                 // indexed
00431                                 for (int i = 0; i < height; i++)
00432                                 {
00433                                         for (int j = 0, k = 0; j < width_bytes; j++, k += 3)
00434                                         {
00435                                                 pHelper1[k] = index_table[pHelper2[j] << 2];
00436                                                 pHelper1[k + 1] = index_table[(pHelper2[j] << 2) + 1];
00437                                                 pHelper1[k + 2] = index_table[(pHelper2[j] << 2) + 2];
00438                                         }
00439                                 
00440                                         pHelper1 += write_width_bytes;
00441                                         pHelper2 += aligned_width_bytes;
00442                                 }
00443                         }
00444                         else
00445                         {
00446                                 // convert from BGR or BGRA to RGB
00447                                 for (int i = 0; i < height; i++)
00448                                 {
00449                                         for (int j = 0, k = 0; j < width_bytes; j += nReadBytesPerPixel, k += 3)
00450                                         {
00451                                                 pHelper1[k] = pHelper2[j + 2];
00452                                                 pHelper1[k + 1] = pHelper2[j + 1];
00453                                                 pHelper1[k + 2] = pHelper2[j];
00454                                         }
00455                                 
00456                                         pHelper1 += write_width_bytes;
00457                                         pHelper2 += aligned_width_bytes;
00458                                 }
00459                         }
00460                 }
00461                 else if (type == eGrayScale)
00462                 {
00463                         const int aligned_width_bytes = width + padding_bytes;
00464 
00465                         unsigned char *pHelper1 = pixels;
00466                         unsigned char *pHelper2 = pTempBuffer;
00467                         
00468                         if (bIndexed)
00469                         {
00470                                 // indexed
00471                                 for (int i = 0; i < height; i++)
00472                                 {
00473                                         for (int j = 0; j < width; j++)
00474                                                 pHelper1[j] = index_table[pHelper2[j << 2]];
00475                                 
00476                                         pHelper1 += width;
00477                                         pHelper2 += aligned_width_bytes;
00478                                 }
00479                         }
00480                         else
00481                         {
00482                                 // just copy
00483                                 for (int i = 0; i < height; i++)
00484                                 {
00485                                         memcpy(pHelper1, pHelper2, width);
00486                                 
00487                                         pHelper1 += width;
00488                                         pHelper2 += aligned_width_bytes;
00489                                 }
00490                         }
00491                 }
00492         }
00493         else
00494         {
00495                 if (type == eRGB24)
00496                 {
00497                         const int write_width_bytes = 3 * width;
00498                         const int width_bytes = nReadBytesPerPixel * width;
00499                         const int aligned_width_bytes = width_bytes + padding_bytes;
00500                         
00501                         unsigned char *pHelper1 = pixels;
00502                         unsigned char *pHelper2 = pTempBuffer + aligned_width_bytes * height - aligned_width_bytes;
00503                         
00504                         if (nReadBytesPerPixel == 1)
00505                         {
00506                                 // indexed
00507                                 for (int i = 0; i < height; i++)
00508                                 {
00509                                         for (int j = 0, k = 0; j < width_bytes; j++, k += 3)
00510                                         {
00511                                                 pHelper1[k] = index_table[pHelper2[j] << 2];
00512                                                 pHelper1[k + 1] = index_table[(pHelper2[j] << 2) + 1];
00513                                                 pHelper1[k + 2] = index_table[(pHelper2[j] << 2) + 2];
00514                                         }
00515                                         
00516                                         pHelper1 += write_width_bytes;
00517                                         pHelper2 -= aligned_width_bytes;
00518                                 }
00519                         }
00520                         else
00521                         {
00522                                 // convert from BGR or BGRA to RGB, and from bottom-left to top-left
00523                                 for (int i = 0; i < height; i++)
00524                                 {
00525                                         for (int j = 0, k = 0; j < width_bytes; j += nReadBytesPerPixel, k += 3)
00526                                         {
00527                                                 pHelper1[k] = pHelper2[j + 2];
00528                                                 pHelper1[k + 1] = pHelper2[j + 1];
00529                                                 pHelper1[k + 2] = pHelper2[j];
00530                                         }
00531                                         
00532                                         pHelper1 += write_width_bytes;
00533                                         pHelper2 -= aligned_width_bytes;
00534                                 }
00535                         }
00536                 }
00537                 else if (type == eGrayScale)
00538                 {
00539                         const int aligned_width_bytes = width + padding_bytes;
00540                         
00541                         unsigned char *pHelper1 = pixels;
00542                         unsigned char *pHelper2 = pTempBuffer + aligned_width_bytes * height - aligned_width_bytes;
00543                         
00544                         if (bIndexed)
00545                         {
00546                                 // indexed
00547                                 for (int i = 0; i < height; i++)
00548                                 {
00549                                         for (int j = 0; j < width; j++)
00550                                                 pHelper1[j] = index_table[pHelper2[j] << 2];
00551                                         
00552                                         pHelper1 += width;
00553                                         pHelper2 -= aligned_width_bytes;
00554                                 }
00555                         }
00556                         else
00557                         {
00558                                 // convert from bottom-left to top-left
00559                                 for (int i = 0; i < height; i++)
00560                                 {
00561                                         memcpy(pHelper1, pHelper2, width);
00562                                         
00563                                         pHelper1 += width;
00564                                         pHelper2 -= aligned_width_bytes;
00565                                 }
00566                         }
00567                 }
00568         }
00569 
00570         fclose(f);
00571         delete [] pTempBuffer;
00572 
00573         return true;
00574 }
00575 
00576 bool CByteImage::SaveToFileBMP(const char *pFileName) const
00577 {
00578         if (!pixels || !width || !height)
00579                 return false;
00580 
00581         const unsigned short MB = 0x4d42;
00582         const int padding_bytes = ((width * bytesPerPixel) % 4 == 0) ? 0 : 4 - ((width * bytesPerPixel) % 4);
00583 
00584         myBITMAPFILEHEADER bitmapFileHeader;
00585         bitmapFileHeader.bfType = MB;
00586         bitmapFileHeader.bfReserved1 = 0;
00587         bitmapFileHeader.bfReserved2 = 0;
00588                 
00589         myBITMAPINFOHEADER bitmapInfoHeader;
00590         bitmapInfoHeader.biSize = 40;
00591         bitmapInfoHeader.biWidth = width;
00592         bitmapInfoHeader.biHeight = height;
00593         bitmapInfoHeader.biPlanes = 1;
00594         bitmapInfoHeader.biXPelsPerMeter = 0;
00595         bitmapInfoHeader.biYPelsPerMeter = 0;
00596         bitmapInfoHeader.biClrUsed = 0;
00597         bitmapInfoHeader.biClrImportant = 0;
00598 
00599         switch (type)
00600         {
00601                 case eGrayScale:
00602                         bitmapInfoHeader.biBitCount = 8;
00603                         bitmapInfoHeader.biSizeImage = (width + padding_bytes) * height;
00604                         bitmapInfoHeader.biCompression = 0;
00605                         bitmapFileHeader.bfOffBits = 14 + 40 + 1024;
00606                         bitmapFileHeader.bfSize = bitmapFileHeader.bfOffBits + bitmapInfoHeader.biSizeImage;
00607                 break;
00608 
00609                 case eRGB24:
00610                 case eRGB24Split:
00611                         bitmapInfoHeader.biBitCount = 24;
00612                         bitmapInfoHeader.biSizeImage = (width * 3 + padding_bytes) * height;
00613                         bitmapInfoHeader.biCompression = 0;
00614                         bitmapFileHeader.bfOffBits = 14 + 40;
00615                         bitmapFileHeader.bfSize = bitmapFileHeader.bfOffBits + bitmapInfoHeader.biSizeImage;
00616                 break;
00617 
00618                 default:
00619                         return false;
00620                 break;
00621         }
00622         
00623         FILE *f = fopen(pFileName, "wb");
00624         if (!f)
00625                 return false;
00626 
00627         unsigned char szHeader[14 + 40];
00628         unsigned char *pBitmapInfoHeaderPosition = szHeader + 14;
00629 
00630 #ifdef IVT_BIG_ENDIAN
00631         *((unsigned short *) (szHeader)) = invert_byte_order_short(bitmapFileHeader.bfType);
00632         *((unsigned int *) (szHeader + 2)) = invert_byte_order_int(bitmapFileHeader.bfSize);
00633         *((unsigned short *) (szHeader + 6)) = invert_byte_order_short(bitmapFileHeader.bfReserved1);
00634         *((unsigned short *) (szHeader + 8)) = invert_byte_order_short(bitmapFileHeader.bfReserved2);
00635         *((unsigned int *) (szHeader + 10)) = invert_byte_order_int(bitmapFileHeader.bfOffBits);
00636 
00637         // write bitmap info header to file
00638         *((unsigned int *) (pBitmapInfoHeaderPosition)) = invert_byte_order_int(bitmapInfoHeader.biSize);
00639         *((unsigned int *) (pBitmapInfoHeaderPosition + 4)) = invert_byte_order_int(bitmapInfoHeader.biWidth);
00640         *((unsigned int *) (pBitmapInfoHeaderPosition + 8)) = invert_byte_order_int(bitmapInfoHeader.biHeight);
00641         *((unsigned short *) (pBitmapInfoHeaderPosition + 12)) = invert_byte_order_short(bitmapInfoHeader.biPlanes);
00642         *((unsigned short *) (pBitmapInfoHeaderPosition + 14)) = invert_byte_order_short(bitmapInfoHeader.biBitCount);
00643         *((unsigned int *) (pBitmapInfoHeaderPosition + 16)) = invert_byte_order_int(bitmapInfoHeader.biCompression);
00644         *((unsigned int *) (pBitmapInfoHeaderPosition + 20)) = invert_byte_order_int(bitmapInfoHeader.biSizeImage);
00645         *((unsigned int *) (pBitmapInfoHeaderPosition + 24)) = invert_byte_order_int(bitmapInfoHeader.biXPelsPerMeter);
00646         *((unsigned int *) (pBitmapInfoHeaderPosition + 28)) = invert_byte_order_int(bitmapInfoHeader.biYPelsPerMeter);
00647         *((unsigned int *) (pBitmapInfoHeaderPosition + 32)) = invert_byte_order_int(bitmapInfoHeader.biClrUsed);
00648         *((unsigned int *) (pBitmapInfoHeaderPosition + 36)) = invert_byte_order_int(bitmapInfoHeader.biClrImportant);
00649 #else
00650         *((unsigned short *) (szHeader)) = bitmapFileHeader.bfType;
00651         *((unsigned int *) (szHeader + 2)) = bitmapFileHeader.bfSize;
00652         *((unsigned short *) (szHeader + 6)) = bitmapFileHeader.bfReserved1;
00653         *((unsigned short *) (szHeader + 8)) = bitmapFileHeader.bfReserved2;
00654         *((unsigned int *) (szHeader + 10)) = bitmapFileHeader.bfOffBits;
00655 
00656         // write bitmap info header to file
00657         *((unsigned int *) (pBitmapInfoHeaderPosition)) = bitmapInfoHeader.biSize;
00658         *((unsigned int *) (pBitmapInfoHeaderPosition + 4)) = bitmapInfoHeader.biWidth;
00659         *((unsigned int *) (pBitmapInfoHeaderPosition + 8)) = bitmapInfoHeader.biHeight;
00660         *((unsigned short *) (pBitmapInfoHeaderPosition + 12)) = bitmapInfoHeader.biPlanes;
00661         *((unsigned short *) (pBitmapInfoHeaderPosition + 14)) = bitmapInfoHeader.biBitCount;
00662         *((unsigned int *) (pBitmapInfoHeaderPosition + 16)) = bitmapInfoHeader.biCompression;
00663         *((unsigned int *) (pBitmapInfoHeaderPosition + 20)) = bitmapInfoHeader.biSizeImage;
00664         *((unsigned int *) (pBitmapInfoHeaderPosition + 24)) = bitmapInfoHeader.biXPelsPerMeter;
00665         *((unsigned int *) (pBitmapInfoHeaderPosition + 28)) = bitmapInfoHeader.biYPelsPerMeter;
00666         *((unsigned int *) (pBitmapInfoHeaderPosition + 32)) = bitmapInfoHeader.biClrUsed;
00667         *((unsigned int *) (pBitmapInfoHeaderPosition + 36)) = bitmapInfoHeader.biClrImportant;
00668 #endif
00669 
00670         // write header to file
00671         if (fwrite(szHeader, 14 + 40, 1, f) != 1)
00672         {
00673                 fclose(f);
00674                 return false;
00675         }
00676 
00677         // if 8 bit grayscale then write color table
00678         if (type == eGrayScale)
00679         {
00680                 char szColorTable[1024];
00681 
00682                 for (int offset = 0, i = 0; i < 256; i++, offset += 4)
00683                 {
00684                         szColorTable[offset] = i;
00685                         szColorTable[offset + 1] = i;
00686                         szColorTable[offset + 2] = i;
00687                         szColorTable[offset + 3] = 0;
00688                 }
00689 
00690                 // write color table to file
00691                 if (fwrite(szColorTable, 1024, 1, f) != 1)
00692                 {
00693                         fclose(f);
00694                         return false;
00695                 }
00696         }
00697 
00698         unsigned char *pTempBuffer = new unsigned char[(width * bytesPerPixel + padding_bytes) * height];
00699         
00700         if (type == eRGB24)
00701         {
00702                 const int width_bytes = 3 * width;
00703                 
00704                 unsigned char *pHelper1 = pTempBuffer;
00705                 unsigned char *pHelper2 = pixels + width * height * 3 - width_bytes;
00706                 
00707                 // convert from RGB to BGR, and from top-left to bottom-left
00708                 for (int i = 0; i < height; i++)
00709                 {
00710                         for (int j = 0; j < width_bytes; j += 3)
00711                         {
00712                                 pHelper1[j] = pHelper2[j + 2];
00713                                 pHelper1[j + 1] = pHelper2[j + 1];
00714                                 pHelper1[j + 2] = pHelper2[j];
00715                         }
00716                         
00717                         pHelper1 += width_bytes + padding_bytes;
00718                         pHelper2 -= width_bytes;
00719                 }
00720         }
00721         else if (type == eRGB24Split)
00722         {
00723                 const int width_bytes = 3 * width;
00724 
00725                 unsigned char *pHelper = pTempBuffer;
00726                 unsigned char *pHelperR = pixels + width * height - width;
00727                 unsigned char *pHelperG = pHelperR + width * height;
00728                 unsigned char *pHelperB = pHelperG + width * height;
00729                 
00730                 // convert from RGB to BGR, and from top-left to bottom-left
00731                 for (int i = 0; i < height; i++)
00732                 {
00733                         for (int j = 0, offset = 0; j < width_bytes; j += 3, offset++)
00734                         {
00735                                 pHelper[j] = pHelperB[offset];
00736                                 pHelper[j + 1] = pHelperG[offset];
00737                                 pHelper[j + 2] = pHelperR[offset];
00738                         }
00739                         
00740                         pHelper += width_bytes + padding_bytes;
00741                         pHelperR -= width;
00742                         pHelperG -= width;
00743                         pHelperB -= width;
00744                 }
00745         }
00746         else if (type == eGrayScale)
00747         {
00748                 unsigned char *pHelper1 = pTempBuffer;
00749                 unsigned char *pHelper2 = pixels + width * height - width;
00750                 
00751                 // convert from top-left to bottom-left
00752                 for (int i = 0; i < height; i++)
00753                 {
00754                         for (int j = 0; j < width; j++)
00755                                 pHelper1[j] = pHelper2[j];
00756                                 
00757                         pHelper1 += width + padding_bytes;
00758                         pHelper2 -= width;
00759                 }
00760 
00761         }
00762         
00763         if (fwrite(pTempBuffer, (width * bytesPerPixel + padding_bytes) * height, 1, f) != 1)
00764         {
00765                 delete [] pTempBuffer;
00766                 fclose(f);
00767                 return false;
00768         }
00769         
00770         delete [] pTempBuffer;
00771         fclose(f);
00772 
00773         return true;
00774 }
00775 
00776 
00777 bool CByteImage::LoadFromFilePNM(const char *pFileName)
00778 {
00779         // first free memory, in any case
00780         FreeMemory();
00781 
00782         FILE *f = fopen(pFileName, "rb");
00783         if (!f)
00784                 return false;
00785 
00786         int character, maxVal; 
00787         char sNumber[16];
00788         short idx;
00789 
00790         character = fgetc(f);
00791         if (character != 'P')
00792         {
00793                 fclose(f);
00794                 return false;
00795         }
00796 
00797         character = fgetc(f);
00798         if (character != '5' && character != '6' )
00799         {
00800                 fclose(f);
00801                 return false;
00802         }
00803 
00804         if (character == '5')
00805         {
00806                 type = eGrayScale;
00807                 bytesPerPixel = 1;
00808         }
00809         else
00810         {
00811                 type = eRGB24;
00812                 bytesPerPixel = 3;
00813         }
00814 
00815         do
00816         {
00817                 // Read whitespaces
00818                 character = fgetc(f);
00819         } while (character == ' ' || character == '\n' || character == '\r');
00820 
00821         // Skip comments
00822         while (character == '#')
00823         {
00824                 while (fgetc(f) != '\n');
00825                 character = fgetc(f);
00826         }
00827 
00828         // Read width
00829         idx = 0;
00830         while (character != ' ' && character != '\n' && character != '\r')
00831         {
00832                 sNumber[idx++] =(char) character;
00833                 character = fgetc(f);
00834         }
00835         sscanf(sNumber,"%d",&width);
00836 
00837         do
00838         {  // Read whitespaces
00839                 character = fgetc(f);
00840         } while (character == ' ' || character == '\n' || character == '\r');
00841 
00842         // Skip comments
00843         while (character == '#')
00844         {
00845                 while (fgetc(f) != '\n');
00846                 character = fgetc(f);
00847         }
00848 
00849         // Read height
00850         idx = 0;
00851         while (character != ' ' && character != '\n' && character != '\r') {
00852                 sNumber[idx++] =(char) character;
00853                 character = fgetc(f);
00854         }
00855         sscanf(sNumber,"%d",&height);
00856 
00857         do
00858         {
00859                 // Read whitespaces
00860                 character = fgetc(f);
00861         } while (character == ' ' || character == '\n' || character == '\r');
00862 
00863         // Skip comments
00864         while (character == '#')
00865         {
00866                 while (fgetc(f) != '\n');
00867                 character = fgetc(f);
00868         }
00869 
00870         // The maximum color value (Maxval)
00871         idx = 0;
00872         while (character != ' ' && character != '\n' && character != '\r')
00873         {
00874                 sNumber[idx++] =(char) character;
00875                 character = fgetc(f);
00876         }
00877         sscanf(sNumber,"%d",&maxVal);
00878 
00879         if (maxVal != 255)
00880         {
00881                 fclose(f);
00882                 return false;
00883         }
00884 
00885         pixels = new unsigned char[width * height * bytesPerPixel + EXTRA_BYTES];
00886         m_bOwnMemory = true;
00887 
00888         if (fread (pixels , width * height * bytesPerPixel, 1, f ) !=  1)
00889         {
00890                 FreeMemory();
00891                 fclose(f);
00892                 return false;
00893         }
00894 
00895         fclose(f);
00896 
00897         return true;
00898 }
00899 
00900 bool CByteImage::SaveToFilePNM(const char *pFileName) const
00901 {
00902         if (!pixels || !width || !height)
00903                 return false;
00904 
00905         FILE *f = fopen(pFileName, "wb");
00906         if (!f)
00907                 return false;
00908 
00909         switch (type)
00910         {
00911                 case eGrayScale:
00912                         if (fprintf(f,"P5\n%d %d\n255\n", width, height) < 10)
00913                         {
00914                                 fclose(f);
00915                                 return false;
00916                         }
00917                 break;
00918                 
00919                 case eRGB24:
00920                 case eRGB24Split:
00921                         if (fprintf(f,"P6\n%d %d\n255\n",width , height) < 10)
00922                         {
00923                                 fclose(f);
00924                                 return false;
00925                         }
00926                 break;
00927                 
00928                 default:
00929                         fclose(f);
00930                         return false;
00931                 break;
00932         }
00933         
00934         if (type == eGrayScale || type == eRGB24)
00935         {
00936                 if (fwrite(pixels, width * height * bytesPerPixel, 1, f ) != 1)
00937                 {
00938                         fclose(f);
00939                         return false;
00940                 }
00941         }
00942         else if (type == eRGB24Split)
00943         {
00944                 const int nPixels = width * height;
00945                 
00946                 unsigned char *pTempBuffer = new unsigned char[nPixels * 3];
00947                 const unsigned char *pHelperR = pixels;
00948                 const unsigned char *pHelperG = pHelperR + nPixels;
00949                 const unsigned char *pHelperB = pHelperG + nPixels;
00950                 
00951                 for (int i = 0, offset = 0; i < nPixels; i++, offset += 3)
00952                 {
00953                         pTempBuffer[offset] = pHelperR[i];
00954                         pTempBuffer[offset + 1] = pHelperG[i];
00955                         pTempBuffer[offset + 2] = pHelperB[i];
00956                 }
00957 
00958                 if (fwrite(pTempBuffer, nPixels * 3, 1, f ) != 1)
00959                 {
00960                         delete [] pTempBuffer;
00961                         fclose(f);
00962                         return false;
00963                 }
00964 
00965                 delete [] pTempBuffer;
00966         }
00967         
00968         fclose(f);
00969 
00970         return true;
00971 }