AS3中置换滤镜的理解

在ActionScription中,DisplacementMapFilter是一个非常强大的滤镜,很多的特效,比如火焰,波纹等都会使用到它。另一方面,它也比较多变,让初学者难以掌握它的功能。下面的分析从AS3中使用的公式开始。

Adobe的官方文档)中,提到DisplacementMapFilter使用如下的公式:

dstPixel[x, y] = srcPixel[x + ((componentX(x, y) - 128)  scaleX) / 256, y + ((componentY(x, y) - 128)  scaleY) / 256)]

我们先来理解该公式。

这里面涉及到三个像素,源图上的srcPixel,置换图上的componentX和componentY以及最后生成的目标图上的dstPixel。为了便于理解,我们把上面的公式变化一下:

dstPixel[x, y] = srcPixel[(x + X), (y + Y)]
X = (componentX(x, y) - 128) scaleX) / 256
Y = (componentY(x, y) - 128)
scaleY) / 256

有上面的公式就可能很容易的看出来,,目标像素dstPixel [x, y] 就是源像素srcPixel [x, y]分别在x方向上偏移X距离,y方向上偏移Y距离后的一个结果。

所以DisplacementMapFilter的根本效果就是像素的偏移!

 

那么像素的偏移如何可以创造出那么绚烂的效果呢?很简单,就是对偏移量的控制。很容易想象一张正常的图片,上面的每个像素经过不同距离的偏移之后,它会产生的扭曲、挤压的效果。结合其他的滤镜,就可以创建很酷的效果。

 

我们回到偏移量的公式:

X = (componentX(x, y) - 128)  scaleX) / 256
Y = (componentY(x, y) - 128)
scaleY) / 256

里面有四个变数:置换图的像素componentX,componentY以及scaleX和scaleY。变数越多,结果就越难以琢磨。这也是置换滤镜的困难所在。

我们来深入看一下这个公式每一个量(变量和常量)的含义。

 

先看componentX和componentY的含义。

我们知道一个像素有四个通道:3个颜色通道RGB和1个Alpha通道。componentX和componentY在这里表示一个像素的颜色通道。因此,componentX(x, y)和componentY表示置换图上位置为(x, y)的像素点的指定颜色通道的值。颜色通道的设置可以通过构造函数来指定,并且源像素srcPixel(x, y)在x与y方向的偏移量可以由componentX(x, y)和componentY(x, y)分别指定。scaleX和scaleY作用类似,不必再提。

举个例子,比如置换图上(x, y)的点RGB值为0xaabbcc。现在指定 x 方向上的颜色通道为红色,y 方向上的颜色通道为绿色。componentX(x, y)的值就是0xaa,componentY(x, y)的值就是0xbb。其他值忽略。

 

再看常量128。这里不说为什么要减128,只看减了128之后是什么。

我们知道一个颜色通道的范围为 0 ~ 255, (componentX(x, y) - 128)的结果为 (-128, 127),其效果就是这个指定的颜色通道的值的范围只有 0 ~ 127,但是它有方向。看偏移量的公式,这个方向也是最后偏移量的方向,这个很好理解,就不再赘述。

 

最后我们看256以及scaleX和scaleY。我们再把偏移量公式稍微变化一下:

X = ((componentX(x, y) - 128) / 256)  scaleX
Y = ((componentY(x, y) - 128) / 256)
scaleY

上面我们知道,(componentX(x, y) - 128)的值为 -128 ~ 127,除以256之后就是±(0, 0.5),这可以看成是scale的一个系数。

 

整个偏移量的含义就比较明显了:scale的值缩小若干倍就是偏移量

 

至此,置换滤镜的含义就可以总结为:用置换图上某个位置的像素的某个颜色通道值控制缩放比例,得到一个偏移量;用该偏移量对源图上对应的像素进行偏移,得到目标图上对应位置的像素值。说白了就是用置换图上的像素控制源图上的像素进行偏移

 

虽然上面的结论比较拗口,但还不是DisplacementMapFilter提供的功能的全部。我们看一下它的构造函数:

