最近把位图的打开、保存、翻转代码给大家贴出来,供大家参考:
再本文中处理1位和24位bmp文件,其他的可以自行研究、、、
首先,你要做好准备工作,在View类中设置好对应的变量和函数:
private:
CFile cFile; //文件打开
BITMAPINFOHEADER bmih; //位图信息头
BITMAPFILEHEADER bmfh; //位图文件头
LPBITMAPINFO bmif; //位图信息,其中包括位图信息头和色彩信息(主要针对有调色板的Bmp,如24位真彩没有色彩信息,即位图信息就等于位图信息头)如果你对这位图方面的东西海不是很了解的话可以看我的MFC中DDB (DEVICE-DEPENDENT BITMAP)详解
byte * bmData; //用来存放位图像素数据的数组指针。
void OnView(); //用来显示调用
void Oneddy(bool bLeft); //对24位的左右90度翻转,其中true 向左
void Ontrun(bool bLeftRight); //对24位的上下,左右镜面,true 左右对称
void OneddyOne(bool bLeft); //对1位的左右90度翻转,其中true 向左
void OntrunOne(bool bLeftRight); //对1位的上下,左右镜面,true 左右对称
下来我们看一下文件的打开:
void
CMFCView
::
OnFileOpen
()
{
char
*
pFilter
="
位图
(*.bmp)|*.bmp|/0";
CFileDialog
openFile
(
TRUE
,"*.bmp",
NULL
,
OFN_HIDEREADONLY
|
OFN_OVERWRITEPROMPT
,
pFilter
);
if
(
IDOK
!=
openFile
.
DoModal
())
return
;
oPenFileOk
=
true
;
CString
bitmapOpenPath
=
openFile
.
GetPathName
();
oPenFileOk
=
true
;
cFile
.
Open
(
bitmapOpenPath
,
CFile
::
modeRead
);
cFile
.
SeekToBegin
();
//
读取文件头
cFile
.
Read
(&
bmfh
,
sizeof
(
bmfh
));
//
读取文件信息头
cFile
.
Read
(&
bmih
,
sizeof
(
bmih
));
//
读取文件信息
cFile
.
SeekToBegin
(); //
返回到文件开始位置
cFile
.
Read
(&
bmfh
,
sizeof
(
bmfh
));
UINT
uBmpInfoLen
=(
UINT
)
bmfh
.
bfOffBits
-
sizeof
(
BITMAPFILEHEADER
);
bmif
=(
LPBITMAPINFO
)
new
BYTE
[
uBmpInfoLen
];
cFile
.
Read
((
LPVOID
)
bmif
,
uBmpInfoLen
);
//
读取数据
DWORD
dwBitlen
=
bmfh
.
bfSize
-
bmfh
.
bfOffBits
;
bmData
=
new
byte
[
dwBitlen
];
cFile
.
Read
(
bmData
,
dwBitlen
);
cFile
.
Close
();
HBITMAP
hBitmap
;
CBitmap
cBitmap
;
hBitmap
= ::
CreateDIBitmap
(
GetDC
()->
m_hDC
,&
bmih
,
CBM_INIT
,
bmData
,
bmif
,
DIB_RGB_COLORS
);
cBitmap
.
Attach
(
hBitmap
);
CDC
dcMemory
;
dcMemory
.
CreateCompatibleDC
(
GetDC
());
CBitmap
*
cUsedBitmap
=
dcMemory
.
SelectObject
(&
cBitmap
);
HWND
safeHwnd
=
GetSafeHwnd
();
RECT
windowRect
;
::
GetClientRect
(
safeHwnd
,&
windowRect
);
POINT
paintPoint
;
paintPoint
.
x
= (
windowRect
.
right
-
bmif
->
bmiHeader
.
biWidth
)/2;
paintPoint
.
y
= (
windowRect
.
bottom
-
bmif
->
bmiHeader
.
biHeight
)/2;
GetDC
()->
BitBlt
(
paintPoint
.
x
,
paintPoint
.
y
,
bmif
->
bmiHeader
.
biWidth
,
bmif
->
bmiHeader
.
biHeight
,&
dcMemory
,0,0,
SRCCOPY
);
dcMemory
.
SelectObject
(
cUsedBitmap
);
cBitmap
.
Detach
();
}
文件的保存:
void
CMFCView
::
OnFileSave
()
{
if
( !
oPenFileOk
)
{
AfxMessageBox
("Place select one BitMap!");
return
;
}
char
*
pFilter
="
位图
(*.bmp)|*.bmp||";
CFileDialog
saveFile
(
FALSE
,"*.bmp",
NULL
,
NULL
,
pFilter
);
if
(
IDOK
!=
saveFile
.
DoModal
())
return
;
CString
bitmapSavePath
=
saveFile
.
GetPathName
();
CFile
cf
;
cf
.
Open
(
bitmapSavePath
,
CFile
::
modeCreate
|
CFile
::
modeReadWrite
);
cf
.
Write
(&
bmfh
,
sizeof
(
bmfh
));
if
(
bmih
.
biBitCount
==1) //
判断是否为一位,来去定是否要写调色板信息
cf
.
Write
(
bmif
,(
UINT
)
bmfh
.
bfOffBits
-
sizeof
(
BITMAPFILEHEADER
));
else
cf
.
Write
(&
bmif
->
bmiHeader
,(
UINT
)
bmfh
.
bfOffBits
-
sizeof
(
BITMAPFILEHEADER
));
cf
.
Write
(
bmData
,
bmfh
.
bfSize
-
bmfh
.
bfOffBits
);
cf
.
Close
();
}
对24
位的左右90
度翻转,其中true
向左
void
CMFCView
::
Oneddy
(
bool
bLeft
)
{
byte
*
bEddyData
;
int
byteCount
=
bmif
->
bmiHeader
.
biBitCount
/8;
int
iAddLineData
= (4-(
bmif
->
bmiHeader
.
biHeight
*
byteCount
)%4)%4;
int
eddySize
=(
bmif
->
bmiHeader
.
biHeight
*
byteCount
+
iAddLineData
)*
bmif
->
bmiHeader
.
biWidth
;
bEddyData
=
new
byte
[
eddySize
];
int
iBmpAddLineData
= (4-
bmif
->
bmiHeader
.
biWidth
*
byteCount
%4)%4;
//
对数据进行操作
int
iImageSize
= (
bmif
->
bmiHeader
.
biWidth
*
byteCount
+
iBmpAddLineData
)*
bmif
->
bmiHeader
.
biHeight
;
int
bEddyDataRowCount
=
bmif
->
bmiHeader
.
biHeight
*
byteCount
+
iAddLineData
;
for
(
int
i
=0;
i
<
bmif
->
bmiHeader
.
biHeight
;
i
++)
{
int
m
=0;
for
(
int
j
=0;
j
<
bmif
->
bmiHeader
.
biWidth
*
byteCount
;
j
+=
byteCount
)
{
int
bmDataIndex
;
int
bEddyDataRowIndex
;
int
bEddyDataColIndex
;
int
locIndex
;
if
(
bLeft
)
{
bmDataIndex
= (
bmif
->
bmiHeader
.
biWidth
*
byteCount
+
iBmpAddLineData
)*
i
;
bEddyDataRowIndex
= (
bmif
->
bmiHeader
.
biWidth
-1-(
m
))*(
bmif
->
bmiHeader
.
biHeight
*
byteCount
+
iAddLineData
);
bEddyDataColIndex
=
i
*
byteCount
;
locIndex
=
bEddyDataRowIndex
+
bEddyDataColIndex
;
}
else
{
bmDataIndex
= (
bmif
->
bmiHeader
.
biWidth
*
byteCount
+
iBmpAddLineData
)*
i
;
bEddyDataRowIndex
=
m
*(
bmif
->
bmiHeader
.
biHeight
*
byteCount
+
iAddLineData
);
bEddyDataColIndex
= (
bmif
->
bmiHeader
.
biHeight
-1-
i
)*
byteCount
;
locIndex
=
bEddyDataRowIndex
+
bEddyDataColIndex
;
}
bEddyData
[
locIndex
] =
bmData
[
j
+
bmDataIndex
];
//B
bEddyData
[
locIndex
+1] =
bmData
[
j
+
bmDataIndex
+1];
//G
bEddyData
[
locIndex
+2] =
bmData
[
j
+
bmDataIndex
+2];
//R
m
++;
}
}
byte
*
bTemp
=
bmData
;
bmData
=
bEddyData
;
//
删除临时信息
delete
bTemp
;
更改头文件信息
bmfh
.
bfSize
=
bmfh
.
bfOffBits
+
eddySize
;
int
iTemp
;
iTemp
=
bmif
->
bmiHeader
.
biHeight
;
bmif
->
bmiHeader
.
biHeight
=
bmif
->
bmiHeader
.
biWidth
;
bmif
->
bmiHeader
.
biWidth
=
iTemp
;
OnView
();
}
对24
位的上下,左右镜面,true
左右对称
void
CMFCView
::
Ontrun
(
bool
bLeftRight
)
{
byte
*
bEddyData
;
int
byteCount
;
byteCount
=
bmif
->
bmiHeader
.
biBitCount
/8;
bEddyData
=
new
byte
[
bmfh
.
bfSize
-
bmfh
.
bfOffBits
];
int
iBmpAddLineData
= (4-
bmif
->
bmiHeader
.
biWidth
*
byteCount
%4)%4;
//
对数据进行操作
int
iImageSize
= (
bmif
->
bmiHeader
.
biWidth
*
byteCount
+
iBmpAddLineData
)*
bmif
->
bmiHeader
.
biHeight
;
for
(
int
i
=0;
i
<
bmif
->
bmiHeader
.
biHeight
;
i
++)
{
int
m
=0;
for
(
int
j
=0;
j
<
bmif
->
bmiHeader
.
biWidth
*
byteCount
;
j
+=
byteCount
)
{
int
bmDataIndex
;
int
bEddyDataRowIndex
;
int
bEddyDataColIndex
;
int
locIndex
;
if
(
bLeftRight
)
{
bmDataIndex
= (
bmif
->
bmiHeader
.
biWidth
*
byteCount
+
iBmpAddLineData
)*
i
;
bEddyDataRowIndex
=
i
*((
bmfh
.
bfSize
-
bmfh
.
bfOffBits
)/
bmif
->
bmiHeader
.
biHeight
);
bEddyDataColIndex
= (
bmif
->
bmiHeader
.
biWidth
-1-
m
)*
byteCount
;
locIndex
=
bEddyDataRowIndex
+
bEddyDataColIndex
;
}
else
{
bmDataIndex
= (
bmif
->
bmiHeader
.
biWidth
*
byteCount
+
iBmpAddLineData
)*
i
;
bEddyDataRowIndex
= (
bmif
->
bmiHeader
.
biHeight
-1-
i
)*((
bmfh
.
bfSize
-
bmfh
.
bfOffBits
)/
bmif
->
bmiHeader
.
biHeight
);
bEddyDataColIndex
= (
m
)*
byteCount
;
locIndex
=
bEddyDataRowIndex
+
bEddyDataColIndex
;
}
bEddyData
[
locIndex
] =
bmData
[
j
+
bmDataIndex
];
//B
bEddyData
[
locIndex
+1] =
bmData
[
j
+
bmDataIndex
+1];
//G
bEddyData
[
locIndex
+2] =
bmData
[
j
+
bmDataIndex
+2];
//R
m
++;
}
}
byte
*
bTemp
=
bmData
;
bmData
=
bEddyData
;
//
删除临时信息
delete
bTemp
;
更改头文件信息
OnView
();
}
对1
位的左右90
度翻转,其中true
向左
void
CMFCView
::
OneddyOne
(
bool
bLeft
)
{
int
bmLineSizeByte
=(
bmif
->
bmiHeader
.
biWidth
+((32 - (
bmif
->
bmiHeader
.
biWidth
%32)))%32)/8;
int
edyLineSizeByte
= (
bmif
->
bmiHeader
.
biHeight
+(32 -(
bmif
->
bmiHeader
.
biHeight
%32))%32)/8;
int
iAddLineData
= (32 -
bmif
->
bmiHeader
.
biHeight
%32)%32;
int
eddySize
=(
bmif
->
bmiHeader
.
biHeight
+
iAddLineData
)*
bmif
->
bmiHeader
.
biWidth
;
//int x= bmfh.bfSize - bmfh.bfOffBits;
byte
*
bEddyData
=
new
byte
[
eddySize
*
bmif
->
bmiHeader
.
biWidth
/8];
for
(
int
iSetZero
= 0;
iSetZero
<
eddySize
*
bmif
->
bmiHeader
.
biWidth
/8;
iSetZero
++)
bEddyData
[
iSetZero
] = 0;
for
(
int
i
=0;
i
<
bmif
->
bmiHeader
.
biHeight
;
i
++)
{
for
(
int
j
=0;
j
<
bmif
->
bmiHeader
.
biWidth
;
j
++)
{
if
(
bLeft
)
{
changeBit
(&
bEddyData
[(
bmif
->
bmiHeader
.
biWidth
-
j
-1)*
edyLineSizeByte
+
i
/8],7-
i
%8,&
bmData
[
i
*
bmLineSizeByte
+
j
/8],7-
j
%8);
}
else
{
changeBit
(&
bEddyData
[
j
*
edyLineSizeByte
+(
bmif
->
bmiHeader
.
biHeight
-1-
i
)/8],7-(
bmif
->
bmiHeader
.
biHeight
-1-
i
)%8,&
bmData
[
i
*
bmLineSizeByte
+
j
/8],7-
j
%8);
}
}
}
byte
*
bTemp
=
bmData
;
bmData
=
bEddyData
;
//
删除临时信息
delete
bTemp
;
更改头文件信息
bmfh
.
bfSize
=
bmfh
.
bfOffBits
+
eddySize
/8;
int
iTemp
;
iTemp
=
bmif
->
bmiHeader
.
biHeight
;
bmif
->
bmiHeader
.
biHeight
=
bmif
->
bmiHeader
.
biWidth
;
bmif
->
bmiHeader
.
biWidth
=
iTemp
;
OnView
();
}
对1
位的上下,左右镜面,true
左右对称
void
CTest8_MFCView
::
OntrunOne
(
bool
bLeftRight
)
{
int
bmLineSizeByte
=(
bmif
->
bmiHeader
.
biWidth
+(32 - (
bmif
->
bmiHeader
.
biWidth
%32))%32)/8;
int
x
=
bmfh
.
bfSize
-
bmfh
.
bfOffBits
;
byte
*
bEddyData
=
new
byte
[
bmLineSizeByte
*
bmif
->
bmiHeader
.
biHeight
];
if
(
bLeftRight
)
{
for
(
int
j
=0;
j
<
bmif
->
bmiHeader
.
biHeight
;
j
++)
{
int
iToPos
=0,
iFromPos
=
bmif
->
bmiHeader
.
biWidth
%8?8-
bmif
->
bmiHeader
.
biWidth
%8:0;
iToPos
= 7;
int
iByteToPos
= 0;
int
iByteFromPos
=
bmif
->
bmiHeader
.
biWidth
%8?(
bmif
->
bmiHeader
.
biWidth
/8):(
bmif
->
bmiHeader
.
biWidth
/8-1);
for
(
int
i
=0;
i
<
bmif
->
bmiHeader
.
biWidth
;
i
++ )
{
if
(
iToPos
==7 )
{
bEddyData
[
bmLineSizeByte
*
j
+
iByteToPos
] = 0;
}
changeBit
( &
bEddyData
[
bmLineSizeByte
*
j
+
iByteToPos
],
iToPos
,&
bmData
[
bmLineSizeByte
*
j
+
iByteFromPos
],
iFromPos
);
iToPos
--;
iFromPos
++;
if
(
iToPos
== -1 )
{
iToPos
=7;
iByteToPos
++;
}
if
(
iFromPos
== 8 )
{
iFromPos
= 0;
iByteFromPos
--;
}
}
}
}
else
{
for
(
int
j
=0;
j
<
bmif
->
bmiHeader
.
biHeight
;
j
++)
{
for
(
int
i
=0;
i
<
bmLineSizeByte
;
i
++ )
{
byte
x
=0;
bEddyData
[(
bmif
->
bmiHeader
.
biHeight
-1-
j
)*
bmLineSizeByte
+
i
]&=
x
;
bEddyData
[(
bmif
->
bmiHeader
.
biHeight
-1-
j
)*
bmLineSizeByte
+
i
]|=
bmData
[
j
*
bmLineSizeByte
+
i
];
}
}
}
byte
*
bTemp
=
bmData
;
bmData
=
bEddyData
;
//
删除临时信息
delete
bTemp
;
OnView
();
}
最后你要用到一个函数用来对指定的两个字节的木一位进行赋值,代码如下:
void
changeBit
(
byte
*
byteTo
,
int
iToPos
,
byte
*
byteFrom
,
int
iFromPos
)
{
int
iToPos2
=
iToPos
;
int
m
=1;
m
=
m
<<
iFromPos
;
m
=
m
&(*
byteFrom
);
if
(
iToPos
>
iFromPos
)
{
m
=
m
<<(
iToPos2
-
iFromPos
);
}
else
{
m
=
m
>>(
iFromPos
-
iToPos2
);
}
*
byteTo
= (*
byteTo
)|
m
;
}
在过程中你要明白位图的数据真正的存放格式,比如数据首先保存的是位图最下放数据的最右边的像素,然后向左到头
->
向上
->
向左到头
->
向上、、、
还要明白每一行数据都必须有
32
位,不足的要补足
32
位,哪怕是一位图像长只有一个像素点,那么它也要占用
32bit
,也就是
4
个
byte
来存放一行。如果你还有什么不懂,你可以留言我或是把代码发给你。