运行测试效果:
代码:
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文件
}