1
2
3
4
5
6
7
8
9
10
11
DisplacementMapFilter(
mapBitmap:[BitmapData](../../flash/display/BitmapData.html) = null,
mapPoint:[Point](../../flash/geom/Point.html) = null,
componentX:[uint](../../uint.html) = 0,
componentY:[uint](../../uint.html) = 0,
scaleX:[Number](../../Number.html) = 0.0,
scaleY:[Number](../../Number.html) = 0.0,
mode:[String](../../String.html) = "wrap",
color:[uint](../../uint.html) = 0,
alpha:[Number](../../Number.html) = 0.0
)

其中mapPoint, mode, color和alpha我们并没有讨论。好在他们的含义并不难以理解,不提。


对三大桌面系统的一点看法

Windows是最流行的桌面系统,虽然现在Apple如日中天,但是短期之内无法撼动windows的地位。不过不可否认的是,windows已经开始走向没落。其实苗头早在几年前就已经显现,只是win7的推出犹如一支强心剂,给垂垂老矣的windows带来新的活力。但是现在那怕win8推出,也达不到那样的效果了。越来越多的人开始在windows之外尝试其他的系统,并且不想再回头。

Linux和OSX是流出的两大方向。几年以前,流出的方向是linux,现在多了一个选择。传奇的贵族式的osx比linux更具有吸引力。在软件行业,如果当年linux吸引的还主要是geek特质的对象,那么osx已经开始吸引普通的工程师。只要给他们机会,大部分人都乐意离开windows,投入osx或者linux的环抱。即使工作的关系在公司不得不使用windows,越来越多的工程师在家也安装了linux系统或是购买了安装osx的苹果电脑。我也是如此,要不是现在工作的需要必须绑定在windows上,我非常乐意去尝试全新的体验。但在家里,我还是购买了iMac并在笔记本上安装了ubuntu。

开发人员的数量和素质决定一个平台的命运。如果他们离开,剩下的就只有没落!而关于开发者离开的原因,就我个人观察,完全不是因为windows不够友好。在使用过osx半年之后,我并不觉得它比windows更出色,除去因为历史原因导致的软件方面的匮乏不谈,就一些系统自身的操作,很多方面windows也是更方便的。方便友好并不能决定开发者的去留。linux是公认的不友好,但是依然有大批的开发者,虽然它也有自身的问题。

影响开发者的选择的原因多种多样,但是有两个是最重要的:暗淡的前景和厌倦!

对真正的开发者来说,在windows上进行投入前景越来越暗淡,说的明确一点,就是收入越来越微薄。造成这一情况的原因也有两个:一个是外部的原因。自由软件吞噬了绝大部分的小软件的市场份额,个人开发者或是小型的开发团体已经无法从市场获利。同时当前整个桌面平台在向网络平台过渡,而微软提出的一些技术方案并没有得到其他公司和社区的支持,进一步压缩了其平台上的开发者的生存空间。另一个是微软自身的原因。频繁的抛出一些没有营养的概念,企图用学习成本把开发者捆绑在他的平台上,却忽略了整个生态环境的建立。当人们花了大力气追在他后面学习各种概念,比如不知所谓的.net,却发现学会了之后发展空间反而变窄了。一方面微软大力宣传学习成本低廉,大量的人员开始进入,另一方面微软并没有或是没能力为他的追随者们创造足够的发展空间。整个生态环境因为拥挤而变得恶劣,甚至微软为开发者们提供更容易使用的工具这样看似正确的事情也在伤害着他现在的开发者。由于门槛的降低,大批平庸的开发者涌入这一领域,必定严重冲击整个市场。如同在一些新技术行业的小公司,他们把是否从该行业中退出的风向标定为是否有中国公司进入一样,先来的开发者会陆续退出,另辟战场,并会很乐意的把windows留个他们。这情形就像投资者丢弃一支烂股票一样。

