我写的图像缩放程序(双立方插值算法)

#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    开放源代码的分享
来自:计算机科学 / 软件综合
 
darkstorm
11年3个月前
1楼
[s:92] 还有速度两倍多倍的GPU版本
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
phpskycn
11年3个月前
2楼
额,提供i7 920OC 4GHZ供测试
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
小俊作者
11年3个月前
3楼
我用Geforce GTX285跑这个程序的OpenCL版本(利用纹理单元优化),速度达到每秒23亿像素,是双核E7200的200多倍,是4核QX6600的100多倍。用4GHz的i7估计也要输六七十倍。
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
10班陈大葱22号
11年3个月前
4楼
白痴问一下,为什么显卡比CPU快那么多?
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
小俊作者
11年3个月前
5楼
引用第4楼10班陈大葱22号于2010-01-24 00:17发表的  :
白痴问一下,为什么显卡比CPU快那么多?


1、本地存储器带宽超高
2、运算单元超多,能并行调度
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
lovehongkong
11年3个月前
6楼
双立方插值不是很普遍的算法么...
[s:257]
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
chobits
11年2个月前
7楼
那现在电脑上的图像咋不用GPU来处理 锕。。
系不系相应的匹配问题啊
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
phpskycn
11年2个月前
8楼
CUDA是最近几年才发展起来的,再加上AMD-ATI的某些问题……
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
小俊作者
11年2个月前
9楼
撇开软件环境不讲,旧GPU架构不适合这些较复杂的算法,而新的统一架构是近几年才出现的。
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
phpskycn
11年2个月前
10楼
G80支持CUDA2.0吗?
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
darkstorm
11年2个月前
11楼
G80是计算能力1.0的,不能完全支持CUDA2.x所有特性,但是没有用到这些特性的话也可以跑程序
CUDA2.x特性需要计算能力1.2/1.3的硬件才能完全支持,双精度浮点需要计算能力1.3才能支持
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
小俊作者
11年2个月前
12楼
对,跟编译选项有关。只要选择对应的计算能力,无论是哪个CUDA版本对哪个GPU都是可以支持的。
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
hmz1063
11年1个月前
13楼
出个beta把
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
soundofwind
10年6个月前
14楼
你好,看了您帖出来的代码,我将代码加进vc6下,怎么跑不起来呢?谢谢你的回答
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
我说要有光
10年6个月前
15楼
回 14楼(soundofwind) 的帖子
这不是C程序,是CUDA程序
回复
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

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

所属专业
上级专业
同级专业
小俊
学者 机友 笔友
文章
71
回复
1158
学术分
47
2006/12/29注册,8 天前活动
暂无简介
%7B%22isDisplay%22%3Atrue%7D

仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。

插入资源
全部
图片
视频
音频
附件
全部
未使用
已使用
正在上传
空空如也~
上传中..{{f.progress}}%
处理中..
上传失败,点击重试
等待中...
{{f.name}}
空空如也~
(视频){{r.oname}}
{{selectedResourcesId.indexOf(r.rid) + 1}}
处理中..
处理失败
插入表情
我的表情
共享表情
Emoji
上传
注意事项
最大尺寸100px,超过会被压缩。为保证效果,建议上传前自行处理。
建议上传自己DIY的表情,严禁上传侵权内容。
点击重试等待上传{{s.progress}}%处理中...已上传
空空如也~
草稿箱
加载中...
此处只插入正文,如果要使用草稿中的其余内容,请点击继续创作。
{{fromNow(d.toc)}}
{{getDraftInfo(d)}}
标题:{{d.t}}
内容:{{d.c}}
继续创作
删除插入插入
{{forum.displayName}}
{{forum.countThreads}}
篇文章,
{{forum.countPosts}}
条回复
{{forum.description || "暂无简介"}}
ID: {{user.uid}}
学术分隐藏
{{submitted?"":"投诉或举报"}}
请选择违规类型:
{{reason.description}}
支持的图片格式:jpg, jpeg, png
插入公式
分享回复:{{shareId}}
加载中...
评论控制
加载中...
文号:{{pid}}
加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
加入关注取消关注
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
建议修改
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}
下载资料
{{fileName}}
大小:{{size}}
下载当前附件将花费 {{costMessage}}
你当前剩余 {{holdMessage}}
{{fileName}}
大小:{{size}}
当前附件免费。
你已购买过此附件,下载当前附件不需要花费积分。
加载中...
{{errorInfo}}
附件已丢失
当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}