运行测试效果:
代码:
void
CMyView::OnReadBmp()
{ // 读取BMP文件并显示
CDC * pDC = GetDC();
CFileDialog dlg(TRUE);
if (dlg.DoModal() == IDOK)
{ // 选择要打开的BMP图片
strFilePath = dlg.GetPathName();
}
if (strFilePath == "" )
{ // 取消
return ;
}
FILE * fp = fopen(strFilePath, " r " );
BITMAPFILEHEADER fileheader;
BITMAPINFO info;
fread( & fileheader, sizeof (fileheader), 1 ,fp);
if (fileheader.bfType != 0x4D42 )
{ // 不是BMP位图文件
pDC -> TextOut( 100 , 200 , " 无位图文件 请选择位图文件 " );
fclose(fp);
return ;
}
UCHAR * buffer = NULL;
// 读位图头部
fread( & info.bmiHeader, sizeof (BITMAPINFOHEADER), 1 , fp);
// 位图宽度
long width = info.bmiHeader.biWidth;
this -> width = width;
// 位图高度
long height = info.bmiHeader.biHeight;
this -> height = height;
DWORD size;
if (info.bmiHeader.biSizeImage != 0 )
{ // 带颜色表
size = info.bmiHeader.biSizeImage;
}
else
{ // 不带颜色表的
size = info.bmiHeader.biHeight * info.bmiHeader.biWidth * 3 ;
}
buffer = new UCHAR[size]; // 分配缓冲区
if (buffer == NULL)
{ // 分配内存失败
delete[] buffer;
return ;
}
// 忽略头部字节
fseek(fp,fileheader.bfOffBits, 0 );
fread(buffer,size, 1 ,fp);
int i,j;
#pragma region 16 color
// 16色图的解析
if (info.bmiHeader.biBitCount == 4 )
{
int pitch;
if (width % 8 == 0 )
pitch = width;
else
pitch = width + 8 - width % 8 ;
RGBQUAD quad[ 16 ];
fseek(fp,fileheader.bfOffBits - sizeof (RGBQUAD) * 16 , 0 );
fread(quad, sizeof (RGBQUAD) * 16 , 1 ,fp);
if (height > 0 )
{ // height>0 表示图片颠倒
for (i = 0 ; i < height; i ++ )
{
for (j = 0 ; j < width; j ++ )
{
int index;
if (j % 2 == 0 )
index = buffer[(i * pitch + j) / 2 ] / 16 ;
if (j % 2 == 1 )
index = buffer[(i * pitch + j) / 2 ] % 16 ;
UCHAR r = quad[index].rgbRed;
UCHAR g = quad[index].rgbGreen;
UCHAR b = quad[index].rgbBlue;
pDC -> SetPixel(j,height - i,RGB(r,g,b));
}
}
}
else
{ // 图片不颠倒
for (i = 0 ; i < 0 - height; i ++ )
{
for (j = 0 ; j < width; j ++ )
{
int index;
if (j % 2 == 0 )
index = buffer[(i * pitch + j) / 2 ] / 16 ;
if (j % 2 == 1 )
index = buffer[(i * pitch + j) / 2 ] % 16 ;
UCHAR r = quad[index].rgbRed;
UCHAR g = quad[index].rgbGreen;
UCHAR b = quad[index].rgbBlue;
pDC -> SetPixel(j,i,RGB(r,g,b));
}
}
}
}
#pragma endregion 16 color
#pragma region 256 color
// 256色图的解析
if (info.bmiHeader.biBitCount == 8 )
{
int pitch;
if (width % 4 == 0 )
{
pitch = width;
}
else
{
pitch = width + 4 - width % 4 ;
}
RGBQUAD quad[ 256 ];
fseek(fp,fileheader.bfOffBits - sizeof (RGBQUAD) * 256 , 0 );
fread(quad, sizeof (RGBQUAD) * 256 , 1 ,fp);
if (height > 0 )
{ // height>0 表示图片颠倒
for ( int i = 0 ;i < height;i ++ )
{
for ( int j = 0 ;j < width;j ++ )
{
int index = buffer[i * pitch + j];
UCHAR r = quad[index].rgbRed;
UCHAR g = quad[index].rgbGreen;
UCHAR b = quad[index].rgbBlue;
pDC -> SetPixel(j,height - i,RGB(r,g,b));
}
}
}
else
{
for ( int i = 0 ;i < 0 - height;i ++ )
{
for ( int j = 0 ;j < width;j ++ )
{
int index = buffer[i * pitch + j];
UCHAR r = quad[index].rgbRed;
UCHAR g = quad[index].rgbGreen;
UCHAR b = quad[index].rgbBlue;
pDC -> SetPixel(j,i,RGB(r,g,b));
}
}
}
}
#pragma endregion 256 color
#pragma region 24 bit
// 24位图解析
if (info.bmiHeader.biBitCount == 24 )
{
int pitch = width % 4 ;
// bgr
if (height > 0 )
{ // height>0 表示图片颠倒
for ( int i = 0 ;i < height;i ++ )
{
int realPitch = i * pitch;
for ( int j = 0 ;j < width;j ++ )
{
UCHAR b = buffer[(i * width + j) * 3 + realPitch];
UCHAR g = buffer[(i * width + j) * 3 + 1 + realPitch];
UCHAR r = buffer[(i * width + j) * 3 + 2 + realPitch];
pDC -> SetPixel(j,height - i,RGB(r,g,b));
}
}
}
else
{
for ( int i = 0 ;i < 0 - height;i ++ )
{
int realPitch = i * pitch;
for ( int j = 0 ;j < width;j ++ )
{
UCHAR b = buffer[(i * width + j) * 3 + realPitch];
UCHAR g = buffer[(i * width + j) * 3 + 1 + realPitch];
UCHAR r = buffer[(i * width + j) * 3 + 2 + realPitch];
pDC -> SetPixel(j,i,RGB(r,g,b));
}
}
}
}
#pragma endregion 24 bit
this -> ReleaseDC(pDC); // 释放掉绘制上下文
delete[] buffer; // 释放缓冲区
fclose(fp); // 关闭BMP文件
}
{ // 读取BMP文件并显示
CDC * pDC = GetDC();
CFileDialog dlg(TRUE);
if (dlg.DoModal() == IDOK)
{ // 选择要打开的BMP图片
strFilePath = dlg.GetPathName();
}
if (strFilePath == "" )
{ // 取消
return ;
}
FILE * fp = fopen(strFilePath, " r " );
BITMAPFILEHEADER fileheader;
BITMAPINFO info;
fread( & fileheader, sizeof (fileheader), 1 ,fp);
if (fileheader.bfType != 0x4D42 )
{ // 不是BMP位图文件
pDC -> TextOut( 100 , 200 , " 无位图文件 请选择位图文件 " );
fclose(fp);
return ;
}
UCHAR * buffer = NULL;
// 读位图头部
fread( & info.bmiHeader, sizeof (BITMAPINFOHEADER), 1 , fp);
// 位图宽度
long width = info.bmiHeader.biWidth;
this -> width = width;
// 位图高度
long height = info.bmiHeader.biHeight;
this -> height = height;
DWORD size;
if (info.bmiHeader.biSizeImage != 0 )
{ // 带颜色表
size = info.bmiHeader.biSizeImage;
}
else
{ // 不带颜色表的
size = info.bmiHeader.biHeight * info.bmiHeader.biWidth * 3 ;
}
buffer = new UCHAR[size]; // 分配缓冲区
if (buffer == NULL)
{ // 分配内存失败
delete[] buffer;
return ;
}
// 忽略头部字节
fseek(fp,fileheader.bfOffBits, 0 );
fread(buffer,size, 1 ,fp);
int i,j;
#pragma region 16 color
// 16色图的解析
if (info.bmiHeader.biBitCount == 4 )
{
int pitch;
if (width % 8 == 0 )
pitch = width;
else
pitch = width + 8 - width % 8 ;
RGBQUAD quad[ 16 ];
fseek(fp,fileheader.bfOffBits - sizeof (RGBQUAD) * 16 , 0 );
fread(quad, sizeof (RGBQUAD) * 16 , 1 ,fp);
if (height > 0 )
{ // height>0 表示图片颠倒
for (i = 0 ; i < height; i ++ )
{
for (j = 0 ; j < width; j ++ )
{
int index;
if (j % 2 == 0 )
index = buffer[(i * pitch + j) / 2 ] / 16 ;
if (j % 2 == 1 )
index = buffer[(i * pitch + j) / 2 ] % 16 ;
UCHAR r = quad[index].rgbRed;
UCHAR g = quad[index].rgbGreen;
UCHAR b = quad[index].rgbBlue;
pDC -> SetPixel(j,height - i,RGB(r,g,b));
}
}
}
else
{ // 图片不颠倒
for (i = 0 ; i < 0 - height; i ++ )
{
for (j = 0 ; j < width; j ++ )
{
int index;
if (j % 2 == 0 )
index = buffer[(i * pitch + j) / 2 ] / 16 ;
if (j % 2 == 1 )
index = buffer[(i * pitch + j) / 2 ] % 16 ;
UCHAR r = quad[index].rgbRed;
UCHAR g = quad[index].rgbGreen;
UCHAR b = quad[index].rgbBlue;
pDC -> SetPixel(j,i,RGB(r,g,b));
}
}
}
}
#pragma endregion 16 color
#pragma region 256 color
// 256色图的解析
if (info.bmiHeader.biBitCount == 8 )
{
int pitch;
if (width % 4 == 0 )
{
pitch = width;
}
else
{
pitch = width + 4 - width % 4 ;
}
RGBQUAD quad[ 256 ];
fseek(fp,fileheader.bfOffBits - sizeof (RGBQUAD) * 256 , 0 );
fread(quad, sizeof (RGBQUAD) * 256 , 1 ,fp);
if (height > 0 )
{ // height>0 表示图片颠倒
for ( int i = 0 ;i < height;i ++ )
{
for ( int j = 0 ;j < width;j ++ )
{
int index = buffer[i * pitch + j];
UCHAR r = quad[index].rgbRed;
UCHAR g = quad[index].rgbGreen;
UCHAR b = quad[index].rgbBlue;
pDC -> SetPixel(j,height - i,RGB(r,g,b));
}
}
}
else
{
for ( int i = 0 ;i < 0 - height;i ++ )
{
for ( int j = 0 ;j < width;j ++ )
{
int index = buffer[i * pitch + j];
UCHAR r = quad[index].rgbRed;
UCHAR g = quad[index].rgbGreen;
UCHAR b = quad[index].rgbBlue;
pDC -> SetPixel(j,i,RGB(r,g,b));
}
}
}
}
#pragma endregion 256 color
#pragma region 24 bit
// 24位图解析
if (info.bmiHeader.biBitCount == 24 )
{
int pitch = width % 4 ;
// bgr
if (height > 0 )
{ // height>0 表示图片颠倒
for ( int i = 0 ;i < height;i ++ )
{
int realPitch = i * pitch;
for ( int j = 0 ;j < width;j ++ )
{
UCHAR b = buffer[(i * width + j) * 3 + realPitch];
UCHAR g = buffer[(i * width + j) * 3 + 1 + realPitch];
UCHAR r = buffer[(i * width + j) * 3 + 2 + realPitch];
pDC -> SetPixel(j,height - i,RGB(r,g,b));
}
}
}
else
{
for ( int i = 0 ;i < 0 - height;i ++ )
{
int realPitch = i * pitch;
for ( int j = 0 ;j < width;j ++ )
{
UCHAR b = buffer[(i * width + j) * 3 + realPitch];
UCHAR g = buffer[(i * width + j) * 3 + 1 + realPitch];
UCHAR r = buffer[(i * width + j) * 3 + 2 + realPitch];
pDC -> SetPixel(j,i,RGB(r,g,b));
}
}
}
}
#pragma endregion 24 bit
this -> ReleaseDC(pDC); // 释放掉绘制上下文
delete[] buffer; // 释放缓冲区
fclose(fp); // 关闭BMP文件
}