关于图片的缩放功能

hunanrenjia 2010-10-25 05:05:54
我要将一张图片按比例缩小显示,不要用像StretchBlt这种函数,效果实在不怎么样。
最好给个算法或是给点代码。
谢谢!
...全文
226 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhengdaodong 2010-11-01
  • 打赏
  • 举报
回复
以下是我自己写的一个关于位图旋转缩放的函数,已经通过测试直接复制就可以用
参数: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;
}
zwt881106 2010-10-31
  • 打赏
  • 举报
回复
缩小就是行列的删除,放大的方法有临近插值,双线性插值等等。具体的效果不同~
tstytmr 2010-10-28
  • 打赏
  • 举报
回复
学习学习。。观摩
martenyong 2010-10-28
  • 打赏
  • 举报
回复
你可以用OpenCV,应该很方便的
另外我以前用双线性插值写过一个放大的函数,希望能对你有用
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;
重复的昵称嘛 2010-10-27
  • 打赏
  • 举报
回复
GDI+里面的 Image类
GetThumbnailImage OK了。
重复的昵称嘛 2010-10-27
  • 打赏
  • 举报
回复
GID+有吧,不然就用第三方的库吧 不少..FreeImage/CxImage等等。
leewckk 2010-10-26
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 hunanrenjia 的回复:]

leewckk:这么大的范围啊!能不能减小一点啊!!
[/Quote]
CSDN上有很多牛人写关于这些的博客,你可以在Google上搜“图片放缩算法 CSDN”
http://blog.csdn.net/wenrenhua08/archive/2008/08/04/2767708.aspx
http://blog.csdn.net/xiayaxin/archive/2010/06/04/5647394.aspx
swlilike 2010-10-26
  • 打赏
  • 举报
回复
学习学习。。观摩
fengbingchun 2010-10-26
  • 打赏
  • 举报
回复
看看OpenCV吧,里面有个cvResize函数可以直接用
hunanrenjia 2010-10-25
  • 打赏
  • 举报
回复
谢谢,zhanzh
能不能给点相关的代码。
zhanzh 2010-10-25
  • 打赏
  • 举报
回复
抽行抽列丢弃数据 实现缩小 ,重复相邻行列实现放大
hunanrenjia 2010-10-25
  • 打赏
  • 举报
回复
leewckk:这么大的范围啊!能不能减小一点啊!!
leewckk 2010-10-25
  • 打赏
  • 举报
回复
我记得CSDN上有人传了示例代码,你自己找找

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