Flashseer BBS
 
»
游客:  注册 | 登录 | 会员 | 统计 | 帮助 | 翻译计划 | FlashSeer QQ群 | FlashSeer QQ群历史记录

RSS 订阅当前论坛  

标题: [翻译计划]DMF Tutorial  
 
雪の猫
2级
Rank: 5Rank: 5



UID 459
精华 0
积分 0
帖子 102
阅读权限 10
注册 2006-10-18
状态 离线
[翻译计划]DMF Tutorial

原文在(以及后两篇)
http://psyark.jp/?entry=20050924181651

中日对照:[attach]121[/attach]

http://psyark.jp
DisplacementMapFilter教程

DisplacementMapFilter是利用位图来操作位图的滤镜。前者的位图一般叫做映射位图(mapBitmap) 这个词因为长,我决定用一个简短的名字。(在日语中mapBitmap是マップビットマップ,确实很长,是但是中文却不是。为了方便,翻译的人在以后中使用英文mapBitmap。)。

输出图象的各象素的值,是根据mapBitmap相同位置的象素,采用源位图上的某一象素来确定的。
任意点(x,y)对应的输出图象的象素可以由下面的公式表示。
m[y][x],d[y][x],s[y][x]分别是mapBitmap,输出图象,输入图象上(x,y)象素的值。

var dx = (getComponent(m[y][x], componentX) - 0x80) * scaleX / 0x100;
var dy = (getComponent(m[y][x], componentY) - 0x80) * scaleY / 0x100;
d[y][x] = s[y + dy][x + dx];

function getComponent(color32:Number, component:Number):Number {
    switch (component) {
        case 1 : return 0xFF & color32 >> 16;
        case 2 : return 0xFF & color32 >> 8;
        case 4 : return 0xFF & color32;
        case 8 : return 0xFF & color32 >> 24;
    }
}

下面演示一些代表性的例子。componentX, componentY是8(alpha通道)以外的数字

·mapBitmap是50%灰度(0x808080)的情况,输出图象和输入图象相同。
·mapBitmap是黑色(0x000000)的情况,输出图象对输入图象有(scaleX / 2, scaleY / 2)的偏移。
·mapBitmap是白色(0xFFFFFF)的情况,输出图象对输入图象有(-scaleX / 2, -scaleY / 2)的偏移。(实际上是0x7F / 0x100,所以有一些误差)。

鼠标在输出图象上移动时,可以看到究竟采用的是输入图象的哪一点。

不支持上传swf --b  err......我有办法 ^_^
Flash: http://www.flashseer.org/bbs/attachment.php?aid=114

--------------------------------------------------------

利用上一次讲到的DisplacementMapFilter的性质,这次考虑的是如何生成能够完成期望变形的那个mapBitmap。

[attach]115[/attach]

这里,我们用把圆柱投影的世界地图的半面映射为地球仪的变形作为例子。输出图象上的地球的每一个象素,都对应输入图象上的一个象素,所以应该先把函数关系式表示出来。

[attach]116[/attach]

这一张是用经纬线表示的地图。从图中看到,几乎所有的经线都在变形后弯曲,而所有的纬线在变形之后还是直线。就是说可以判断,输出图象中Y相同的点,在输入图象中也有相同的Y。所以,变形前后的Y与X无关。

那让我们先从纬度(Y轴)方向的对应开始考虑。
下图表示的是输出图象的左视图。图中的蓝色曲线代表输入图象的映射。

[attach]117[/attach]

