我写的图像缩放程序(双立方插值算法)
小俊2010/01/10软件综合 IP:北京

#include <cmath>

typedef struct
{
  unsigned char x;
  unsigned char y;
  unsigned char z;
  unsigned char w;
} uchar4;

#define INT_SCALE  256
#define INT_SCALE_SHF  8

// w0, w1, w2, and w3 are the four cubic B-spline basis functions
__inline long w0_int(long a)
{
  return ((a*(a*(-a + 3*INT_SCALE) - 3*INT_SCALE*INT_SCALE) + INT_SCALE*INT_SCALE*INT_SCALE)/6)>>(INT_SCALE_SHF*2);   // optimized
}

__inline long w1_int(long a)
{
   return ((a*a*(3*a - 6*INT_SCALE) + 4*INT_SCALE*INT_SCALE*INT_SCALE)/6)>>(INT_SCALE_SHF*2);
}

__inline long w2_int(long a)
{
  return ((a*(a*(-3*a + 3*INT_SCALE) + 3*INT_SCALE*INT_SCALE) + INT_SCALE*INT_SCALE*INT_SCALE)/6)>>(INT_SCALE_SHF*2);
}

__inline long w3_int(long a)
{
  return ((a*a*a)/6)>>(INT_SCALE_SHF*2);
}

__inline unsigned long texPick(unsigned long *image, int x, int y, unsigned long p, unsigned long h)
{
  if(x < 0)
    x = 0;
  else if(x >= p)
    x = p - 1;
  if(y < 0)
    y = 0;
  else if (y >= h)
    y = h - 1;

  return image[y * p + x];
}

__inline unsigned long cubicFilter_int(long x, unsigned long c0, unsigned long c1, unsigned long c2, unsigned long c3)
{

  uchar4 *p[4];
  p[0] = (uchar4 *)&c0;
  p[1] = (uchar4 *)&c1;
  p[2] = (uchar4 *)&c2;
  p[3] = (uchar4 *)&c3;

  uchar4 r;

  long w0x = w0_int(x);
  long w1x = w1_int(x);
  long w2x = w2_int(x);
  long w3x = w3_int(x);

  r.x = (p[0]->x * w0x + p[1]->x * w1x + p[2]->x * w2x + p[3]->x * w3x + INT_SCALE / 2) >> INT_SCALE_SHF;

  r.y = (p[0]->y * w0x + p[1]->y * w1x + p[2]->y * w2x + p[3]->y * w3x + INT_SCALE / 2) >> INT_SCALE_SHF;

  r.z = (p[0]->z * w0x + p[1]->z * w1x + p[2]->z * w2x + p[3]->z * w3x + INT_SCALE / 2) >> INT_SCALE_SHF;

  r.w = 0xff;

  return *((unsigned long *)&r);
}

// using 16 texture lookups
__inline unsigned long tex2DBicubic(unsigned long *image, float x, float y, unsigned long pitch4, unsigned long height)
{
  x -= 0.5f;
  y -= 0.5f;
  int px = (int)x;
  int py = (int)y;
  long fx = (x - px) * INT_SCALE + 0.500001f;
  long fy = (y - py) * INT_SCALE + 0.500001f;

  return cubicFilter_int(fy,
               cubicFilter_int(fx, texPick(image, px-1, py-1, pitch4, height), texPick(image, px, py-1, pitch4, height), texPick(image, px+1, py-1, pitch4, height), texPick(image, px+2,py-1, pitch4, height)),
               cubicFilter_int(fx, texPick(image, px-1, py, pitch4, height),   texPick(image, px, py, pitch4, height),   texPick(image, px+1, py, pitch4, height),   texPick(image, px+2, py, pitch4, height)),
               cubicFilter_int(fx, texPick(image, px-1, py+1, pitch4, height), texPick(image, px, py+1, pitch4, height), texPick(image, px+1, py+1, pitch4, height), texPick(image, px+2, py+1, pitch4, height)),
               cubicFilter_int(fx, texPick(image, px-1, py+2, pitch4, height), texPick(image, px, py+2, pitch4, height), texPick(image, px+1, py+2, pitch4, height), texPick(image, px+2, py+2, pitch4, height))
               );
}

UINT AFX_CDECL CPUBicubicThread(LPVOID param)
{
  unsigned long *p = (unsigned long *)param;

  unsigned long *image = (unsigned long *)p[0];
  unsigned long pitch = p[1];
  unsigned long pitch4 = p[1] / 4;
  unsigned long width = p[2];
  unsigned long height = p[3];
  unsigned long y_amount = p[4];
  unsigned long y_start = p[5];
  unsigned long *image_out = (unsigned long *)p[6];
  float scale = *((float *)&p[7]);
  unsigned long pitch_org = p[8];
  unsigned long pitch4_org = p[8] / 4;
  unsigned long height_org = p[9];

  long x, y;

  image_out += pitch4 * y_start;

  for(y = y_start; y < y_start + y_amount; y ++)
  {
    if(y >= height)
      break;

    for(x = 0; x < width; x ++)
    {
      float u = x / scale;
      float v = y / scale;
      image_out[x] = tex2DBicubic(image, u, v, pitch4_org, height_org);
    }
    image_out += pitch4;
  }

  return 0;
}



双立方插值,没什么可解释的,看看photoshop的缩放就知道了。用的是比较常规的方法,目标图像的每个点由原图像相应坐标附近16个点插值得到。主函数我写成线程函数了,就是为了调动几个核一起跑。关键函数是tex2DBicubic。

在E7200双核CPU上能跑出每秒处理1128万像素的速度。

计算过程我全部改成整型计算了。如果用float的话会慢约50%。
+300  科创币    虎哥    2010/01/10
+200  科创币    我说要有光    2010/01/10 开放源代码的分享
来自:计算机科学 / 软件综合
16
 
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
小俊 作者
15年0个月前 IP:未同步
177042
我用Geforce GTX285跑这个程序的OpenCL版本(利用纹理单元优化),速度达到每秒23亿像素,是双核E7200的200多倍,是4核QX6600的100多倍。用4GHz的i7估计也要输六七十倍。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
小俊作者
15年0个月前 IP:未同步
181063
引用第4楼10班陈大葱22号于2010-01-24 00:17发表的  :
白痴问一下,为什么显卡比CPU快那么多?


1、本地存储器带宽超高
2、运算单元超多,能并行调度
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
小俊作者
14年11个月前 IP:未同步
195582
撇开软件环境不讲,旧GPU架构不适合这些较复杂的算法,而新的统一架构是近几年才出现的。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
小俊作者
14年11个月前 IP:未同步
195775
对,跟编译选项有关。只要选择对应的计算能力,无论是哪个CUDA版本对哪个GPU都是可以支持的。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
小俊
进士 学者 机友 笔友
文章
71
回复
1156
学术分
47
2006/12/29注册,2个月1天前活动
暂无简介
主体类型:个人
所属领域:无
认证方式:手机号
IP归属地:未同步
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}