C++实现以下功能:
1、实现对硬盘中的8位BMP图像的读取和存储;
2、实现对指定矩形框区域图像的剪切;
3、实现对任意形状图像的任意比例缩放;
4、实现对任意形状图像的任意角度选装。
程序编辑环境:在visual c++6.0中建立console application工程,win32平台,无MFC,空Project
程序运行说明:
1、添加文件Ex1.cpp、Ex1.h
2、编译、运行
3、按程序提示完成操作(注意文件名称的大小写)
4、进入文件夹,查看Cutresult.bmp(裁剪结果)、Scalresult.bmp(缩放结果)和Rotresult.bmp(旋转结果)文件。
感谢以下三篇博文:
http:
//blog.csdn.net/xiajun07061225/article/details/5813726
http:
//blog.csdn.net/wangyadong/article/details/3549284
http:
//blog.csdn.net/xiajun07061225/article/details/6633938
以下代码是参照以上内容做适当修改完成的。
头文件
Ex1
.
h
内容如下:
typedef
unsigned
char
BYTE
;
typedef
unsigned
short
WORD
;
typedef
unsigned
int
DWORD
;
typedef
long
LONG
;
//位图文件头定义;
//其中不包含文件类型信息(由于结构体的内存结构决定,
//要是加了的话将不能正确读取文件信息)
typedef
struct
tagBITMAPFILEHEADER
{
// WORD bfType;//文件类型,必须是0x424D,即字符“BM”
DWORD
bfSize
;
//文件大小
WORD
bfReserved1
;
//保留字
WORD
bfReserved2
;
//保留字
DWORD
bfOffBits
;
//从文件头到实际位图数据的偏移字节数
}
BITMAPFILEHEADER
;
typedef
struct
tagBITMAPINFOHEADER
{
DWORD
biSize
;
//信息头大小
LONG
biWidth
;
//图像宽度
LONG
biHeight
;
//图像高度
WORD
biPlanes
;
//位平面数,必须为1
WORD
biBitCount
;
//每像素位数
DWORD
biCompression
;
//压缩类型
DWORD
biSizeImage
;
//压缩图像大小字节数
LONG
biXPelsPerMeter
;
//水平分辨率
LONG
biYPelsPerMeter
;
//垂直分辨率
DWORD
biClrUsed
;
//位图实际用到的色彩数
DWORD
biClrImportant
;
//本位图中重要的色彩数
}
BITMAPINFOHEADER
;
//位图信息头定义
typedef
struct
tagRGBQUAD
{
BYTE
rgbBlue
;
//该颜色的蓝色分量
BYTE
rgbGreen
;
//该颜色的绿色分量
BYTE
rgbRed
;
//该颜色的红色分量
BYTE
rgbReserved
;
//保留值
}
RGBQUAD
;
//调色板定义
//像素信息
typedef
struct
tagIMAGEDATA
{
BYTE
blue
;
///8位灰度图用其中1个
//BYTE green;
//BYTE red;
}
IMAGEDATA
;
源文件
Ex1
.
cpp
内容如下:
// Ex1.cpp : Defines the entry point for the console application.
//
#include <stdio.h>
#include "Ex1.h"
#include "stdlib.h"
#include "math.h"
#include <iostream>
#define PI 3.14159
//圆周率宏定义
#define LENGTH_NAME_BMP 30
//bmp图片文件名的最大长度
using
namespace
std
;
//变量定义
BITMAPFILEHEADER
strHead
;
//位图文件头
RGBQUAD
strPla
[
256
];
//256色调色板
BITMAPINFOHEADER
strInfo
;
//显示位图文件头信息
void
showBmpHead
(
BITMAPFILEHEADER
pBmpHead
)
{
cout
<<
"读取的位图文件信息:"
<<
endl
;
cout
<<
"文件大小:"
<<
pBmpHead
.
bfSize
<<
endl
;
// cout<<"保留字_1:"<<pBmpHead.bfReserved1<<endl;
// cout<<"保留字_2:"<<pBmpHead.bfReserved2<<endl;
cout
<<
"实际位图数据的偏移字节数:"
<<
pBmpHead
.
bfOffBits
<<
endl
;
}
void
showBmpInforHead
(
tagBITMAPINFOHEADER
pBmpInforHead
)
{
// cout<<"读取的位图信息头:"<<endl;
cout
<<
"结构体的长度:"
<<
pBmpInforHead
.
biSize
<<
endl
;
cout
<<
"位图宽:"
<<
pBmpInforHead
.
biWidth
<<
endl
;
cout
<<
"位图高:"
<<
pBmpInforHead
.
biHeight
<<
endl
;
cout
<<
"biPlanes平面数:"
<<
pBmpInforHead
.
biPlanes
<<
endl
;
cout
<<
"biBitCount采用颜色位数:"
<<
pBmpInforHead
.
biBitCount
<<
endl
;
cout
<<
"压缩方式:"
<<
pBmpInforHead
.
biCompression
<<
endl
;
cout
<<
"biSizeImage实际位图数据占用的字节数:"
<<
pBmpInforHead
.
biSizeImage
<<
endl
;
cout
<<
"X方向分辨率:"
<<
pBmpInforHead
.
biXPelsPerMeter
<<
endl
;
cout
<<
"Y方向分辨率:"
<<
pBmpInforHead
.
biYPelsPerMeter
<<
endl
;
cout
<<
"使用的颜色数:"
<<
pBmpInforHead
.
biClrUsed
<<
endl
;
cout
<<
"重要颜色数:"
<<
pBmpInforHead
.
biClrImportant
<<
endl
<<
endl
;
}
int
max
(
int
i
,
int
j
)
{
if
(
i
>=
j
)
return
i
;
else
return
j
;
}
int
main
()
{
char
strFile
[
LENGTH_NAME_BMP
];
//bmp文件名
WORD
bfType_w
=
0x4d42
;
IMAGEDATA
*
imagedata
=
NULL
;
//动态分配存储原图片的像素信息的二维数组
IMAGEDATA
*
imagedataCut
=
NULL
;
//动态分配存储裁剪后的图片的像素信息的二维数组
IMAGEDATA
*
imagedataScal
=
NULL
;
//动态分配存储缩放后的图片的像素信息的二维数组
IMAGEDATA
*
imagedataRot
=
NULL
;
//动态分配存储旋转后的图片的像素信息的二维数组
int
width
,
height
;
//图片的宽度和高度
float
ExpScalValue
=
0
;
期望的缩放倍数(允许小数)
int
FloatToIntwidth
,
FloatToIntheight
;
/小数变成整数(float To Int)
int
RotateAngle
=
90
;
//要缩放的角度,默认90
cout
<<
"请输入所要读取的文件名(w.bmp或者06.bmp或者07.bmp):"
<<
endl
;
cin
>>
strFile
;
FILE
*
fpi
,
*
fpw
;
fpi
=
fopen
(
strFile
,
"rb"
);
if
(
fpi
!=
NULL
)
{
//先读取文件类型
WORD
bfType
;
fread
(
&
bfType
,
1
,
sizeof
(
WORD
),
fpi
);
if
(
0x4d42
!=
bfType
)
///if !=BMP
{
cout
<<
"the file is not a bmp file!"
<<
endl
;
return
NULL
;
}
printf
(
"
\n
读取到的文件是%s。
\n\n
"
,
strFile
);
//读取bmp文件的文件头和信息头
fread
(
&
strHead
,
1
,
sizeof
(
tagBITMAPFILEHEADER
),
fpi
);
showBmpHead
(
strHead
);
//显示文件头
fread
(
&
strInfo
,
1
,
sizeof
(
tagBITMAPINFOHEADER
),
fpi
);
showBmpInforHead
(
strInfo
);
//显示文件信息头
//读取调色板
for
(
unsigned
int
nCounti
=
0
;
nCounti
<
strInfo
.
biClrUsed
;
nCounti
++
)
{
fread
((
char
*
)
&
(
strPla
[
nCounti
].
rgbBlue
),
1
,
sizeof
(
BYTE
),
fpi
);
fread
((
char
*
)
&
(
strPla
[
nCounti
].
rgbGreen
),
1
,
sizeof
(
BYTE
),
fpi
);
fread
((
char
*
)
&
(
strPla
[
nCounti
].
rgbRed
),
1
,
sizeof
(
BYTE
),
fpi
);
fread
((
char
*
)
&
(
strPla
[
nCounti
].
rgbReserved
),
1
,
sizeof
(
BYTE
),
fpi
);
}
}
else
{
cout
<<
"file open error!"
<<
endl
;
return
NULL
;
}
width
=
strInfo
.
biWidth
;
height
=
strInfo
.
biHeight
;
imagedata
=
(
IMAGEDATA
*
)
malloc
(
width
*
height
*
sizeof
(
IMAGEDATA
));
///为原始图像分配存储空间
//初始化原始图片的像素数组
for
(
int
i
=
0
;
i
<
height
;
++
i
)
{
for
(
int
j
=
0
;
j
<
width
;
++
j
)
{
(
*
(
imagedata
+
i
*
width
+
j
)).
blue
=
0
;
//(*(imagedata + i * width + j)).green = 0;
//(*(imagedata + i * width + j)).red = 0;
}
}
//读出图片的像素数据 读取时一次一行 读高度数的行
fread
(
imagedata
,
sizeof
(
struct
tagIMAGEDATA
)
*
width
,
height
,
fpi
);
/size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
fclose
(
fpi
);
//=====图片裁剪处理======//
int
leftdownx
,
leftdowny
,
rightupx
,
rightupy
;
/用户输入数值
int
Rleftdownx
,
Rleftdowny
,
Rrightupx
,
Rrightupy
;
/转换成实际可以使用数值
cout
<<
"请输入要裁剪的矩形区域的左下角和右上角的坐标(连续四个整数值,如50 50 300 300):"
<<
endl
;
cin
>>
leftdownx
;
cin
>>
leftdowny
;
cin
>>
rightupx
;
cin
>>
rightupy
;
if
(
leftdownx
<=
0
||
leftdowny
<=
0
)
将用户输入的矩形框限定在原图像中
{
Rleftdownx
=
0
;
Rleftdowny
=
0
;
}
else
{
Rleftdownx
=
leftdownx
;
Rleftdowny
=
leftdowny
;
}
if
(
rightupx
>=
width
)
{
Rrightupx
=
width
;
}
else
{
Rrightupx
=
rightupx
;
}
if
(
rightupy
>=
height
)
{
Rrightupy
=
height
;
}
else
{
Rrightupy
=
rightupy
;
}
int
CutWidth
=
Rrightupx
-
Rleftdownx
;
图像每一行的字节数必须是4的整数倍
CutWidth
=
(
CutWidth
*
sizeof
(
IMAGEDATA
)
+
3
)
/
4
*
4
;
矩形框实际宽度
int
CutHeight
=
Rrightupy
-
Rleftdowny
;
矩形框实际高度
imagedataCut
=
(
IMAGEDATA
*
)
malloc
(
CutWidth
*
CutHeight
*
sizeof
(
IMAGEDATA
));
///为裁剪后图像分配存储空间
//初始化裁剪后图片的像素数组 一个字节一个字的写入
for
(
i
=
1
;
i
<
CutHeight
;
++
i
)
{
for
(
int
j
=
0
;
j
<
CutWidth
;
++
j
)
{
(
*
(
imagedataCut
+
i
*
CutWidth
+
j
)).
blue
=
0
;
}
}
imagedata
+=
(
Rleftdowny
)
*
width
+
Rleftdownx
;
原始图像数据数组指针移动到矩形框的左下角。
for
(
int
k
=
0
;
k
<
CutHeight
;
++
k
)
裁剪区域数据提取
{
for
(
int
l
=
0
;
l
<
CutWidth
;
++
l
)
*
(
imagedataCut
+
k
*
CutWidth
+
l
)
=
*
(
imagedata
+
k
*
width
+
l
+
Rleftdownx
);
此式子一定要注意写法。主要是注意二维数组指针的用法。
}
//保存bmp图片
if
((
fpw
=
fopen
(
"Cutresult.bmp"
,
"wb"
))
==
NULL
)
{
cout
<<
"create the bmp file error!"
<<
endl
;
return
NULL
;
}
fwrite
(
&
bfType_w
,
1
,
sizeof
(
WORD
),
fpw
);
fwrite
(
&
strHead
,
1
,
sizeof
(
tagBITMAPFILEHEADER
),
fpw
);
strInfo
.
biWidth
=
CutWidth
;
strInfo
.
biHeight
=
CutHeight
;
fwrite
(
&
strInfo
,
1
,
sizeof
(
tagBITMAPINFOHEADER
),
fpw
);
//保存调色板数据
for
(
unsigned
int
nCounti
=
0
;
nCounti
<
strInfo
.
biClrUsed
;
nCounti
++
)
{
fwrite
(
&
strPla
[
nCounti
].
rgbBlue
,
1
,
sizeof
(
BYTE
),
fpw
);
fwrite
(
&
strPla
[
nCounti
].
rgbGreen
,
1
,
sizeof
(
BYTE
),
fpw
);
fwrite
(
&
strPla
[
nCounti
].
rgbRed
,
1
,
sizeof
(
BYTE
),
fpw
);
fwrite
(
&
strPla
[
nCounti
].
rgbReserved
,
1
,
sizeof
(
BYTE
),
fpw
);
}
//保存像素数据
for
(
i
=
0
;
i
<
CutHeight
;
++
i
)
{
for
(
int
j
=
0
;
j
<
CutWidth
;
++
j
)
{
fwrite
(
&
((
*
(
imagedataCut
+
i
*
CutWidth
+
j
)).
blue
),
1
,
sizeof
(
BYTE
),
fpw
);
//fwrite( &((*(imagedataRot + i * FloatToIntwidth + j)).green),1,sizeof(BYTE),fpw);
//fwrite( &((*(imagedataRot + i * FloatToIntwidth + j)).red),1,sizeof(BYTE),fpw);
}
}
printf
(
"裁剪变换完成,请查看Cutresult.bmp文件。
\n\n
"
);
fclose
(
fpw
);
//释放内存
//delete[] imagedata;///不能释放imagedata,里面还有数据。
delete
[]
imagedataCut
;
///===========图片裁剪处理结束======
///==========重新打开文件======
cout
<<
"请输入所要读取的文件名(Cutresult.bmp):"
<<
endl
;
cin
>>
strFile
;
fpi
=
fopen
(
strFile
,
"rb"
);
if
(
fpi
!=
NULL
)
{
//先读取文件类型
WORD
bfType
;
fread
(
&
bfType
,
1
,
sizeof
(
WORD
),
fpi
);
if
(
0x4d42
!=
bfType
)
///if !=BMP
{
cout
<<
"the file is not a bmp file!"
<<
endl
;
return
NULL
;
}
printf
(
"
\n
读取到的文件是%s。
\n\n
"
,
strFile
);
//读取bmp文件的文件头和信息头
fread
(
&
strHead
,
1
,
sizeof
(
tagBITMAPFILEHEADER
),
fpi
);
showBmpHead
(
strHead
);
//显示文件头
fread
(
&
strInfo
,
1
,
sizeof
(
tagBITMAPINFOHEADER
),
fpi
);
showBmpInforHead
(
strInfo
);
//显示文件信息头
//读取调色板
for
(
unsigned
int
nCounti
=
0
;
nCounti
<
strInfo
.
biClrUsed
;
nCounti
++
)
{
fread
((
char
*
)
&
(
strPla
[
nCounti
].
rgbBlue
),
1
,
sizeof
(
BYTE
),
fpi
);
fread
((
char
*
)
&
(
strPla
[
nCounti
].
rgbGreen
),
1
,
sizeof
(
BYTE
),
fpi
);
fread
((
char
*
)
&
(
strPla
[
nCounti
].
rgbRed
),
1
,
sizeof
(
BYTE
),
fpi
);
fread
((
char
*
)
&
(
strPla
[
nCounti
].
rgbReserved
),
1
,
sizeof
(
BYTE
),
fpi
);
}
width
=
strInfo
.
biWidth
;
height
=
strInfo
.
biHeight
;
imagedata
=
(
IMAGEDATA
*
)
malloc
(
width
*
height
*
sizeof
(
IMAGEDATA
));
///为原始图像分配存储空间
//初始化原始图片的像素数组
for
(
int
i
=
0
;
i
<
height
;
++
i
)
{
for
(
int
j
=
0
;
j
<
width
;
++
j
)
{
(
*
(
imagedata
+
i
*
width
+
j
)).
blue
=
0
;
//(*(imagedata + i * width + j)).green = 0;
//(*(imagedata + i * width + j)).red = 0;
}
}
//读出图片的像素数据 读取时一次一行 读高度数的行
fread
(
imagedata
,
sizeof
(
struct
tagIMAGEDATA
)
*
width
,
height
,
fpi
);
/
fclose
(
fpi
);
}
else
{
cout
<<
"file open error!"
<<
endl
;
return
NULL
;
}
//图片缩放处理
cout
<<
"请输入要缩放的倍数:"
<<
endl
;
cin
>>
ExpScalValue
;
///如果ExpScalValue含有小数,需要整数化
///对期望的缩放结果取整
FloatToIntwidth
=
(
int
)(
ExpScalValue
*
width
);
FloatToIntheight
=
(
int
)(
ExpScalValue
*
height
);
//图像每一行的字节数必须是4的整数倍
FloatToIntwidth
=
(
FloatToIntwidth
*
sizeof
(
IMAGEDATA
)
+
3
)
/
4
*
4
;
imagedataScal
=
(
IMAGEDATA
*
)
malloc
(
FloatToIntwidth
*
FloatToIntheight
*
sizeof
(
IMAGEDATA
));
///为缩放后图像分配存储空间
//初始化缩放后图片的像素数组 一个字节一个字的写入
for
(
i
=
1
;
i
<
FloatToIntheight
;
++
i
)
{
for
(
int
j
=
0
;
j
<
FloatToIntwidth
;
++
j
)
{
(
*
(
imagedataScal
+
i
*
FloatToIntwidth
+
j
)).
blue
=
0
;
//(*(imagedataRot + i * FloatToIntwidth + j)).green = 0;
//(*(imagedataRot + i * FloatToIntwidth + j)).red = 0;
}
}
int
pre_i
,
pre_j
,
after_i
,
after_j
;
//缩放前后对应的像素点坐标
for
(
i
=
0
;
i
<
FloatToIntheight
;
++
i
)
{
for
(
int
j
=
0
;
j
<
FloatToIntwidth
;
++
j
)
{
after_i
=
i
;
after_j
=
j
;
pre_i
=
(
int
)(
after_i
/
ExpScalValue
);
/取整,插值方法为:最邻近插值(近邻取样法)
pre_j
=
(
int
)(
after_j
/
ExpScalValue
);
if
(
pre_i
>=
0
&&
pre_i
<
height
&&
pre_j
>=
0
&&
pre_j
<
width
)
//在原图范围内
*
(
imagedataScal
+
i
*
FloatToIntwidth
+
j
)
=
*
(
imagedata
+
pre_i
*
width
+
pre_j
);
}
}
//保存bmp图片
if
((
fpw
=
fopen
(
"Scalresult.bmp"
,
"wb"
))
==
NULL
)
{
cout
<<
"create the bmp file error!"
<<
endl
;
return
NULL
;
}
fwrite
(
&
bfType_w
,
1
,
sizeof
(
WORD
),
fpw
);
fwrite
(
&
strHead
,
1
,
sizeof
(
tagBITMAPFILEHEADER
),
fpw
);
strInfo
.
biWidth
=
FloatToIntwidth
;
strInfo
.
biHeight
=
FloatToIntheight
;
fwrite
(
&
strInfo
,
1
,
sizeof
(
tagBITMAPINFOHEADER
),
fpw
);
//保存调色板数据
for
(
nCounti
=
0
;
nCounti
<
strInfo
.
biClrUsed
;
nCounti
++
)
{
fwrite
(
&
strPla
[
nCounti
].
rgbBlue
,
1
,
sizeof
(
BYTE
),
fpw
);
fwrite
(
&
strPla
[
nCounti
].
rgbGreen
,
1
,
sizeof
(
BYTE
),
fpw
);
fwrite
(
&
strPla
[
nCounti
].
rgbRed
,
1
,
sizeof
(
BYTE
),
fpw
);
fwrite
(
&
strPla
[
nCounti
].
rgbReserved
,
1
,
sizeof
(
BYTE
),
fpw
);
}
//保存像素数据
for
(
i
=
0
;
i
<
FloatToIntheight
;
++
i
)
{
for
(
int
j
=
0
;
j
<
FloatToIntwidth
;
++
j
)
{
fwrite
(
&
((
*
(
imagedataScal
+
i
*
FloatToIntwidth
+
j
)).
blue
),
1
,
sizeof
(
BYTE
),
fpw
);
//fwrite( &((*(imagedataRot + i * FloatToIntwidth + j)).green),1,sizeof(BYTE),fpw);
//fwrite( &((*(imagedataRot + i * FloatToIntwidth + j)).red),1,sizeof(BYTE),fpw);
}
}
printf
(
"缩放变换完成,请查看Scalresult.bmp文件。
\n\n
"
);
fclose
(
fpw
);
//释放内存
delete
[]
imagedata
;
delete
[]
imagedataScal
;
==============图像缩放处理结束==============///
///===============图片旋转处理====================///
cout
<<
"请输入所要读取的文件名(Scalresult.bmp):"
<<
endl
;
cin
>>
strFile
;
FILE
*
fRor
,
*
fRow
;
int
AnyX
=
0
;
为适应任意形状做的长宽调整参数
fRor
=
fopen
(
strFile
,
"rb"
);
if
(
fRor
!=
NULL
){
//先读取文件类型
WORD
bfType
;
fread
(
&
bfType
,
1
,
sizeof
(
WORD
),
fRor
);
if
(
0x4d42
!=
bfType
)
{
cout
<<
"the file is not a bmp file!"
<<
endl
;
return
NULL
;
}
printf
(
"
\n
读取到的文件是%s。
\n\n
"
,
strFile
);
//读取bmp文件的文件头和信息头
fread
(
&
strHead
,
1
,
sizeof
(
tagBITMAPFILEHEADER
),
fRor
);
showBmpHead
(
strHead
);
//显示文件头
fread
(
&
strInfo
,
1
,
sizeof
(
tagBITMAPINFOHEADER
),
fRor
);
showBmpInforHead
(
strInfo
);
//显示文件信息头
//读取调色板
for
(
unsigned
int
nCounti
=
0
;
nCounti
<
strInfo
.
biClrUsed
;
nCounti
++
)
{
fread
((
char
*
)
&
(
strPla
[
nCounti
].
rgbBlue
),
1
,
sizeof
(
BYTE
),
fRor
);
fread
((
char
*
)
&
(
strPla
[
nCounti
].
rgbGreen
),
1
,
sizeof
(
BYTE
),
fRor
);
fread
((
char
*
)
&
(
strPla
[
nCounti
].
rgbRed
),
1
,
sizeof
(
BYTE
),
fRor
);
fread
((
char
*
)
&
(
strPla
[
nCounti
].
rgbReserved
),
1
,
sizeof
(
BYTE
),
fRor
);
}
width
=
strInfo
.
biWidth
;
height
=
strInfo
.
biHeight
;
AnyX
=
max
(
width
,
height
);
///适合任意形状图形
//图像每一行的字节数必须是4的整数倍
width
=
(
width
*
sizeof
(
IMAGEDATA
)
+
3
)
/
4
*
4
;
//imagedata = (IMAGEDATA*)malloc(width * height * sizeof(IMAGEDATA));
imagedata
=
(
IMAGEDATA
*
)
malloc
(
width
*
height
);
// imagedataRot = (IMAGEDATA*)malloc(2 * width * 2 * height * sizeof(IMAGEDATA));
imagedataRot
=
(
IMAGEDATA
*
)
malloc
(
2
*
AnyX
*
2
*
AnyX
*
sizeof
(
IMAGEDATA
));
//初始化原始图片的像素数组
for
(
int
i
=
0
;
i
<
height
;
++
i
)
{
for
(
int
j
=
0
;
j
<
width
;
++
j
)
{
(
*
(
imagedata
+
i
*
width
+
j
)).
blue
=
0
;
//(*(imagedata + i * width + j)).green = 0;
//(*(imagedata + i * width + j)).red = 0;
}
}
//初始化旋转后图片的像素数组
//for( i = 0;i < 2 * height;++i)
for
(
i
=
0
;
i
<
2
*
AnyX
;
++
i
)
{
for
(
int
j
=
0
;
j
<
2
*
AnyX
;
++
j
)
{
(
*
(
imagedataRot
+
i
*
2
*
AnyX
+
j
)).
blue
=
0
;
//(*(imagedataRot + i * 2 * width + j)).green = 0;
//(*(imagedataRot + i * 2 * width + j)).red = 0;
}
}
//读出图片的像素数据
fread
(
imagedata
,
sizeof
(
struct
tagIMAGEDATA
)
*
width
,
height
,
fRor
);
fclose
(
fRor
);
}
else
{
cout
<<
"file open error!"
<<
endl
;
return
NULL
;
}
//图片旋转处理
double
angle
;
//要旋转的弧度数
int
midX_pre
,
midY_pre
,
midX_aft
,
midY_aft
;
//旋转所围绕的中心点的坐标
midX_pre
=
width
/
2
;
midY_pre
=
height
/
2
;
midX_aft
=
AnyX
;
midY_aft
=
AnyX
;
cout
<<
"请输入要旋转的角度(0度到360度,逆时针旋转):"
<<
endl
;
cin
>>
RotateAngle
;
angle
=
1.0
*
RotateAngle
*
PI
/
180
;
/* 图像旋转的几何公式
x2=x1*cos(θ2)-y1*sin(θ2);
y2=x1*sin(θ2)+y1*cos(θ2);
*/
// for( i = 0;i < 2 * height;++i)
for
(
i
=
0
;
i
<
2
*
AnyX
;
++
i
)
{
for
(
int
j
=
0
;
j
<
2
*
AnyX
;
++
j
)
{
after_i
=
i
-
midX_aft
;
//坐标变换,如果不变换坐标,以(0,0)为参考点旋转后图片将转出坐标外。
after_j
=
j
-
midY_aft
;
pre_i
=
(
int
)(
cos
((
double
)
angle
)
*
after_i
-
sin
((
double
)
angle
)
*
after_j
)
+
midX_pre
;
/取整,插值方法为:最邻近插值(近邻取样法)
pre_j
=
(
int
)(
sin
((
double
)
angle
)
*
after_i
+
cos
((
double
)
angle
)
*
after_j
)
+
midY_pre
;
/*after_i = i;
after_j = j; 坐标不变换
pre_i = (int)(cos((double)angle) * after_i - sin((double)angle) * after_j) ;
pre_j = (int)(sin((double)angle) * after_i + cos((double)angle) * after_j) ;*/
坐标不变换效果
if
(
pre_i
>=
0
&&
pre_i
<
height
&&
pre_j
>=
0
&&
pre_j
<
width
)
//在原图范围内
*
(
imagedataRot
+
i
*
2
*
AnyX
+
j
)
=
*
(
imagedata
+
pre_i
*
AnyX
+
pre_j
);
}
}
//保存bmp图片
if
((
fRow
=
fopen
(
"Rotresult.bmp"
,
"wb"
))
==
NULL
)
{
cout
<<
"create the bmp file error!"
<<
endl
;
return
NULL
;
}
bfType_w
=
0x4d42
;
fwrite
(
&
bfType_w
,
1
,
sizeof
(
WORD
),
fRow
);
//fRow自动+=2;
fwrite
(
&
strHead
,
1
,
sizeof
(
tagBITMAPFILEHEADER
),
fRow
);
strInfo
.
biWidth
=
2
*
AnyX
;
//width;
strInfo
.
biHeight
=
2
*
AnyX
;
//height;
fwrite
(
&
strInfo
,
1
,
sizeof
(
tagBITMAPINFOHEADER
),
fRow
);
//保存调色板数据
for
(
nCounti
=
0
;
nCounti
<
strInfo
.
biClrUsed
;
nCounti
++
)
{
fwrite
(
&
strPla
[
nCounti
].
rgbBlue
,
1
,
sizeof
(
BYTE
),
fRow
);
fwrite
(
&
strPla
[
nCounti
].
rgbGreen
,
1
,
sizeof
(
BYTE
),
fRow
);
fwrite
(
&
strPla
[
nCounti
].
rgbRed
,
1
,
sizeof
(
BYTE
),
fRow
);
fwrite
(
&
strPla
[
nCounti
].
rgbReserved
,
1
,
sizeof
(
BYTE
),
fRow
);
}
//保存像素数据
for
(
i
=
0
;
i
<
2
*
AnyX
;
++
i
)
{
//for(int j = 0;j < 2 * width;++j)
for
(
int
j
=
0
;
j
<
2
*
AnyX
;
++
j
)
{
fwrite
(
&
((
*
(
imagedataRot
+
i
*
2
*
AnyX
+
j
)).
blue
),
1
,
sizeof
(
BYTE
),
fRow
);
//fwrite( &((*(imagedataRot + i * 2 * width + j)).green),1,sizeof(BYTE),fpw);
//fwrite( &((*(imagedataRot + i * 2 * width + j)).red),1,sizeof(BYTE),fpw);
}
}
printf
(
"旋转变换完成,请查看Rotresult.bmp文件。
\n\n
"
);
fclose
(
fRow
);
//释放内存
delete
[]
imagedata
;
delete
[]
imagedataRot
;
/==================图像旋转处理结束============///
return
1
;
}
/*
程序用到的图片从谷歌图片里可以搜到,只要是8位BMP位图即可。 将名字改成06.bmp、07.bmp或w.bmp
*/
【数字图像处理】<纯C++>读取、裁剪、缩放、旋转和存储8位bmp灰度图像
最新推荐文章于 2022-12-06 20:15:49 发布