除了客观的原因以外,也有一些非理性的因素在起着影响。或多或少像我这样的人会对windows有一种厌倦感。我曾和朋友说,如果windows phone要成功,首先需要抛弃windows这个词,至少在商标和宣传上应该如此。这个词除了兼容性,并不能给我们其他的美好感觉,甚至在兼容性方面,他代表的也并不是完美。开发者喜欢新鲜感,但是windows,大家太熟悉了。他们有勇气承认不懂linux和osx,但是不好意思说自己不懂windows,哪怕他们确实对windows phone一无所知!人们第一印象并不会区分这是桌面和移动两个不同的系统,他们首先注意到的是相同点,这大概也是微软为什么要在phone前加上windows的原因,只是这个想法完全错了!而另一方面,windows的知识越来越没有特殊性,难于彰显个性。人们只有对自己不熟悉的东西才有好奇心。而失去好奇心的开发者根本就不能称为工程师。

windows开始没落,而桌面版linux,一开始就走入了歧途。桌面版linux的目标,如果他们有目标的话,就是在linux上建立windows的用户体验。看看这几年这个社区努力在做的事情,看看wine,看看gnome。他们只是在把linux变成免费的windows,可是他们并不成功,哪怕在个人市场以及非商业领域。现在使用linux的人,依然是那些应该使用linux的人。在我看来,沿着这条路走下去,他们永远也不可能成功。

osx的情况和linux的不同。它本来就是一个完善和强大桌面系统,只是价格限制了它的发展。它以某种方式被人们看作是一种奢侈品,是一种象征或是一种精神。当它走下神坛后必将立刻吸引大批的追随者,但是这种情况是否会持久并不能立刻作出判断。和windows以及它的近亲linux不同,osx平台上几乎所有的程序都是需要收费的。这对开发者而言却是一种很好的生存环境,只是这必然会阻碍它长期占据大众市场。

我对这三个主要的桌面系统的看法是它们应该根据各自的特色形成一个不交叉的定位:osx不应该想着打入主流市场,它甚至不应该进入服务器市场,这些与它长久以来的贵族式的特质并不吻合,强行进入反而会削弱原来的影响力。linux应该替换的是unix,除了服务器外还有科研领域。它应该为他的大批geek追随者提供更强的功能。他们不会在乎有没有ui界面,只要console足够强大,开发环境足够强大,社区支持足够强大,总之功能要足够强大。windows面向大众,它需要把自己弱化成一个工具并向osx和linux提供接口以接受他们的成果。他需要作出牺牲,放弃把人人都变成程序员的梦想,把专业的事情留个专业的人,而不是抢走他们的饭碗。

关于“十三个球用天平称三次,找出其中一个质量不同的球”的解

这个问题最重要的是如何分配这些球。我们可以假设该质量不同的球为x,并把13个球分成两组:A组8个球,B组5个球。
1. 把A组均分成两组:a组4个球,b组也是4个球。
2. 假如a=b,则x在B组; (第一次称)
1.)在A组中拿出3个正常的球组成c组;在B组5个球中取3个作为d组,剩余2个球为e组。
2.)假如c=d,则x在e组。 (第二次称)
(1.)在A组中取出一正常球作为f;在e组取出一球作为g,余下一球为h。
(2.)假如f=g,则h即为x。 (第三次称)
(结束)
(3.)否则g即为x。
(结束)
3.)假如c>d,则x在d组,并且为重球。
(1.)把d组的三个球分别表示为f,g,h。
(2.)假如f=g,则h即为x。 (第三次称)
(结束)
(3.)假如f>g,则f即为x,因为x是重球。
(结束)
(4.)假如f<g,则g即为x,因为x是重球。
(结束)
4.)假如c<d,则x在d组,并且为轻球。过程同3.)。
3. 否则,则x在A组。假如a>b,
1.)在a中取三个球组成c组,余下一球为d。
2.)在b中取两个球组成e组,余下两球为f组。
3.)假如(c+e)=B,则x在(d+f)中。 (第二次称)
(1.)把f组中两球分别表示为g,h。
(2.)假如(d+g)=e,则h即为x。 (第三次称)
(结束)
(3.)假如(d+g)>e,可知x为重球,因已知a>b,可得d即为x。
(结束)
(4.)假如(d+g)<e,可知x为轻球,因已知a>b,可知g即为x。
(结束)
4.)假如(c+e)>B,则x在(c+e)中,且为重球。
(1.)因为a>b,而x为重球,则x在c中。
(2.)由2.3.),可以得出x所在。
(结束)
5.)假如(c+e)<B,则x在(c+e)中,且为轻球。
(1.)因为a>b,而x为轻球,则x在e中。
(2.)把e组的两个球分别表示为g,h。
(3.)假如g>h,则h为x。 (第三次称)
(结束)
(4.)假如g<h,则g为x。
(结束)
4. 否则,则x在A组。假如a<b,
1.)过程同3.

