图片的二次线性缩放

项目需要,要截图屏幕图片,并缩放1/4显示,使用已有的方式,缩小的效果不好,要用二次线性,在网络上找了一个算法加以修改,得到可接受的图像。代码如下:

采用浮点数运算可以得到比较好的效果,

而定点数,得到的效果比较差,用公司内部的定点数方式,得到的效果有所改善,但与浮点数效果还是有差距,感觉是取的定点数不是最合适的,谁有更好的取得定点数的方式可以分享一下。

#if 1  //浮点数的二次线性缩放
void RotateBmpB0(SFNColor* pSrcBuf,SFNColor* pDestBuf,int nSrcWi,int nSrcHe,int nDestWi,int nDestHe);
void Bilinear0(SFNColor* pic,double fx,double fy,int width,SFNColor* result);
#else  //定点数的二次线性缩放,但是定点数没有取好,导致图像模糊严重,所以才要浮点数的
void Bilinear0(SFNColor* pic,long fx,long fy,int width,SFNColor* result);
void RotateBmpB0(SFNColor* pSrcBuf,SFNColor* pDestBuf,int nSrcWi,int nSrcHe,int nDestWi,int nDestHe);
#endif

#if 1
void Bilinear0(SFNColor* pic,double fx,double fy,int width,SFNColor* result)
{
    long x= (long)fx;
    long y=(long)fy;
    if (x>fx)
         --x;
    //x=floor(fx);
    if (y>fy)
        --y;
    //y=floor(fy);
    {
        SFNColor Color0=pic[y * width + x];
        SFNColor Color2=pic[y * width + x+1];
        SFNColor Color1=pic[(y+1) * width + x];
        SFNColor Color3=pic[(y +1)* width + (x+1)];

        double u=fx-x;
        double v=fy-y;
        double pm3=u*v;
        double pm2=u*(1-v);
        double pm1=v*(1-u);
        double pm0=(1-u)*(1-v);

        SFInt8 R=(pm0*(Color0>>11)+pm1*(Color1>>11)+pm2*(Color2>>11)+pm3*(Color3>>11));//(Color0>>11);//
        SFInt8 G=(pm0*((Color0&0x07E0)>> 5)+pm1*((Color1&0x07E0)>> 5)+pm2*((Color2&0x07E0)>> 5)+pm3*((Color3&0x07E0)>> 5));//(Color0&0x07E0)>> 5;//
        SFInt8 B=(pm0*((Color0&0x001F))+pm1*((Color1&0x001F))+pm2*((Color2&0x001F))+pm3*((Color3&0x001F)));//(Color0&0x001F);//
        *result = (R<<11)|(G<<5)|B;
    }
   
}

 void RotateBmpB0(SFNColor* pSrcBuf,SFNColor* pDestBuf,int nSrcWi,int nSrcHe,int nDestWi,int nDestHe)
{
    SFNColor* pDstLine = pDestBuf;
    long y=0;
    for ( y=0;y<nDestHe;++y)
    {
        long x=0;
        double srcy=(y+0.4999999)*nSrcHe/nDestHe-0.5;
        if(srcy<0)srcy = 0;
       
        for ( x=0;x<nDestWi;++x)
        {
            double srcx=(x+0.4999999)*nSrcWi/nDestWi-0.5;
            if(srcx<0)srcx = 0;
            Bilinear0(pSrcBuf,srcx,srcy,nSrcWi,&pDstLine[x]);
        }
        pDstLine += nDestWi;
    }
}
#else
void Bilinear0(SFNColor* pic,long fx,long fy,int width,SFNColor* result)
{
    long x=fx >> 16; //if (x>fx) --x; x=floor(fx);  
    long y=fy >> 16;// if (y>fy) --y; y=floor(fy);

    SFUint16 Color0=pic[y * width + x];
    SFUint16 Color2=pic[y * width + x+1];
    SFUint16 Color1=pic[(y+1) * width + x];
    SFUint16 Color3=pic[(y +1)* width + (x+1)];

    SFUint32 u_8=(fx & 0xFFFF)>>8;
    SFUint32 v_8=(fy & 0xFFFF)>>8;
    SFUint32 pm3=(u_8*v_8);
    SFUint32 pm2=(u_8*(SFUint32)(256-v_8));
    SFUint32 pm1=(v_8*(SFUint32)(256-u_8));
    SFUint32 pm0=((256-u_8)*(256-v_8));

    SFUint8 R=(pm0*((Color0&0xF800)>>11)+pm1*((Color1&0xF800)>>11)+pm2*((Color2&0xF800)>>11)+pm3*((Color3&0xF800)>>11))>>16;//(Color0>>11);//
    SFUint8 G=(pm0*((Color0&0x07E0)>> 5)+pm1*((Color1&0x07E0)>> 5)+pm2*((Color2&0x07E0)>> 5)+pm3*((Color3&0x07E0)>> 5))>>16;//(Color0&0x07E0)>> 5;//
    SFUint8 B=(pm0*((Color0&0x001F))+pm1*((Color1&0x001F))+pm2*((Color2&0x001F))+pm3*((Color3&0x001F)))>>16;//(Color0&0x001F);//
 
    *result = (R<<11)|(G<<5)|B;
}

