bmp 缩放代码(BMP位图任意放大 和缩小)

来源:互联网 发布:心事谁人知葫芦丝 编辑:程序博客网 时间:2024/06/05 20:35

前几天碰上需要对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,unsignedchar *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));
  intredress1=bitmapH1%4;
  intbitmapNH1=bitmapH1*3+redress1;
  bitmapLen1=bitmapNH1*bitmapV1;
  bitmapSize1=bitmapLen1+54;
  intredress2=h%4;
  intbitmapNH2=h*3+redress2;
  bitmapLen2=bitmapNH2*bitmapV1;
  bitmapSize2=bitmapLen2+54;
  memcpy(bitmap2,bitmap,54);
  memcpy(bitmap2+2,&bitmapSize2,4);
  memcpy(bitmap2+18,&h,4);
  doubleHval=(double)bitmapH1/h;
  doubleHvala=0;
  intHvalb=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,unsignedchar *bitmap2)
{  
 
doubleVval,Vvala=0;
  inti,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;
 elseVvalb=Vvala;
 start2=bitsize2-j*bitNH1+i*3;
 start1=bitsize1-Vvalb*bitNH1+i*3;
 if(Vvalb<bitV1)
 {
 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[])
{
  unsignedchar *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);
return0;
}

看到这确实不容易,这里脚本之家小编就为大家分享另一个代码

?
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
 
structheader{
  shortBM;
  unsignedint filesize;
  unsignedint recv;
  unsignedint offset;
  unsignedint bitmapheadlong;
  unsignedint bitmapwith;
  unsignedint bitmaphight;
  shortbitmappageinfo;
  shortbitperpixel;
  unsignedint compress;
  unsignedint bitmapsize;
  unsignedint levelresolution;
  unsignedint verticalresolution;
  unsignedint colourmap;
  unsignedint colourmapsize;
}bitmapheader;
#if 0
  typedefstruct tagBITMAPFILEHEADER
  {
  WORDbfType; // 位图文件的类型,必须为BM(0-1字节)
  DWORDbfSize; // 位图文件的大小,以字节为单位(2-5字节)
  WORDbfReserved1; // 位图文件保留字,必须为0(6-7字节)
  WORDbfReserved2; // 位图文件保留字,必须为0(8-9字节)
  DWORDbfOffBits; // 位图数据的起始位置,以相对于位图(10-13字节)
  // 文件头的偏移量表示,以字节为单位
  } BITMAPFILEHEADER;
 
 typedefstruct tagBITMAPINFOHEADER{
  DWORDbiSize; // 本结构所占用字节数(14-17字节)
  LONGbiWidth; // 位图的宽度,以像素为单位(18-21字节)
  LONGbiHeight; // 位图的高度,以像素为单位(22-25字节)
  WORDbiPlanes; // 目标设备的级别,必须为1(26-27字节)
  WORDbiBitCount;// 每个像素所需的位数,必须是1(双色),(28-29字节)
  // 4(16色),8(256色)或24(真彩色)之一
  DWORDbiCompression; // 位图压缩类型,必须是 0(不压缩),(30-33字节)
  // 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
  DWORDbiSizeImage; // 位图的大小,以字节为单位(34-37字节)
  LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数(38-41字节)
  LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数(42-45字节)
  DWORDbiClrUsed;// 位图实际使用的颜色表中的颜色数(46-49字节)
  DWORDbiClrImportant;// 位图显示过程中重要的颜色数(50-53字节)
  } BITMAPINFOHEADER;
 
  typedefstruct tagRGBQUAD {
  BYTErgbBlue;// 蓝色的亮度(值范围为0-255)
  BYTErgbGreen; // 绿色的亮度(值范围为0-255)
  BYTErgbRed; // 红色的亮度(值范围为0-255)
  BYTErgbReserved;// 保留,必须为0
  } RGBQUAD;
#endif
voidscale(int srcwith,int srcheight,intdestwith,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));
  DWORDdwSize = (bi.biWidth*bi.biBitCount+31)/32*4*bi.biHeight;
  PBYTEpBuf = 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
  DWORDdwSize1 = (bi1.biWidth * bi1.biBitCount + 31)/32*4*bi1.biHeight;
  PBYTEpBuf1 = new BYTE[dwSize1];
  BYTE*pSrc,*pDest;
 
  //ofstream file1("D:\\tmp.log");
 
#if 0
///////////////////////////////////最邻近值采样法(速度快)////////////////////////////////////////////////
  floatm_xscale,m_yscale;
  m_xscale = (float)bi.biWidth/(float)bi1.biWidth;
  m_yscale = (float)bi.biHeight/(float)bi1.biHeight;
  unsignedlong k=0;
  for(inty = 0; y  {
    for(intx=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
/////////////////////////////////////双线性插值法(经过优化)/////////////////////////////////////////////////////
  intsw = bi.biWidth - 1, sh = bi.biHeight - 1, dw = bi1.biWidth - 1, dh = bi1.biHeight - 1;   //源图像宽度,目标图像宽度
  intB, N, x, y;                                          //计算出的目标点对应于源图像中的浮点数横坐标N、纵坐标B,目标整数横坐标x、纵坐标y
  intnPixelSize = 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==
deletepBuf;
pBuf = NULL;
deletepBuf1;
pBuf1 = NULL;
//==release p memory===
if(pDest!=NULL)
{
pDest = NULL;
}
//if (pSrc!=NULL)
//{
//pSrc = NULL;
//}
//////////////////////////////////////////////////////////////
//MessageBox("Test successful","Info",MB_OKCANCEL);
 
  return0;
}

如对本文有疑问,请提交到交流社区,广大热心网友会为你解答!! 点击进入社区

原创粉丝点击