├── main.cpp ├── captcha0.BMP ├── captcha1.BMP ├── captcha2.BMP ├── captcha3.BMP ├── captcha4.BMP ├── captcha5.BMP ├── captcha6.BMP ├── captcha7.BMP ├── EasyBMP_VariousBMPutilities.h ├── EasyBMP.h ├── EasyBMP_BMP.h ├── EasyBMP_DataStructures.h └── EasyBMP.cpp /main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/circleCaptcha/master/main.cpp -------------------------------------------------------------------------------- /captcha0.BMP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/circleCaptcha/master/captcha0.BMP -------------------------------------------------------------------------------- /captcha1.BMP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/circleCaptcha/master/captcha1.BMP -------------------------------------------------------------------------------- /captcha2.BMP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/circleCaptcha/master/captcha2.BMP -------------------------------------------------------------------------------- /captcha3.BMP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/circleCaptcha/master/captcha3.BMP -------------------------------------------------------------------------------- /captcha4.BMP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/circleCaptcha/master/captcha4.BMP -------------------------------------------------------------------------------- /captcha5.BMP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/circleCaptcha/master/captcha5.BMP -------------------------------------------------------------------------------- /captcha6.BMP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/circleCaptcha/master/captcha6.BMP -------------------------------------------------------------------------------- /captcha7.BMP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/edlerd/circleCaptcha/master/captcha7.BMP -------------------------------------------------------------------------------- /EasyBMP_VariousBMPutilities.h: -------------------------------------------------------------------------------- 1 | /************************************************* 2 | * * 3 | * EasyBMP Cross-Platform Windows Bitmap Library * 4 | * * 5 | * Author: Paul Macklin * 6 | * email: macklin01@users.sourceforge.net * 7 | * support: http://easybmp.sourceforge.net * 8 | * * 9 | * file: EasyBMP_VariousBMPutilities.h * 10 | * date added: 05-02-2005 * 11 | * date modified: 12-01-2006 * 12 | * version: 1.06 * 13 | * * 14 | * License: BSD (revised/modified) * 15 | * Copyright: 2005-6 by the EasyBMP Project * 16 | * * 17 | * description: Various utilities. * 18 | * * 19 | *************************************************/ 20 | 21 | #ifndef _EasyBMP_VariousBMPutilities_h_ 22 | #define _EasyBMP_VariousBMPutilities_h_ 23 | 24 | BMFH GetBMFH( const char* szFileNameIn ); 25 | BMIH GetBMIH( const char* szFileNameIn ); 26 | void DisplayBitmapInfo( const char* szFileNameIn ); 27 | int GetBitmapColorDepth( const char* szFileNameIn ); 28 | void PixelToPixelCopy( BMP& From, int FromX, int FromY, 29 | BMP& To, int ToX, int ToY); 30 | void PixelToPixelCopyTransparent( BMP& From, int FromX, int FromY, 31 | BMP& To, int ToX, int ToY, 32 | RGBApixel& Transparent ); 33 | void RangedPixelToPixelCopy( BMP& From, int FromL , int FromR, int FromB, int FromT, 34 | BMP& To, int ToX, int ToY ); 35 | void RangedPixelToPixelCopyTransparent( 36 | BMP& From, int FromL , int FromR, int FromB, int FromT, 37 | BMP& To, int ToX, int ToY , 38 | RGBApixel& Transparent ); 39 | bool CreateGrayscaleColorTable( BMP& InputImage ); 40 | 41 | bool Rescale( BMP& InputImage , char mode, int NewDimension ); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /EasyBMP.h: -------------------------------------------------------------------------------- 1 | /************************************************* 2 | * * 3 | * EasyBMP Cross-Platform Windows Bitmap Library * 4 | * * 5 | * Author: Paul Macklin * 6 | * email: macklin01@users.sourceforge.net * 7 | * support: http://easybmp.sourceforge.net * 8 | * * 9 | * file: EasyBMP.h * 10 | * date added: 01-31-2005 * 11 | * date modified: 12-01-2006 * 12 | * version: 1.06 * 13 | * * 14 | * License: BSD (revised/modified) * 15 | * Copyright: 2005-6 by the EasyBMP Project * 16 | * * 17 | * description: Main include file * 18 | * * 19 | *************************************************/ 20 | 21 | #ifdef _MSC_VER 22 | // MS Visual Studio gives warnings when using 23 | // fopen. But fopen_s is not going to work well 24 | // with most compilers, and fopen_s uses different 25 | // syntax than fopen. (i.e., a macro won't work) 26 | // So, we'lll use this: 27 | #define _CRT_SECURE_NO_DEPRECATE 28 | #endif 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #ifndef EasyBMP 36 | #define EasyBMP 37 | 38 | #ifdef __BCPLUSPLUS__ 39 | // The Borland compiler must use this because something 40 | // is wrong with their cstdio file. 41 | #include 42 | #else 43 | #include 44 | #endif 45 | 46 | #ifdef __GNUC__ 47 | // If g++ specific code is ever required, this is 48 | // where it goes. 49 | #endif 50 | 51 | #ifdef __INTEL_COMPILER 52 | // If Intel specific code is ever required, this is 53 | // where it goes. 54 | #endif 55 | 56 | #ifndef _DefaultXPelsPerMeter_ 57 | #define _DefaultXPelsPerMeter_ 58 | #define DefaultXPelsPerMeter 3780 59 | // set to a default of 96 dpi 60 | #endif 61 | 62 | #ifndef _DefaultYPelsPerMeter_ 63 | #define _DefaultYPelsPerMeter_ 64 | #define DefaultYPelsPerMeter 3780 65 | // set to a default of 96 dpi 66 | #endif 67 | 68 | #include "EasyBMP_DataStructures.h" 69 | #include "EasyBMP_BMP.h" 70 | #include "EasyBMP_VariousBMPutilities.h" 71 | 72 | #ifndef _EasyBMP_Version_ 73 | #define _EasyBMP_Version_ 1.06 74 | #define _EasyBMP_Version_Integer_ 106 75 | #define _EasyBMP_Version_String_ "1.06" 76 | #endif 77 | 78 | #ifndef _EasyBMPwarnings_ 79 | #define _EasyBMPwarnings_ 80 | #endif 81 | 82 | void SetEasyBMPwarningsOff( void ); 83 | void SetEasyBMPwarningsOn( void ); 84 | bool GetEasyBMPwarningState( void ); 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /EasyBMP_BMP.h: -------------------------------------------------------------------------------- 1 | /************************************************* 2 | * * 3 | * EasyBMP Cross-Platform Windows Bitmap Library * 4 | * * 5 | * Author: Paul Macklin * 6 | * email: macklin01@users.sourceforge.net * 7 | * support: http://easybmp.sourceforge.net * 8 | * * 9 | * file: EasyBMP_VariousBMPutilities.h * 10 | * date added: 05-02-2005 * 11 | * date modified: 12-01-2006 * 12 | * version: 1.06 * 13 | * * 14 | * License: BSD (revised/modified) * 15 | * Copyright: 2005-6 by the EasyBMP Project * 16 | * * 17 | * description: Defines BMP class * 18 | * * 19 | *************************************************/ 20 | 21 | #ifndef _EasyBMP_BMP_h_ 22 | #define _EasyBMP_BMP_h_ 23 | 24 | bool SafeFread( char* buffer, int size, int number, FILE* fp ); 25 | bool EasyBMPcheckDataSize( void ); 26 | 27 | class BMP 28 | {private: 29 | 30 | int BitDepth; 31 | int Width; 32 | int Height; 33 | RGBApixel** Pixels; 34 | RGBApixel* Colors; 35 | int XPelsPerMeter; 36 | int YPelsPerMeter; 37 | 38 | ebmpBYTE* MetaData1; 39 | int SizeOfMetaData1; 40 | ebmpBYTE* MetaData2; 41 | int SizeOfMetaData2; 42 | 43 | bool Read32bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 44 | bool Read24bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 45 | bool Read8bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 46 | bool Read4bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 47 | bool Read1bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 48 | 49 | bool Write32bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 50 | bool Write24bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 51 | bool Write8bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 52 | bool Write4bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 53 | bool Write1bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ); 54 | 55 | ebmpBYTE FindClosestColor( RGBApixel& input ); 56 | 57 | public: 58 | 59 | int TellBitDepth( void ); 60 | int TellWidth( void ); 61 | int TellHeight( void ); 62 | int TellNumberOfColors( void ); 63 | void SetDPI( int HorizontalDPI, int VerticalDPI ); 64 | int TellVerticalDPI( void ); 65 | int TellHorizontalDPI( void ); 66 | 67 | BMP(); 68 | BMP( BMP& Input ); 69 | ~BMP(); 70 | RGBApixel* operator()(int i,int j); 71 | 72 | RGBApixel GetPixel( int i, int j ) const; 73 | bool SetPixel( int i, int j, RGBApixel NewPixel ); 74 | 75 | bool CreateStandardColorTable( void ); 76 | 77 | bool SetSize( int NewWidth, int NewHeight ); 78 | bool SetBitDepth( int NewDepth ); 79 | bool WriteToFile( const char* FileName ); 80 | bool ReadFromFile( const char* FileName ); 81 | 82 | RGBApixel GetColor( int ColorNumber ); 83 | bool SetColor( int ColorNumber, RGBApixel NewColor ); 84 | }; 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /EasyBMP_DataStructures.h: -------------------------------------------------------------------------------- 1 | /************************************************* 2 | * * 3 | * EasyBMP Cross-Platform Windows Bitmap Library * 4 | * * 5 | * Author: Paul Macklin * 6 | * email: macklin01@users.sourceforge.net * 7 | * support: http://easybmp.sourceforge.net * 8 | * * 9 | * file: EasyBMP_DataStructures.h * 10 | * date added: 05-02-2005 * 11 | * date modified: 12-01-2006 * 12 | * version: 1.06 * 13 | * * 14 | * License: BSD (revised/modified) * 15 | * Copyright: 2005-6 by the EasyBMP Project * 16 | * * 17 | * description: Defines basic data structures for * 18 | * the BMP class * 19 | * * 20 | *************************************************/ 21 | 22 | #ifndef _EasyBMP_Custom_Math_Functions_ 23 | #define _EasyBMP_Custom_Math_Functions_ 24 | inline double Square( double number ) 25 | { return number*number; } 26 | 27 | inline int IntSquare( int number ) 28 | { return number*number; } 29 | #endif 30 | 31 | int IntPow( int base, int exponent ); 32 | 33 | #ifndef _EasyBMP_Defined_WINGDI 34 | #define _EasyBMP_Defined_WINGDI 35 | typedef unsigned char ebmpBYTE; 36 | typedef unsigned short ebmpWORD; 37 | typedef unsigned int ebmpDWORD; 38 | #endif 39 | 40 | #ifndef _EasyBMP_DataStructures_h_ 41 | #define _EasyBMP_DataStructures_h_ 42 | 43 | inline bool IsBigEndian() 44 | { 45 | short word = 0x0001; 46 | if((*(char *)& word) != 0x01 ) 47 | { return true; } 48 | return false; 49 | } 50 | 51 | inline ebmpWORD FlipWORD( ebmpWORD in ) 52 | { return ( (in >> 8) | (in << 8) ); } 53 | 54 | inline ebmpDWORD FlipDWORD( ebmpDWORD in ) 55 | { 56 | return ( ((in&0xFF000000)>>24) | ((in&0x000000FF)<<24) | 57 | ((in&0x00FF0000)>>8 ) | ((in&0x0000FF00)<<8 ) ); 58 | } 59 | 60 | // it's easier to use a struct than a class 61 | // because we can read/write all four of the bytes 62 | // at once (as we can count on them being continuous 63 | // in memory 64 | 65 | typedef struct RGBApixel { 66 | ebmpBYTE Blue; 67 | ebmpBYTE Green; 68 | ebmpBYTE Red; 69 | ebmpBYTE Alpha; 70 | } RGBApixel; 71 | 72 | class BMFH{ 73 | public: 74 | ebmpWORD bfType; 75 | ebmpDWORD bfSize; 76 | ebmpWORD bfReserved1; 77 | ebmpWORD bfReserved2; 78 | ebmpDWORD bfOffBits; 79 | 80 | BMFH(); 81 | void display( void ); 82 | void SwitchEndianess( void ); 83 | }; 84 | 85 | class BMIH{ 86 | public: 87 | ebmpDWORD biSize; 88 | ebmpDWORD biWidth; 89 | ebmpDWORD biHeight; 90 | ebmpWORD biPlanes; 91 | ebmpWORD biBitCount; 92 | ebmpDWORD biCompression; 93 | ebmpDWORD biSizeImage; 94 | ebmpDWORD biXPelsPerMeter; 95 | ebmpDWORD biYPelsPerMeter; 96 | ebmpDWORD biClrUsed; 97 | ebmpDWORD biClrImportant; 98 | 99 | BMIH(); 100 | void display( void ); 101 | void SwitchEndianess( void ); 102 | }; 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /EasyBMP.cpp: -------------------------------------------------------------------------------- 1 | /************************************************* 2 | * * 3 | * EasyBMP Cross-Platform Windows Bitmap Library * 4 | * * 5 | * Author: Paul Macklin * 6 | * email: macklin01@users.sourceforge.net * 7 | * support: http://easybmp.sourceforge.net * 8 | * * 9 | * file: EasyBMP.cpp * 10 | * date added: 03-31-2006 * 11 | * date modified: 12-01-2006 * 12 | * version: 1.06 * 13 | * * 14 | * License: BSD (revised/modified) * 15 | * Copyright: 2005-6 by the EasyBMP Project * 16 | * * 17 | * description: Actual source file * 18 | * * 19 | *************************************************/ 20 | 21 | #include "EasyBMP.h" 22 | 23 | /* These functions are defined in EasyBMP.h */ 24 | 25 | bool EasyBMPwarnings = true; 26 | 27 | void SetEasyBMPwarningsOff( void ) 28 | { EasyBMPwarnings = false; } 29 | void SetEasyBMPwarningsOn( void ) 30 | { EasyBMPwarnings = true; } 31 | bool GetEasyBMPwarningState( void ) 32 | { return EasyBMPwarnings; } 33 | 34 | /* These functions are defined in EasyBMP_DataStructures.h */ 35 | 36 | int IntPow( int base, int exponent ) 37 | { 38 | int i; 39 | int output = 1; 40 | for( i=0 ; i < exponent ; i++ ) 41 | { output *= base; } 42 | return output; 43 | } 44 | 45 | BMFH::BMFH() 46 | { 47 | bfType = 19778; 48 | bfReserved1 = 0; 49 | bfReserved2 = 0; 50 | } 51 | 52 | void BMFH::SwitchEndianess( void ) 53 | { 54 | bfType = FlipWORD( bfType ); 55 | bfSize = FlipDWORD( bfSize ); 56 | bfReserved1 = FlipWORD( bfReserved1 ); 57 | bfReserved2 = FlipWORD( bfReserved2 ); 58 | bfOffBits = FlipDWORD( bfOffBits ); 59 | return; 60 | } 61 | 62 | BMIH::BMIH() 63 | { 64 | biPlanes = 1; 65 | biCompression = 0; 66 | biXPelsPerMeter = DefaultXPelsPerMeter; 67 | biYPelsPerMeter = DefaultYPelsPerMeter; 68 | biClrUsed = 0; 69 | biClrImportant = 0; 70 | } 71 | 72 | void BMIH::SwitchEndianess( void ) 73 | { 74 | biSize = FlipDWORD( biSize ); 75 | biWidth = FlipDWORD( biWidth ); 76 | biHeight = FlipDWORD( biHeight ); 77 | biPlanes = FlipWORD( biPlanes ); 78 | biBitCount = FlipWORD( biBitCount ); 79 | biCompression = FlipDWORD( biCompression ); 80 | biSizeImage = FlipDWORD( biSizeImage ); 81 | biXPelsPerMeter = FlipDWORD( biXPelsPerMeter ); 82 | biYPelsPerMeter = FlipDWORD( biYPelsPerMeter ); 83 | biClrUsed = FlipDWORD( biClrUsed ); 84 | biClrImportant = FlipDWORD( biClrImportant ); 85 | return; 86 | } 87 | 88 | void BMIH::display( void ) 89 | { 90 | using namespace std; 91 | cout << "biSize: " << (int) biSize << endl 92 | << "biWidth: " << (int) biWidth << endl 93 | << "biHeight: " << (int) biHeight << endl 94 | << "biPlanes: " << (int) biPlanes << endl 95 | << "biBitCount: " << (int) biBitCount << endl 96 | << "biCompression: " << (int) biCompression << endl 97 | << "biSizeImage: " << (int) biSizeImage << endl 98 | << "biXPelsPerMeter: " << (int) biXPelsPerMeter << endl 99 | << "biYPelsPerMeter: " << (int) biYPelsPerMeter << endl 100 | << "biClrUsed: " << (int) biClrUsed << endl 101 | << "biClrImportant: " << (int) biClrImportant << endl << endl; 102 | } 103 | 104 | void BMFH::display( void ) 105 | { 106 | using namespace std; 107 | cout << "bfType: " << (int) bfType << endl 108 | << "bfSize: " << (int) bfSize << endl 109 | << "bfReserved1: " << (int) bfReserved1 << endl 110 | << "bfReserved2: " << (int) bfReserved2 << endl 111 | << "bfOffBits: " << (int) bfOffBits << endl << endl; 112 | } 113 | 114 | /* These functions are defined in EasyBMP_BMP.h */ 115 | 116 | RGBApixel BMP::GetPixel( int i, int j ) const 117 | { 118 | using namespace std; 119 | bool Warn = false; 120 | if( i >= Width ) 121 | { i = Width-1; Warn = true; } 122 | if( i < 0 ) 123 | { i = 0; Warn = true; } 124 | if( j >= Height ) 125 | { j = Height-1; Warn = true; } 126 | if( j < 0 ) 127 | { j = 0; Warn = true; } 128 | if( Warn && EasyBMPwarnings ) 129 | { 130 | cout << "EasyBMP Warning: Attempted to access non-existent pixel;" << endl 131 | << " Truncating request to fit in the range [0," 132 | << Width-1 << "] x [0," << Height-1 << "]." << endl; 133 | } 134 | return Pixels[i][j]; 135 | } 136 | 137 | bool BMP::SetPixel( int i, int j, RGBApixel NewPixel ) 138 | { 139 | Pixels[i][j] = NewPixel; 140 | return true; 141 | } 142 | 143 | 144 | bool BMP::SetColor( int ColorNumber , RGBApixel NewColor ) 145 | { 146 | using namespace std; 147 | if( BitDepth != 1 && BitDepth != 4 && BitDepth != 8 ) 148 | { 149 | if( EasyBMPwarnings ) 150 | { 151 | cout << "EasyBMP Warning: Attempted to change color table for a BMP object" << endl 152 | << " that lacks a color table. Ignoring request." << endl; 153 | } 154 | return false; 155 | } 156 | if( !Colors ) 157 | { 158 | if( EasyBMPwarnings ) 159 | { 160 | cout << "EasyBMP Warning: Attempted to set a color, but the color table" << endl 161 | << " is not defined. Ignoring request." << endl; 162 | } 163 | return false; 164 | } 165 | if( ColorNumber >= TellNumberOfColors() ) 166 | { 167 | if( EasyBMPwarnings ) 168 | { 169 | cout << "EasyBMP Warning: Requested color number " 170 | << ColorNumber << " is outside the allowed" << endl 171 | << " range [0," << TellNumberOfColors()-1 172 | << "]. Ignoring request to set this color." << endl; 173 | } 174 | return false; 175 | } 176 | Colors[ColorNumber] = NewColor; 177 | return true; 178 | } 179 | 180 | // RGBApixel BMP::GetColor( int ColorNumber ) const 181 | RGBApixel BMP::GetColor( int ColorNumber ) 182 | { 183 | RGBApixel Output; 184 | Output.Red = 255; 185 | Output.Green = 255; 186 | Output.Blue = 255; 187 | Output.Alpha = 0; 188 | 189 | using namespace std; 190 | if( BitDepth != 1 && BitDepth != 4 && BitDepth != 8 ) 191 | { 192 | if( EasyBMPwarnings ) 193 | { 194 | cout << "EasyBMP Warning: Attempted to access color table for a BMP object" << endl 195 | << " that lacks a color table. Ignoring request." << endl; 196 | } 197 | return Output; 198 | } 199 | if( !Colors ) 200 | { 201 | if( EasyBMPwarnings ) 202 | { 203 | cout << "EasyBMP Warning: Requested a color, but the color table" << endl 204 | << " is not defined. Ignoring request." << endl; 205 | } 206 | return Output; 207 | } 208 | if( ColorNumber >= TellNumberOfColors() ) 209 | { 210 | if( EasyBMPwarnings ) 211 | { 212 | cout << "EasyBMP Warning: Requested color number " 213 | << ColorNumber << " is outside the allowed" << endl 214 | << " range [0," << TellNumberOfColors()-1 215 | << "]. Ignoring request to get this color." << endl; 216 | } 217 | return Output; 218 | } 219 | Output = Colors[ColorNumber]; 220 | return Output; 221 | } 222 | 223 | BMP::BMP() 224 | { 225 | Width = 1; 226 | Height = 1; 227 | BitDepth = 24; 228 | Pixels = new RGBApixel* [Width]; 229 | Pixels[0] = new RGBApixel [Height]; 230 | Colors = NULL; 231 | 232 | XPelsPerMeter = 0; 233 | YPelsPerMeter = 0; 234 | 235 | MetaData1 = NULL; 236 | SizeOfMetaData1 = 0; 237 | MetaData2 = NULL; 238 | SizeOfMetaData2 = 0; 239 | } 240 | 241 | // BMP::BMP( const BMP& Input ) 242 | BMP::BMP( BMP& Input ) 243 | { 244 | // first, make the image empty. 245 | 246 | Width = 1; 247 | Height = 1; 248 | BitDepth = 24; 249 | Pixels = new RGBApixel* [Width]; 250 | Pixels[0] = new RGBApixel [Height]; 251 | Colors = NULL; 252 | XPelsPerMeter = 0; 253 | YPelsPerMeter = 0; 254 | 255 | MetaData1 = NULL; 256 | SizeOfMetaData1 = 0; 257 | MetaData2 = NULL; 258 | SizeOfMetaData2 = 0; 259 | 260 | // now, set the correct bit depth 261 | 262 | SetBitDepth( Input.TellBitDepth() ); 263 | 264 | // set the correct pixel size 265 | 266 | SetSize( Input.TellWidth() , Input.TellHeight() ); 267 | 268 | // set the DPI information from Input 269 | 270 | SetDPI( Input.TellHorizontalDPI() , Input.TellVerticalDPI() ); 271 | 272 | // if there is a color table, get all the colors 273 | 274 | if( BitDepth == 1 || BitDepth == 4 || 275 | BitDepth == 8 ) 276 | { 277 | for( int k=0 ; k < TellNumberOfColors() ; k++ ) 278 | { 279 | SetColor( k, Input.GetColor( k )); 280 | } 281 | } 282 | 283 | // get all the pixels 284 | 285 | for( int j=0; j < Height ; j++ ) 286 | { 287 | for( int i=0; i < Width ; i++ ) 288 | { 289 | Pixels[i][j] = *Input(i,j); 290 | // Pixels[i][j] = Input.GetPixel(i,j); // *Input(i,j); 291 | } 292 | } 293 | } 294 | 295 | BMP::~BMP() 296 | { 297 | int i; 298 | for(i=0;i= Width ) 315 | { i = Width-1; Warn = true; } 316 | if( i < 0 ) 317 | { i = 0; Warn = true; } 318 | if( j >= Height ) 319 | { j = Height-1; Warn = true; } 320 | if( j < 0 ) 321 | { j = 0; Warn = true; } 322 | if( Warn && EasyBMPwarnings ) 323 | { 324 | cout << "EasyBMP Warning: Attempted to access non-existent pixel;" << endl 325 | << " Truncating request to fit in the range [0," 326 | << Width-1 << "] x [0," << Height-1 << "]." << endl; 327 | } 328 | return &(Pixels[i][j]); 329 | } 330 | 331 | // int BMP::TellBitDepth( void ) const 332 | int BMP::TellBitDepth( void ) 333 | { return BitDepth; } 334 | 335 | // int BMP::TellHeight( void ) const 336 | int BMP::TellHeight( void ) 337 | { return Height; } 338 | 339 | // int BMP::TellWidth( void ) const 340 | int BMP::TellWidth( void ) 341 | { return Width; } 342 | 343 | // int BMP::TellNumberOfColors( void ) const 344 | int BMP::TellNumberOfColors( void ) 345 | { 346 | int output = IntPow( 2, BitDepth ); 347 | if( BitDepth == 32 ) 348 | { output = IntPow( 2, 24 ); } 349 | return output; 350 | } 351 | 352 | bool BMP::SetBitDepth( int NewDepth ) 353 | { 354 | using namespace std; 355 | if( NewDepth != 1 && NewDepth != 4 && 356 | NewDepth != 8 && NewDepth != 16 && 357 | NewDepth != 24 && NewDepth != 32 ) 358 | { 359 | if( EasyBMPwarnings ) 360 | { 361 | cout << "EasyBMP Warning: User attempted to set unsupported bit depth " 362 | << NewDepth << "." << endl 363 | << " Bit depth remains unchanged at " 364 | << BitDepth << "." << endl; 365 | } 366 | return false; 367 | } 368 | 369 | BitDepth = NewDepth; 370 | if( Colors ) 371 | { delete [] Colors; } 372 | int NumberOfColors = IntPow( 2, BitDepth ); 373 | if( BitDepth == 1 || BitDepth == 4 || BitDepth == 8 ) 374 | { Colors = new RGBApixel [NumberOfColors]; } 375 | else 376 | { Colors = NULL; } 377 | if( BitDepth == 1 || BitDepth == 4 || BitDepth == 8 ) 378 | { CreateStandardColorTable(); } 379 | 380 | return true; 381 | } 382 | 383 | bool BMP::SetSize(int NewWidth , int NewHeight ) 384 | { 385 | using namespace std; 386 | if( NewWidth <= 0 || NewHeight <= 0 ) 387 | { 388 | if( EasyBMPwarnings ) 389 | { 390 | cout << "EasyBMP Warning: User attempted to set a non-positive width or height." << endl 391 | << " Size remains unchanged at " 392 | << Width << " x " << Height << "." << endl; 393 | } 394 | return false; 395 | } 396 | 397 | int i,j; 398 | 399 | for(i=0;i -1 ) 570 | { 571 | bool Success = false; 572 | if( BitDepth == 32 ) 573 | { Success = Write32bitRow( Buffer, BufferSize, j ); } 574 | if( BitDepth == 24 ) 575 | { Success = Write24bitRow( Buffer, BufferSize, j ); } 576 | if( BitDepth == 8 ) 577 | { Success = Write8bitRow( Buffer, BufferSize, j ); } 578 | if( BitDepth == 4 ) 579 | { Success = Write4bitRow( Buffer, BufferSize, j ); } 580 | if( BitDepth == 1 ) 581 | { Success = Write1bitRow( Buffer, BufferSize, j ); } 582 | if( Success ) 583 | { 584 | int BytesWritten = (int) fwrite( (char*) Buffer, 1, BufferSize, fp ); 585 | if( BytesWritten != BufferSize ) 586 | { Success = false; } 587 | } 588 | if( !Success ) 589 | { 590 | if( EasyBMPwarnings ) 591 | { 592 | cout << "EasyBMP Error: Could not write proper amount of data." << endl; 593 | } 594 | j = -1; 595 | } 596 | j--; 597 | } 598 | 599 | delete [] Buffer; 600 | } 601 | 602 | if( BitDepth == 16 ) 603 | { 604 | // write the bit masks 605 | 606 | ebmpWORD BlueMask = 31; // bits 12-16 607 | ebmpWORD GreenMask = 2016; // bits 6-11 608 | ebmpWORD RedMask = 63488; // bits 1-5 609 | ebmpWORD ZeroWORD; 610 | 611 | if( IsBigEndian() ) 612 | { RedMask = FlipWORD( RedMask ); } 613 | fwrite( (char*) &RedMask , 2 , 1 , fp ); 614 | fwrite( (char*) &ZeroWORD , 2 , 1 , fp ); 615 | 616 | if( IsBigEndian() ) 617 | { GreenMask = FlipWORD( GreenMask ); } 618 | fwrite( (char*) &GreenMask , 2 , 1 , fp ); 619 | fwrite( (char*) &ZeroWORD , 2 , 1 , fp ); 620 | 621 | if( IsBigEndian() ) 622 | { BlueMask = FlipWORD( BlueMask ); } 623 | fwrite( (char*) &BlueMask , 2 , 1 , fp ); 624 | fwrite( (char*) &ZeroWORD , 2 , 1 , fp ); 625 | 626 | int DataBytes = Width*2; 627 | int PaddingBytes = ( 4 - DataBytes % 4 ) % 4; 628 | 629 | // write the actual pixels 630 | 631 | for( j=Height-1 ; j >= 0 ; j-- ) 632 | { 633 | // write all row pixel data 634 | i=0; 635 | int WriteNumber = 0; 636 | while( WriteNumber < DataBytes ) 637 | { 638 | ebmpWORD TempWORD; 639 | 640 | ebmpWORD RedWORD = (ebmpWORD) ((Pixels[i][j]).Red / 8); 641 | ebmpWORD GreenWORD = (ebmpWORD) ((Pixels[i][j]).Green / 4); 642 | ebmpWORD BlueWORD = (ebmpWORD) ((Pixels[i][j]).Blue / 8); 643 | 644 | TempWORD = (RedWORD<<11) + (GreenWORD<<5) + BlueWORD; 645 | if( IsBigEndian() ) 646 | { TempWORD = FlipWORD( TempWORD ); } 647 | 648 | fwrite( (char*) &TempWORD , 2, 1, fp); 649 | WriteNumber += 2; 650 | i++; 651 | } 652 | // write any necessary row padding 653 | WriteNumber = 0; 654 | while( WriteNumber < PaddingBytes ) 655 | { 656 | ebmpBYTE TempBYTE; 657 | fwrite( (char*) &TempBYTE , 1, 1, fp); 658 | WriteNumber++; 659 | } 660 | } 661 | 662 | } 663 | 664 | fclose(fp); 665 | return true; 666 | } 667 | 668 | bool BMP::ReadFromFile( const char* FileName ) 669 | { 670 | using namespace std; 671 | if( !EasyBMPcheckDataSize() ) 672 | { 673 | if( EasyBMPwarnings ) 674 | { 675 | cout << "EasyBMP Error: Data types are wrong size!" << endl 676 | << " You may need to mess with EasyBMP_DataTypes.h" << endl 677 | << " to fix these errors, and then recompile." << endl 678 | << " All 32-bit and 64-bit machines should be" << endl 679 | << " supported, however." << endl << endl; 680 | } 681 | return false; 682 | } 683 | 684 | FILE* fp = fopen( FileName, "rb" ); 685 | if( fp == NULL ) 686 | { 687 | if( EasyBMPwarnings ) 688 | { 689 | cout << "EasyBMP Error: Cannot open file " 690 | << FileName << " for input." << endl; 691 | } 692 | SetBitDepth(1); 693 | SetSize(1,1); 694 | return false; 695 | } 696 | 697 | // read the file header 698 | 699 | BMFH bmfh; 700 | bool NotCorrupted = true; 701 | 702 | NotCorrupted &= SafeFread( (char*) &(bmfh.bfType) , sizeof(ebmpWORD), 1, fp); 703 | 704 | bool IsBitmap = false; 705 | 706 | if( IsBigEndian() && bmfh.bfType == 16973 ) 707 | { IsBitmap = true; } 708 | if( !IsBigEndian() && bmfh.bfType == 19778 ) 709 | { IsBitmap = true; } 710 | 711 | if( !IsBitmap ) 712 | { 713 | if( EasyBMPwarnings ) 714 | { 715 | cout << "EasyBMP Error: " << FileName 716 | << " is not a Windows BMP file!" << endl; 717 | } 718 | fclose( fp ); 719 | return false; 720 | } 721 | 722 | NotCorrupted &= SafeFread( (char*) &(bmfh.bfSize) , sizeof(ebmpDWORD) , 1, fp); 723 | NotCorrupted &= SafeFread( (char*) &(bmfh.bfReserved1) , sizeof(ebmpWORD) , 1, fp); 724 | NotCorrupted &= SafeFread( (char*) &(bmfh.bfReserved2) , sizeof(ebmpWORD) , 1, fp); 725 | NotCorrupted &= SafeFread( (char*) &(bmfh.bfOffBits) , sizeof(ebmpDWORD) , 1 , fp); 726 | 727 | if( IsBigEndian() ) 728 | { bmfh.SwitchEndianess(); } 729 | 730 | // read the info header 731 | 732 | BMIH bmih; 733 | 734 | NotCorrupted &= SafeFread( (char*) &(bmih.biSize) , sizeof(ebmpDWORD) , 1 , fp); 735 | NotCorrupted &= SafeFread( (char*) &(bmih.biWidth) , sizeof(ebmpDWORD) , 1 , fp); 736 | NotCorrupted &= SafeFread( (char*) &(bmih.biHeight) , sizeof(ebmpDWORD) , 1 , fp); 737 | NotCorrupted &= SafeFread( (char*) &(bmih.biPlanes) , sizeof(ebmpWORD) , 1, fp); 738 | NotCorrupted &= SafeFread( (char*) &(bmih.biBitCount) , sizeof(ebmpWORD) , 1, fp); 739 | 740 | NotCorrupted &= SafeFread( (char*) &(bmih.biCompression) , sizeof(ebmpDWORD) , 1 , fp); 741 | NotCorrupted &= SafeFread( (char*) &(bmih.biSizeImage) , sizeof(ebmpDWORD) , 1 , fp); 742 | NotCorrupted &= SafeFread( (char*) &(bmih.biXPelsPerMeter) , sizeof(ebmpDWORD) , 1 , fp); 743 | NotCorrupted &= SafeFread( (char*) &(bmih.biYPelsPerMeter) , sizeof(ebmpDWORD) , 1 , fp); 744 | NotCorrupted &= SafeFread( (char*) &(bmih.biClrUsed) , sizeof(ebmpDWORD) , 1 , fp); 745 | NotCorrupted &= SafeFread( (char*) &(bmih.biClrImportant) , sizeof(ebmpDWORD) , 1 , fp); 746 | 747 | if( IsBigEndian() ) 748 | { bmih.SwitchEndianess(); } 749 | 750 | // a safety catch: if any of the header information didn't read properly, abort 751 | // future idea: check to see if at least most is self-consistent 752 | 753 | if( !NotCorrupted ) 754 | { 755 | if( EasyBMPwarnings ) 756 | { 757 | cout << "EasyBMP Error: " << FileName 758 | << " is obviously corrupted." << endl; 759 | } 760 | SetSize(1,1); 761 | SetBitDepth(1); 762 | fclose(fp); 763 | return false; 764 | } 765 | 766 | XPelsPerMeter = bmih.biXPelsPerMeter; 767 | YPelsPerMeter = bmih.biYPelsPerMeter; 768 | 769 | // if bmih.biCompression 1 or 2, then the file is RLE compressed 770 | 771 | if( bmih.biCompression == 1 || bmih.biCompression == 2 ) 772 | { 773 | if( EasyBMPwarnings ) 774 | { 775 | cout << "EasyBMP Error: " << FileName << " is (RLE) compressed." << endl 776 | << " EasyBMP does not support compression." << endl; 777 | } 778 | SetSize(1,1); 779 | SetBitDepth(1); 780 | fclose(fp); 781 | return false; 782 | } 783 | 784 | // if bmih.biCompression > 3, then something strange is going on 785 | // it's probably an OS2 bitmap file. 786 | 787 | if( bmih.biCompression > 3 ) 788 | { 789 | if( EasyBMPwarnings ) 790 | { 791 | cout << "EasyBMP Error: " << FileName << " is in an unsupported format." 792 | << endl 793 | << " (bmih.biCompression = " 794 | << bmih.biCompression << ")" << endl 795 | << " The file is probably an old OS2 bitmap or corrupted." 796 | << endl; 797 | } 798 | SetSize(1,1); 799 | SetBitDepth(1); 800 | fclose(fp); 801 | return false; 802 | } 803 | 804 | if( bmih.biCompression == 3 && bmih.biBitCount != 16 ) 805 | { 806 | if( EasyBMPwarnings ) 807 | { 808 | cout << "EasyBMP Error: " << FileName 809 | << " uses bit fields and is not a" << endl 810 | << " 16-bit file. This is not supported." << endl; 811 | } 812 | SetSize(1,1); 813 | SetBitDepth(1); 814 | fclose(fp); 815 | return false; 816 | } 817 | 818 | // set the bit depth 819 | 820 | int TempBitDepth = (int) bmih.biBitCount; 821 | if( TempBitDepth != 1 && TempBitDepth != 4 822 | && TempBitDepth != 8 && TempBitDepth != 16 823 | && TempBitDepth != 24 && TempBitDepth != 32 ) 824 | { 825 | if( EasyBMPwarnings ) 826 | { 827 | cout << "EasyBMP Error: " << FileName << " has unrecognized bit depth." << endl; 828 | } 829 | SetSize(1,1); 830 | SetBitDepth(1); 831 | fclose(fp); 832 | return false; 833 | } 834 | SetBitDepth( (int) bmih.biBitCount ); 835 | 836 | // set the size 837 | 838 | if( (int) bmih.biWidth <= 0 || (int) bmih.biHeight <= 0 ) 839 | { 840 | if( EasyBMPwarnings ) 841 | { 842 | cout << "EasyBMP Error: " << FileName 843 | << " has a non-positive width or height." << endl; 844 | } 845 | SetSize(1,1); 846 | SetBitDepth(1); 847 | fclose(fp); 848 | return false; 849 | } 850 | SetSize( (int) bmih.biWidth , (int) bmih.biHeight ); 851 | 852 | // some preliminaries 853 | 854 | double dBytesPerPixel = ( (double) BitDepth ) / 8.0; 855 | double dBytesPerRow = dBytesPerPixel * (Width+0.0); 856 | dBytesPerRow = ceil(dBytesPerRow); 857 | 858 | int BytePaddingPerRow = 4 - ( (int) (dBytesPerRow) )% 4; 859 | if( BytePaddingPerRow == 4 ) 860 | { BytePaddingPerRow = 0; } 861 | 862 | // if < 16 bits, read the palette 863 | 864 | if( BitDepth < 16 ) 865 | { 866 | // determine the number of colors specified in the 867 | // color table 868 | 869 | int NumberOfColorsToRead = ((int) bmfh.bfOffBits - 54 )/4; 870 | if( NumberOfColorsToRead > IntPow(2,BitDepth) ) 871 | { NumberOfColorsToRead = IntPow(2,BitDepth); } 872 | 873 | if( NumberOfColorsToRead < TellNumberOfColors() ) 874 | { 875 | if( EasyBMPwarnings ) 876 | { 877 | cout << "EasyBMP Warning: file " << FileName << " has an underspecified" << endl 878 | << " color table. The table will be padded with extra" << endl 879 | << " white (255,255,255,0) entries." << endl; 880 | } 881 | } 882 | 883 | int n; 884 | for( n=0; n < NumberOfColorsToRead ; n++ ) 885 | { 886 | SafeFread( (char*) &(Colors[n]) , 4 , 1 , fp); 887 | } 888 | for( n=NumberOfColorsToRead ; n < TellNumberOfColors() ; n++ ) 889 | { 890 | RGBApixel WHITE; 891 | WHITE.Red = 255; 892 | WHITE.Green = 255; 893 | WHITE.Blue = 255; 894 | WHITE.Alpha = 0; 895 | SetColor( n , WHITE ); 896 | } 897 | 898 | 899 | } 900 | 901 | // skip blank data if bfOffBits so indicates 902 | 903 | int BytesToSkip = bmfh.bfOffBits - 54;; 904 | if( BitDepth < 16 ) 905 | { BytesToSkip -= 4*IntPow(2,BitDepth); } 906 | if( BitDepth == 16 && bmih.biCompression == 3 ) 907 | { BytesToSkip -= 3*4; } 908 | if( BytesToSkip < 0 ) 909 | { BytesToSkip = 0; } 910 | if( BytesToSkip > 0 && BitDepth != 16 ) 911 | { 912 | if( EasyBMPwarnings ) 913 | { 914 | cout << "EasyBMP Warning: Extra meta data detected in file " << FileName << endl 915 | << " Data will be skipped." << endl; 916 | } 917 | ebmpBYTE* TempSkipBYTE; 918 | TempSkipBYTE = new ebmpBYTE [BytesToSkip]; 919 | SafeFread( (char*) TempSkipBYTE , BytesToSkip , 1 , fp); 920 | delete [] TempSkipBYTE; 921 | } 922 | 923 | // This code reads 1, 4, 8, 24, and 32-bpp files 924 | // with a more-efficient buffered technique. 925 | 926 | int i,j; 927 | if( BitDepth != 16 ) 928 | { 929 | int BufferSize = (int) ( (Width*BitDepth) / 8.0 ); 930 | while( 8*BufferSize < Width*BitDepth ) 931 | { BufferSize++; } 932 | while( BufferSize % 4 ) 933 | { BufferSize++; } 934 | ebmpBYTE* Buffer; 935 | Buffer = new ebmpBYTE [BufferSize]; 936 | j= Height-1; 937 | while( j > -1 ) 938 | { 939 | int BytesRead = (int) fread( (char*) Buffer, 1, BufferSize, fp ); 940 | if( BytesRead < BufferSize ) 941 | { 942 | j = -1; 943 | if( EasyBMPwarnings ) 944 | { 945 | cout << "EasyBMP Error: Could not read proper amount of data." << endl; 946 | } 947 | } 948 | else 949 | { 950 | bool Success = false; 951 | if( BitDepth == 1 ) 952 | { Success = Read1bitRow( Buffer, BufferSize, j ); } 953 | if( BitDepth == 4 ) 954 | { Success = Read4bitRow( Buffer, BufferSize, j ); } 955 | if( BitDepth == 8 ) 956 | { Success = Read8bitRow( Buffer, BufferSize, j ); } 957 | if( BitDepth == 24 ) 958 | { Success = Read24bitRow( Buffer, BufferSize, j ); } 959 | if( BitDepth == 32 ) 960 | { Success = Read32bitRow( Buffer, BufferSize, j ); } 961 | if( !Success ) 962 | { 963 | if( EasyBMPwarnings ) 964 | { 965 | cout << "EasyBMP Error: Could not read enough pixel data!" << endl; 966 | } 967 | j = -1; 968 | } 969 | } 970 | j--; 971 | } 972 | delete [] Buffer; 973 | } 974 | 975 | if( BitDepth == 16 ) 976 | { 977 | int DataBytes = Width*2; 978 | int PaddingBytes = ( 4 - DataBytes % 4 ) % 4; 979 | 980 | // set the default mask 981 | 982 | ebmpWORD BlueMask = 31; // bits 12-16 983 | ebmpWORD GreenMask = 992; // bits 7-11 984 | ebmpWORD RedMask = 31744; // bits 2-6 985 | 986 | // read the bit fields, if necessary, to 987 | // override the default 5-5-5 mask 988 | 989 | if( bmih.biCompression != 0 ) 990 | { 991 | // read the three bit masks 992 | 993 | ebmpWORD TempMaskWORD; 994 | ebmpWORD ZeroWORD; 995 | 996 | SafeFread( (char*) &RedMask , 2 , 1 , fp ); 997 | if( IsBigEndian() ) 998 | { RedMask = FlipWORD(RedMask); } 999 | SafeFread( (char*) &TempMaskWORD , 2, 1, fp ); 1000 | 1001 | SafeFread( (char*) &GreenMask , 2 , 1 , fp ); 1002 | if( IsBigEndian() ) 1003 | { GreenMask = FlipWORD(GreenMask); } 1004 | SafeFread( (char*) &TempMaskWORD , 2, 1, fp ); 1005 | 1006 | SafeFread( (char*) &BlueMask , 2 , 1 , fp ); 1007 | if( IsBigEndian() ) 1008 | { BlueMask = FlipWORD(BlueMask); } 1009 | SafeFread( (char*) &TempMaskWORD , 2, 1, fp ); 1010 | } 1011 | 1012 | // read and skip any meta data 1013 | 1014 | if( BytesToSkip > 0 ) 1015 | { 1016 | if( EasyBMPwarnings ) 1017 | { 1018 | cout << "EasyBMP Warning: Extra meta data detected in file " 1019 | << FileName << endl 1020 | << " Data will be skipped." << endl; 1021 | } 1022 | ebmpBYTE* TempSkipBYTE; 1023 | TempSkipBYTE = new ebmpBYTE [BytesToSkip]; 1024 | SafeFread( (char*) TempSkipBYTE , BytesToSkip , 1 , fp); 1025 | delete [] TempSkipBYTE; 1026 | } 1027 | 1028 | // determine the red, green and blue shifts 1029 | 1030 | int GreenShift = 0; 1031 | ebmpWORD TempShiftWORD = GreenMask; 1032 | while( TempShiftWORD > 31 ) 1033 | { TempShiftWORD = TempShiftWORD>>1; GreenShift++; } 1034 | int BlueShift = 0; 1035 | TempShiftWORD = BlueMask; 1036 | while( TempShiftWORD > 31 ) 1037 | { TempShiftWORD = TempShiftWORD>>1; BlueShift++; } 1038 | int RedShift = 0; 1039 | TempShiftWORD = RedMask; 1040 | while( TempShiftWORD > 31 ) 1041 | { TempShiftWORD = TempShiftWORD>>1; RedShift++; } 1042 | 1043 | // read the actual pixels 1044 | 1045 | for( j=Height-1 ; j >= 0 ; j-- ) 1046 | { 1047 | i=0; 1048 | int ReadNumber = 0; 1049 | while( ReadNumber < DataBytes ) 1050 | { 1051 | ebmpWORD TempWORD; 1052 | SafeFread( (char*) &TempWORD , 2 , 1 , fp ); 1053 | if( IsBigEndian() ) 1054 | { TempWORD = FlipWORD(TempWORD); } 1055 | ReadNumber += 2; 1056 | 1057 | ebmpWORD Red = RedMask & TempWORD; 1058 | ebmpWORD Green = GreenMask & TempWORD; 1059 | ebmpWORD Blue = BlueMask & TempWORD; 1060 | 1061 | ebmpBYTE BlueBYTE = (ebmpBYTE) 8*(Blue>>BlueShift); 1062 | ebmpBYTE GreenBYTE = (ebmpBYTE) 8*(Green>>GreenShift); 1063 | ebmpBYTE RedBYTE = (ebmpBYTE) 8*(Red>>RedShift); 1064 | 1065 | (Pixels[i][j]).Red = RedBYTE; 1066 | (Pixels[i][j]).Green = GreenBYTE; 1067 | (Pixels[i][j]).Blue = BlueBYTE; 1068 | 1069 | i++; 1070 | } 1071 | ReadNumber = 0; 1072 | while( ReadNumber < PaddingBytes ) 1073 | { 1074 | ebmpBYTE TempBYTE; 1075 | SafeFread( (char*) &TempBYTE , 1, 1, fp); 1076 | ReadNumber++; 1077 | } 1078 | } 1079 | 1080 | } 1081 | 1082 | fclose(fp); 1083 | return true; 1084 | } 1085 | 1086 | bool BMP::CreateStandardColorTable( void ) 1087 | { 1088 | using namespace std; 1089 | if( BitDepth != 1 && BitDepth != 4 && BitDepth != 8 ) 1090 | { 1091 | if( EasyBMPwarnings ) 1092 | { 1093 | cout << "EasyBMP Warning: Attempted to create color table at a bit" << endl 1094 | << " depth that does not require a color table." << endl 1095 | << " Ignoring request." << endl; 1096 | } 1097 | return false; 1098 | } 1099 | 1100 | if( BitDepth == 1 ) 1101 | { 1102 | int i; 1103 | for( i=0 ; i < 2 ; i++ ) 1104 | { 1105 | Colors[i].Red = i*255; 1106 | Colors[i].Green = i*255; 1107 | Colors[i].Blue = i*255; 1108 | Colors[i].Alpha = 0; 1109 | } 1110 | return true; 1111 | } 1112 | 1113 | if( BitDepth == 4 ) 1114 | { 1115 | int i = 0; 1116 | int j,k,ell; 1117 | 1118 | // simplify the code for the first 8 colors 1119 | for( ell=0 ; ell < 2 ; ell++ ) 1120 | { 1121 | for( k=0 ; k < 2 ; k++ ) 1122 | { 1123 | for( j=0 ; j < 2 ; j++ ) 1124 | { 1125 | Colors[i].Red = j*128; 1126 | Colors[i].Green = k*128; 1127 | Colors[i].Blue = ell*128; 1128 | i++; 1129 | } 1130 | } 1131 | } 1132 | 1133 | // simplify the code for the last 8 colors 1134 | for( ell=0 ; ell < 2 ; ell++ ) 1135 | { 1136 | for( k=0 ; k < 2 ; k++ ) 1137 | { 1138 | for( j=0 ; j < 2 ; j++ ) 1139 | { 1140 | Colors[i].Red = j*255; 1141 | Colors[i].Green = k*255; 1142 | Colors[i].Blue = ell*255; 1143 | i++; 1144 | } 1145 | } 1146 | } 1147 | 1148 | // overwrite the duplicate color 1149 | i=8; 1150 | Colors[i].Red = 192; 1151 | Colors[i].Green = 192; 1152 | Colors[i].Blue = 192; 1153 | 1154 | for( i=0 ; i < 16 ; i++ ) 1155 | { Colors[i].Alpha = 0; } 1156 | return true; 1157 | } 1158 | 1159 | if( BitDepth == 8 ) 1160 | { 1161 | int i=0; 1162 | int j,k,ell; 1163 | 1164 | // do an easy loop, which works for all but colors 1165 | // 0 to 9 and 246 to 255 1166 | for( ell=0 ; ell < 4 ; ell++ ) 1167 | { 1168 | for( k=0 ; k < 8 ; k++ ) 1169 | { 1170 | for( j=0; j < 8 ; j++ ) 1171 | { 1172 | Colors[i].Red = j*32; 1173 | Colors[i].Green = k*32; 1174 | Colors[i].Blue = ell*64; 1175 | Colors[i].Alpha = 0; 1176 | i++; 1177 | } 1178 | } 1179 | } 1180 | 1181 | // now redo the first 8 colors 1182 | i=0; 1183 | for( ell=0 ; ell < 2 ; ell++ ) 1184 | { 1185 | for( k=0 ; k < 2 ; k++ ) 1186 | { 1187 | for( j=0; j < 2 ; j++ ) 1188 | { 1189 | Colors[i].Red = j*128; 1190 | Colors[i].Green = k*128; 1191 | Colors[i].Blue = ell*128; 1192 | i++; 1193 | } 1194 | } 1195 | } 1196 | 1197 | // overwrite colors 7, 8, 9 1198 | i=7; 1199 | Colors[i].Red = 192; 1200 | Colors[i].Green = 192; 1201 | Colors[i].Blue = 192; 1202 | i++; // 8 1203 | Colors[i].Red = 192; 1204 | Colors[i].Green = 220; 1205 | Colors[i].Blue = 192; 1206 | i++; // 9 1207 | Colors[i].Red = 166; 1208 | Colors[i].Green = 202; 1209 | Colors[i].Blue = 240; 1210 | 1211 | // overwrite colors 246 to 255 1212 | i=246; 1213 | Colors[i].Red = 255; 1214 | Colors[i].Green = 251; 1215 | Colors[i].Blue = 240; 1216 | i++; // 247 1217 | Colors[i].Red = 160; 1218 | Colors[i].Green = 160; 1219 | Colors[i].Blue = 164; 1220 | i++; // 248 1221 | Colors[i].Red = 128; 1222 | Colors[i].Green = 128; 1223 | Colors[i].Blue = 128; 1224 | i++; // 249 1225 | Colors[i].Red = 255; 1226 | Colors[i].Green = 0; 1227 | Colors[i].Blue = 0; 1228 | i++; // 250 1229 | Colors[i].Red = 0; 1230 | Colors[i].Green = 255; 1231 | Colors[i].Blue = 0; 1232 | i++; // 251 1233 | Colors[i].Red = 255; 1234 | Colors[i].Green = 255; 1235 | Colors[i].Blue = 0; 1236 | i++; // 252 1237 | Colors[i].Red = 0; 1238 | Colors[i].Green = 0; 1239 | Colors[i].Blue = 255; 1240 | i++; // 253 1241 | Colors[i].Red = 255; 1242 | Colors[i].Green = 0; 1243 | Colors[i].Blue = 255; 1244 | i++; // 254 1245 | Colors[i].Red = 0; 1246 | Colors[i].Green = 255; 1247 | Colors[i].Blue = 255; 1248 | i++; // 255 1249 | Colors[i].Red = 255; 1250 | Colors[i].Green = 255; 1251 | Colors[i].Blue = 255; 1252 | 1253 | return true; 1254 | } 1255 | return true; 1256 | } 1257 | 1258 | bool SafeFread( char* buffer, int size, int number, FILE* fp ) 1259 | { 1260 | using namespace std; 1261 | int ItemsRead; 1262 | if( feof(fp) ) 1263 | { return false; } 1264 | ItemsRead = (int) fread( buffer , size , number , fp ); 1265 | if( ItemsRead < number ) 1266 | { return false; } 1267 | return true; 1268 | } 1269 | 1270 | void BMP::SetDPI( int HorizontalDPI, int VerticalDPI ) 1271 | { 1272 | XPelsPerMeter = (int) ( HorizontalDPI * 39.37007874015748 ); 1273 | YPelsPerMeter = (int) ( VerticalDPI * 39.37007874015748 ); 1274 | } 1275 | 1276 | // int BMP::TellVerticalDPI( void ) const 1277 | int BMP::TellVerticalDPI( void ) 1278 | { 1279 | if( !YPelsPerMeter ) 1280 | { YPelsPerMeter = DefaultYPelsPerMeter; } 1281 | return (int) ( YPelsPerMeter / (double) 39.37007874015748 ); 1282 | } 1283 | 1284 | // int BMP::TellHorizontalDPI( void ) const 1285 | int BMP::TellHorizontalDPI( void ) 1286 | { 1287 | if( !XPelsPerMeter ) 1288 | { XPelsPerMeter = DefaultXPelsPerMeter; } 1289 | return (int) ( XPelsPerMeter / (double) 39.37007874015748 ); 1290 | } 1291 | 1292 | /* These functions are defined in EasyBMP_VariousBMPutilities.h */ 1293 | 1294 | BMFH GetBMFH( const char* szFileNameIn ) 1295 | { 1296 | using namespace std; 1297 | BMFH bmfh; 1298 | 1299 | FILE* fp; 1300 | fp = fopen( szFileNameIn,"rb"); 1301 | 1302 | if( !fp ) 1303 | { 1304 | if( EasyBMPwarnings ) 1305 | { 1306 | cout << "EasyBMP Error: Cannot initialize from file " 1307 | << szFileNameIn << "." << endl 1308 | << " File cannot be opened or does not exist." 1309 | << endl; 1310 | } 1311 | bmfh.bfType = 0; 1312 | return bmfh; 1313 | } 1314 | 1315 | SafeFread( (char*) &(bmfh.bfType) , sizeof(ebmpWORD) , 1 , fp ); 1316 | SafeFread( (char*) &(bmfh.bfSize) , sizeof(ebmpDWORD) , 1 , fp ); 1317 | SafeFread( (char*) &(bmfh.bfReserved1) , sizeof(ebmpWORD) , 1 , fp ); 1318 | SafeFread( (char*) &(bmfh.bfReserved2) , sizeof(ebmpWORD) , 1 , fp ); 1319 | SafeFread( (char*) &(bmfh.bfOffBits) , sizeof(ebmpDWORD) , 1 , fp ); 1320 | 1321 | fclose( fp ); 1322 | 1323 | if( IsBigEndian() ) 1324 | { bmfh.SwitchEndianess(); } 1325 | 1326 | return bmfh; 1327 | } 1328 | 1329 | BMIH GetBMIH( const char* szFileNameIn ) 1330 | { 1331 | using namespace std; 1332 | BMFH bmfh; 1333 | BMIH bmih; 1334 | 1335 | FILE* fp; 1336 | fp = fopen( szFileNameIn,"rb"); 1337 | 1338 | if( !fp ) 1339 | { 1340 | if( EasyBMPwarnings ) 1341 | { 1342 | cout << "EasyBMP Error: Cannot initialize from file " 1343 | << szFileNameIn << "." << endl 1344 | << " File cannot be opened or does not exist." 1345 | << endl; 1346 | } 1347 | return bmih; 1348 | } 1349 | 1350 | // read the bmfh, i.e., first 14 bytes (just to get it out of the way); 1351 | 1352 | ebmpBYTE TempBYTE; 1353 | int i; 1354 | for( i = 14 ; i > 0 ; i-- ) 1355 | { SafeFread( (char*) &TempBYTE , sizeof(ebmpBYTE) , 1, fp ); } 1356 | 1357 | // read the bmih 1358 | 1359 | SafeFread( (char*) &(bmih.biSize) , sizeof(ebmpDWORD) , 1 , fp ); 1360 | SafeFread( (char*) &(bmih.biWidth) , sizeof(ebmpDWORD) , 1 , fp ); 1361 | SafeFread( (char*) &(bmih.biHeight) , sizeof(ebmpDWORD) , 1 , fp ); 1362 | SafeFread( (char*) &(bmih.biPlanes) , sizeof(ebmpWORD) , 1 , fp ); 1363 | 1364 | SafeFread( (char*) &(bmih.biBitCount) , sizeof(ebmpWORD) , 1 , fp ); 1365 | SafeFread( (char*) &(bmih.biCompression) , sizeof(ebmpDWORD) , 1 , fp ); 1366 | SafeFread( (char*) &(bmih.biSizeImage) , sizeof(ebmpDWORD) , 1 , fp ); 1367 | SafeFread( (char*) &(bmih.biXPelsPerMeter) , sizeof(ebmpDWORD) , 1 , fp ); 1368 | 1369 | SafeFread( (char*) &(bmih.biYPelsPerMeter) , sizeof(ebmpDWORD) , 1 , fp ); 1370 | SafeFread( (char*) &(bmih.biClrUsed) , sizeof(ebmpDWORD) , 1 , fp ); 1371 | SafeFread( (char*) &(bmih.biClrImportant) , sizeof(ebmpDWORD) , 1 , fp ); 1372 | 1373 | fclose( fp ); 1374 | 1375 | if( IsBigEndian() ) 1376 | { bmih.SwitchEndianess(); } 1377 | 1378 | return bmih; 1379 | } 1380 | 1381 | void DisplayBitmapInfo( const char* szFileNameIn ) 1382 | { 1383 | using namespace std; 1384 | FILE* fp; 1385 | fp = fopen( szFileNameIn,"rb"); 1386 | 1387 | if( !fp ) 1388 | { 1389 | if( EasyBMPwarnings ) 1390 | { 1391 | cout << "EasyBMP Error: Cannot initialize from file " 1392 | << szFileNameIn << "." << endl 1393 | << " File cannot be opened or does not exist." 1394 | << endl; 1395 | } 1396 | return; 1397 | } 1398 | fclose( fp ); 1399 | 1400 | // don't duplicate work! Just use the functions from above! 1401 | 1402 | BMFH bmfh = GetBMFH(szFileNameIn); 1403 | BMIH bmih = GetBMIH(szFileNameIn); 1404 | 1405 | cout << "File information for file " << szFileNameIn 1406 | << ":" << endl << endl; 1407 | 1408 | cout << "BITMAPFILEHEADER:" << endl 1409 | << "bfType: " << bmfh.bfType << endl 1410 | << "bfSize: " << bmfh.bfSize << endl 1411 | << "bfReserved1: " << bmfh.bfReserved1 << endl 1412 | << "bfReserved2: " << bmfh.bfReserved2 << endl 1413 | << "bfOffBits: " << bmfh.bfOffBits << endl << endl; 1414 | 1415 | cout << "BITMAPINFOHEADER:" << endl 1416 | << "biSize: " << bmih.biSize << endl 1417 | << "biWidth: " << bmih.biWidth << endl 1418 | << "biHeight: " << bmih.biHeight << endl 1419 | << "biPlanes: " << bmih.biPlanes << endl 1420 | << "biBitCount: " << bmih.biBitCount << endl 1421 | << "biCompression: " << bmih.biCompression << endl 1422 | << "biSizeImage: " << bmih.biSizeImage << endl 1423 | << "biXPelsPerMeter: " << bmih.biXPelsPerMeter << endl 1424 | << "biYPelsPerMeter: " << bmih.biYPelsPerMeter << endl 1425 | << "biClrUsed: " << bmih.biClrUsed << endl 1426 | << "biClrImportant: " << bmih.biClrImportant << endl << endl; 1427 | return; 1428 | } 1429 | 1430 | int GetBitmapColorDepth( const char* szFileNameIn ) 1431 | { 1432 | BMIH bmih = GetBMIH( szFileNameIn ); 1433 | return (int) bmih.biBitCount; 1434 | } 1435 | 1436 | void PixelToPixelCopy( BMP& From, int FromX, int FromY, 1437 | BMP& To, int ToX, int ToY) 1438 | { 1439 | *To(ToX,ToY) = *From(FromX,FromY); 1440 | return; 1441 | } 1442 | 1443 | void PixelToPixelCopyTransparent( BMP& From, int FromX, int FromY, 1444 | BMP& To, int ToX, int ToY, 1445 | RGBApixel& Transparent ) 1446 | { 1447 | if( From(FromX,FromY)->Red != Transparent.Red || 1448 | From(FromX,FromY)->Green != Transparent.Green || 1449 | From(FromX,FromY)->Blue != Transparent.Blue ) 1450 | { *To(ToX,ToY) = *From(FromX,FromY); } 1451 | return; 1452 | } 1453 | 1454 | void RangedPixelToPixelCopy( BMP& From, int FromL , int FromR, int FromB, int FromT, 1455 | BMP& To, int ToX, int ToY ) 1456 | { 1457 | // make sure the conventions are followed 1458 | if( FromB < FromT ) 1459 | { int Temp = FromT; FromT = FromB; FromB = Temp; } 1460 | 1461 | // make sure that the copied regions exist in both bitmaps 1462 | if( FromR >= From.TellWidth() ) 1463 | { FromR = From.TellWidth()-1; } 1464 | if( FromL < 0 ){ FromL = 0; } 1465 | 1466 | if( FromB >= From.TellHeight() ) 1467 | { FromB = From.TellHeight()-1; } 1468 | if( FromT < 0 ){ FromT = 0; } 1469 | 1470 | if( ToX+(FromR-FromL) >= To.TellWidth() ) 1471 | { FromR = To.TellWidth()-1+FromL-ToX; } 1472 | if( ToY+(FromB-FromT) >= To.TellHeight() ) 1473 | { FromB = To.TellHeight()-1+FromT-ToY; } 1474 | 1475 | int i,j; 1476 | for( j=FromT ; j <= FromB ; j++ ) 1477 | { 1478 | for( i=FromL ; i <= FromR ; i++ ) 1479 | { 1480 | PixelToPixelCopy( From, i,j, 1481 | To, ToX+(i-FromL), ToY+(j-FromT) ); 1482 | } 1483 | } 1484 | 1485 | return; 1486 | } 1487 | 1488 | void RangedPixelToPixelCopyTransparent( 1489 | BMP& From, int FromL , int FromR, int FromB, int FromT, 1490 | BMP& To, int ToX, int ToY , 1491 | RGBApixel& Transparent ) 1492 | { 1493 | // make sure the conventions are followed 1494 | if( FromB < FromT ) 1495 | { int Temp = FromT; FromT = FromB; FromB = Temp; } 1496 | 1497 | // make sure that the copied regions exist in both bitmaps 1498 | if( FromR >= From.TellWidth() ) 1499 | { FromR = From.TellWidth()-1; } 1500 | if( FromL < 0 ){ FromL = 0; } 1501 | 1502 | if( FromB >= From.TellHeight() ) 1503 | { FromB = From.TellHeight()-1; } 1504 | if( FromT < 0 ){ FromT = 0; } 1505 | 1506 | if( ToX+(FromR-FromL) >= To.TellWidth() ) 1507 | { FromR = To.TellWidth()-1+FromL-ToX; } 1508 | if( ToY+(FromB-FromT) >= To.TellHeight() ) 1509 | { FromB = To.TellHeight()-1+FromT-ToY; } 1510 | 1511 | int i,j; 1512 | for( j=FromT ; j <= FromB ; j++ ) 1513 | { 1514 | for( i=FromL ; i <= FromR ; i++ ) 1515 | { 1516 | PixelToPixelCopyTransparent( From, i,j, 1517 | To, ToX+(i-FromL), ToY+(j-FromT) , 1518 | Transparent); 1519 | } 1520 | } 1521 | 1522 | return; 1523 | } 1524 | 1525 | bool CreateGrayscaleColorTable( BMP& InputImage ) 1526 | { 1527 | using namespace std; 1528 | int BitDepth = InputImage.TellBitDepth(); 1529 | if( BitDepth != 1 && BitDepth != 4 && BitDepth != 8 ) 1530 | { 1531 | if( EasyBMPwarnings ) 1532 | { 1533 | cout << "EasyBMP Warning: Attempted to create color table at a bit" << endl 1534 | << " depth that does not require a color table." << endl 1535 | << " Ignoring request." << endl; 1536 | } 1537 | return false; 1538 | } 1539 | int i; 1540 | int NumberOfColors = InputImage.TellNumberOfColors(); 1541 | 1542 | ebmpBYTE StepSize; 1543 | if( BitDepth != 1 ) 1544 | { StepSize = 255/(NumberOfColors-1); } 1545 | else 1546 | { StepSize = 255; } 1547 | 1548 | for( i=0 ; i < NumberOfColors ; i++ ) 1549 | { 1550 | ebmpBYTE TempBYTE = i*StepSize; 1551 | RGBApixel TempColor; 1552 | TempColor.Red = TempBYTE; 1553 | TempColor.Green = TempBYTE; 1554 | TempColor.Blue = TempBYTE; 1555 | TempColor.Alpha = 0; 1556 | InputImage.SetColor( i , TempColor ); 1557 | } 1558 | return true; 1559 | } 1560 | 1561 | bool BMP::Read32bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ) 1562 | { 1563 | int i; 1564 | if( Width*4 > BufferSize ) 1565 | { return false; } 1566 | for( i=0 ; i < Width ; i++ ) 1567 | { memcpy( (char*) &(Pixels[i][Row]), (char*) Buffer+4*i, 4 ); } 1568 | return true; 1569 | } 1570 | 1571 | bool BMP::Read24bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ) 1572 | { 1573 | int i; 1574 | if( Width*3 > BufferSize ) 1575 | { return false; } 1576 | for( i=0 ; i < Width ; i++ ) 1577 | { memcpy( (char*) &(Pixels[i][Row]), Buffer+3*i, 3 ); } 1578 | return true; 1579 | } 1580 | 1581 | bool BMP::Read8bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ) 1582 | { 1583 | int i; 1584 | if( Width > BufferSize ) 1585 | { return false; } 1586 | for( i=0 ; i < Width ; i++ ) 1587 | { 1588 | int Index = Buffer[i]; 1589 | *( this->operator()(i,Row) )= GetColor(Index); 1590 | } 1591 | return true; 1592 | } 1593 | 1594 | bool BMP::Read4bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ) 1595 | { 1596 | int Shifts[2] = {4 ,0 }; 1597 | int Masks[2] = {240,15}; 1598 | 1599 | int i=0; 1600 | int j; 1601 | int k=0; 1602 | if( Width > 2*BufferSize ) 1603 | { return false; } 1604 | while( i < Width ) 1605 | { 1606 | j=0; 1607 | while( j < 2 && i < Width ) 1608 | { 1609 | int Index = (int) ( (Buffer[k]&Masks[j]) >> Shifts[j]); 1610 | *( this->operator()(i,Row) )= GetColor(Index); 1611 | i++; j++; 1612 | } 1613 | k++; 1614 | } 1615 | return true; 1616 | } 1617 | bool BMP::Read1bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ) 1618 | { 1619 | int Shifts[8] = {7 ,6 ,5 ,4 ,3,2,1,0}; 1620 | int Masks[8] = {128,64,32,16,8,4,2,1}; 1621 | 1622 | int i=0; 1623 | int j; 1624 | int k=0; 1625 | 1626 | if( Width > 8*BufferSize ) 1627 | { return false; } 1628 | while( i < Width ) 1629 | { 1630 | j=0; 1631 | while( j < 8 && i < Width ) 1632 | { 1633 | int Index = (int) ( (Buffer[k]&Masks[j]) >> Shifts[j]); 1634 | *( this->operator()(i,Row) )= GetColor(Index); 1635 | i++; j++; 1636 | } 1637 | k++; 1638 | } 1639 | return true; 1640 | } 1641 | 1642 | bool BMP::Write32bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ) 1643 | { 1644 | int i; 1645 | if( Width*4 > BufferSize ) 1646 | { return false; } 1647 | for( i=0 ; i < Width ; i++ ) 1648 | { memcpy( (char*) Buffer+4*i, (char*) &(Pixels[i][Row]), 4 ); } 1649 | return true; 1650 | } 1651 | 1652 | bool BMP::Write24bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ) 1653 | { 1654 | int i; 1655 | if( Width*3 > BufferSize ) 1656 | { return false; } 1657 | for( i=0 ; i < Width ; i++ ) 1658 | { memcpy( (char*) Buffer+3*i, (char*) &(Pixels[i][Row]), 3 ); } 1659 | return true; 1660 | } 1661 | 1662 | bool BMP::Write8bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ) 1663 | { 1664 | int i; 1665 | if( Width > BufferSize ) 1666 | { return false; } 1667 | for( i=0 ; i < Width ; i++ ) 1668 | { Buffer[i] = FindClosestColor( Pixels[i][Row] ); } 1669 | return true; 1670 | } 1671 | 1672 | bool BMP::Write4bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ) 1673 | { 1674 | int PositionWeights[2] = {16,1}; 1675 | 1676 | int i=0; 1677 | int j; 1678 | int k=0; 1679 | if( Width > 2*BufferSize ) 1680 | { return false; } 1681 | while( i < Width ) 1682 | { 1683 | j=0; 1684 | int Index = 0; 1685 | while( j < 2 && i < Width ) 1686 | { 1687 | Index += ( PositionWeights[j]* (int) FindClosestColor( Pixels[i][Row] ) ); 1688 | i++; j++; 1689 | } 1690 | Buffer[k] = (ebmpBYTE) Index; 1691 | k++; 1692 | } 1693 | return true; 1694 | } 1695 | 1696 | bool BMP::Write1bitRow( ebmpBYTE* Buffer, int BufferSize, int Row ) 1697 | { 1698 | int PositionWeights[8] = {128,64,32,16,8,4,2,1}; 1699 | 1700 | int i=0; 1701 | int j; 1702 | int k=0; 1703 | if( Width > 8*BufferSize ) 1704 | { return false; } 1705 | while( i < Width ) 1706 | { 1707 | j=0; 1708 | int Index = 0; 1709 | while( j < 8 && i < Width ) 1710 | { 1711 | Index += ( PositionWeights[j]* (int) FindClosestColor( Pixels[i][Row] ) ); 1712 | i++; j++; 1713 | } 1714 | Buffer[k] = (ebmpBYTE) Index; 1715 | k++; 1716 | } 1717 | return true; 1718 | } 1719 | 1720 | ebmpBYTE BMP::FindClosestColor( RGBApixel& input ) 1721 | { 1722 | using namespace std; 1723 | 1724 | int i=0; 1725 | int NumberOfColors = TellNumberOfColors(); 1726 | ebmpBYTE BestI = 0; 1727 | int BestMatch = 999999; 1728 | 1729 | while( i < NumberOfColors ) 1730 | { 1731 | RGBApixel Attempt = GetColor( i ); 1732 | int TempMatch = IntSquare( (int) Attempt.Red - (int) input.Red ) 1733 | + IntSquare( (int) Attempt.Green - (int) input.Green ) 1734 | + IntSquare( (int) Attempt.Blue - (int) input.Blue ); 1735 | if( TempMatch < BestMatch ) 1736 | { BestI = (ebmpBYTE) i; BestMatch = TempMatch; } 1737 | if( BestMatch < 1 ) 1738 | { i = NumberOfColors; } 1739 | i++; 1740 | } 1741 | return BestI; 1742 | } 1743 | 1744 | bool EasyBMPcheckDataSize( void ) 1745 | { 1746 | using namespace std; 1747 | bool ReturnValue = true; 1748 | if( sizeof( ebmpBYTE ) != 1 ) 1749 | { 1750 | if( EasyBMPwarnings ) 1751 | { 1752 | cout << "EasyBMP Error: ebmpBYTE has the wrong size (" 1753 | << sizeof( ebmpBYTE ) << " bytes)," << endl 1754 | << " Compared to the expected 1 byte value" << endl; 1755 | } 1756 | ReturnValue = false; 1757 | } 1758 | if( sizeof( ebmpWORD ) != 2 ) 1759 | { 1760 | if( EasyBMPwarnings ) 1761 | { 1762 | cout << "EasyBMP Error: ebmpWORD has the wrong size (" 1763 | << sizeof( ebmpWORD ) << " bytes)," << endl 1764 | << " Compared to the expected 2 byte value" << endl; 1765 | } 1766 | ReturnValue = false; 1767 | } 1768 | if( sizeof( ebmpDWORD ) != 4 ) 1769 | { 1770 | if( EasyBMPwarnings ) 1771 | { 1772 | cout << "EasyBMP Error: ebmpDWORD has the wrong size (" 1773 | << sizeof( ebmpDWORD ) << " bytes)," << endl 1774 | << " Compared to the expected 4 byte value" << endl; 1775 | } 1776 | ReturnValue = false; 1777 | } 1778 | return ReturnValue; 1779 | } 1780 | 1781 | bool Rescale( BMP& InputImage , char mode, int NewDimension ) 1782 | { 1783 | using namespace std; 1784 | int CapMode = toupper( mode ); 1785 | 1786 | BMP OldImage( InputImage ); 1787 | 1788 | if( CapMode != 'P' && 1789 | CapMode != 'W' && 1790 | CapMode != 'H' && 1791 | CapMode != 'F' ) 1792 | { 1793 | if( EasyBMPwarnings ) 1794 | { 1795 | char ErrorMessage [1024]; 1796 | sprintf( ErrorMessage, "EasyBMP Error: Unknown rescale mode %c requested\n" , mode ); 1797 | cout << ErrorMessage; 1798 | } 1799 | return false; 1800 | } 1801 | 1802 | int NewWidth =0; 1803 | int NewHeight =0; 1804 | 1805 | int OldWidth = OldImage.TellWidth(); 1806 | int OldHeight= OldImage.TellHeight(); 1807 | 1808 | if( CapMode == 'P' ) 1809 | { 1810 | NewWidth = (int) floor( OldWidth * NewDimension / 100.0 ); 1811 | NewHeight = (int) floor( OldHeight * NewDimension / 100.0 ); 1812 | } 1813 | if( CapMode == 'F' ) 1814 | { 1815 | if( OldWidth > OldHeight ) 1816 | { CapMode = 'W'; } 1817 | else 1818 | { CapMode = 'H'; } 1819 | } 1820 | 1821 | if( CapMode == 'W' ) 1822 | { 1823 | double percent = (double) NewDimension / (double) OldWidth; 1824 | NewWidth = NewDimension; 1825 | NewHeight = (int) floor( OldHeight * percent ); 1826 | } 1827 | if( CapMode == 'H' ) 1828 | { 1829 | double percent = (double) NewDimension / (double) OldHeight; 1830 | NewHeight = NewDimension; 1831 | NewWidth = (int) floor( OldWidth * percent ); 1832 | } 1833 | 1834 | if( NewWidth < 1 ) 1835 | { NewWidth = 1; } 1836 | if( NewHeight < 1 ) 1837 | { NewHeight = 1; } 1838 | 1839 | InputImage.SetSize( NewWidth, NewHeight ); 1840 | InputImage.SetBitDepth( 24 ); 1841 | 1842 | int I,J; 1843 | double ThetaI,ThetaJ; 1844 | 1845 | for( int j=0; j < NewHeight-1 ; j++ ) 1846 | { 1847 | ThetaJ = (double)(j*(OldHeight-1.0)) 1848 | /(double)(NewHeight-1.0); 1849 | J = (int) floor( ThetaJ ); 1850 | ThetaJ -= J; 1851 | 1852 | for( int i=0; i < NewWidth-1 ; i++ ) 1853 | { 1854 | ThetaI = (double)(i*(OldWidth-1.0)) 1855 | /(double)(NewWidth-1.0); 1856 | I = (int) floor( ThetaI ); 1857 | ThetaI -= I; 1858 | 1859 | InputImage(i,j)->Red = (ebmpBYTE) 1860 | ( (1.0-ThetaI-ThetaJ+ThetaI*ThetaJ)*(OldImage(I,J)->Red) 1861 | +(ThetaI-ThetaI*ThetaJ)*(OldImage(I+1,J)->Red) 1862 | +(ThetaJ-ThetaI*ThetaJ)*(OldImage(I,J+1)->Red) 1863 | +(ThetaI*ThetaJ)*(OldImage(I+1,J+1)->Red) ); 1864 | InputImage(i,j)->Green = (ebmpBYTE) 1865 | ( (1.0-ThetaI-ThetaJ+ThetaI*ThetaJ)*OldImage(I,J)->Green 1866 | +(ThetaI-ThetaI*ThetaJ)*OldImage(I+1,J)->Green 1867 | +(ThetaJ-ThetaI*ThetaJ)*OldImage(I,J+1)->Green 1868 | +(ThetaI*ThetaJ)*OldImage(I+1,J+1)->Green ); 1869 | InputImage(i,j)->Blue = (ebmpBYTE) 1870 | ( (1.0-ThetaI-ThetaJ+ThetaI*ThetaJ)*OldImage(I,J)->Blue 1871 | +(ThetaI-ThetaI*ThetaJ)*OldImage(I+1,J)->Blue 1872 | +(ThetaJ-ThetaI*ThetaJ)*OldImage(I,J+1)->Blue 1873 | +(ThetaI*ThetaJ)*OldImage(I+1,J+1)->Blue ); 1874 | } 1875 | InputImage(NewWidth-1,j)->Red = (ebmpBYTE) 1876 | ( (1.0-ThetaJ)*(OldImage(OldWidth-1,J)->Red) 1877 | + ThetaJ*(OldImage(OldWidth-1,J+1)->Red) ); 1878 | InputImage(NewWidth-1,j)->Green = (ebmpBYTE) 1879 | ( (1.0-ThetaJ)*(OldImage(OldWidth-1,J)->Green) 1880 | + ThetaJ*(OldImage(OldWidth-1,J+1)->Green) ); 1881 | InputImage(NewWidth-1,j)->Blue = (ebmpBYTE) 1882 | ( (1.0-ThetaJ)*(OldImage(OldWidth-1,J)->Blue) 1883 | + ThetaJ*(OldImage(OldWidth-1,J+1)->Blue) ); 1884 | } 1885 | 1886 | for( int i=0 ; i < NewWidth-1 ; i++ ) 1887 | { 1888 | ThetaI = (double)(i*(OldWidth-1.0)) 1889 | /(double)(NewWidth-1.0); 1890 | I = (int) floor( ThetaI ); 1891 | ThetaI -= I; 1892 | InputImage(i,NewHeight-1)->Red = (ebmpBYTE) 1893 | ( (1.0-ThetaI)*(OldImage(I,OldHeight-1)->Red) 1894 | + ThetaI*(OldImage(I,OldHeight-1)->Red) ); 1895 | InputImage(i,NewHeight-1)->Green = (ebmpBYTE) 1896 | ( (1.0-ThetaI)*(OldImage(I,OldHeight-1)->Green) 1897 | + ThetaI*(OldImage(I,OldHeight-1)->Green) ); 1898 | InputImage(i,NewHeight-1)->Blue = (ebmpBYTE) 1899 | ( (1.0-ThetaI)*(OldImage(I,OldHeight-1)->Blue) 1900 | + ThetaI*(OldImage(I,OldHeight-1)->Blue) ); 1901 | } 1902 | 1903 | *InputImage(NewWidth-1,NewHeight-1) = *OldImage(OldWidth-1,OldHeight-1); 1904 | return true; 1905 | } 1906 | --------------------------------------------------------------------------------