前几天碰上需要对bmp位图进行缩放的功能,
调用API函数,虽然能实现位图缩放,但是对有放大的效果好,缩小会造成失真,图像上有花点,让人难以接受
,因为本人以前学易语言,易语言有一段代码,对bmp图像缩放效果非常 好,
昨天抽空,把它翻译成c++代码了,经验证,非常 好用,帖上代码:
这一段是对宽度进行缩放:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
void
__stdcall bmpsetH(unsigned
char
*bitmap,
int
h,unsigned
char
*bitmap2)
{
int
i,j,k,bitmapH1,bitmapH2,bitmapV1,bitmapV2,bitmapSize1,bitmapSize2,bitmapLen1,bitmapLen2;
int
startH1,startH2,R,G,B,R1,G1,B1;
// 位图宽1 = 取字节集数据 (位图数据, #整数型, 19)
bitmapH1=*((
int
*)(bitmap+18));
bitmapV1=*((
int
*)(bitmap+22));
int
redress1=bitmapH1%4;
int
bitmapNH1=bitmapH1*3+redress1;
bitmapLen1=bitmapNH1*bitmapV1;
bitmapSize1=bitmapLen1+54;
int
redress2=h%4;
int
bitmapNH2=h*3+redress2;
bitmapLen2=bitmapNH2*bitmapV1;
bitmapSize2=bitmapLen2+54;
memcpy
(bitmap2,bitmap,54);
memcpy
(bitmap2+2,&bitmapSize2,4);
memcpy
(bitmap2+18,&h,4);
double
Hval=(
double
)bitmapH1/h;
double
Hvala=0;
int
Hvalb=0,Hvalc=0;
for
(i=1;i<=bitmapV1;i++)
{
startH2=bitmapSize2-i*bitmapNH2;
startH1=bitmapSize1-i*bitmapNH1;
B1=bitmap[startH1];
G1=bitmap[startH1+1];
R1=bitmap[startH1+2];
for
(j=1;j<=h;j++)
{
startH2=startH2+3;
Hvala=Hvala+Hval;
if
(Hvala<1)
{
Hvalb=3;
}
else
{
Hvalc=Hvala;
Hvalb=Hvalc*3;
}
startH1=bitmapSize1-i*bitmapNH1+Hvalb;
B=(bitmap[startH1-3]+B1)/2;
G=(bitmap[startH1-2]+G1)/2;
R=(bitmap[startH1-1]+R1)/2;
bitmap2[startH2-3]=B;
bitmap2[startH2-2]=G;
bitmap2[startH2-1]=R;
B1=bitmap[startH1-3];
G1=bitmap[startH1-2];
R1=bitmap[startH1-1];
}
Hvala=0;
}
}
|
这一段是对高度进行缩放:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
void
BmpSetV(unsigned
char
*bitmap,
int
v,unsigned
char
*bitmap2)
{
double
Vval,Vvala=0;
int
i,j,Vvalb=0,bitH1,bitNH1,bitV1,redress,bitLen1,bitsize1,bitLen2,bitsize2;
int
start3=0,start2=0,start1=0,G1,B1,R1,R,G,B;
bitH1=*((
int
*)(bitmap+18));
bitV1=*((
int
*)(bitmap+22));
redress=bitH1%4;
bitNH1=bitH1*3+redress;
bitLen1=bitNH1*bitV1;
bitsize1=bitLen1+54;
bitLen2=bitNH1*v;
bitsize2=bitLen2+54;
memcpy
(bitmap2,bitmap,54);
memcpy
(bitmap2+2,&bitsize2,4);
memcpy
(bitmap2+22,&v,4);
Vval=bitV1/(
double
)v;
for
(i=1;i<=bitH1;i++)
{
start3=bitsize1-bitNH1+i*3;
B1=bitmap[start3-3];
G1=bitmap[start3-2];
R1=bitmap[start3-1];
for
(j=1;j<=v;j++)
{
Vvala=Vvala+Vval;
if
(Vvala<1)Vvalb=1;
else
Vvalb=Vvala;
start2=bitsize2-j*bitNH1+i*3;
start1=bitsize1-Vvalb*bitNH1+i*3;
if
(Vvalb
{
start3=bitsize1-Vvalb*bitNH1-bitNH1+i*3;
if
(i==1)
{
bitmap2[start2-3]=bitmap[start1-3];
bitmap2[start2-2]=bitmap[start1-2];
bitmap2[start2-1]=bitmap[start1-1];
}
else
{
B=(B1+bitmap[start1-3])/2;
G=(G1+bitmap[start1-2])/2;
R=(R1+bitmap[start1-1])/2;
bitmap2[start2-3]=B;
bitmap2[start2-2]=G;
bitmap2[start2-1]=R;
B1=bitmap[start3-3];
G1=bitmap[start3-2];
R1=bitmap[start3-1];
}
}
else
{
bitmap2[start2-3]=bitmap[start1-3];
bitmap2[start2-2]=bitmap[start1-2];
bitmap2[start2-1]=bitmap[start1-1];
}
}
Vvala=0;
}
}
|
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
int
main(
int
argc,
char
* argv[])
{
unsigned
char
*bmp,*bmp2;
bmp=(unsigned
char
*)
malloc
(1244214);
bmp2=(unsigned
char
*)
malloc
(1244214);
FILE
*fp=
fopen
(
"D:\\开机画面.bmp"
,
"rb"
);
fread
(bmp,1,304182,fp);
fclose
(fp);
//bmpsetH(bmp,720,bmp2);
// memcpy(bmp,bmp2,1244214);
BmpSetV(bmp,290,bmp2);
fp=
fopen
(
"D:\\开机.bmp"
,
"wb"
);
fwrite
(bmp2,1,1244214,fp);
fclose
(fp);
free
(bmp);
free
(bmp2);
return
0;
}
|
看到这确实不容易,这里脚本之家小编就为大家分享另一个代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
|
// suofang.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
struct
header{
short
BM;
unsigned
int
filesize;
unsigned
int
recv;
unsigned
int
offset;
unsigned
int
bitmapheadlong;
unsigned
int
bitmapwith;
unsigned
int
bitmaphight;
short
bitmappageinfo;
short
bitperpixel;
unsigned
int
compress;
unsigned
int
bitmapsize;
unsigned
int
levelresolution;
unsigned
int
verticalresolution;
unsigned
int
colourmap;
unsigned
int
colourmapsize;
}bitmapheader;
#if 0
typedef
struct
tagBITMAPFILEHEADER
{
WORD
bfType;
// 位图文件的类型,必须为BM(0-1字节)
DWORD
bfSize;
// 位图文件的大小,以字节为单位(2-5字节)
WORD
bfReserved1;
// 位图文件保留字,必须为0(6-7字节)
WORD
bfReserved2;
// 位图文件保留字,必须为0(8-9字节)
DWORD
bfOffBits;
// 位图数据的起始位置,以相对于位图(10-13字节)
// 文件头的偏移量表示,以字节为单位
} BITMAPFILEHEADER;
typedef
struct
tagBITMAPINFOHEADER{
DWORD
biSize;
// 本结构所占用字节数(14-17字节)
LONG
biWidth;
// 位图的宽度,以像素为单位(18-21字节)
LONG
biHeight;
// 位图的高度,以像素为单位(22-25字节)
WORD
biPlanes;
// 目标设备的级别,必须为1(26-27字节)
WORD
biBitCount;
// 每个像素所需的位数,必须是1(双色),(28-29字节)
// 4(16色),8(256色)或24(真彩色)之一
DWORD
biCompression;
// 位图压缩类型,必须是 0(不压缩),(30-33字节)
// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
DWORD
biSizeImage;
// 位图的大小,以字节为单位(34-37字节)
LONG
biXPelsPerMeter;
// 位图水平分辨率,每米像素数(38-41字节)
LONG
biYPelsPerMeter;
// 位图垂直分辨率,每米像素数(42-45字节)
DWORD
biClrUsed;
// 位图实际使用的颜色表中的颜色数(46-49字节)
DWORD
biClrImportant;
// 位图显示过程中重要的颜色数(50-53字节)
} BITMAPINFOHEADER;
typedef
struct
tagRGBQUAD {
BYTE
rgbBlue;
// 蓝色的亮度(值范围为0-255)
BYTE
rgbGreen;
// 绿色的亮度(值范围为0-255)
BYTE
rgbRed;
// 红色的亮度(值范围为0-255)
BYTE
rgbReserved;
// 保留,必须为0
} RGBQUAD;
#endif
void
scale(
int
srcwith,
int
srcheight,
int
destwith,
int
destheight)
{
}
int
_tmain(
int
argc, _TCHAR* argv[4000000])
{
BITMAPFILEHEADER bmfHdr;
BITMAPINFOHEADER bi,bi1;
CFile file(
"d:\\pic1.bmp"
,CFile::modeRead);
file.Read(&bmfHdr,
sizeof
(BITMAPFILEHEADER));
file.Read(&bi,
sizeof
(BITMAPINFOHEADER));
DWORD
dwSize = (bi.biWidth*bi.biBitCount+31)/32*4*bi.biHeight;
PBYTE
pBuf =
new
BYTE
[dwSize];
file.Read(pBuf,dwSize);
file.Close();
/////////////////////////////////////////////////////////////////////////
file.Open(
"d:\\tmp1.bmp"
,CFile::modeCreate|CFile::modeReadWrite);
memcpy
(&bi1,&bi,
sizeof
(BITMAPINFOHEADER));
bi1.biWidth = 4000;
//400->200 ,718->359
bi1.biHeight = 4000;
//266->133,397->794
DWORD
dwSize1 = (bi1.biWidth * bi1.biBitCount + 31)/32*4*bi1.biHeight;
PBYTE
pBuf1 =
new
BYTE
[dwSize1];
BYTE
*pSrc,*pDest;
//ofstream file1("D:\\tmp.log");
#if 0
///////////////////////////////////最邻近值采样法(速度快)////////////////////////////////////////////////
float
m_xscale,m_yscale;
m_xscale = (
float
)bi.biWidth/(
float
)bi1.biWidth;
m_yscale = (
float
)bi.biHeight/(
float
)bi1.biHeight;
unsigned
long
k=0;
for
(
int
y = 0; y {
for
(
int
x=0; x {
pSrc = pBuf+(
int
)(y*m_yscale)*bi.biWidth*3+(
int
)(x*m_xscale)*3;
pDest = pBuf1+(
int
)(y*bi1.biWidth*3+x*3);
memcpy
(pDest,pSrc,3);
//*(unsigned long*)pDest=k++;
//*(unsigned long*)pDest=0x000000ff;
}
}
////////////////////////////////////缩放结束///////////////////////////////////////////////
#endif
#if 1
/////////////////////////////////////双线性插值法(经过优化)/////////////////////////////////////////////////////
int
sw = bi.biWidth - 1, sh = bi.biHeight - 1, dw = bi1.biWidth - 1, dh = bi1.biHeight - 1;
//源图像宽度,目标图像宽度
int
B, N, x, y;
//计算出的目标点对应于源图像中的浮点数横坐标N、纵坐标B,目标整数横坐标x、纵坐标y
int
nPixelSize = bi.biBitCount/8;
//像素大小
BYTE
* pLinePrev, *pLineNext;
//源图像中的行开始坐标和下一行开始坐标
//BYTE * pDest;
BYTE
* pA, *pB, *pC, *pD;
//源图像中最邻近的四个点
for
(
int
i = 0; i <= dh; ++i )
//高度递增
{
pDest = (
BYTE
* )(pBuf1+bi1.biWidth*i*nPixelSize);
y = i * sh / dh;
N = dh - i * sh % dh;
pLinePrev = (
BYTE
* )(pBuf+bi.biWidth*y*nPixelSize);
y++;
pLineNext = ( N == dh ) ? pLinePrev : (
BYTE
* )(pBuf+bi.biWidth*y*nPixelSize);
for
(
int
j = 0; j <= dw; ++j )
//宽度递增
{
x = j * sw / dw * nPixelSize;
B = dw - j * sw % dw;
pA = pLinePrev + x;
pB = pA + nPixelSize;
pC = pLineNext + x;
pD = pC + nPixelSize;
if
( B == dw )
{
pB = pA;
pD = pC;
}
for
(
int
k = 0; k < nPixelSize; ++k )
*pDest++ = (
BYTE
)(
int
)(
( B * N * ( *pA++ - *pB - *pC + *pD ) + dw * N * *pB++
+ dh * B * *pC++ + ( dw * dh - dh * B - dw * N ) * *pD++
+ dw * dh / 2 ) / (
double
)( dw * dh )
);
}
}
#endif
file.Write(&bmfHdr,
sizeof
(BITMAPFILEHEADER));
file.Write(&bi1,
sizeof
(BITMAPINFOHEADER));
file.Write(pBuf1,dwSize1);
file.Close();
//==release p memory==
delete
pBuf;
pBuf = NULL;
delete
pBuf1;
pBuf1 = NULL;
//==release p memory===
if
(pDest!=NULL)
{
pDest = NULL;
}
//if (pSrc!=NULL)
//{
//pSrc = NULL;
//}
//////////////////////////////////////////////////////////////
//MessageBox("Test successful","Info",MB_OKCANCEL);
return
0;
}
|
如对本文有疑问,请提交到交流社区,广大热心网友会为你解答!! 点击进入社区