那么,试着把输入图象上任意的Y对应的输出图象的Y坐标(Y')的公式表示出来。
从图上Y的1/3处(输入图象的上1/3)入手。这可以用北纬PI/6表示。这时到赤道的距离是sin(PI/6),所以输出图象上的Y坐标(Y')是(1 - sin(PI / 6)) / 2

一般化得到 Y' = (1 - sin(PI * (0.5 - Y))) / 2

我们是根据“输出图象的某一坐标,是输入图象的哪一个坐标”来确定mapBitmap,所以把式子中Y作为函数解得:

Y = 0.5 - asin(1 - Y' * 2) / PI

而mapBitmap要使用的值是Y到 Y' 的距离,移项得:

yd = 0.5 - asin(1 - Y' * 2) / PI - Y'

然后就能写出Y轴方向变换的代码了。来试用一下滤镜吧。

import flash.display.BitmapData;
import flash.filters.DisplacementMapFilter;
import flash.geom.Rectangle;
Stage.scaleMode = "noScale";
//为了以后使用方便,宽高用变量表示
var W:Number = 160;
var H:Number = 160;
var earth:BitmapData = BitmapData.loadBitmap("earth");
var map:BitmapData = new BitmapData(W, H, false);
var out:BitmapData = map.clone();
for (var y = 0; y < H; ++y) {
    var yr = y / H; // 图象高度对应的Y的比例
    var lat = Math.asin(1 - yr * 2); // 纬度
    var yd = 0.5 - lat / Math.PI - yr; // 变形前后Y坐标的比例的差
    var yc = Math.round(yd * 0x100) + 0x80;
    map.fillRect(new Rectangle(0, y, W, 1), yc);
}
var disp:DisplacementMapFilter = new DisplacementMapFilter(map, null, 1, 4, 0, H);
out.applyFilter(earth, map.rectangle, null, disp);
attachBitmap(out, 0);

第13,14行使用了上面讲到的公式。

Flash: http://www.flashseer.org/bbs/attachment.php?aid=119
运行结果

Y轴方向的变换成功了。

因为文章较长,X周方向的变换下一次再讲。
※地球的图象是NASA的the Blue Marble经过同意使用
使用NASA网站的图象参照Guide line。

------------------------------------

接着上一次讲解DisplacementMapFilter的mapBitmap的制作方法。

上一次我们得到了Y轴方向的变换公式。

Y = 0.5 - asin(1 - Y' * 2) / PI
yd = 0.5 - asin(1 - Y' * 2) / PI - Y'

X轴方向的变换也按照这样来求取。

[attach]118[/attach]

图是输出图象的俯视图。蓝色的曲线表示赤道。

和上一次一样,输入图象的赤道上的点X和输出图象赤道上的点X',以及两点距离xd的关系式可以表示为

X' = (1 - cos(PI * X)) / 2
X = acos((0.5 - X') * 2) / PI
xd = acos((0.5 - X') * 2) / PI - X'

纬线的长度因为要随着纬度变高而变短,对于赤道,纬线的长度ew是:

X' = (1 - cos(PI * X) * ew) / 2
X = acos((0.5 - X') / ew * 2) / PI
xd = acos((0.5 - X') / ew * 2) / PI - X'

又,ew可以用式 cos(纬度) 得到,参考上一次的方法:

ew = cos(asin(1 - Y' * 2))

这样输出图象上任意一点的坐标(X', Y')所对应的输入图象的坐标(X,Y)就可以用公式表达出来了。

用下面的代码放到上一次的Actionscript代码中(替换掉11-18)。

for (var y = 0; y < H; ++y) {
    var yr = y / H; // 图象高度对应Y坐标的比例
    var lat = Math.asin(1 - yr * 2); // 纬度
    var yd = 0.5 - lat / Math.PI - yr; // 变形前后的Y坐标比例的差
    var yc = Math.round(yd * 0x100) + 0x80 << 8; // mapBitmap的Y分量
    var ew = Math.cos(lat); //纬线长
    for (var x = 0; x < W; ++x) {
        var xr = x / W; //图象宽对应X坐标的比例
        var xd = Math.acos((0.5 - xr) / ew * 2) / Math.PI - xr; //变形前后的X坐标比例的差
        var xc = Math.round(xd * 0x100) + 0x80; //mapBitmap的X分量
        map.setPixel(x, y, yc | xc);
    }
}
var disp:DisplacementMapFilter = new DisplacementMapFilter(map, null, 4, 2, W, H);


不过代码没有考虑地球仪所在圆外边的部分,圆的外边还残留有图象。

那么,圆外(0.5 - xr) / ew * 2不在-1~1的区间,所以可以利用Math.acos返回NaN。

    for (var x = 0; x < W; ++x) {
        var xr = x / W; // 图象宽对应X坐标的比例
        var lap = Math.acos((0.5 - xr) / ew * 2); // 经度
        if (isNaN(lap)) { //如果经度得不到,说明点在圆外
            var xc = xr > 0.5 ? 0xFF : 0; // 为mapBitmap的X分量指定一个最大数
        } else {
            var xd = lap / Math.PI - xr; //变形前后的X坐标比例的差
            var xc = Math.round(xd * 0x100) + 0x80; // mapBitmap的X分量
        }
        map.setPixel(x, y, yc | xc);
    }


然后,输入图象上得不到坐标点被涂黑了,所以要改一下滤镜的参数

var disp:DisplacementMapFilter = new DisplacementMapFilter(map, null, 4, 2, W, H, "color", 0x000000);

这样滤镜就完成了。大家辛苦了。

Flash: http://www.flashseer.org/bbs/attachment.php?aid=120
运行结果



mapBitmap中各分量在0x00~0xFF的范围应尽量有效的使用,这样可以提高画质量。

以下的的步骤在这一次省略了,但是都很简单请尝试:

让mapBitmap的X分量以0x80为中心变成原来的N倍
让mapBitmap的scaleX被N除
N太大导致超出0x00~0xFF的范围的调整

附件的rar文件其实都是swf文件,如果要下载的话,得改名:p

[ 本帖最后由 雪の猫 于 2007-3-15 00:47 编辑 ]


 附件: 您所在的用户组无法下载或查看附件
2007-3-14 23:00#1
查看资料  访问主页  发短消息  顶部
 
iiley
管理员
Rank: 9Rank: 9Rank: 9



UID 2
精华 0
积分 0
帖子 346
阅读权限 200
注册 2006-8-10
状态 离线
cool,赞!!!

对了,n0rthwood,文章也有一些了,什么时候提交给Adobe啊? ;]




http://www.iiley.com
http://www.aswing.org
http://www.flashseer.org
2007-3-15 11:04#2
查看资料  访问主页  Blog  发短消息  顶部
 
n0rthwood
管理员
Rank: 9Rank: 9Rank: 9


UID 24
精华 0
积分 0
帖子 302
阅读权限 200
注册 2006-8-10
状态 离线
雪猫好强,还懂日语!
你在北京吗?
提交的事情正在等待他们答复。




http://n0rthwood.blogspot.com/
2007-3-15 12:32#3
查看资料  访问主页  Blog  发短消息  顶部
 
iiley
管理员
Rank: 9Rank: 9Rank: 9



UID 2
精华 0
积分 0
帖子 346
阅读权限 200
注册 2006-8-10
状态 离线
哇靠,原来是日语的……………………太强了

QUOTE:
提交的事情正在等待他们答复
哦……期待,哈哈 ;]




http://www.iiley.com
http://www.aswing.org
http://www.flashseer.org
2007-3-16 13:03#4
查看资料  访问主页  Blog  发短消息  顶部
       





ICP证:粤ICP备06089120号;版权所有 flashseer.org 保留所有权flashseer.org
Processed in 0.093586 second(s), 9 queries

所有时间为 GMT+8, 现在时间是 2010-9-8 19:52
清除 Cookies - 联系我们 - Flashseer.org - Archiver - WAP