} } return true; }其中Img那个结构体是这样的: typedef struct Img_struct { unsigned char *Img; //图像地址 int width; int height; //int biBitCount; }Img_struct,*Img_struct_p;
以下是我自己写的一个关于位图旋转缩放的函数,已经通过测试直接复制就可以用 参数:rad 角度 nID 位图ID CDC:CClientDC 本函数的优点是直接操作位图数据,在内存中计算后重新生成位图,效率是比较高的,如果哪位图高人有更好的方法请拿出来与大家分享 int MyBitmap::RotateBitmap(double rad, unsigned int nID,CDC *pDC) {
CDC thisDC; thisDC.CreateCompatibleDC(pDC);//创建与屏幕兼容的DC CBitmap bmp; if (!bmp.LoadBitmap(nID)) return -1 ; int Count,Count2; BITMAP bm1; bmp.GetBitmap(&bm1); int tempc; int xo,yo;//用于记录图形的中心点 double rad1=rad/(180/Pi);//旋转角度转换成弧度 tempc=bm1.bmWidth*bm1.bmWidth+bm1.bmHeight*bm1.bmHeight; Count = bm1.bmWidthBytes* bm1.bmHeight;//得到buf大小 Count2=tempc*4;//由于一个像素点4个字节所以将它*4 tempc=int(sqrt((double)tempc));//得到要创建的位图的宽度,为原来位图对角线的宽度 DWORD *Cl=new DWORD[Count]; DWORD *Cl2=new DWORD[Count2]; bmp.GetBitmapBits(Count,Cl);//将像素传入数组 bmp.DeleteObject(); xo=yo=tempc/2;//算出中心坐标 int x1,y1; int x2=bm1.bmWidth/2; int y2=bm1.bmHeight/2; int x3=0,y3=0; double pi=2*Pi; //半径变量//每取样一周半径增0.7.如果加1,会影响旋转的精度,会产生失真 //增量越大,失真越大.笔者实验得到0.7比较合理,如果太小,在旋转大位图时会影响速度 for (float r=1;r<=xo;r+=0.7){ //角度增量,/R是为了随着取样半径的增大减小失真 for (double a=0;a<pi;a+=0.7/r){ //计算出X1,Y1坐标 //即要取样的点 x1=int(r*cos(a));//x1=int(r*cos(a)/n)除以n就可以缩放了 y1=int(r*sin(a));//y1=int(r*sin(a)/n); //如果取样的点已经超出了原图像边界,则跳过 if (y1>=y2||y1<-y2||x1>=x2||x1<-x2) continue; //算出旋转旋转后的坐标 x3=int(r*cos(a+rad1)); y3=int (r*sin(a+rad1)); //将取样的点的坐标的像素赋给旋转后的坐标 Cl2[(yo+y3)*tempc+xo+x3]=Cl[(y2+y1)*bm1.bmWidth+x2+x1]; } } //中点是不旋转的 Cl2[yo*tempc+xo]=Cl[y2*bm1.bmWidth+x2]; bmp.CreateCompatibleBitmap(pDC,tempc,tempc);//创建宽度为原图对角线长度的位图. bmp.SetBitmapBits(Count2,Cl2);//将像素值写入位图 thisDC.SelectObject(&bmp); bmp.DeleteObject(); pDC->BitBlt(0,0,tempc,tempc,&thisDC,0,0,SRCCOPY); thisDC.DeleteDC(); delete [Count] Cl; delete [Count2] Cl2; return 0; }
能不能给点相关的代码。
http://blog.csdn.net/wenrenhua08/archive/2008/08/04/2767708.aspx
http://blog.csdn.net/xiayaxin/archive/2010/06/04/5647394.aspx
GetThumbnailImage OK了。
另外我以前用双线性插值写过一个放大的函数,希望能对你有用
bool ImgZoom(Img_struct *SImg,Img_struct *DImg,float rate)
{
if(0==SImg || 0==DImg)
return false; //扩大后的图像长宽
//这一步应该在申请内存空间的时候赋值和计算,源图像的长度和宽度最好是20的倍数
//这样放大后的图像长宽就是4的倍数
DImg->width=SImg->width*rate;
DImg->height=SImg->height*rate; unsigned char *tempDP=DImg->Img;
unsigned char *tempSP=SImg->Img;
//开始放大程序
//放大原理
//f(i+u,j+v)=(1-u)(1-v)f(i,j)+(1-u)vf(i,j+1)+u(1-v)f(i+1,j)+uvf(i+1,j+1)
int i,j;
float i_temp;
float j_temp;
float i_rest;
float j_rest;
int i_after;
int j_after;
for (i=0;i<DImg->height;i++)
{
for(j=0;j<DImg->width;j++)
{
//计算
i_temp=(float)(i/1.2);
j_temp=(float)(j/1.2); i_rest=i_temp-(int)(i_temp);
j_rest=j_temp-(int)(j_temp); i_after=(int)(i_temp);
j_after=(int)(j_temp);
*(tempDP+i*DImg->width*3+j*3)=((1-i_rest)*(1-j_rest)*(*(tempSP+i_after*SImg->width*3+j_after*3))+
(1-i_rest)*j_rest*(*(tempSP+i_after*SImg->width*3+(j_after+1)*3))+
i_rest*(1-j_rest)*(*(tempSP+(i_after+1)*SImg->width*3+j_after*3))+
i_rest*j_rest*(*(tempSP+(i_after+1)*SImg->width*3+(j_after+1)*3)));
*(tempDP+i*DImg->width*3+j*3+1)=((1-i_rest)*(1-j_rest)*(*(tempSP+i_after*SImg->width*3+j_after*3)+1)+
(1-i_rest)*j_rest*(*(tempSP+i_after*SImg->width*3+(j_after+1)*3+1))+
i_rest*(1-j_rest)*(*(tempSP+(i_after+1)*SImg->width*3+j_after*3+1))+
i_rest*j_rest*(*(tempSP+(i_after+1)*SImg->width*3+(j_after+1)*3+1)));
*(tempDP+i*DImg->width*3+j*3+2)=((1-i_rest)*(1-j_rest)*(*(tempSP+i_after*SImg->width*3+j_after*3+2))+
(1-i_rest)*j_rest*(*(tempSP+i_after*SImg->width*3+(j_after+1)*3+2))+
i_rest*(1-j_rest)*(*(tempSP+(i_after+1)*SImg->width*3+j_after*3+2))+
i_rest*j_rest*(*(tempSP+(i_after+1)*SImg->width*3+(j_after+1)*3+2)));
}
}
return true;
}其中Img那个结构体是这样的:
typedef struct Img_struct
{
unsigned char *Img; //图像地址
int width;
int height;
//int biBitCount;
}Img_struct,*Img_struct_p;
参数:rad 角度
nID 位图ID
CDC:CClientDC
本函数的优点是直接操作位图数据,在内存中计算后重新生成位图,效率是比较高的,如果哪位图高人有更好的方法请拿出来与大家分享
int MyBitmap::RotateBitmap(double rad, unsigned int nID,CDC *pDC)
{
CDC thisDC;
thisDC.CreateCompatibleDC(pDC);//创建与屏幕兼容的DC
CBitmap bmp;
if (!bmp.LoadBitmap(nID))
return -1 ;
int Count,Count2;
BITMAP bm1;
bmp.GetBitmap(&bm1);
int tempc;
int xo,yo;//用于记录图形的中心点
double rad1=rad/(180/Pi);//旋转角度转换成弧度
tempc=bm1.bmWidth*bm1.bmWidth+bm1.bmHeight*bm1.bmHeight;
Count = bm1.bmWidthBytes* bm1.bmHeight;//得到buf大小
Count2=tempc*4;//由于一个像素点4个字节所以将它*4
tempc=int(sqrt((double)tempc));//得到要创建的位图的宽度,为原来位图对角线的宽度
DWORD *Cl=new DWORD[Count];
DWORD *Cl2=new DWORD[Count2];
bmp.GetBitmapBits(Count,Cl);//将像素传入数组
bmp.DeleteObject();
xo=yo=tempc/2;//算出中心坐标
int x1,y1;
int x2=bm1.bmWidth/2;
int y2=bm1.bmHeight/2;
int x3=0,y3=0;
double pi=2*Pi;
//半径变量//每取样一周半径增0.7.如果加1,会影响旋转的精度,会产生失真
//增量越大,失真越大.笔者实验得到0.7比较合理,如果太小,在旋转大位图时会影响速度
for (float r=1;r<=xo;r+=0.7){
//角度增量,/R是为了随着取样半径的增大减小失真
for (double a=0;a<pi;a+=0.7/r){
//计算出X1,Y1坐标
//即要取样的点
x1=int(r*cos(a));//x1=int(r*cos(a)/n)除以n就可以缩放了
y1=int(r*sin(a));//y1=int(r*sin(a)/n);
//如果取样的点已经超出了原图像边界,则跳过
if (y1>=y2||y1<-y2||x1>=x2||x1<-x2)
continue;
//算出旋转旋转后的坐标
x3=int(r*cos(a+rad1));
y3=int (r*sin(a+rad1));
//将取样的点的坐标的像素赋给旋转后的坐标
Cl2[(yo+y3)*tempc+xo+x3]=Cl[(y2+y1)*bm1.bmWidth+x2+x1];
}
}
//中点是不旋转的
Cl2[yo*tempc+xo]=Cl[y2*bm1.bmWidth+x2];
bmp.CreateCompatibleBitmap(pDC,tempc,tempc);//创建宽度为原图对角线长度的位图.
bmp.SetBitmapBits(Count2,Cl2);//将像素值写入位图
thisDC.SelectObject(&bmp);
bmp.DeleteObject();
pDC->BitBlt(0,0,tempc,tempc,&thisDC,0,0,SRCCOPY);
thisDC.DeleteDC();
delete [Count] Cl;
delete [Count2] Cl2;
return 0;
}