00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #include <new>
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
00065
00066
00067
00068
00069
00070
00071
00072 #define EXTRA_BYTES 1
00073
00074
00075
00076
00077
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
00695 if (fwrite(szHeader, 14 + 40, 1, f) != 1)
00696 {
00697 fclose(f);
00698 return false;
00699 }
00700
00701
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
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
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
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
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
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
00851 character = fgetc(f);
00852 } while (character == ' ' || character == '\n' || character == '\r');
00853
00854
00855 while (character == '#')
00856 {
00857 while (fgetc(f) != '\n');
00858 character = fgetc(f);
00859 }
00860
00861
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 {
00872 character = fgetc(f);
00873 } while (character == ' ' || character == '\n' || character == '\r');
00874
00875
00876 while (character == '#')
00877 {
00878 while (fgetc(f) != '\n');
00879 character = fgetc(f);
00880 }
00881
00882
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
00893 character = fgetc(f);
00894 } while (character == ' ' || character == '\n' || character == '\r');
00895
00896
00897 while (character == '#')
00898 {
00899 while (fgetc(f) != '\n');
00900 character = fgetc(f);
00901 }
00902
00903
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 }