Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1361857
  • 博文数量: 343
  • 博客积分: 13098
  • 博客等级: 上将
  • 技术积分: 2862
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-06 00:35
文章存档

2012年(131)

2011年(31)

2010年(53)

2009年(23)

2008年(62)

2007年(2)

2006年(36)

2005年(5)

分类: C/C++

2009-01-19 14:22:36

今天基于gtk 2.0实现了一个双线性内插值的图像缩放。其实由于程序主要用在320x240的手机上,图像放大的user cases会远小于图像缩小。图像尺寸缩小到原来的1/4,感觉质量还是令人满意的;效率还没有测试过。
 
 

/*
 * Description:
 *
 * Image scaling based on bilinear interpolation algorithm
 *
 * Arguments:
 * @d: GdkDrawable object
 * @xoff, @yoff: Background picture offset to screen
 * @bgfile: Background picture filename. Alpha channel is ignored.
 * @x, @y: Foregorund picture offset to background picture
 * @fgfile: Foreground picture filename.
 * @nx, @ny: New geometry of fgfile after scaling.
 * @threshod: If foreground picture carrys alpha channel, alpha values
 * exceed this threshold get displayed.
 */


static void draw_scale(
    GdkDrawable* d,
    int xoff, int yoff,
    const char* bgfile,
    int x, int y,
    const char* fgfile,
    int nx, int ny,
    unsigned char threshold)
{
    GdkPixbuf* bgbuf = gdk_pixbuf_new_from_file(bgfile, NULL);
    GdkPixbuf* fgbuf = gdk_pixbuf_new_from_file(fgfile, NULL);

    if(bgbuf == NULL || fgbuf == NULL)
    {
        g_print("Can not open %s or %s\n", bgfile, fgfile);
        return;
    }

    int nbgchs = gdk_pixbuf_get_n_channels (bgbuf);
    int nfgchs = gdk_pixbuf_get_n_channels (fgbuf);

    int bgrowsz = gdk_pixbuf_get_rowstride(bgbuf);
    int fgrowsz = gdk_pixbuf_get_rowstride(fgbuf);

    int bgheight = gdk_pixbuf_get_height(bgbuf);
    int fgheight = gdk_pixbuf_get_height(fgbuf);

    int bgwidth = gdk_pixbuf_get_width(bgbuf);
    int fgwidth = gdk_pixbuf_get_width(fgbuf);

#ifdef _DEBUG
    g_print("bg file=%s, fg file=%s\n", bgfile, fgfile);
    g_print("bg channels=%d, fg channels=%d\n", nbgchs, nfgchs);
    g_print("bg row_size=%d, fg row_size=%d\n", bgrowsz, fgrowsz);
    g_print("bg height=%d, fg height=%d\n", bgheight, fgheight);
    g_print("bg width=%d, fg width=%d\n", bgwidth, fgwidth);
#endif

    unsigned char* bp = gdk_pixbuf_get_pixels (bgbuf);
    unsigned char* fp = gdk_pixbuf_get_pixels (fgbuf);

    float rx = (float)fgwidth/(float)nx;
    float ry = (float)fgheight/(float)ny;

    int i,j, n;
    for(j=0; j<ny; j++)
    {
        float oy = j*ry;
        int iy = (int)oy;
        float v = oy - iy;

        for(i=0; i<nx; i++)
        {
            float ox = i*rx;
            int ix = (int)ox;
            float u = ox - ix;

            int soff = (j+y)*bgrowsz+(i+x)*nbgchs;

            if( (ix+1 > fgwidth) || (iy+1 > fgheight) )
            {
                for(n=0; n<3; n++)
                    bp[soff+n] = 0xff;
            }
            else
            {
                int toff = iy*fgrowsz + ix*nfgchs;
                float nr = (1-u)*(1-v)*fp[toff];
                float ng = (1-u)*(1-v)*fp[toff+1];
                float nb = (1-u)*(1-v)*fp[toff+2];

                toff = (iy+1)*fgrowsz + ix*nfgchs;
                nr += (1-u)*v*fp[toff];
                ng += (1-u)*v*fp[toff+1];
                nb += (1-u)*v*fp[toff+2];

                toff = iy*fgrowsz + (ix+1)*nfgchs;
                nr += u*(1-v)*fp[toff];
                ng += u*(1-v)*fp[toff+1];
                nb += u*(1-v)*fp[toff+2];

                toff = (iy+1)*fgrowsz + (ix+1)*nfgchs;
                nr += u*v*fp[toff];
                ng += u*v*fp[toff+1];
                nb += u*v*fp[toff+2];


                bp[soff] = (unsigned char)nr;
                bp[soff+1] = (unsigned char)ng;
                bp[soff+2] = (unsigned char)nb;
            }
        } /* end for(i=...) */
    } /* end for(j=...) */

    gdk_draw_pixbuf(d, NULL, bgbuf, xoff, yoff, 0, 0, bgwidth, bgheight, GDK_RGB_DITHER_NONE, 0, 0);

    g_object_unref(bgbuf);
    g_object_unref(fgbuf);
}

 

文件: biliner.tar.gz
大小: 64KB
下载: 下载

阅读(1451) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~