如何补全proxy switchy!的功能

Proxy Switch!是一个Google Chrome浏览器的插件,通过它可以方便的设置和切换代理(Auto Switch Mode)。但是,Proxy Switch!新建的规则只能使用shExpMatch函数,这导致了一些局限性。下面的揭示如何让其支持自动代理脚步的其他的函数,唯一的要求是要有一个web空间可以存放自动代理脚步。

方法很简单,

  1. 把那些用shExpMatch无法满足的url和host放在一个文件中,比如proxy.pac,然后传到一个web空间。
  2. 在Switchy!新建的proxy profiles,比如ssh_proxy中,不使用manual configuration,而是Automatic Configuration,并在Auto Config URL中指明proxy.pac的地址。
  3. 在Switch Rules中,Default Rule的Proxy Profile中指定ssh_proxy。
  4. 由于proxy switchy!1.6.3版本的bug,除了在Default rule中指定ssh_proxy外,在自定义的rule中必须要有至少一项的profile也指定为ssh_proxy。
    这样设置后,虽然同一个url会被匹配两次,但是与获得的便利相比,性能的损失可以忽略。

'Go to work' and 'Get to work'

今天看New York Times一则关于防雪的报道,里面提到

… and people could not get to work.

平时我一直用”go to work”表示去上班的意思,这里为什么用”get to work”呢?好奇驱使下搜索了一下,发现它们还真是两个不同意思的词组。

“go to”表示的是动身去做,而”get to”的意思是到达。所以这两个词组的含义其实是:
“go to work”, 动身去上班,比如从家里出发;而”get to work”,是到达上班(的地方)。

如果说”could not go to work”,表示的是不能出发去上班,比如生病了之类,强调的是不能动身;”could not get to work”,表示的是不能到达上班的地方,比如大雪封路,强调的是不能到达。前面的报道如果用”go to work”,意思就错了。

所以如果要问某人是搭什么交通工具上班的,也需要用”get to work”:

How do you get to work?
By bus.

New features in DaCalc v1.7.1.0

The new version of DaCalc 1.7.1.0 comes with several new features.1. Automatically use the last result as the first operand if an operator is the first input in normal mode. For example, after calc an expression, 2+3, we get 5 as the result. Now the expression box is empty and user press a + button directly, the last result 5 will be added as the first operand and the expression looks like: 5+. If there is no last result, 0.0 will be added.

  1. Minus sign is supported. Now user can press - to add a minus sign before an operand. The following expression is supported now: -5+3
    In order to add the last result for -, user need to long press the - button.
  2. The default n-th of a root operator is a Square root. In the earlier version, the n-th of a root operator can not be omitted. It must be written as x√y. Now if the n-th (x) is absent, the operator will be recognized as a Square root operator. It is easier for some common usage.
    It can be downloaded from Android Market now.

用C++开发MYSQL应用

简单的介绍如何用Visual Studio C++开发MYSQL的应用。为新手指明开发环境的准备和资源的位置。
首先是准备工作。需要下载三个开发库:

  1. 去官方网站下载mysql-connector/c++。有多个版本,我下载的是mysql-connector-c++-noinstall-1.1.0-win32-vs2005.zip。connector-c++提供了两个lib,mysqlcppconn.lib和mysqlcppconn-static.lib,不幸的是最终运行的时候他们都需要libmysql.dll。
  2. 所以还需要下载connector/c。同样有多个版本可以选择,我下载的是mysql-connector-c-noinstall-6.0.2-win32-vs2005.zip。把两个压缩包解压到同一个地方,开发包就准备好了,但是准备工作还没有完成。
  3. 你还需要下载boost库才可以编译程序,因为新的版本的connector中使用了boost。
    然后是工程的配置, 主要是选择哪个lib。我选择使用mysqlcppconn.lib+libmysql.lib。其他的组合在visual studio 2010下都会有很多链接错误。相信所有的错误都是可以通过配置解决的,具体策略视需求而定。

