|
IVT
|
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 }