学习资料主要来源是CSDN论坛,维基百科,和Microsoft官方文档。
BMP,BitMap图,是微软提出的用来存储位图的标准格式,它现在不仅仅只适用于Windows系统,还已经拓展到了其他平台,于是 BMP 也有了别名 DIB Device-independent BitMap 设备独立的位图。
首先BMP格式使用的是小端模式记录数据块。比如有一个数据块是0x123456 其中数学上,最高位的一个字节直接为12,中间位的一个字节为34,最低位的一个字节为56。用低地址去记录低位,是谓“小端模式”。于是BMP格式中,实际存储的是0x563412。(计算机按字节存储!)
BMP图片主要由文件头,信息头,调色板和像素组四部分构成。
文件头是交代图片的文件属性信息的。通常,在BMP图片装载入内存后,此部分将被抛弃。
信息头是交代图片的图像属性信息的,诸如图片每像素所使用的位数、图片宽度、高度、压缩方式等等。历史上,这个头有着各种各样的标准,常见的形式是windows NT版本时提出来的。虽年代久远,但仍被广泛使用,以致于现在大多数BMP图片依然是这个的组成结构。不同的BMP格式标准的区别主要在于信息头的大小,这可以通过信息头的第一个参数,长为四个字节的DIB Header Size 区分。本文及程序只考虑DIB Header Size = 40 , 这即是这种最常见的情况。
调色板一般只有在颜色位数小于等于8时,才存在。它交代该位图所使用的颜色索引。颜色索引即是一种从颜色到序号的映射,存在的目的是节省空间开销(这主要是当前情况下,一般显示器所能显示的RGB颜色内,每个通道被限制为8位,取值为0~255)
像素组是记录每个像素点具体的颜色或颜色索引。在颜色位数小于等于8时,像素组用相应位数记录颜色索引。比如1位图中,一个字节描述了8个像素的信息。颜色位数为16时,有RGB555和RGB565两种情况,BMP图片不压缩时(信息头的参数Compress = 0),使用的就是RGB555模式。即R、G、B三个通道分别用五位,最高位悬空置零。颜色位数为24位时,R、G、B三个通道分别用八位。颜色位数为32位时,R、G、B三个通道依旧分别用八位,剩下八位悬空置零。
值得注意的是,像素组有比特补零的标准。这主要是因为计算机一次处理四字节的效率更好这个特点决定的。也就是说如果一张图片的尺寸是121*120,它的BMP的像素组尺寸实际是124*120,多出的位置零。注意,信息头的参数宽不因此改变,是121。
另一个值得注意的是,当信息头的参数高为正数时,图片将是倒立的,即像素组第一行第一列的数据实际为图像的最后一行第一列的像素,像素组第一行第二列的数据实际为图像最后一行第二列的像素。这或许是定义标准的大师更倾向于数学坐标系的方向吧!
真正去写程序时,建议使用那些二进制查看器,来打开BMP格式的图片,并对照着标准,一 一比对,相信很快就能上手了!
最后,完整程序如下,需要另行使用其他程序 显示这个输出的格式为 " *.txt " 的图像矩阵。
个人建议用 matlab 的 importdata 函数和相关矩阵函数。
// BMP图片格式读取与图像矩阵输出
# include
# include
# include
# include
# include
# include
using namespace std;
// 此类用以记录颜色本身
class Color
{
public:
Color( unsigned short red_new = 0, unsigned short green_new = 0,
unsigned short blue_new = 0, unsigned short alpha_new = 0 );
void setRed( unsigned short red_new );
void setGreen( unsigned short green_new );
void setBlue( unsigned short blue_new );
void setAlpha( unsigned short alpha_new);
unsigned short getRed() const;
unsigned short getGreen() const;
unsigned short getBlue() const;
unsigned short getAlpha() const;
private:
unsigned short red,green,blue,alpha;
};
// 此类用以记录文件头
// signature 文件属性
// size 文件大小
// reserved1 / reserved2 保留字
// offset 文件头到像素组的偏移量
class FileHeader
{
public:
void open( ifstream &bmpFile );
void setSignature( unsigned short signature_new );
void setFileSize( unsigned long fileSize_new );
void setReserved1( unsigned short Reserved1_new );
void setReserved2( unsigned short Reserved2_new);
void setOffset( unsigned long offset_new);
unsigned short getSignature() const;
unsigned long getFileSize() const;
unsigned short getReserved1() const;
unsigned short getReserved2() const;
unsigned long getOffset() const;
void display() const;
private:
unsigned short signature, reserved1, reserved2;
unsigned long fileSize, offset;
};
// 此类用以记录信息头
// headerSize 信息头大小(字节数)
// width 图像宽度(像素)
// height 图像高度(像素)
// planes 缺省为1
// bitsPerPixel 每像素所使用的比特数
// compression 压缩方式 0为不压缩
// imageSize 图像大小 不压缩时,此项为 0
// xPixelsPerMeter 水平分辨率
// yPixelsPerMeter 垂直分辨率
// colorTableCount 调色板的颜色索引数 0为使用所有调色板项
// impoColorCount 重要影响的颜色索引数 0为所有颜色索引都重要
class InfoHeader
{
public:
void open( ifstream &bmpFile );
void setHeaderSize( unsigned long headerSize_new );
void setWidth( unsigned long width_new );
void setHeight( unsigned long height_new );
void setPlanes( unsigned short planes_new);
void setBitsPerPixel( unsigned short bitsPerPixel_new );
void setCompression( unsigned long compression_new );
void setImageSize( unsigned long imageSize_new );
void setXPixelsPerMeter( unsigned long xPixelsPerMeter_new );
void setYPixelsPerMeter( unsigned long yPixelsPerMeter_new );
void setColorTableCount( unsigned long colorTableCount_new );
void setImpoColorCount( unsigned long impoColorCount_new );
unsigned long getHeaderSize() const;
unsigned long getWidth() const;
unsigned long getHeight() const;
unsigned short getPlanes() const;
unsigned short getBitsPerPixel() const;
unsigned long getCompression() const;
unsigned long getImageSize() const;
unsigned long getXPixelsPerMeter() const;
unsigned long getYPixelsPerMeter() const;
unsigned long getColorTableCount() const;
unsigned long getImpoColorCount() const;
void display() const;
private:
unsigned long headerSize, width, height, compression, imageSize,
xPixelsPerMeter, yPixelsPerMeter, colorTableCount, impoColorCount;
unsigned short planes, bitsPerPixel;
};
// 此类用以描述调色板
// colorCount 颜色索引数
// 颜色索引值存在 vector
class ColorTable: public vector< Color >
{
public:
void open( ifstream& bmpFile );
void setColorCount( unsigned short colorCount_new );
unsigned short getColorCount() const;
void display() const;
private:
unsigned short colorCount;
};
// 此类为像素组的基类
// 为像素组类提供必要的信息
class BaseOfPixelArray
{
public:
void setWidth( unsigned long width_new );
void setHeight( unsigned long height_new );
void setBitsPerPixel( unsigned long height_new );
unsigned long getWidth() const;
unsigned long getHeight() const;
unsigned long getBitsPerPixel() const;
protected:
unsigned short bitsPerPixel;
unsigned long width, height;
} ;
// 1, 4, 8位时的像素组
// 由于当图像的高为正数时,图像数据为倒向,于是我们反过来输出
class PixelArray8: public BaseOfPixelArray, public vector< vector< unsigned short > >
{
public:
void open( ifstream & );
};
// 16, 24, 32位时的像素组
// 由于当图像的高为正数时,图像数据为倒向,于是我们反过来输出
class PixelArray32: public BaseOfPixelArray, public vector< vector< Color > >
{
public:
void open( ifstream & );
};
// 此类用以记录整个BMP图像文件
class BmpImgFile
{
public:
void open( ifstream &bmpFile );
FileHeader& getFileHeader();
InfoHeader& getInfoHeader();
ColorTable& getColorTable();
PixelArray8& getPixelArray8();
PixelArray32& getPixelArray32();
void displayPixelArray( ofstream &bmpTxT ) const;
private:
FileHeader fHeader;
InfoHeader iHeader;
ColorTable cTable;
PixelArray8 pArray8;
PixelArray32 pArray32;
};
Color::Color( unsigned short red_new, unsigned short green_new ,
unsigned short blue_new, unsigned short alpha_new )
{
setRed( red_new );
setGreen( green_new );
setBlue( blue_new );
setAlpha( alpha_new );
}
void Color::setRed( unsigned short red_new )
{
red = red_new;
}
void Color::setGreen( unsigned short green_new )
{
green = green_new;
}
void Color::setBlue( unsigned short blue_new )
{
blue = blue_new;
}
void Color::setAlpha( unsigned short alpha_new)
{
alpha = alpha_new;
}
unsigned short Color::getRed() const
{
return red;
}
unsigned short Color::getGreen() const
{
return green;
}
unsigned short Color::getBlue() const
{
return blue;
}
unsigned short Color::getAlpha() const
{
return alpha;
}
void FileHeader::open( ifstream &bmpFile )
{
unsigned short signature_new, reserved1_new, reserved2_new;
unsigned long fileSize_new, offset_new;
bmpFile.read( reinterpret_cast< char * >( &signature_new ), sizeof( unsigned short ) );
bmpFile.read( reinterpret_cast< char * >( &fileSize_new ), sizeof( unsigned long ) );
bmpFile.read( reinterpret_cast< char * >( &reserved1_new ), sizeof( unsigned short ) );
bmpFile.read( reinterpret_cast< char * >( &reserved2_new ), sizeof( unsigned short ) );
bmpFile.read( reinterpret_cast< char * >( &offset_new ), sizeof( unsigned long ) );
setSignature( signature_new );
setFileSize( fileSize_new );
setReserved1( reserved1_new );
setReserved2( reserved2_new );
setOffset( offset_new );
}
void FileHeader::setSignature( unsigned short signature_new )
{
signature = signature_new;
}
void FileHeader::setFileSize( unsigned long fileSize_new )
{
fileSize = fileSize_new;
}
void FileHeader::setReserved1( unsigned short reserved1_new )
{
reserved1 = reserved1_new;
}
void FileHeader::setReserved2( unsigned short reserved2_new)
{
reserved2 = reserved2_new;
}
void FileHeader::setOffset( unsigned long offset_new)
{
offset = offset_new;
}
unsigned short FileHeader::getSignature() const
{
return signature;
}
unsigned long FileHeader::getFileSize() const
{
return fileSize;
}
unsigned short FileHeader::getReserved1() const
{
return reserved1;
}
unsigned short FileHeader::getReserved2() const
{
return reserved2;
}
unsigned long FileHeader::getOffset() const
{
return offset;
}
void FileHeader::display() const
{
cout << "Loading file header..." << endl;
cout << left << setw(15) << "signature:" << signature << endl;
cout << left << setw(15) << "fileSize:" << fileSize << endl;
cout << left << setw(15) << "reserved1:" << reserved1 << endl;
cout << left << setw(15) << "reserved2:" << reserved2 << endl;
cout << left << setw(15) << "offset:" << offset << endl;
cout << "File header has been successfully outputed;" << endl;
}
void InfoHeader::open( ifstream &bmpFile )
{
unsigned long headerSize_new, width_new, height_new, compression_new, imageSize_new,
xPixelsPerMeter_new, yPixelsPerMeter_new, colorTableCount_new, impoColorCount_new;
unsigned short planes_new, bitsPerPixel_new;
bmpFile.read( reinterpret_cast< char * >( &headerSize_new ), sizeof( unsigned long ) );
bmpFile.read( reinterpret_cast< char * >( &width_new ), sizeof( unsigned long ) );
bmpFile.read( reinterpret_cast< char * >( &height_new ), sizeof( unsigned long ) );
bmpFile.read( reinterpret_cast< char * >( &planes_new ), sizeof( unsigned short ) );
bmpFile.read( reinterpret_cast< char * >( &bitsPerPixel_new ), sizeof( unsigned short ) );
bmpFile.read( reinterpret_cast< char * >( &compression_new ), sizeof( unsigned long ) );
bmpFile.read( reinterpret_cast< char * >( &imageSize_new ), sizeof( unsigned long ) );
bmpFile.read( reinterpret_cast< char * >( &xPixelsPerMeter_new ), sizeof( unsigned long ) );
bmpFile.read( reinterpret_cast< char * >( &yPixelsPerMeter_new ), sizeof( unsigned long ) );
bmpFile.read( reinterpret_cast< char * >( &colorTableCount_new ), sizeof( unsigned long ) );
bmpFile.read( reinterpret_cast< char * >( &impoColorCount_new ), sizeof( unsigned long ) );
setHeaderSize( headerSize_new );
setWidth( width_new );
setHeight( height_new );
setPlanes( planes_new );
setBitsPerPixel( bitsPerPixel_new );
setCompression( compression_new );
setImageSize( imageSize_new );
setXPixelsPerMeter( xPixelsPerMeter_new );
setYPixelsPerMeter( yPixelsPerMeter_new );
setColorTableCount( colorTableCount_new );
setImpoColorCount( impoColorCount_new );
}
void InfoHeader::setHeaderSize( unsigned long headerSize_new )
{
headerSize = headerSize_new;
}
void InfoHeader::setWidth( unsigned long width_new )
{
width = width_new;
}
void InfoHeader::setHeight( unsigned long height_new )
{
height = height_new;
}
void InfoHeader::setPlanes( unsigned short planes_new)
{
planes = planes_new;
}
void InfoHeader::setBitsPerPixel( unsigned short bitsPerPixel_new )
{
bitsPerPixel = bitsPerPixel_new;
}
void InfoHeader::setCompression( unsigned long compression_new )
{
compression = compression_new;
}
void InfoHeader::setImageSize( unsigned long imageSize_new )
{
imageSize = imageSize_new;
}
void InfoHeader::setXPixelsPerMeter( unsigned long xPixelsPerMeter_new )
{
xPixelsPerMeter = xPixelsPerMeter_new;
}
void InfoHeader::setYPixelsPerMeter( unsigned long yPixelsPerMeter_new )
{
yPixelsPerMeter = yPixelsPerMeter_new;
}
void InfoHeader::setColorTableCount( unsigned long colorTableCount_new )
{
colorTableCount = colorTableCount_new;
}
void InfoHeader::setImpoColorCount( unsigned long impoColorCount_new )
{
impoColorCount = impoColorCount_new;
}
unsigned long InfoHeader::getHeaderSize() const
{
return headerSize;
}
unsigned long InfoHeader::getWidth() const
{
return width;
}
unsigned long InfoHeader::getHeight() const
{
return height;
}
unsigned short InfoHeader::getPlanes() const
{
return planes;
}
unsigned short InfoHeader::getBitsPerPixel() const
{
return bitsPerPixel;
}
unsigned long InfoHeader::getCompression() const
{
return compression;
}
unsigned long InfoHeader::getImageSize() const
{
return imageSize;
}
unsigned long InfoHeader::getXPixelsPerMeter() const
{
return xPixelsPerMeter;
}
unsigned long InfoHeader::getYPixelsPerMeter() const
{
return yPixelsPerMeter;
}
unsigned long InfoHeader::getColorTableCount() const
{
return colorTableCount;
}
unsigned long InfoHeader::getImpoColorCount() const
{
return impoColorCount;
}
void InfoHeader::display() const
{
cout << "Loading information header..." << endl;
cout << left << setw(20) << "headerSize:" << headerSize << endl;
cout << left << setw(20) << "width:" << width << endl;
cout << left << setw(20) << "height:" << height << endl;
cout << left << setw(20) << "planes:" << planes << endl;
cout << left << setw(20) << "bitsPerPixel:" << bitsPerPixel << endl;
cout << left << setw(20) << "compression:" << compression << endl;
cout << left << setw(20) << "imageSize:" << imageSize << endl;
cout << left << setw(20) << "xPixelsPerMeter:" << xPixelsPerMeter << endl;
cout << left << setw(20) << "yPixelsPerMeter:" << yPixelsPerMeter << endl;
cout << left << setw(20) << "colorTableCount:" << colorTableCount << endl;
cout << left << setw(20) << "impoColorCount:" << impoColorCount << endl;
cout << "Information header has been successfully outputed;" << endl;
}
void ColorTable::open( ifstream &bmpFile )
{
unsigned long nowColor;
this->resize( colorCount );
for ( int i=0; i < colorCount; ++i )
{
bmpFile.read( reinterpret_cast< char * >( &nowColor ), sizeof( unsigned long ) );
this->at( i ).setRed( nowColor << 8 >> 3*8 );
this->at( i ).setGreen( nowColor << 2*8 >> 3*8 );
this->at( i ).setBlue( nowColor <<3*8 >> 3*8 );
this->at( i ).setAlpha( nowColor >> 3*8);
}
}
void ColorTable::setColorCount( unsigned short colorCount_new )
{
colorCount = colorCount_new;
}
unsigned short ColorTable::getColorCount() const
{
return colorCount;
}
void ColorTable::display() const
{
cout << "Loading color table..." << endl;
cout << "index Red Green Blue Alpha" << endl;
for ( int i = 0; i < colorCount; ++i )
cout << left << setw( 8 ) << i << left << setw( 8 ) << this->at( i ).getRed()
<< left << setw( 8 ) << this->at( i ).getGreen() << left << setw( 8 )
<< this->at( i ).getBlue() << left << setw( 8 ) << this->at( i ).getAlpha() << endl;
cout << "Color table has been successfully outputed;" << endl;
}
void BaseOfPixelArray::setWidth( unsigned long width_new )
{
width = width_new;
}
void BaseOfPixelArray::setHeight( unsigned long height_new )
{
height = height_new;
}
void BaseOfPixelArray::setBitsPerPixel( unsigned long bitsPerPixel_new )
{
bitsPerPixel = bitsPerPixel_new;
}
unsigned long BaseOfPixelArray::getWidth() const
{
return width;
}
unsigned long BaseOfPixelArray::getHeight() const
{
return height;
}
unsigned long BaseOfPixelArray::getBitsPerPixel() const
{
return bitsPerPixel;
}
void PixelArray8::open( ifstream &bmpFile )
{
unsigned long nw, i, nh, dataItem;
this->resize( height );
for ( i = 0; i < height; ++i )
this->at( i ).resize( width );
for ( nh = 0; nh < height; ++nh )
{
nw = 0;
while ( nw < width )
{
bmpFile.read( reinterpret_cast< char * >( &dataItem ), sizeof( unsigned long ) );
dataItem = ( dataItem << 24 ) + ( dataItem >> 8 << 24 >> 8 )
+ ( dataItem << 8 >> 24 << 8 ) + ( dataItem >> 24 );
i = 0;
while ( (i < 32 / bitsPerPixel ) && ( nw < width ) )
{
++i;
++nw;
this->at( nh ).at( nw - 1 ) = dataItem >> ( 32 - bitsPerPixel );
dataItem = dataItem << bitsPerPixel;
}
}
}
}
void PixelArray32::open( ifstream &bmpFile )
{
unsigned short red_new, green_new, blue_new, nothing;
unsigned long nw, nh, i;
unsigned char temp1, temp2, temp3, temp4;
this->resize( height );
for ( i = 0; i < height; ++i )
this->at( i ).resize( width );
if ( ( width * bitsPerPixel ) % 32 == 0)
nothing = 0;
else
nothing = ( ( ( width * bitsPerPixel ) / 32 + 1 ) * 32 - width * bitsPerPixel ) / 8;
for ( nh = 0; nh < height; ++nh )
{
if (nh == 0)
{
int b;
b=1;
}
for ( nw = 0; nw < width; ++nw )
{
bmpFile.read( reinterpret_cast< char * >( &temp1 ), sizeof( unsigned char ) );
bmpFile.read( reinterpret_cast< char * >( &temp2 ), sizeof( unsigned char ) );
switch ( bitsPerPixel)
{
case 16 :
red_new = ( ( ( temp2 & 0x7C ) >> 2 ) + 1 ) * 8;
blue_new = ( ( temp1 & 0x1F ) + 1 ) * 8;
green_new = ( ( ( ( temp1 & 0xE0 ) >> 5 )+ ( ( temp2 & 3 ) << 3 ) ) + 1 ) * 8;
break;
case 24 :
bmpFile.read( reinterpret_cast< char * >( &temp3 ), sizeof( unsigned char ) );
red_new = temp3;
green_new = temp2;
blue_new = temp1;
break;
case 32 :
bmpFile.read( reinterpret_cast< char * >( &temp3 ), sizeof( unsigned char ) );
bmpFile.read( reinterpret_cast< char * >( &temp4 ), sizeof( unsigned char ) );
red_new = temp3;
green_new = temp2;
blue_new = temp1;
break;
}
this->at( nh ).at( nw ).setBlue( blue_new );
this->at( nh ).at( nw ).setGreen( green_new );
this->at( nh ).at( nw ).setRed( red_new );
}
for ( i = 1; i <= nothing; ++i )
bmpFile.read( reinterpret_cast< char * >( &temp1 ), sizeof( unsigned char ) );
}
}
void BmpImgFile::open( ifstream &bmpFile )
{
fHeader.open( bmpFile );
iHeader.open( bmpFile );
if ( iHeader.getBitsPerPixel() <= 8 )
{
if ( iHeader.getColorTableCount() == 0 )
cTable.setColorCount( 1 << iHeader.getBitsPerPixel() );
else
cTable.setColorCount( iHeader.getColorTableCount() );
cTable.open( bmpFile );
iHeader.getWidth();
pArray8.setWidth( iHeader.getWidth() );
pArray8.setHeight( iHeader.getHeight() );
pArray8.setBitsPerPixel( iHeader.getBitsPerPixel() );
pArray8.open( bmpFile );
}
else
{
pArray32.setWidth( iHeader.getWidth() );
pArray32.setHeight( iHeader.getHeight() );
pArray32.setBitsPerPixel( iHeader.getBitsPerPixel() );
pArray32.open( bmpFile );
}
}
FileHeader& BmpImgFile::getFileHeader()
{
return fHeader;
}
InfoHeader& BmpImgFile::getInfoHeader()
{
return iHeader;
}
ColorTable& BmpImgFile::getColorTable()
{
return cTable;
}
void BmpImgFile::displayPixelArray( ofstream &bmpTxT ) const
{
cout << "Loading the pixel array..." << endl;
long i, j, height = iHeader.getHeight(),
width = iHeader.getWidth(), bitsPerPixel = iHeader.getBitsPerPixel();
for ( i = height - 1; i >= 0; --i )
{
for ( j = 0; j < width; ++j )
{
if ( bitsPerPixel <= 8 )
bmpTxT << cTable.at( pArray8.at( i ).at( j ) ).getRed() << " ";
else
bmpTxT << pArray32.at( i ).at( j ).getRed() << " ";
}
bmpTxT << endl;
}
for ( i = height - 1; i >= 0; --i )
{
for ( j = 0; j < width; ++j )
if ( bitsPerPixel <= 8 )
bmpTxT << cTable.at( pArray8.at( i ).at( j ) ).getGreen() << " ";
else
bmpTxT << pArray32.at( i ).at( j ).getGreen() << " ";
bmpTxT << endl;
}
for ( i = height - 1; i >= 0; --i )
{
for ( j = 0; j < width; ++j )
if ( bitsPerPixel <= 8 )
bmpTxT << cTable.at( pArray8.at( i ).at( j ) ).getBlue() << " ";
else
bmpTxT << pArray32.at( i ).at( j ).getBlue() << " ";
bmpTxT << endl;
}
cout << "It has been successfully outputed in the root directory with the \"txt\" postfix." << endl;
}
int main()
{
unsigned short order;
string path;
cout << "Welcome to will's ImageRead program" << endl;
cout << "Just choose the order number and the program will implement the order." << endl;
cout << "1 Read the image" << endl;
cout << "0 Terminate the program" << endl;
cin >> order;
if ( order == 0 )
{
return 0;
}
cout << "Please input the path of the image file. Case sensitive." << endl;
cout << "If the image file is just in the root diretory, just input the file name, like \"lena.bmp\"." << endl;
cin >> path;
ifstream inBmpFile( path.c_str(), ios::in | ios::binary );
ofstream outBmpFile;
BmpImgFile bmp1;
bmp1.open( inBmpFile );
do
{
cout << endl;
cout << "1 Show the file header" << endl;
cout << "2 Show the information header" << endl;
cout << "3 Show the color table" << endl;
cout << "4 Output the pixel array" << endl;
cout << "5 Read another image file" << endl;
cout << "0 Terminate the program"<< endl;
cin >> order;
cout << endl;
switch ( order )
{
case 1 :
bmp1.getFileHeader().display();
break;
case 2 :
bmp1.getInfoHeader().display();
break;
case 3 :
if (bmp1.getInfoHeader().getBitsPerPixel() > 8)
cout << "The bmp file doesn't contain the color table!" << endl;
else
bmp1.getColorTable().display();
break;
case 4 :
path.at( path.size() - 1 )='t';
path.at( path.size() - 2 )='x';
path.at( path.size() - 3 )='t';
outBmpFile.open( path.c_str(), ios::out | ios::binary );
bmp1.displayPixelArray( outBmpFile );
break;
case 5 :
cout << "Please input the path of the image file. Case sensitive." << endl;
cout << "If the image file is just in the root diretory, ";
cout << "just input the file name, like \"lena.bmp\"." << endl;
cin >> path;
inBmpFile.open( path.c_str(), ios::in | ios::binary );
bmp1.open( inBmpFile );
break;
}
}
while ( order != 0 );
cout << "Good day!";
}