我要将一张图片按比例缩小显示,不要用像StretchBlt这种函数,效果实在不怎么样。
最好给个算法或是给点代码。
谢谢!

解决方案 »

  1.   

    我记得CSDN上有人传了示例代码,你自己找找
      

  2.   

    leewckk:这么大的范围啊!能不能减小一点啊!!
      

  3.   

    谢谢,zhanzh
    能不能给点相关的代码。
      

  4.   

    看看OpenCV吧,里面有个cvResize函数可以直接用
      

  5.   

    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
      

  6.   

    GID+有吧,不然就用第三方的库吧 不少..FreeImage/CxImage等等。
      

  7.   

    GDI+里面的 Image类 
    GetThumbnailImage OK了。
      

  8.   

    你可以用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;
      

  9.   

    以下是我自己写的一个关于位图旋转缩放的函数,已经通过测试直接复制就可以用
    参数: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;
    }