35 union BmpImage::WordParts
46 union BmpImage::DWordParts
60 union BmpImage::LongParts
76 void RotateWORD (WORD& w)
78 BmpImage::WordParts& wp = (BmpImage::WordParts&)w;
80 BmpImage::WordParts temp = wp;
82 wp.parts.c1 = temp.parts.c2;
83 wp.parts.c2 = temp.parts.c1;
89 void RotateDWORD (DWORD& w)
91 BmpImage::DWordParts& wp = (BmpImage::DWordParts&)w;
93 BmpImage::DWordParts temp = wp;
95 wp.parts.c1 = temp.parts.c4;
96 wp.parts.c2 = temp.parts.c3;
97 wp.parts.c3 = temp.parts.c2;
98 wp.parts.c4 = temp.parts.c1;
104 void RotateLONG (LONG& l)
106 BmpImage::LongParts& lp = (BmpImage::LongParts&)l;
108 BmpImage::LongParts temp = lp;
110 lp.parts.c1 = temp.parts.c4;
111 lp.parts.c2 = temp.parts.c3;
112 lp.parts.c3 = temp.parts.c2;
113 lp.parts.c4 = temp.parts.c1;
117 void WriteWORD (FILE* outFile, WORD w)
120 fwrite (&w,
sizeof (w), 1, outFile);
124 void WriteDWORD (FILE* outFile, DWORD dw)
127 fwrite (&dw,
sizeof (dw), 1, outFile);
132 void WriteLONG (FILE* outFile, LONG l)
135 fwrite (&l,
sizeof (l), 1, outFile);
139 void WriteBYTE (FILE* outFile, BYTE b)
141 fwrite (&b,
sizeof (b), 1, outFile);
207 codesAllocated = height * (width + 4);
210 codes =
new CodePair[codesAllocated];
225 if (used >= codesAllocated)
228 cerr <<
"CodedPixels::AddPixel *** Error ***, Exceeding codesAllocated." << std::endl;
279 kkint32 buffSize = codesAllocated;
282 memset (buff, 0, codesAllocated);
290 while (curPair < used)
294 kkint32 newBuffSize = buffSize * 2;
296 memset (newBuff, 0, newBuffSize);
297 memcpy (newBuff, buff, buffSize);
301 buffSize = newBuffSize;
360 kkint32 buffSize = codesAllocated;
363 memset (buff, 0, codesAllocated);
370 while (curPair < used)
372 if (bp >= (buffSize - 1))
374 kkint32 newBuffSize = buffSize * 2;
378 KKStr errMsg =
"BmpImage::CodedPixels::CreatePixelDataStructure8Bit ***ERROR*** Allocation of 'newBuff' failed.";
379 cerr << std::endl << std::endl << errMsg << std::endl << std::endl;
383 memset (newBuff, 0, newBuffSize);
384 memcpy (newBuff, buff, buffSize);
388 buffSize = newBuffSize;
454 fileName
(_fileName
),
475 x = fread (&hdr,
sizeof (hdr), 1, inFile);
484 memcpy (buff, &hdr,
sizeof (buff));
485 if ((buff[0] ==
'B') && (buff[1] ==
'M'))
489 else if ((buff[0] == 137) && (buff[1] ==
'P') && (buff[2] ==
'N') && (buff[3] ==
'G'))
493 <<
"File[" << _fileName <<
"] is a PNG formatted file." << std::endl
502 <<
"File[" << _fileName <<
"] is of a unknown file format." << std::endl
510 x = fread (&bmh,
sizeof (bmh), 1, inFile);
518 if ((bmh.biCompression == BI_RGB) && (bmh.biBitCount == 24))
520 numOfColors = 16777216;
524 Load24BitColor (inFile, successfull);
529 if ((bmh.biCompression == BI_RGB) && (bmh.biBitCount == 8))
531 Load8BitColor (inFile, successfull);
536 else if ((bmh.biCompression == BI_RGB) || (bmh.biCompression == BI_RLE4))
539 else if (bmh.biBitCount == 1)
546 paletteEntries = BMIcolorArraySize (bmh);
547 if (paletteEntries < 0)
554 bool imageIsRevGrayscale =
false;
557 palette =
new RGBQUAD[paletteEntries];
558 x = fread (palette,
sizeof (RGBQUAD), paletteEntries, inFile);
559 imageIsRevGrayscale = ReversedGrayscaleImage ();
564 paletteEntries = 256;
565 palette =
new RGBQUAD[paletteEntries];
566 SetUp256BitPalette (palette);
570 for (x = 0; x < 256; x++)
573 if (numOfColors == 16)
575 for (
kkint32 palletIdx = 0; palletIdx < paletteEntries; palletIdx++)
577 if (imageIsRevGrayscale)
578 y = 255 - palette[palletIdx].rgbGreen;
580 y = palette[palletIdx].rgbGreen;
581 if (y < 0) y = 0;
else if (y > 255) y = 255;
582 paletteMap[palletIdx] = y;
587 for (
kkint32 palletIdx = 0; palletIdx < paletteEntries; palletIdx++)
589 if (imageIsRevGrayscale)
590 y = 255 - palette[palletIdx].rgbGreen;
592 y = palette[palletIdx].rgbGreen;
593 if (y < 0) y = 0;
else if (y > 255) y = 255;
594 paletteMap[palletIdx] = y;
599 paletteEntries = 256;
600 palette =
new RGBQUAD[paletteEntries];
601 SetUp256BitPalette (palette);
605 image =
new uchar*[bmh.biHeight];
606 for (row = 0; row < bmh.biHeight; row++)
608 image[row] =
new uchar[bmh.biWidth];
609 memset (image[row], 0, bmh.biWidth);
612 x = fseek (inFile, hdr.bfOffBits, SEEK_SET);
614 if (bmh.biBitCount == 1)
616 Load1BitColor (inFile, successfull);
619 else if (bmh.biBitCount == 4)
621 if (bmh.biCompression == BI_RGB)
623 Load4BitColor (inFile, successfull);
626 else if (bmh.biCompression == BI_RLE4)
628 Load4BitColorCompressed (inFile, successfull);
633 cerr <<
"***ERROR*** Invalid Compression Mode[" << bmh.biCompression
634 <<
"] Specified for 4 bit File[" 642 else if (bmh.biBitCount == 8)
644 if (bmh.biCompression == BI_RGB)
646 Load8BitColor (inFile, successfull);
649 else if (bmh.biCompression == BI_RLE8)
651 Load8BitColorCompressed (inFile, successfull);
656 cerr <<
"***ERROR*** Invalid Compression Mode[" << bmh.biCompression
657 <<
"] Specified for 8 bit File[" 664 else if (bmh.biBitCount == 16)
666 cerr <<
"***ERROR*** 16 Bit Not Supported. File[" << fileName <<
"]." << std::endl;
670 else if (bmh.biBitCount == 24)
672 cerr <<
"***ERROR*** 24 Bit Not Supported. File[" << fileName <<
"]." << std::endl;
675 else if (bmh.biBitCount == 32)
677 cerr <<
"***ERROR*** 32 Bit Not Supported. File[" << fileName <<
"]." << std::endl;
697 numOfColors (_numOfColors),
727 for (row = 0; row < bmh.biHeight; row++)
729 for (col = 0; col < bmh.biWidth; col++)
731 image[row][col] = rasterData[row][col];
734 red[row][col] = rasterRed [row][col];
735 blue[row][col] = rasterBlue[row][col];
755 bool BmpImage::ReversedGrayscaleImage ()
758 bool allChannelsSameValue =
true;
759 bool alwaysDecending =
true;
762 for (x = 0; (x < paletteEntries) && allChannelsSameValue; ++x)
764 RGBQUAD& p = (palette[x]);
765 allChannelsSameValue = (p.rgbBlue == p.rgbGreen) && (p.rgbBlue == p.rgbRed) && (p.rgbGreen == p.rgbRed);
767 if ((x > 0) && (p.rgbBlue >= palette[x - 1].rgbBlue))
768 alwaysDecending =
false;
771 if (allChannelsSameValue && alwaysDecending && (palette[0].rgbBlue == 255) && (palette[paletteEntries - 1].rgbBlue == 0))
785 if (_bmh.biBitCount == 0)
790 else if (_bmh.biBitCount == 1)
795 else if (_bmh.biBitCount == 4)
800 else if (_bmh.biBitCount == 8)
802 if (_bmh.biClrUsed == 0)
805 return _bmh.biClrUsed;
808 else if (_bmh.biBitCount == 16)
810 if (_bmh.biCompression == BI_RGB)
814 else if (_bmh.biBitCount == 24)
816 return _bmh.biClrUsed;
827 delete palette; palette = NULL;
829 palette =
new RGBQUAD[paletteEntries];
831 uchar pixelVal = 255;
832 for (
kkint32 x = 0; x < 16; x++)
834 palette[x].rgbBlue = pixelVal;
835 palette[x].rgbGreen = pixelVal;
836 palette[x].rgbRed = pixelVal;
837 pixelVal = pixelVal - 17;
847 delete palette; palette = NULL;
848 paletteEntries = 256;
849 palette =
new RGBQUAD[paletteEntries];
851 uchar pixelVal = 255;
852 for (
kkint32 x = 0; x < 256; x++)
854 palette[x].rgbBlue = pixelVal;
855 palette[x].rgbGreen = pixelVal;
856 palette[x].rgbRed = pixelVal;
864 void BmpImage::SetUp16BitPallet (RGBQUAD* palette)
866 palette[0].rgbBlue = 255;
867 palette[0].rgbGreen = 255;
868 palette[0].rgbRed = 255;
870 palette[1].rgbBlue = 219;
871 palette[1].rgbGreen = 219;
872 palette[1].rgbRed = 219;
874 palette[2].rgbBlue = 182;
875 palette[2].rgbGreen = 182;
876 palette[2].rgbRed = 182;
878 palette[3].rgbBlue = 146;
879 palette[3].rgbGreen = 146;
880 palette[3].rgbRed = 146;
882 palette[4].rgbBlue = 109;
883 palette[4].rgbGreen = 109;
884 palette[4].rgbRed = 109;
886 palette[5].rgbBlue = 73;
887 palette[5].rgbGreen = 73;
888 palette[5].rgbRed = 73;
890 palette[6].rgbBlue = 36;
891 palette[6].rgbGreen = 36;
892 palette[6].rgbRed = 36;
894 palette[7].rgbBlue = 0;
895 palette[7].rgbGreen = 0;
896 palette[7].rgbRed = 0;
898 palette[8].rgbBlue = 255;
899 palette[8].rgbGreen = 40;
900 palette[8].rgbRed = 40;
902 palette[9].rgbBlue = 40;
903 palette[9].rgbGreen = 40;
904 palette[9].rgbRed = 255;
906 palette[10].rgbBlue = 40;
907 palette[10].rgbGreen = 210;
908 palette[10].rgbRed = 40;
910 palette[11].rgbBlue = 40;
911 palette[11].rgbGreen = 210;
912 palette[11].rgbRed = 210;
914 palette[12].rgbBlue = 210;
915 palette[12].rgbGreen = 40;
916 palette[12].rgbRed = 40;
918 palette[13].rgbBlue = 210;
919 palette[13].rgbGreen = 40;
920 palette[13].rgbRed = 210;
922 palette[14].rgbBlue = 210;
923 palette[14].rgbGreen = 210;
924 palette[14].rgbRed = 40;
926 palette[15].rgbBlue = 210;
927 palette[15].rgbGreen = 210;
928 palette[15].rgbRed = 210;
939 if ((palletIndex < 0) || (palletIndex > 255))
942 cerr << std::endl << std::endl << std::endl
943 <<
"BmpImage::SetPaletteEntry Invalid PalletIndex[" << palletIndex <<
"]" << std::endl
951 cerr << std::endl << std::endl << std::endl
952 <<
"BmpImage::SetPaletteEntry The palette is not defined!" << std::endl
958 palette[palletIndex].rgbBlue = pixValue.b;
959 palette[palletIndex].rgbGreen = pixValue.g;
960 palette[palletIndex].rgbRed = pixValue.r;
967 void BmpImage::SetUp256BitPalette (RGBQUAD* palette)
973 for (x = 0; x < 256; x++)
976 palette[x].rgbBlue = pixVal;
977 palette[x].rgbGreen = pixVal;
978 palette[x].rgbRed = pixVal;
992 bool isGrayScaleImage =
true;
994 for (
kkint32 x = 0; ((x < palletSize) && isGrayScaleImage); x++)
996 kkint32 expectedColor = 255 - x;
997 if ((palette[x].rgbBlue != expectedColor) ||
998 (palette[x].rgbGreen != expectedColor) ||
999 (palette[x].rgbRed != expectedColor)
1002 isGrayScaleImage =
false;
1006 return isGrayScaleImage;
1016 hdr.bfReserved1 = 0;
1017 hdr.bfReserved2 = 0;
1021 bmh.biSize =
sizeof (bmh);
1022 bmh.biWidth = _width;
1023 bmh.biHeight = _height;
1030 if (numOfColors <= 16)
1032 delete palette; palette = NULL;
1034 paletteEntries = 16;
1035 bmh.biCompression = BI_RLE4;
1036 palette =
new RGBQUAD[paletteEntries];
1038 SetUp16BitPallet (palette);
1042 delete palette; palette = NULL;
1044 paletteEntries = 256;
1045 bmh.biCompression = BI_RLE8;
1046 palette =
new RGBQUAD[paletteEntries];
1047 SetUp256BitPalette (palette);
1050 bmh.biSizeImage = 0;
1051 bmh.biXPelsPerMeter = 2835;
1052 bmh.biYPelsPerMeter = 2835;
1054 bmh.biClrImportant = 0;
1059 hdr.bfOffBits =
sizeof (bmh) +
sizeof (RGBQUAD) * paletteEntries;
1073 const RGBQUAD& right
1076 if (left.rgbRed != right.rgbRed)
1077 return (left.rgbRed < right.rgbRed);
1079 if (left.rgbGreen != right.rgbGreen)
1080 return (left.rgbGreen < right.rgbGreen);
1082 return (left.rgbBlue < right.rgbBlue);
1089 lastColorsSet =
false;
1101 key.rgbGreen = green;
1103 idx = colorsUsed.find (key);
1104 if (idx == colorsUsed.end ())
1116 if (lastColorsSet && (red == lastRed) && (green == lastGreen) && (blue == lastBlue))
1121 key.rgbGreen = green;
1123 idx = colorsUsed.find (key);
1124 if (idx == colorsUsed.end ())
1126 kkint32 numEntries = (kkint32)colorsUsed.size ();
1127 colorsUsed.insert (pair<RGBQUAD,kkint32> (key, numEntries));
1130 lastRed = red; lastGreen = green; lastBlue = blue;
1131 lastColorsSet =
true;
1139 size = (kkint32)colorsUsed.size ();
1140 delete palette; palette = NULL;
1144 palette =
new RGBQUAD[size];
1145 for (idx = colorsUsed.begin (); idx != colorsUsed.end (); idx++)
1147 palette[idx->second] = idx->first;
1152 map<RGBQUAD, kkint32, RGBQUAD_Pred> colorsUsed;
1153 map<RGBQUAD, kkint32, RGBQUAD_Pred>::iterator idx;
1171 uchar* rowRed = NULL;
1172 uchar* rowGreen = NULL;
1173 uchar* rowBlue = NULL;
1175 for (row = 0; row < bmh.biHeight; row++)
1178 rowGreen = image[row];
1179 rowBlue = blue [row];
1181 for (col = 0; col < bmh.biWidth; col++)
1183 palletBuilder
->AddColor (rowRed[col]
, rowGreen[col]
, rowBlue[col]
);
1188 return palletBuilder;
1200 paletteEntries = 16;
1201 palette =
new RGBQUAD[paletteEntries];
1202 SetUp16BitPallet (palette);
1214 paletteEntries = 256;
1215 palette =
new RGBQUAD[paletteEntries];
1216 SetUp256BitPalette (palette);
1237 struct BmpImage::Bmp1BitRec
1252 void BmpImage::Load1BitColor (FILE* inFile,
1258 kkuint32 bmpRowWidthInBytes = bmh.biWidth / 8;
1260 while ((bmpRowWidthInBytes % 2) > 0)
1262 bmpRowWidthInBytes++;
1266 uchar* rowData =
new uchar [bmpRowWidthInBytes * 8];
1274 for (row = bmh.biHeight - 1; row >= 0; row--)
1276 x = fread (packedRowData, 1, bmpRowWidthInBytes, inFile);
1277 if (x < bmpRowWidthInBytes)
1279 successfull =
false;
1280 cerr <<
"***ERROR*** BmpImage::Load1BitColor Error Reading File." << std::endl;
1286 for (byteNum = 0; byteNum < x; byteNum++)
1288 b = packedRowData[byteNum];
1290 rowData[col + 0] = b
.pix1;
1291 rowData[col + 1] = b
.pix2;
1292 rowData[col + 2] = b
.pix3;
1293 rowData[col + 3] = b
.pix4;
1294 rowData[col + 4] = b
.pix5;
1295 rowData[col + 5] = b
.pix6;
1296 rowData[col + 6] = b
.pix7;
1297 rowData[col + 7] = b
.pix8;
1302 for (col = 0; col < bmh.biWidth; col++)
1304 x = paletteMap[rowData[col]];
1312 delete[] packedRowData;
1324 kkint32 newHeight = bmh.biHeight + 6;
1325 kkint32 newWidth = bmh.biWidth + 6;
1329 uchar** newRed = NULL;
1330 uchar** newBlue = NULL;
1333 newRed =
new uchar*[newHeight];
1334 newBlue =
new uchar*[newHeight];
1337 for (newRow = 0; newRow < newHeight; newRow++)
1339 newImage[newRow] =
new uchar[newWidth];
1340 memset (newImage[newRow], 0, newWidth);
1343 newRed [newRow] =
new uchar[newWidth];
1344 newBlue[newRow] =
new uchar[newWidth];
1345 memset (newRed [newRow], 0, newWidth);
1346 memset (newBlue [newRow], 0, newWidth);
1351 for (oldRow = 0; oldRow < bmh.biHeight; oldRow++)
1353 memcpy ((newImage[newRow] + 3), image[oldRow], bmh.biWidth);
1356 memcpy ((newRed[newRow] + 3), red [oldRow], bmh.biWidth);
1357 memcpy ((newBlue[newRow] + 3), blue[oldRow], bmh.biWidth);
1362 for (oldRow = 0; oldRow < bmh.biHeight; oldRow++)
1364 delete image[oldRow];
1365 image[oldRow] = NULL;
1368 delete red [oldRow]; red [oldRow] = NULL;
1369 delete blue[oldRow]; blue[oldRow] = NULL;
1379 red = newRed; newRed = NULL;
1380 blue = newBlue; newBlue = NULL;
1382 bmh.biHeight = newHeight;
1383 bmh.biWidth = newWidth;
1400 struct BmpImage::Bmp4BitRecs
1412 void BmpImage::Load4BitColor (FILE* inFile,
1417 kkuint32 bmpRowWidthInBytes = (bmh.biWidth + 1) / 2;
1419 kkint32 paddingBytes = bmpRowWidthInBytes % 4;
1420 if (paddingBytes != 0)
1421 paddingBytes = 4 - paddingBytes;
1423 bmpRowWidthInBytes = bmpRowWidthInBytes + paddingBytes;
1431 for (row = bmh.biHeight - 1; row >= 0; row--)
1433 x = fread (rowData,
sizeof (Bmp4BitRecs), bmpRowWidthInBytes, inFile);
1435 if (x < bmpRowWidthInBytes)
1437 successfull =
false;
1438 cerr <<
"***ERROR*** BmpImage::Load4BitColor Error Reading File" << std::endl;
1444 for (col = 0; col < bmh.biWidth; col++)
1452 nextPixel = rowData[offset]
.pix1;
1456 nextPixel = rowData[offset]
.pix2;
1471 void BmpImage::Load8BitColor (FILE* inFile,
1479 paletteEntries = numOfColors;
1482 fseek (inFile,
sizeof (hdr) +
sizeof (bmh), SEEK_SET);
1483 fread (palette,
sizeof (RGBQUAD), paletteEntries, inFile);
1496 kkuint32 bmpRowWidthInBytes = bmh.biWidth;
1497 kkuint32 paddingBytes = bmpRowWidthInBytes % 4;
1498 if (paddingBytes != 0)
1499 paddingBytes = 4 - paddingBytes;
1501 bmpRowWidthInBytes = bmpRowWidthInBytes + paddingBytes;
1503 fseek (inFile, hdr.bfOffBits, SEEK_SET);
1505 uchar* rowData =
new uchar[bmpRowWidthInBytes];
1509 for (row = bmh.biHeight - 1; row >= 0; row--)
1511 memset (rowData, 0, bmpRowWidthInBytes);
1512 size_t buffRead = fread (rowData, 1, bmpRowWidthInBytes, inFile);
1513 if (buffRead < bmpRowWidthInBytes)
1516 <<
"***ERROR*** BmpImage::Load8BitColor, Error Reading File" << std::endl
1518 successfull =
false;
1519 delete[] rowData; rowData = NULL;
1525 for (col = 0; col < bmh.biWidth; col++)
1527 kkint32 palletIdx = rowData[col];
1530 blue [row][col] = palette[palletIdx].rgbBlue;
1531 image [row][col] = palette[palletIdx].rgbGreen;
1532 red [row][col] = palette[palletIdx].rgbRed;
1538 delete[] rowData; rowData = NULL;
1545 void BmpImage::Load4BitColorCompressed (FILE* inFile,
1552 size_t imageBuffSize = bmh.biSizeImage;
1556 size_t buffRead = fread (imageBuff,
sizeof (uchar), imageBuffSize, inFile);
1558 if (buffRead < imageBuffSize)
1560 cerr <<
"***ERROR*** BmpImage::Load4BitColorCompressed *** Error ***, Invalid File Format." << std::endl;
1561 successfull =
false;
1566 kkint32 row = bmh.biHeight - 1;
1570 while (ifIDX < imageBuffSize)
1572 if (imageBuff[ifIDX] == 0)
1577 if (imageBuff[ifIDX] == 0)
1585 else if (imageBuff[ifIDX] == 1)
1589 ifIDX = imageBuffSize;
1592 else if (imageBuff[ifIDX] == 2)
1595 col = col + imageBuff[ifIDX];
1598 row = row + imageBuff[ifIDX];
1606 kkint32 len = imageBuff[ifIDX];
1609 for (x = 0; x < len;)
1611 uchar pix1 = imageBuff[ifIDX] / 16;
1612 uchar pix2 = imageBuff[ifIDX] % 16;
1627 if (((len + 1) / 2) % 2 != 0)
1635 kkint32 len = imageBuff[ifIDX];
1638 uchar pix1 = imageBuff[ifIDX] / 16;
1639 uchar pix2 = imageBuff[ifIDX] % 16;
1641 for (x = 0; x < len;)
1666 void BmpImage::Load8BitColorCompressed (FILE* inFile,
1674 kkuint32 imageBuffSize = bmh.biSizeImage;
1678 size_t buffRead = fread (imageBuff,
sizeof (uchar), imageBuffSize, inFile);
1680 if (buffRead < imageBuffSize)
1682 cerr <<
"***ERROR***, Load4BitColorCompressed *** Error ***, Invalid File Format." << std::endl;
1683 successfull =
false;
1688 kkint32 row = bmh.biHeight - 1;
1692 while (ifIDX < imageBuffSize)
1694 if (imageBuff[ifIDX] == 0)
1699 if (imageBuff[ifIDX] == 0)
1707 else if (imageBuff[ifIDX] == 1)
1711 ifIDX = imageBuffSize;
1714 else if (imageBuff[ifIDX] == 2)
1717 col = col + imageBuff[ifIDX];
1720 row = row + imageBuff[ifIDX];
1729 kkint32 len = imageBuff[ifIDX];
1732 for (x = 0; x < len;)
1748 kkint32 len = imageBuff[ifIDX];
1751 kkint32 pixelVal = paletteMap[imageBuff[ifIDX]];
1759 for (x = 0; x < len;)
1788 void BmpImage::Load24BitColor (FILE* inFile,
1796 kkuint32 bmpRowWidthInBytes = bmh.biWidth * 3;
1797 kkuint32 paddingBytes = bmpRowWidthInBytes % 4;
1798 if (paddingBytes != 0)
1799 paddingBytes = 4 - paddingBytes;
1801 bmpRowWidthInBytes = bmpRowWidthInBytes + paddingBytes;
1803 fseek (inFile, hdr.bfOffBits, SEEK_SET);
1805 uchar* rowData =
new uchar[bmpRowWidthInBytes];
1809 for (row = bmh.biHeight - 1; row >= 0; row--)
1811 memset (rowData, 0, bmpRowWidthInBytes);
1812 size_t buffRead = fread (rowData, 1, bmpRowWidthInBytes, inFile);
1813 if (buffRead < bmpRowWidthInBytes)
1816 <<
"***ERROR*** BmpImage::Load24BitColor, Error Reading File" << std::endl
1818 successfull =
false;
1819 delete[] rowData; rowData = NULL;
1825 for (col = 0; col < bmh.biWidth; col++)
1828 blue [row][col] = rowData[offset];
1829 image [row][col] = rowData[offset + 1];
1830 red [row][col] = rowData[offset + 2];
1836 delete[] rowData; rowData = NULL;
1846 if (paletteEntries > 1000000)
1848 cerr << std::endl << std::endl
1849 <<
"BmpImage::AllocateRaster ***ERROR*** paletteEntries[" << paletteEntries <<
"] Is a unreasonable value." << std::endl
1854 if (paletteEntries > 0)
1855 palette =
new RGBQUAD[paletteEntries];
1859 image =
new uchar*[bmh.biHeight];
1862 red =
new uchar*[bmh.biHeight];
1863 blue =
new uchar*[bmh.biHeight];
1866 for (row = 0; row < bmh.biHeight; row++)
1868 image[row] =
new uchar[bmh.biWidth];
1869 memset (image[row], 0, bmh.biWidth);
1872 red[row] =
new uchar[bmh.biWidth];
1873 blue[row] =
new uchar[bmh.biWidth];
1874 memset (red [row], 0, bmh.biWidth);
1875 memset (blue[row], 0, bmh.biWidth);
1888 for (x = bmh.biHeight - 1; x >= 0; x--)
1901 for (x = bmh.biHeight - 1; x >= 0; x--)
1903 delete red [x]; red [x] = NULL;
1904 delete blue[x]; blue[x] = NULL;
1907 delete red; red = NULL;
1908 delete blue; blue = NULL;
1911 delete palette; palette = NULL;
1920 kkint32 newHeight = bmh.biHeight / 2;
1921 kkint32 newWidth = bmh.biWidth / 2;
1928 for (newRow = 0; newRow < newHeight; newRow++)
1930 oldRow = newRow * 2;
1932 newImage[newRow] =
new uchar[newWidth];
1934 for (newCol = 0; newCol < newWidth; newCol++)
1936 oldCol = newCol * 2;
1937 newImage[newRow][newCol] = image[oldRow][oldCol];
1941 for (oldRow = 0; oldRow < bmh.biHeight; oldRow++)
1943 delete image[oldRow];
1944 image[oldRow] = NULL;
1951 bmh.biHeight = newHeight;
1952 bmh.biWidth = newWidth;
1961 return image[row][col];
1974 cerr <<
"BmpImage::SetPixelValue ***ERROR*** pixel[" << pixel <<
"] out of range. Needs to be in range of 0..255." << std::endl;
1977 else if (pixel > 255)
1979 cerr <<
"BmpImage::SetPixelValue ***ERROR*** pixel[" << pixel <<
"] out of range. Needs to be in range of 0..255." << std::endl;
1983 if ((row < 0) || (row >= bmh.biHeight))
1985 cerr <<
"BmpImage::SetPixelValue *** Error ***, Row[" << row
1986 <<
"] out of range[0-" << bmh.biHeight <<
"]." 1991 if ((col < 0) || (col >= bmh.biWidth))
1993 cerr <<
"BmpImage::SetPixelValue *** Error ***, Col[" << col
1994 <<
"] out of range[0-" << bmh.biWidth <<
"]." 1998 image[row][col] = (
uchar)pixel;
2019 uchar* row0 = image[0];
2020 uchar* row1 = image[1];
2021 uchar* row2 = image[2];
2023 uchar* rowL0 = image[height - 3];
2024 uchar* rowL1 = image[height - 2];
2025 uchar* rowL2 = image[height - 1];
2028 for (col = 0; col < width; col++)
2030 if ((row0[col] > 0) ||
2044 kkint32 lastRowToCheck = height - 3;
2046 for (row = 3; row < lastRowToCheck; row++)
2048 if ((image[row][0] > 0) ||
2049 (image[row][1] > 0) ||
2050 (image[row][2] > 0) ||
2051 (image[row][lastCol0] > 0) ||
2052 (image[row][lastCol1] > 0) ||
2053 (image[row][lastCol2] > 0)
2070 bool* potVertLine =
new bool[bmh.biWidth];
2071 bool* pvl = potVertLine;
2073 for (col = 0; col < bmh.biWidth; col++)
2076 for (row = 0; ((row < bmh.biHeight) && (*pvl)); row++)
2078 if (image[row][col] == 7)
2088 while (col < bmh.biWidth)
2090 if (potVertLine[col])
2092 kkint32 firstCol = col;
2093 kkint32 lastCol = col;
2095 if (col < (bmh.biWidth - 1))
2097 while ((col < bmh.biWidth) && (potVertLine[col]))
2103 if (!potVertLine[col])
2114 bool leftSideIsClear =
true;
2115 bool rightSizeIsClear =
true;
2117 uchar leftPixel = 0;
2118 uchar rightPixel = 0;
2120 for (row = 0; row < bmh.biHeight; row++)
2124 leftPixel = image[row][firstCol - 1];
2126 leftSideIsClear =
false;
2133 if (lastCol < (bmh.biWidth - 1))
2135 rightPixel = image[row][lastCol + 1];
2137 if (rightPixel != 0)
2138 rightSizeIsClear =
false;
2141 if (leftSideIsClear && rightSizeIsClear)
2143 for (x = firstCol; x <= lastCol; x++)
2148 for (x = firstCol; x <= lastCol; x++)
2149 image[row][x] = (leftPixel + rightPixel) / 2;
2152 leftSideIsClear =
true;
2153 rightSizeIsClear =
true;
2161 delete[] potVertLine;
2173 for (x = 0; x < bmh.biHeight; x++)
2175 for (y = 0; y < Min ((
long)bmh.biWidth, 76L); y++)
2194 for (row = 0; row < bmh.biHeight; row++)
2196 for (col = 0; col < bmh.biWidth; col++)
2198 if (image[row][col] < 7)
2199 image[row][col] = 0;
2209 fileName
= _fileName;
2213 KKStr errMsg =
"BmpImage::SaveGrayscaleInverted4Bit, Error opening BMP File[" + fileName
+ "].";
2214 cerr << errMsg << std::endl;
2221 CodedPixels pixelData (bmh.biHeight, bmh.biWidth);
2223 for (x = (kkint32)bmh.biHeight - 1; x >= 0; x--)
2225 for (y = 0; y < bmh.biWidth; y++)
2229 kkint32 gsVal = (
kkint32)((
float)(0.5f + red[x][y]) * 0.30f + (
float)(image[x][y]) * 0.59f + (
float)(blue[x][y]) * 0.11f);
2242 uchar* imageBuff = NULL;
2247 bmh.biCompression = BI_RLE4;
2250 bmh.biSizeImage = imageBuffLen;
2251 bmh.biClrUsed = numOfColors;
2252 bmh.biClrImportant = numOfColors;
2254 hdr.bfSize = 14 + 40 + paletteEntries * 4 + bmh.biSizeImage;
2255 hdr.bfOffBits = 40 + 14 + paletteEntries * 4;
2257 x = (kkint32)fwrite (&hdr,
sizeof (hdr), 1, outFile);
2258 x = (kkint32)fwrite (&bmh,
sizeof (bmh), 1, outFile);
2259 x = (kkint32)fwrite (palette,
sizeof (RGBQUAD), paletteEntries, outFile);
2260 x = (kkint32)fwrite (imageBuff, 1, imageBuffLen, outFile);
2270 fileName
= _fileName;
2274 KKStr errMsg =
"BmpImage::SaveGrayscaleInverted8Bit, Error opening BMP File[" + fileName
+ "].";
2275 cerr << errMsg << std::endl;
2282 CodedPixels pixelData (bmh.biHeight, bmh.biWidth);
2284 for (x = (kkint32)bmh.biHeight - 1; x >= 0; x--)
2286 for (y = 0; y < bmh.biWidth; y++)
2290 kkint32 gsVal = (
kkint32)((
float)(0.5f + red[x][y]) * 0.30f + (
float)(image[x][y]) * 0.59f + (
float)(blue[x][y]) * 0.11f);
2303 uchar* imageBuff = NULL;
2308 bmh.biCompression = BI_RLE8;
2311 bmh.biSizeImage = imageBuffLen;
2312 bmh.biClrUsed = numOfColors;
2313 bmh.biClrImportant = numOfColors;
2315 hdr.bfSize = 14 + 40 + paletteEntries * 4 + bmh.biSizeImage;
2316 hdr.bfOffBits = 40 + 14 + paletteEntries * 4;
2318 x = (kkint32)fwrite (&hdr,
sizeof (hdr), 1, outFile);
2319 x = (kkint32)fwrite (&bmh,
sizeof (bmh), 1, outFile);
2320 x = (kkint32)fwrite (palette,
sizeof (RGBQUAD), paletteEntries, outFile);
2321 x = (kkint32)fwrite (imageBuff, 1, imageBuffLen, outFile);
2333 fileName
= _fileName;
2337 KKStr errMsg =
"BmpImage::Save, Error opening BMP File[" + fileName
+ "].";
2338 cerr << errMsg << std::endl;
2344 SaveColor (outFile);
2348 SaveGrayScale (outFile);
2357 void BmpImage::SaveGrayScale (FILE* outFile)
2362 CodedPixels pixelData (bmh.biHeight, bmh.biWidth);
2364 for (x = (kkint32)bmh.biHeight - 1; x >= 0; x--)
2366 for (y = 0; y < bmh.biWidth; y++)
2379 bmh.biCompression = BI_RLE8;
2382 bmh.biSizeImage = imageBuffLen;
2383 bmh.biClrUsed = numOfColors;
2384 bmh.biClrImportant = numOfColors;
2385 paletteEntries = numOfColors;
2387 hdr.bfSize = 14 + 40 + paletteEntries * 4 + bmh.biSizeImage;
2388 hdr.bfOffBits = 40 + 14 + paletteEntries * 4;
2391 WriteWORD (outFile, hdr.bfType);
2392 WriteDWORD (outFile, hdr.bfSize);
2393 WriteWORD (outFile, hdr.bfReserved1);
2394 WriteWORD (outFile, hdr.bfReserved2);
2395 WriteDWORD (outFile, hdr.bfOffBits);
2398 x = (kkint32)fwrite (&hdr,
sizeof (hdr), 1, outFile);
2403 WriteDWORD (outFile, bmh.biSize);
2404 WriteLONG (outFile, bmh.biWidth);
2405 WriteLONG (outFile, bmh.biHeight);
2406 WriteWORD (outFile, bmh.biPlanes);
2407 WriteWORD (outFile, bmh.biBitCount);
2408 WriteDWORD (outFile, bmh.biCompression);
2409 WriteDWORD (outFile, bmh.biSizeImage);
2410 WriteLONG (outFile, bmh.biXPelsPerMeter);
2411 WriteLONG (outFile, bmh.biYPelsPerMeter);
2412 WriteDWORD (outFile, bmh.biClrUsed);
2413 WriteDWORD (outFile, bmh.biClrImportant);
2416 x = (kkint32)fwrite (&bmh,
sizeof (bmh), 1, outFile);
2421 for (x = 0; x < paletteEntries; x++)
2423 WriteBYTE (outFile, palette[x].rgbBlue);
2424 WriteBYTE (outFile, palette[x].rgbGreen);
2425 WriteBYTE (outFile, palette[x].rgbRed);
2426 WriteBYTE (outFile, palette[x].rgbReserved);
2429 x = (kkint32)fwrite (palette,
sizeof (RGBQUAD), paletteEntries, outFile);
2432 x = (kkint32)fwrite (imageBuff, 1, imageBuffLen, outFile);
2439 void BmpImage::SaveColor (FILE* outFile)
2442 PalletBuilderPtr palletBuilder = BuildPalletFromRasterData ();
2444 SaveColorCompressed256 (palletBuilder, outFile);
2446 SaveColor24BPP (outFile);
2447 delete palletBuilder;
2448 palletBuilder = NULL;
2456 void BmpImage::SaveColorCompressed256 (PalletBuilderPtr palletBuilder,
2463 uchar* redRow = NULL;
2464 uchar* greenRow = NULL;
2465 uchar* blueRow = NULL;
2469 CodedPixels pixelData (bmh.biHeight, bmh.biWidth);
2471 for (x = (kkint32)bmh.biHeight - 1; x >= 0; x--)
2474 greenRow = image[x];
2476 for (y = 0; y < bmh.biWidth; y++)
2483 else if (palletIdx > 255)
2495 numOfColors = paletteEntries;
2497 bmh.biCompression = BI_RLE8;
2500 bmh.biSizeImage = imageBuffLen;
2501 bmh.biClrUsed = numOfColors;
2502 bmh.biClrImportant = numOfColors;
2504 hdr.bfSize = 14 + 40 + paletteEntries * 4 + bmh.biSizeImage;
2505 hdr.bfOffBits = 40 + 14 + paletteEntries * 4;
2508 WriteWORD (outFile, hdr.bfType);
2509 WriteDWORD (outFile, hdr.bfSize);
2510 WriteWORD (outFile, hdr.bfReserved1);
2511 WriteWORD (outFile, hdr.bfReserved2);
2512 WriteDWORD (outFile, hdr.bfOffBits);
2515 x = (kkint32)fwrite (&hdr,
sizeof (hdr), 1, outFile);
2520 WriteDWORD (outFile, bmh.biSize);
2521 WriteLONG (outFile, bmh.biWidth);
2522 WriteLONG (outFile, bmh.biHeight);
2523 WriteWORD (outFile, bmh.biPlanes);
2524 WriteWORD (outFile, bmh.biBitCount);
2525 WriteDWORD (outFile, bmh.biCompression);
2526 WriteDWORD (outFile, bmh.biSizeImage);
2527 WriteLONG (outFile, bmh.biXPelsPerMeter);
2528 WriteLONG (outFile, bmh.biYPelsPerMeter);
2529 WriteDWORD (outFile, bmh.biClrUsed);
2530 WriteDWORD (outFile, bmh.biClrImportant);
2533 x = (kkint32)fwrite (&bmh,
sizeof (bmh), 1, outFile);
2538 for (x = 0; x < paletteEntries; x++)
2540 WriteBYTE (outFile, palette[x].rgbBlue);
2541 WriteBYTE (outFile, palette[x].rgbGreen);
2542 WriteBYTE (outFile, palette[x].rgbRed);
2543 WriteBYTE (outFile, palette[x].rgbReserved);
2546 x = (kkint32)fwrite (palette,
sizeof (RGBQUAD), paletteEntries, outFile);
2550 x = (kkint32)fwrite (imageBuff, 1, imageBuffLen, outFile);
2556 void BmpImage::SaveColor24BPP (FILE* outFile)
2561 while ((bytesPerRow % 4) != 0)
2571 bmh.biBitCount = 24;
2572 bmh.biCompression = BI_RGB;
2573 bmh.biSizeImage = Height () * bytesPerRow;
2574 bmh.biXPelsPerMeter = 2835;
2575 bmh.biYPelsPerMeter = 2835;
2577 bmh.biClrImportant = 0;
2579 hdr.bfSize = 14 + 40 + 0 * 4 + bmh.biSizeImage;
2580 hdr.bfOffBits = 40 + 14 + 0 * 4;
2583 WriteWORD (outFile, hdr.bfType);
2584 WriteDWORD (outFile, hdr.bfSize);
2585 WriteWORD (outFile, hdr.bfReserved1);
2586 WriteWORD (outFile, hdr.bfReserved2);
2587 WriteDWORD (outFile, hdr.bfOffBits);
2589 x = (kkint32)fwrite (&hdr,
sizeof (hdr), 1, outFile);
2594 WriteDWORD (outFile, bmh.biSize);
2595 WriteLONG (outFile, bmh.biWidth);
2596 WriteLONG (outFile, bmh.biHeight);
2597 WriteWORD (outFile, bmh.biPlanes);
2598 WriteWORD (outFile, bmh.biBitCount);
2599 WriteDWORD (outFile, bmh.biCompression);
2600 WriteDWORD (outFile, bmh.biSizeImage);
2601 WriteLONG (outFile, bmh.biXPelsPerMeter);
2602 WriteLONG (outFile, bmh.biYPelsPerMeter);
2603 WriteDWORD (outFile, bmh.biClrUsed);
2604 WriteDWORD (outFile, bmh.biClrImportant);
2607 x = (kkint32)fwrite (&bmh,
sizeof (bmh), 1, outFile);
2616 fwrite (&(blue [row][col]), 1, 1, outFile);
2617 fwrite (&(image[row][col]), 1, 1, outFile);
2618 fwrite (&(red [row][col]), 1, 1, outFile);
2622 for (x = 0; x < bufferPerRow; x++)
2623 fwrite (&pad, 1, 1, outFile);
2635 image[row][col] = pixValue;
2643 for (row = 0; row < bmh.biHeight; row++)
2645 memset (image[row], 0, bmh.biWidth );
2655 throw KKException("BmpImage::BlueRow 'blue' channel is set to NULL.");
2660 <<
"BmpImage::BlueRow *** ERROR *** Invalid Row[" << row <<
"]." << std::endl
2680 <<
"BmpImage *** ERROR *** Invalid Row[" << row <<
"]." << std::endl
2693 throw KKException("BmpImage::RedRow 'red' channel is set to NULL.");
2698 <<
"BmpImage::RedRow *** ERROR *** Invalid Row[" << row <<
"]." << std::endl
2711 return ((bmh.biBitCount == 4) && (bmh.biCompression == BI_RGB));
bool AreThereEdgePixels()
void BuildPallet(RGBQUAD *&palette, kkint32 &size)
kkint32 NumOfColors() const
KKStr & operator=(const char *src)
void ReAllocateForBiggerScreen()
Used to expand dimensions of image by 6 pixels so as to make sure that no image is along the edge...
A class that is used by to represent a single image in memory.
void SaveGrayscaleInverted8Bit(const KKStr &_fileName)
Saves image using compressed gray-scale where Background = 255 and foreground = 0.
This object is used to help encode the data stored in BMPImage::image into 8 or 4 bit compressed form...
CodedPixels(kkint32 _height, kkint32 _width)
KKStr operator+(const char *right) const
const uchar * RedRow(kkint32 row) const
Returns the specified Row from the Red Channel.
unsigned __int32 kkuint32
const uchar * ImageRow(kkint32 row) const
Returns the specified Row from the Green Channel.
BmpImage(const Raster &raster)
Constructs a BMPImage instance from a Raster image; this is one way to save a Raster image to disk...
uchar & Pixel(kkint32 row, kkint32 col)
KKStr operator+(const char *left, const KKStr &right)
Used to encode and decode BMP Images.
BmpImage(kkint32 _height, kkint32 _width, kkint32 _numOfColors)
void SaveGrayscaleInverted4Bit(const KKStr &_fileName)
Saves image using 4 bit compressed gray-scale where Background = 255 and foreground = 0...
KKStr(const KKStr &str)
Copy Constructor.
uchar * CreatePixelDataStructure8Bit(kkint32 &len)
unsigned char uchar
Unsigned character.
static KKStr Concat(const std::vector< std::string > &values)
Concatenates the list of 'std::string' strings.
void AddColor(uchar red, uchar green, uchar blue)
void EliminateVerticalLines()
bool operator()(const RGBQUAD &left, const RGBQUAD &right) const
void Save(const KKStr &fileName)
void AddPixel(uchar pixel)
std::ostream &__cdecl operator<<(std::ostream &os, const KKStr &str)
KKStr operator+(const KKStr &right) const
const uchar * BlueRow(kkint32 row) const
Returns the specified Row from the Blue Channel.
void SetPaletteEntry(kkint32 palletIndex, const PixelValue &pixValue)
const char * Str() const
Returns a pointer to a ascii string.
FILE * osFOPEN(const char *fileName, const char *mode)
uchar * CreatePixelDataStructure4Bit(kkint32 &len)
KKException(const char *_exceptionStr)
KKStr & operator=(const KKStr &src)
void InitializeFields(kkint32 _height, kkint32 _width)
void AddPixel(kkuint32 row, kkuint32 col, uchar pixValue)
void SetPixelValue(kkint32 row, kkint32 col, kkint32 pixel)
Will set the pixel value of the specified row and col to 'pixel'.
KKException(const KKStr &_exceptionStr)
bool FourBitUncompressed()
BmpImage(const KKStr &_fileName, bool &successful)
Constructs a BMP image from the file specified by '_fileName'.
bool GrayScaleImage(RGBQUAD *palette, kkint32 palletSize)
Returns true if palette is for a grayscale image.
kkint32 PalletIndex(uchar red, uchar green, uchar blue)
Used by the Raster Class to represent the contents of one pixel.
KKStr StrFromInt32(kkint32 i)