extern const SFUint16 _xs_fast_div_table_i16[513];
 SFInt32 fx32divi(SFInt32 a, int b)  //定点数除法,用这个方式,显示效果有所改善
{
    if(!a)
    {
        return 0;
    }
    else if(b>=-512 && b<=512)
    {
        if(b<0)
        {
            return (SFInt32)(((SFInt64)a*(-(int)_xs_fast_div_table_i16[-b]))>>16);
        }
        else
        {
            return (SFInt32)(((SFInt64)a*((int)_xs_fast_div_table_i16[b]))>>16);
        }
    }
    else
    {
        return (SFInt32)(a/b);
    }
}

 void RotateBmpB0(SFNColor* pSrcBuf,SFNColor* pDestBuf,int nSrcWi,int nSrcHe,int nDestWi,int nDestHe)
{
    //int nSrcX = 0,nSrcY= 0;
    long srcy=0;
    long y=0;
    SFNColor* pDstLine = pDestBuf;
    //SFUint64 nSrcXStep = nSrcWi / (float)nDestWi * (1<<16);
    //SFUint64 nSrcYStep = nSrcHe / (float)nDestHe* (1<<16);
    //long nSrcXStep = fx32div(nSrcWi<<16,nDestWi<<16);
    //long nSrcYStep = fx32div(nSrcHe<<16,nDestHe<<16);
   // sf_dbgprintf(L"_______nSrcXStep=%d ; nSrcYStep=%d",nSrcXStep,nSrcYStep);

    /*long nSrcXStep = fx32divi(nSrcWi<<16,nDestWi);
    long nSrcYStep = fx32divi(nSrcHe<<16,nDestHe);*/
    long nSrcXStep = (nSrcWi<<16)/nDestWi;
    long nSrcYStep = (nSrcHe<<16)/nDestHe;
    //sf_dbgprintf(L"_______nSrcXStep=%d ; nSrcYStep=%d",nSrcXStep,nSrcYStep);
    if (nSrcXStep > nSrcYStep)
    {
        nSrcXStep = nSrcYStep;
    }
    else
    {
        nSrcYStep = nSrcXStep;
    }
    //sf_dbgprintf(L"___222____nSrcXStep=%d ; nSrcYStep=%d",nSrcXStep,nSrcYStep);
    for ( y=0;y<nDestHe;++y)
    {
        long srcx=0;
        long x=0;
        for ( x=0;x<nDestWi;++x)
        {
            Bilinear0(pSrcBuf,srcx,srcy,nSrcWi,&pDstLine[x]);
            srcx += nSrcXStep;
        }
        srcy += nSrcYStep;
        pDstLine += nDestWi;
    }
}
#endif

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值