最后,mysql网站提供了一些manualexample

下面是一个简单的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include "stdafx.h"
#include
#include
#include
#include

#include "mysql_connection.h"
#include "mysql_driver.h"

#include
#include
#include
#include
#include

#define EXAMPLE_HOST "xxx"
#define EXAMPLE_USER "xxxxx"
#define EXAMPLE_PASS "xxxxxx"
#define EXAMPLE_DB "xxxxxx"

using namespace std;

int main(int argc, const char **argv)
{


string url(argc >= 2 ? argv[1] : EXAMPLE_HOST);
const string user(argc >= 3 ? argv[2] : EXAMPLE_USER);
const string pass(argc >= 4 ? argv[3] : EXAMPLE_PASS);
const string database(argc >= 5 ? argv[4] : EXAMPLE_DB);

cout < < "Connecting to MYSQL server..." << endl;
cout << endl;

try {

sql::mysql::MySQL_Driver *driver;
sql::Connection *con;

driver = sql::mysql::get_driver_instance();
con = driver->connect(EXAMPLE_HOST, EXAMPLE_USER, EXAMPLE_PASS);

cout < < "Done! Querying..." << endl;

sql::Statement *stmt;
stmt = con->createStatement();
stmt->execute("USE " EXAMPLE_DB);
//stmt->execute("DROP TABLE IF EXISTS test");
//stmt->execute("SELECT * FROM `test` LIMIT 0, 30 ");

sql::ResultSet *res;
res = stmt->executeQuery("SELECT * FROM test LIMIT 0, 30 ");

cout < < "Done! Printing..." << endl;

while (res->next()) {
//// You can use either numeric offsets...
//cout < < "id = " << res->getInt(1); // getInt(1) returns the first column
// ... or column names for accessing results.
// The latter is recommended.
cout < < "Project: " << res->getString("project") < < endl;
cout << "Deadline:" << res->getString("deadline") < < endl;
cout << "Price: " << res->getString("price") < < endl;
cout << "People: " << res->getString("people") < < endl;
}

delete res;

delete stmt;

delete con;

} catch (sql::SQLException &e) {
/*
The MySQL Connector/C++ throws three different exceptions:

- sql::MethodNotImplementedException (derived from sql::SQLException)
- sql::InvalidArgumentException (derived from sql::SQLException)
- sql::SQLException (derived from std::runtime_error)
*/

cout << "# ERR: SQLException in " << __FILE__;
cout << "(" << __FUNCTION__ << ") on line " << __LINE__ << endl;
/* Use what() (derived from std::runtime_error) to fetch the error message */
cout << "# ERR: " << e.what();
cout << " (MySQL error code: " << e.getErrorCode();
cout << ", SQLState: " << e.getSQLState() << " )" << endl;

return EXIT_FAILURE;
}

cout << "Done." << endl;
return EXIT_SUCCESS;
}

The lights in Froyd Villainrom 1.5

Froyd villainrom is a great rom. But if you don’t like the lights (the led blinking, the trackball light) you can replace the lights.hero.so file under the path /system/lib/hw/ with the file from older versions. If you don’t have one, you can download from here.

You can do following steps in console to replace a file under /system/ folder if you have adb tools:

adb remount

adb pull /system/lib/hw/lights.hero.so ./lights.hero.so.bk

adb push ./lights.hero.so /system/lib/hw/

Ads free version for DaysandDate and AdjBrightness

I just uploaded the ads free version of AdjBrightness to Android Market. If you don’t like to see ads on your application, you can try the ads free version. All permissions for Ads are also removed.

Ads free version for DaysandDate has been Android Market for several weeks.

If you won’t like to spend money on them, you can still use the ads versions. They are all full function versions.