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) 2014 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 static int my_strcmpi(const char *pString1, const char *pString2)
00219 {
00220         for (int i = 0;; i++)
00221         {
00222                 const unsigned char c1 = (unsigned char) toupper((int) pString1[i]);
00223                 const unsigned char c2 = (unsigned char) toupper((int) pString2[i]);
00224 
00225                 if (c1 == '\0' || c1 != c2)
00226                         return c1 - c2;
00227         }
00228  
00229         return 0;
00230 }
00231 
00232 bool CByteImage::LoadFromFile(const char *pFileName)
00233 {
00234         const char *pBeginEnding = pFileName + strlen(pFileName) - 4;
00235         if (my_strcmpi(pBeginEnding, ".bmp") ==  0)
00236                 return LoadFromFileBMP(pFileName);
00237         else if (my_strcmpi(pBeginEnding, ".pgm") ==  0 || my_strcmpi(pBeginEnding, ".ppm") ==  0)
00238                 return LoadFromFilePNM(pFileName);
00239                 
00240         return false;
00241 }
00242 
00243 bool CByteImage::SaveToFile(const char *pFileName) const
00244 {
00245         const char *pBeginEnding = pFileName + strlen(pFileName) - 4;
00246         if (my_strcmpi(pBeginEnding, ".bmp") ==  0)
00247                 return SaveToFileBMP(pFileName);
00248         else if (my_strcmpi(pBeginEnding, ".pgm") ==  0 || my_strcmpi(pBeginEnding, ".ppm") ==  0)
00249                 return SaveToFilePNM(pFileName);
00250                 
00251         return false;
00252 }
00253 
00254 
00255 bool CByteImage::LoadFromFileBMP(const char *pFileName)
00256 {
00257         const unsigned short MB = 0x4d42;
00258 
00259         // first free memory, in any case
00260         FreeMemory();
00261 
00262         FILE *f = fopen(pFileName, "rb");
00263         if (!f)
00264                 return false;
00265 
00266         unsigned char szHeader[4096];
00267 
00268         if (fread(szHeader, 14, 1, f) != 1)
00269         {
00270                 fclose(f);
00271                 return false;
00272         }
00273         
00274         myBITMAPFILEHEADER bitmapFileHeader;
00275         
00276 #ifdef IVT_BIG_ENDIAN
00277         bitmapFileHeader.bfType = invert_byte_order_short(*((unsigned short *) (szHeader)));
00278         bitmapFileHeader.bfSize = invert_byte_order_int(*((unsigned int *) (szHeader + 2)));
00279         bitmapFileHeader.bfReserved1 = invert_byte_order_short(*((unsigned short *) (szHeader + 6)));
00280         bitmapFileHeader.bfReserved2 = invert_byte_order_short(*((unsigned short *) (szHeader + 8)));
00281         bitmapFileHeader.bfOffBits = invert_byte_order_int(*((unsigned int *) (szHeader + 10)));
00282 #else
00283         bitmapFileHeader.bfType = *((unsigned short *) (szHeader));
00284         bitmapFileHeader.bfSize = *((unsigned int *) (szHeader + 2));
00285         bitmapFileHeader.bfReserved1 = *((unsigned short *) (szHeader + 6));
00286         bitmapFileHeader.bfReserved2 = *((unsigned short *) (szHeader + 8));
00287         bitmapFileHeader.bfOffBits = *((unsigned int *) (szHeader + 10));
00288 #endif
00289 
00290         if (bitmapFileHeader.bfType != MB || bitmapFileHeader.bfReserved1 != 0 || bitmapFileHeader.bfReserved2 != 0 || bitmapFileHeader.bfOffBits >= 4096)
00291         {
00292                 fclose(f);
00293                 return false;
00294         }
00295 
00296         if (fread(szHeader + 14, bitmapFileHeader.bfOffBits - 14, 1, f) != 1)
00297         {
00298                 fclose(f);
00299                 return false;
00300         }
00301 
00302         myBITMAPINFOHEADER bitmapInfoHeader;
00303         unsigned char *pBitmapInfoHeaderPosition = szHeader + 14;
00304 
00305 #ifdef IVT_BIG_ENDIAN
00306         bitmapInfoHeader.biSize = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition)));
00307         bitmapInfoHeader.biWidth = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition + 4)));
00308         bitmapInfoHeader.biHeight = invert_byte_order_int(*((int *) (pBitmapInfoHeaderPosition + 8)));
00309         bitmapInfoHeader.biPlanes = invert_byte_order_short(*((unsigned short *) (pBitmapInfoHeaderPosition + 12)));
00310         bitmapInfoHeader.biBitCount = invert_byte_order_short(*((unsigned short *) (pBitmapInfoHeaderPosition + 14)));
00311         bitmapInfoHeader.biCompression = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition + 16)));
00312         bitmapInfoHeader.biSizeImage = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition + 20)));
00313         bitmapInfoHeader.biXPelsPerMeter = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition + 24)));
00314         bitmapInfoHeader.biYPelsPerMeter = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition + 28)));
00315         bitmapInfoHeader.biClrUsed = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition + 32)));
00316         bitmapInfoHeader.biClrImportant = invert_byte_order_int(*((unsigned int *) (pBitmapInfoHeaderPosition + 36)));
00317 #else
00318         bitmapInfoHeader.biSize = *((unsigned int *) (pBitmapInfoHeaderPosition));
00319         bitmapInfoHeader.biWidth = *((unsigned int *) (pBitmapInfoHeaderPosition + 4));
00320         bitmapInfoHeader.biHeight = *((int *) (pBitmapInfoHeaderPosition + 8));
00321         bitmapInfoHeader.biPlanes = *((unsigned short *) (pBitmapInfoHeaderPosition + 12));
00322         bitmapInfoHeader.biBitCount = *((unsigned short *) (pBitmapInfoHeaderPosition + 14));
00323         bitmapInfoHeader.biCompression = *((unsigned int *) (pBitmapInfoHeaderPosition + 16));
00324         bitmapInfoHeader.biSizeImage = *((unsigned int *) (pBitmapInfoHeaderPosition + 20));
00325         bitmapInfoHeader.biXPelsPerMeter = *((unsigned int *) (pBitmapInfoHeaderPosition + 24));
00326         bitmapInfoHeader.biYPelsPerMeter = *((unsigned int *) (pBitmapInfoHeaderPosition + 28));
00327         bitmapInfoHeader.biClrUsed = *((unsigned int *) (pBitmapInfoHeaderPosition + 32));
00328         bitmapInfoHeader.biClrImportant = *((unsigned int *) (pBitmapInfoHeaderPosition + 36));
00329 #endif
00330 
00331         if ((bitmapInfoHeader.biBitCount != 8 && bitmapInfoHeader.biBitCount != 24 && bitmapInfoHeader.biBitCount != 32) || bitmapInfoHeader.biWidth <= 0)
00332         {
00333                 fclose(f);
00334                 return false;
00335         }
00336 
00337         if (bitmapInfoHeader.biCompression != 0)
00338         {
00339                 fclose(f);
00340                 return false;
00341         }
00342 
00343         if (bitmapInfoHeader.biBitCount != 8 && bitmapInfoHeader.biClrUsed > 256)
00344         {
00345                 fclose(f);
00346                 return false;
00347         }
00348 
00349         // allocate image
00350         width = bitmapInfoHeader.biWidth;
00351         height = abs(bitmapInfoHeader.biHeight);
00352 
00353         int nReadBytesPerPixel;
00354 
00355         const int nTableSize = bitmapInfoHeader.biClrUsed == 0 ? 1024 : 4 * bitmapInfoHeader.biClrUsed;
00356         unsigned char index_table[1024];
00357         memcpy(index_table, pBitmapInfoHeaderPosition + bitmapInfoHeader.biSize, nTableSize);
00358 
00359         bool bIndexed = false;
00360 
00361         if (bitmapInfoHeader.biBitCount == 8)
00362         {
00363                 if (bitmapFileHeader.bfOffBits - 14 - bitmapInfoHeader.biSize != nTableSize)
00364                 {
00365                         fclose(f);
00366                         return false;
00367                 }
00368 
00369                 bIndexed = false;
00370 
00371                 bool bGrayScale = true;
00372 
00373                 for (int i = 0; i < nTableSize; i += 4)
00374                 {
00375                         if (index_table[i] != index_table[i + 1] || index_table[i] != index_table[i + 2])
00376                         {
00377                                 // contains non grayscale data
00378                                 bIndexed = true;
00379                                 bGrayScale = false;
00380                                 break;
00381                         }
00382 
00383                         if (index_table[i] != (i >> 2))
00384                                 bIndexed = true;
00385                 }
00386 
00387                 if (bGrayScale)
00388                 {
00389                         type = eGrayScale;
00390                         bytesPerPixel = 1;
00391                         nReadBytesPerPixel = 1;
00392                 }
00393                 else
00394                 {
00395                         type = eRGB24;
00396                         bytesPerPixel = 3;
00397                         nReadBytesPerPixel = 1;
00398                 }
00399         }
00400         else
00401         {
00402                 switch (bitmapInfoHeader.biBitCount)
00403                 {
00404                         case 24:
00405                                 type = eRGB24;
00406                                 bytesPerPixel = 3;
00407                                 nReadBytesPerPixel = 3;
00408                         break;
00409 
00410                         case 32:
00411                                 type = eRGB24;
00412                                 bytesPerPixel = 3;
00413                                 nReadBytesPerPixel = 4;
00414                         break;
00415 
00416                         default:
00417                                 fclose(f);
00418                                 return false;
00419                         break;
00420                 }
00421         }
00422 
00423         const int padding_bytes = ((width * nReadBytesPerPixel) % 4 == 0) ? 0 : 4 - ((width * nReadBytesPerPixel) % 4);
00424 
00425         const int nPixels = width * height;
00426 
00427         // allocate memory
00428         pixels = new unsigned char[nPixels * bytesPerPixel + EXTRA_BYTES];
00429         unsigned char *pTempBuffer = new unsigned char[(width * nReadBytesPerPixel + padding_bytes) * height + EXTRA_BYTES];
00430         m_bOwnMemory = true;
00431 
00432         // fill pixels from file
00433         if (fread(pTempBuffer, (width * nReadBytesPerPixel + padding_bytes) * height, 1, f) != 1)
00434         {
00435                 FreeMemory();
00436                 fclose(f);
00437                 delete [] pTempBuffer;
00438                 return false;
00439         }
00440 
00441         if (bitmapInfoHeader.biHeight < 0)
00442         {
00443                 if (type == eRGB24)
00444                 {
00445                         const int write_width_bytes = 3 * width;
00446                         const int width_bytes = nReadBytesPerPixel * width;
00447                         const int aligned_width_bytes = width_bytes + padding_bytes;
00448                                                 
00449                         unsigned char *pHelper1 = pixels;
00450                         unsigned char *pHelper2 = pTempBuffer;
00451 
00452                         if (nReadBytesPerPixel == 1)
00453                         {
00454                                 // indexed
00455                                 for (int i = 0; i < height; i++)
00456                                 {
00457                                         for (int j = 0, k = 0; j < width_bytes; j++, k += 3)
00458                                         {
00459                                                 pHelper1[k] = index_table[pHelper2[j] << 2];
00460                                                 pHelper1[k + 1] = index_table[(pHelper2[j] << 2) + 1];
00461                                                 pHelper1[k + 2] = index_table[(pHelper2[j] << 2) + 2];
00462                                         }
00463                                 
00464                                         pHelper1 += write_width_bytes;
00465                                         pHelper2 += aligned_width_bytes;
00466                                 }
00467                         }
00468                         else
00469                         {
00470                                 // convert from BGR or BGRA to RGB
00471                                 for (int i = 0; i < height; i++)
00472                                 {
00473                                         for (int j = 0, k = 0; j < width_bytes; j += nReadBytesPerPixel, k += 3)
00474                                         {
00475                                                 pHelper1[k] = pHelper2[j + 2];
00476                                                 pHelper1[k + 1] = pHelper2[j + 1];
00477                                                 pHelper1[k + 2] = pHelper2[j];
00478                                         }
00479                                 
00480                                         pHelper1 += write_width_bytes;
00481                                         pHelper2 += aligned_width_bytes;
00482                                 }
00483                         }
00484                 }
00485                 else if (type == eGrayScale)
00486                 {
00487                         const int aligned_width_bytes = width + padding_bytes;
00488 
00489                         unsigned char *pHelper1 = pixels;
00490                         unsigned char *pHelper2 = pTempBuffer;
00491                         
00492                         if (bIndexed)
00493                         {
00494                                 // indexed
00495                                 for (int i = 0; i < height; i++)
00496                                 {
00497                                         for (int j = 0; j < width; j++)
00498                                                 pHelper1[j] = index_table[pHelper2[j << 2]];
00499                                 
00500                                         pHelper1 += width;
00501                                         pHelper2 += aligned_width_bytes;
00502                                 }
00503                         }
00504                         else
00505                         {
00506                                 // just copy
00507                                 for (int i = 0; i < height; i++)
00508                                 {
00509                                         memcpy(pHelper1, pHelper2, width);
00510                                 
00511                                         pHelper1 += width;
00512                                         pHelper2 += aligned_width_bytes;
00513                                 }
00514                         }
00515                 }
00516         }
00517         else
00518         {
00519                 if (type == eRGB24)
00520                 {
00521                         const int write_width_bytes = 3 * width;
00522                         const int width_bytes = nReadBytesPerPixel * width;
00523                         const int aligned_width_bytes = width_bytes + padding_bytes;
00524                         
00525                         unsigned char *pHelper1 = pixels;
00526                         unsigned char *pHelper2 = pTempBuffer + aligned_width_bytes * height - aligned_width_bytes;
00527                         
00528                         if (nReadBytesPerPixel == 1)
00529                         {
00530                                 // indexed
00531                                 for (int i = 0; i < height; i++)
00532                                 {
00533                                         for (int j = 0, k = 0; j < width_bytes; j++, k += 3)
00534                                         {
00535                                                 pHelper1[k] = index_table[pHelper2[j] << 2];
00536                                                 pHelper1[k + 1] = index_table[(pHelper2[j] << 2) + 1];
00537                                                 pHelper1[k + 2] = index_table[(pHelper2[j] << 2) + 2];
00538                                         }
00539                                         
00540                                         pHelper1 += write_width_bytes;
00541                                         pHelper2 -= aligned_width_bytes;
00542                                 }
00543                         }
00544                         else
00545                         {
00546                                 // convert from BGR or BGRA to RGB, and from bottom-left to top-left
00547                                 for (int i = 0; i < height; i++)
00548                                 {
00549                                         for (int j = 0, k = 0; j < width_bytes; j += nReadBytesPerPixel, k += 3)
00550                                         {
00551                                                 pHelper1[k] = pHelper2[j + 2];
00552                                                 pHelper1[k + 1] = pHelper2[j + 1];
00553                                                 pHelper1[k + 2] = pHelper2[j];
00554                                         }
00555                                         
00556                                         pHelper1 += write_width_bytes;
00557                                         pHelper2 -= aligned_width_bytes;
00558                                 }
00559                         }
00560                 }
00561                 else if (type == eGrayScale)
00562                 {
00563                         const int aligned_width_bytes = width + padding_bytes;
00564                         
00565                         unsigned char *pHelper1 = pixels;
00566                         unsigned char *pHelper2 = pTempBuffer + aligned_width_bytes * height - aligned_width_bytes;
00567                         
00568                         if (bIndexed)
00569                         {
00570                                 // indexed
00571                                 for (int i = 0; i < height; i++)
00572                                 {
00573                                         for (int j = 0; j < width; j++)
00574                                                 pHelper1[j] = index_table[pHelper2[j] << 2];
00575                                         
00576                                         pHelper1 += width;
00577                                         pHelper2 -= aligned_width_bytes;
00578                                 }
00579                         }
00580                         else
00581                         {
00582                                 // convert from bottom-left to top-left
00583                                 for (int i = 0; i < height; i++)
00584                                 {
00585                                         memcpy(pHelper1, pHelper2, width);
00586                                         
00587                                         pHelper1 += width;
00588                                         pHelper2 -= aligned_width_bytes;
00589                                 }
00590                         }
00591                 }
00592         }
00593 
00594         fclose(f);
00595         delete [] pTempBuffer;
00596 
00597         return true;
00598 }
00599 
00600 bool CByteImage::SaveToFileBMP(const char *pFileName) const
00601 {
00602         if (!pixels || !width || !height)
00603                 return false;
00604 
00605         const unsigned short MB = 0x4d42;
00606         const int padding_bytes = ((width * bytesPerPixel) % 4 == 0) ? 0 : 4 - ((width * bytesPerPixel) % 4);
00607 
00608         myBITMAPFILEHEADER bitmapFileHeader;
00609         bitmapFileHeader.bfType = MB;
00610         bitmapFileHeader.bfReserved1 = 0;
00611         bitmapFileHeader.bfReserved2 = 0;
00612                 
00613         myBITMAPINFOHEADER bitmapInfoHeader;
00614         bitmapInfoHeader.biSize = 40;
00615         bitmapInfoHeader.biWidth = width;
00616         bitmapInfoHeader.biHeight = height;
00617         bitmapInfoHeader.biPlanes = 1;
00618         bitmapInfoHeader.biXPelsPerMeter = 0;
00619         bitmapInfoHeader.biYPelsPerMeter = 0;
00620         bitmapInfoHeader.biClrUsed = 0;
00621         bitmapInfoHeader.biClrImportant = 0;
00622 
00623         switch (type)
00624         {
00625                 case eGrayScale:
00626                         bitmapInfoHeader.biBitCount = 8;
00627                         bitmapInfoHeader.biSizeImage = (width + padding_bytes) * height;
00628                         bitmapInfoHeader.biCompression = 0;
00629                         bitmapFileHeader.bfOffBits = 14 + 40 + 1024;
00630                         bitmapFileHeader.bfSize = bitmapFileHeader.bfOffBits + bitmapInfoHeader.biSizeImage;
00631                 break;
00632 
00633                 case eRGB24:
00634                 case eRGB24Split:
00635                         bitmapInfoHeader.biBitCount = 24;
00636                         bitmapInfoHeader.biSizeImage = (width * 3 + padding_bytes) * height;
00637                         bitmapInfoHeader.biCompression = 0;
00638                         bitmapFileHeader.bfOffBits = 14 + 40;
00639                         bitmapFileHeader.bfSize = bitmapFileHeader.bfOffBits + bitmapInfoHeader.biSizeImage;
00640                 break;
00641 
00642                 default:
00643                         return false;
00644                 break;
00645         }
00646         
00647         FILE *f = fopen(pFileName, "wb");
00648         if (!f)
00649                 return false;
00650 
00651         unsigned char szHeader[14 + 40];
00652         unsigned char *pBitmapInfoHeaderPosition = szHeader + 14;
00653 
00654 #ifdef IVT_BIG_ENDIAN
00655         *((unsigned short *) (szHeader)) = invert_byte_order_short(bitmapFileHeader.bfType);
00656         *((unsigned int *) (szHeader + 2)) = invert_byte_order_int(bitmapFileHeader.bfSize);
00657         *((unsigned short *) (szHeader + 6)) = invert_byte_order_short(bitmapFileHeader.bfReserved1);
00658         *((unsigned short *) (szHeader + 8)) = invert_byte_order_short(bitmapFileHeader.bfReserved2);
00659         *((unsigned int *) (szHeader + 10)) = invert_byte_order_int(bitmapFileHeader.bfOffBits);
00660 
00661         // write bitmap info header to file
00662         *((unsigned int *) (pBitmapInfoHeaderPosition)) = invert_byte_order_int(bitmapInfoHeader.biSize);
00663         *((unsigned int *) (pBitmapInfoHeaderPosition + 4)) = invert_byte_order_int(bitmapInfoHeader.biWidth);
00664         *((unsigned int *) (pBitmapInfoHeaderPosition + 8)) = invert_byte_order_int(bitmapInfoHeader.biHeight);
00665         *((unsigned short *) (pBitmapInfoHeaderPosition + 12)) = invert_byte_order_short(bitmapInfoHeader.biPlanes);
00666         *((unsigned short *) (pBitmapInfoHeaderPosition + 14)) = invert_byte_order_short(bitmapInfoHeader.biBitCount);
00667         *((unsigned int *) (pBitmapInfoHeaderPosition + 16)) = invert_byte_order_int(bitmapInfoHeader.biCompression);
00668         *((unsigned int *) (pBitmapInfoHeaderPosition + 20)) = invert_byte_order_int(bitmapInfoHeader.biSizeImage);
00669         *((unsigned int *) (pBitmapInfoHeaderPosition + 24)) = invert_byte_order_int(bitmapInfoHeader.biXPelsPerMeter);
00670         *((unsigned int *) (pBitmapInfoHeaderPosition + 28)) = invert_byte_order_int(bitmapInfoHeader.biYPelsPerMeter);
00671         *((unsigned int *) (pBitmapInfoHeaderPosition + 32)) = invert_byte_order_int(bitmapInfoHeader.biClrUsed);
00672         *((unsigned int *) (pBitmapInfoHeaderPosition + 36)) = invert_byte_order_int(bitmapInfoHeader.biClrImportant);
00673 #else
00674         *((unsigned short *) (szHeader)) = bitmapFileHeader.bfType;
00675         *((unsigned int *) (szHeader + 2)) = bitmapFileHeader.bfSize;
00676         *((unsigned short *) (szHeader + 6)) = bitmapFileHeader.bfReserved1;
00677         *((unsigned short *) (szHeader + 8)) = bitmapFileHeader.bfReserved2;
00678         *((unsigned int *) (szHeader + 10)) = bitmapFileHeader.bfOffBits;
00679 
00680         // write bitmap info header to file
00681         *((unsigned int *) (pBitmapInfoHeaderPosition)) = bitmapInfoHeader.biSize;
00682         *((unsigned int *) (pBitmapInfoHeaderPosition + 4)) = bitmapInfoHeader.biWidth;
00683         *((unsigned int *) (pBitmapInfoHeaderPosition + 8)) = bitmapInfoHeader.biHeight;
00684         *((unsigned short *) (pBitmapInfoHeaderPosition + 12)) = bitmapInfoHeader.biPlanes;
00685         *((unsigned short *) (pBitmapInfoHeaderPosition + 14)) = bitmapInfoHeader.biBitCount;
00686         *((unsigned int *) (pBitmapInfoHeaderPosition + 16)) = bitmapInfoHeader.biCompression;
00687         *((unsigned int *) (pBitmapInfoHeaderPosition + 20)) = bitmapInfoHeader.biSizeImage;
00688         *((unsigned int *) (pBitmapInfoHeaderPosition + 24)) = bitmapInfoHeader.biXPelsPerMeter;
00689         *((unsigned int *) (pBitmapInfoHeaderPosition + 28)) = bitmapInfoHeader.biYPelsPerMeter;
00690         *((unsigned int *) (pBitmapInfoHeaderPosition + 32)) = bitmapInfoHeader.biClrUsed;
00691         *((unsigned int *) (pBitmapInfoHeaderPosition + 36)) = bitmapInfoHeader.biClrImportant;
00692 #endif
00693 
00694         // write header to file
00695         if (fwrite(szHeader, 14 + 40, 1, f) != 1)
00696         {
00697                 fclose(f);
00698                 return false;
00699         }
00700 
00701         // if 8 bit grayscale then write color table
00702         if (type == eGrayScale)
00703         {
00704                 char szColorTable[1024];
00705 
00706                 for (int offset = 0, i = 0; i < 256; i++, offset += 4)
00707                 {
00708                         szColorTable[offset] = i;
00709                         szColorTable[offset + 1] = i;
00710                         szColorTable[offset + 2] = i;
00711                         szColorTable[offset + 3] = 0;
00712                 }
00713 
00714                 // write color table to file
00715                 if (fwrite(szColorTable, 1024, 1, f) != 1)
00716                 {
00717                         fclose(f);
00718                         return false;
00719                 }
00720         }
00721 
00722         unsigned char *pTempBuffer = new unsigned char[(width * bytesPerPixel + padding_bytes) * height];
00723         
00724         if (type == eRGB24)
00725         {
00726                 const int width_bytes = 3 * width;
00727                 
00728                 unsigned char *pHelper1 = pTempBuffer;
00729                 unsigned char *pHelper2 = pixels + width * height * 3 - width_bytes;
00730                 
00731                 // convert from RGB to BGR, and from top-left to bottom-left
00732                 for (int i = 0; i < height; i++)
00733                 {
00734                         for (int j = 0; j < width_bytes; j += 3)
00735                         {
00736                                 pHelper1[j] = pHelper2[j + 2];
00737                                 pHelper1[j + 1] = pHelper2[j + 1];
00738                                 pHelper1[j + 2] = pHelper2[j];
00739                         }
00740 
00741                         for (int j = width_bytes; j < width_bytes + padding_bytes; j++)
00742                                 pHelper1[j] = 0;
00743                         
00744                         pHelper1 += width_bytes + padding_bytes;
00745                         pHelper2 -= width_bytes;
00746                 }
00747         }
00748         else if (type == eRGB24Split)
00749         {
00750                 const int width_bytes = 3 * width;
00751 
00752                 unsigned char *pHelper = pTempBuffer;
00753                 unsigned char *pHelperR = pixels + width * height - width;
00754                 unsigned char *pHelperG = pHelperR + width * height;
00755                 unsigned char *pHelperB = pHelperG + width * height;
00756                 
00757                 // convert from RGB to BGR, and from top-left to bottom-left
00758                 for (int i = 0; i < height; i++)
00759                 {
00760                         for (int j = 0, offset = 0; j < width_bytes; j += 3, offset++)
00761                         {
00762                                 pHelper[j] = pHelperB[offset];
00763                                 pHelper[j + 1] = pHelperG[offset];
00764                                 pHelper[j + 2] = pHelperR[offset];
00765                         }
00766 
00767                         for (int j = width_bytes; j < width_bytes + padding_bytes; j++)
00768                                 pHelper[j] = 0;
00769                         
00770                         pHelper += width_bytes + padding_bytes;
00771                         pHelperR -= width;
00772                         pHelperG -= width;
00773                         pHelperB -= width;
00774                 }
00775         }
00776         else if (type == eGrayScale)
00777         {
00778                 unsigned char *pHelper1 = pTempBuffer;
00779                 unsigned char *pHelper2 = pixels + width * height - width;
00780                 
00781                 // convert from top-left to bottom-left
00782                 for (int i = 0; i < height; i++)
00783                 {
00784                         for (int j = 0; j < width; j++)
00785                                 pHelper1[j] = pHelper2[j];
00786 
00787                         for (int j = width; j < width + padding_bytes; j++)
00788                                 pHelper1[j] = 0;
00789                                 
00790                         pHelper1 += width + padding_bytes;
00791                         pHelper2 -= width;
00792                 }
00793 
00794         }
00795         
00796         if (fwrite(pTempBuffer, (width * bytesPerPixel + padding_bytes) * height, 1, f) != 1)
00797         {
00798                 delete [] pTempBuffer;
00799                 fclose(f);
00800                 return false;
00801         }
00802         
00803         delete [] pTempBuffer;
00804         fclose(f);
00805 
00806         return true;
00807 }
00808 
00809 
00810 bool CByteImage::LoadFromFilePNM(const char *pFileName)
00811 {
00812         // first free memory, in any case
00813         FreeMemory();
00814 
00815         FILE *f = fopen(pFileName, "rb");
00816         if (!f)
00817                 return false;
00818 
00819         int character, maxVal; 
00820         char sNumber[16];
00821         short idx;
00822 
00823         character = fgetc(f);
00824         if (character != 'P')
00825         {
00826                 fclose(f);
00827                 return false;
00828         }
00829 
00830         character = fgetc(f);
00831         if (character != '5' && character != '6' )
00832         {
00833                 fclose(f);
00834                 return false;
00835         }
00836 
00837         if (character == '5')
00838         {
00839                 type = eGrayScale;
00840                 bytesPerPixel = 1;
00841         }
00842         else
00843         {
00844                 type = eRGB24;
00845                 bytesPerPixel = 3;
00846         }
00847 
00848         do
00849         {
00850                 // Read whitespaces
00851                 character = fgetc(f);
00852         } while (character == ' ' || character == '\n' || character == '\r');
00853 
00854         // Skip comments
00855         while (character == '#')
00856         {
00857                 while (fgetc(f) != '\n');
00858                 character = fgetc(f);
00859         }
00860 
00861         // Read width
00862         idx = 0;
00863         while (character != ' ' && character != '\n' && character != '\r')
00864         {
00865                 sNumber[idx++] =(char) character;
00866                 character = fgetc(f);
00867         }
00868         sscanf(sNumber,"%d",&width);
00869 
00870         do
00871         {  // Read whitespaces
00872                 character = fgetc(f);
00873         } while (character == ' ' || character == '\n' || character == '\r');
00874 
00875         // Skip comments
00876         while (character == '#')
00877         {
00878                 while (fgetc(f) != '\n');
00879                 character = fgetc(f);
00880         }
00881 
00882         // Read height
00883         idx = 0;
00884         while (character != ' ' && character != '\n' && character != '\r') {
00885                 sNumber[idx++] =(char) character;
00886                 character = fgetc(f);
00887         }
00888         sscanf(sNumber,"%d",&height);
00889 
00890         do
00891         {
00892                 // Read whitespaces
00893                 character = fgetc(f);
00894         } while (character == ' ' || character == '\n' || character == '\r');
00895 
00896         // Skip comments
00897         while (character == '#')
00898         {
00899                 while (fgetc(f) != '\n');
00900                 character = fgetc(f);
00901         }
00902 
00903         // The maximum color value (Maxval)
00904         idx = 0;
00905         while (character != ' ' && character != '\n' && character != '\r')
00906         {
00907                 sNumber[idx++] =(char) character;
00908                 character = fgetc(f);
00909         }
00910         sscanf(sNumber,"%d",&maxVal);
00911 
00912         if (maxVal != 255)
00913         {
00914                 fclose(f);
00915                 return false;
00916         }
00917 
00918         pixels = new unsigned char[width * height * bytesPerPixel + EXTRA_BYTES];
00919         m_bOwnMemory = true;
00920 
00921         if (fread (pixels , width * height * bytesPerPixel, 1, f ) !=  1)
00922         {
00923                 FreeMemory();
00924                 fclose(f);
00925                 return false;
00926         }
00927 
00928         fclose(f);
00929 
00930         return true;
00931 }
00932 
00933 bool CByteImage::SaveToFilePNM(const char *pFileName) const
00934 {
00935         if (!pixels || !width || !height)
00936                 return false;
00937 
00938         FILE *f = fopen(pFileName, "wb");
00939         if (!f)
00940                 return false;
00941 
00942         switch (type)
00943         {
00944                 case eGrayScale:
00945                         if (fprintf(f,"P5\n%d %d\n255\n", width, height) < 10)
00946                         {
00947                                 fclose(f);
00948                                 return false;
00949                         }
00950                 break;
00951                 
00952                 case eRGB24:
00953                 case eRGB24Split:
00954                         if (fprintf(f,"P6\n%d %d\n255\n",width , height) < 10)
00955                         {
00956                                 fclose(f);
00957                                 return false;
00958                         }
00959                 break;
00960                 
00961                 default:
00962                         fclose(f);
00963                         return false;
00964                 break;
00965         }
00966         
00967         if (type == eGrayScale || type == eRGB24)
00968         {
00969                 if (fwrite(pixels, width * height * bytesPerPixel, 1, f ) != 1)
00970                 {
00971                         fclose(f);
00972                         return false;
00973                 }
00974         }
00975         else if (type == eRGB24Split)
00976         {
00977                 const int nPixels = width * height;
00978                 
00979                 unsigned char *pTempBuffer = new unsigned char[nPixels * 3];
00980                 const unsigned char *pHelperR = pixels;
00981                 const unsigned char *pHelperG = pHelperR + nPixels;
00982                 const unsigned char *pHelperB = pHelperG + nPixels;
00983                 
00984                 for (int i = 0, offset = 0; i < nPixels; i++, offset += 3)
00985                 {
00986                         pTempBuffer[offset] = pHelperR[i];
00987                         pTempBuffer[offset + 1] = pHelperG[i];
00988                         pTempBuffer[offset + 2] = pHelperB[i];
00989                 }
00990 
00991                 if (fwrite(pTempBuffer, nPixels * 3, 1, f ) != 1)
00992                 {
00993                         delete [] pTempBuffer;
00994                         fclose(f);
00995                         return false;
00996                 }
00997 
00998                 delete [] pTempBuffer;
00999         }
01000         
01001         fclose(f);
01002 
01003         return true;
01004 }


asr_ivt
Author(s): Allgeyer Tobias, Hutmacher Robin, Kleinert Daniel, Meißner Pascal, Scholz Jonas, Stöckle Patrick
autogenerated on Thu Jun 6 2019 21:46:57