盛泽有个“老刘谦” “热恋”魔术40年
小顾和他老师说,我爷爷上报纸了,很牛气的样子。
把那个新闻帖出来吧。
近日,东太湖论坛网友“慢悠悠”发帖《老先生的小魔术》,三段视频中,一名老人展示了自动滑落的螺母、手臂解结、变红布三个近景魔术。“慢悠悠”在帖子中介绍,这个会变魔术的老先生是他在同里景区看到的,录下视频与市民分享魔术的乐趣。
帖子贴出后,网友第一反应是“有点本事”,“有点猜不透”。而更多的网友则对老先生赞赏有加:“老有所乐”、“老人家精神”、“人才啊”、“老人家乐在其中,这点岁数有点爱好,会让老年生活更充实。”
记者了解到,东太湖网友关注的老人不是同里人,而是盛泽人。老先生名叫顾建明,今年68岁。2月底,记者在盛泽目澜洲公园遇到他,并观看了他的义务魔术表演。
目澜洲公园内的义务演出
看到顾建明拎着道具箱走进目澜洲公园,很多老人都聚拢到湖边的水榭内看义务魔术表演。“天气好,他每天下午都为我们表演2套魔术。”65岁的顾青老人高兴地介绍,从去年4月开始,他们就经常在公园免费享受“魔术盛宴”,至今,老人们已经观看了顾建明的50多套魔术表演了。
顾建明近日在南京儿子家小住,只要他回吴江,天气好的日子,他都会去公园为老人们表演各类魔术。变纸牌、硬币穿玻璃杯、连环套圈、报纸还原……40多年来,他积累了300多套魔术。“有机会我都要变给大家看。”顾建明告诉记者,他能变“飞桌”,在桌子上蒙一块布,可以叫桌子自动上升。由于场地限制,很多大魔术他在公园里没法变。
“要是能有道具,我也会变镜子穿人,刘谦会变的魔术,很多我都可以变。”顾建明解释,一些魔术的原理是相通的,但是需要道具支持。好的道具,有的价格高达20多万元,不是他这样的企业退休人员可以承受得起。顾建明的魔术演出道具都是他自己制作的。
春节去同里顺带“露一手”
顾建明从小就迷恋魔术,只要有魔术团来吴江,他都观看到结束,然后回家好好揣摩里面的奥妙。从20多岁开始,顾建明无师自通,业余时间他就在家做魔术道具,自学理论,开始实践魔术手法,参加企业演出。他的专业表演让他成为了江苏杂技艺术家协会会员,顾建明成为了专业魔术师。
“魔术界人士都会交流心得,但是不会拆穿其他魔术师的表演。”顾建明说,魔术都是假的,展示给群众的是一种神秘感,他就喜欢为大家表演。顾建明春节期间去同里岳母家小住时,顺便带上了一些魔术小道具在街头“露一手”,这就有了东太湖网友的视频记录。当记者询问有网友提及的“手臂中藏电机”之说是否为真,顾建明笑了,他说:“这个肯定没有。”老先生随后开怀一乐:“我最享受魔术带给大家的神秘感,你们感觉越神秘,我就越开心。”
独乐不如和老人们共乐
“看他表演,我们都很开心,就是猜不出他怎么变的。”67岁的徐振松老人说,顾建明来表演,大家都一眼不眨地看他演,想找出其中的门道,可就是“破”不了他的魔术。
弹牛皮筋的表演,顾建明拿了记者给的皮筋,真正是和刘谦一样的近景魔术表演,记者就是看不出破绽。目澜洲公园内,不时传来老人们的笑声,一名老人说,他还看过顾建明表演的“变出一连串烟斗”、火棍变鸟笼等节目,“我们算是过足了瘾啦。”老人们个个笑容灿烂。
顾建明平时不抽烟不喝酒,就只有变魔术这点爱好,家人很支持他,不过他的“门道”,不会和任何人说,不然,魔术就不稀奇了。蛇年春晚的魔术表演,顾建明基本都能看懂,不过他说魔术师的道德首先是“不可说破”。
“40多年了,我一直在学,魔术最主要的是手法。”顾建明说,他也尝试着教自己的老朋友几个小魔术,但是,手法做不到位,就会穿帮。而“手臂解结”这样的魔术,光学打结一天都很难学会。“给大家演个‘稀奇’,看老人们乐呵,我就开心,自个儿乐呵,不如带动一片人开心。”顾建明把自己的晚年生活过得无限舒畅。
来源:这里
小顾复盘
昨天和小顾复盘下午的指导棋,我有意没给他看谱,没想到,这家伙居然可以直接摆出前面60手棋,而且有几个点还给专门摆了了几个变化。后面的棋,经过提醒也多半能摆出来。
看来他真是用心在下棋了,加油。
Agg vs. Cairo 二维绘图引擎之比较和选择
当今时代对于作为二维图形软件开发者, 是幸运的。因为除了Windows GDI/GDI+之外,我们还有很多其他的选择。而且这些选择除了能跨平台之外,性能上与原始GDI/GDI+相比,都不逊色。
如果不考虑绘图的效果,使用Win32 GDI函数直接绘图的效率大约是同样的GDI Plus的10倍以上。为了反走样的美观,只有牺牲效率了。老式的程序还在使用GDI绘图,不是这些程序不想提升到GDI+,可能这样改动的代码量太大,所谓船大不好掉头所致。
因此,后发的优势就是可以利用当今软件发展的最新成果,快速切入一个领域,所谓迎头赶上。
言归正传。仍以我们假定的目标:开发一个二维图形软件为例。对于绘图核心引擎这块,有几种选择:
1、使用Windows/Linux原生的GDI绘图原语。
2、使用开源的绘图核心。
开源的软件目前越来越显示出强大的生命力。因此,目前虽然直接调用底层GDI/GDIPlus的函数,可以获得比较灵活的性能,但是对于商业应用软件的开发来说都不是最优的。连google这样的大公司,都有采用开源的绘图引擎(skia-后来被google收购),因此我们有理由相信,选择一个适合的引擎是必要的。
网络上对AGG的陈述不乏溢美之词:
“AGG,全名:Anti-Grain Geometry,是一个开源的、高效的2D图形库,它的网站: http://www.antigrain.com/ 。AGG的功能与GDI+的功能非常类似,但提供了比GDI+更灵活的编程接口,其产生的图形的质量也非常高,而且它是跨平台的,其宣传可以在非常多的操作系统上运行,至少在Windows、Wince、Linux三个台平上测试通过。”
“在设计上,它是师出Boost库,在其中使用了大量的现代标准C++语言的语法规则,包括模板、仿函数等处理,但是为了能在更多的平台上使用,它并没有直接使用Boost和STL库,而是自己实现了部分STL功能。”
AGG 2.5 License
Anti-Grain Geometry is an Open Source, free library released under the terms and conditions of GNU GPLlicense.
再看看另外一个大名鼎鼎的绘图引擎Cairo:
“cairo 的目标是以跨平台的方式在打印机和屏幕上产生相同的输出,它正在成为 Linux® 图形领域的重要软件。GNOME、GTK+、Pango 等许多软件已经使用了它提供的 2D 功能。 cairo 是一个免费的矢量绘图软件库,它可以绘制多种输出格式。cairo 支持许多平台,包括 Linux、BSD、Microsoft® Windows® 和 OSX(BeOS 和 OS2 后端也正在开发)。Linux 绘图可以通过 X Window 系统、Quartz、图像缓冲格式或 OpenGL 上下文来实现。另外,cairo 还支持生成 PostScript 或 PDF 输出,从而产生高质量的打印结果。在理想情况下,cairo 的用户可以在打印机和屏幕上获得非常接近的输出效果。”
“cairo 的一项主要设计目标是提供尽可能接近的输出。这种一致的输出使 cairo 非常适合 GUI 工具集编程和跨平台应用程序开发。使用同一个绘图库打印高分辨率的屏幕和绘制屏幕内容,这种功能具有显著的优点。另外,在支持的每种目标平台上,cairo 尝试智能化地使用底层硬件和软件支持。高质量矢量图形和高性能的结合使 cairo 成为优秀的 UNIX® 绘图系统。”
“cairo 是用 C 编写的,但是为大多数常用的语言提供了绑定。选用 C 语言有助于创建新的绑定,同时在进行 C 语言调用时可以提供高性能。应该特别注意 Python 绑定,它支持快速原型开发,而且降低了学习 cairo 绘图 API 的门槛。 ”
Cairo is free software and is available to be redistributed and/or modified under the terms of either the GNU Lesser General Public License (LGPL) version 2.1 or the Mozilla Public License (MPL) version 1.1 at your option.
原谅我引用了3个段落来描述Cairo这个精巧的东西。因为从网络上搜索得出的结果不成正比的偏向于Cairo。
经过测试分析,我总结出不宜使用AGG的几点原因:
1)AGG是C++编写的,因此,它不能被C语言很好地调用。由于 其中使用了大量的现代标准C++语言的语法规则,包括模板、仿函数等处理 ,导致这样的库的学习过程将是痛苦的。
2)AGG采用的版权协议是GNU GPL的。而Cairo至少是LGPL的。AGG采用的协议表明它不适合用于商业的闭源软件开发。
3)Cairo的绘图效率是接近GDI/GDIPlus的。经过优化算法,可以做到完全忽略绘图效率上的差别。
4)AGG自从2006年之后就没有更新过。我怀疑这个社区已经不存在了。对于这样一个发展中的引擎,在长达5年的时间里没有更新,无论如何是说不过去的,也是无法让人信赖的。
5)Cairo社区至今保持着旺盛的生命力。作为名震江湖的FireFox的核心绘图引擎,作为Linux的绘图引擎,我们可以足够信赖它。
6)具体到库中的功能,只有用过才知道孰优孰劣。
7)C语言相比C++更具有简洁和高效的特性。更适合跨平台软件的开发。
当然,我的孤陋寡闻可能导致忽略了目前存在的更优秀的绘图引擎,请您不妨告诉我,这样把它们都加入到这个讨论之中。
最后,请相信Linux的选择,请相信FireFox的选择。同时也是我的选择。
AGG手册最后关于适应性细分法描画贝塞尔曲线的感触
看到第八节,是关于Bezier Curves的讨论,翻看其代码, files agg_curves.h, agg_curves.cpp
中间有不少演进的过程,从文章看,作者原来使用的是土办法。不过效果还是不错的。
后面还写道:
在 comp.graphics.algorithms 新闻组,我因为对与著的丌熟悉而受到了相当严历的批评。完整的
讨论在这里可以找到,你也可以使用“Adaptive Subdivision of Bezier Curves McSeem”在
http://groups.google.com 里迚行搜索。 在网上可以很容易地找到一篇叨“Adaptive forward
differencing for rendering curves and surfaces”的文章。里面介绍的方法很好,不过仍然不能解决平滑 stroke 中遇到的所有问题。
特地回去回顾了下计算机图形学关于贝塞尔曲线的特性描述
Bezier曲线的性质
1\. 端点
根据Bezier曲线的公式,可以得到Bezier曲线总是通过起始点和终止点。
2\. 一阶导数
Bezier曲线在起点处的切线位于前两个控制点的连线上,而终点处的切线位于最后两个控制点的连线上,即曲线起点和终点处的切线方向与起始折线段和终止折线段的切线方向一致。
3\. 二阶导数
Bezier曲线在起始点和终止点处的二阶导数分别取决于最开始和最后的三个控制点。可以证明,Bezier曲线在起始点和终止点处的r阶导数由起始点或终止点和它们的r个邻近的控制多边形顶点来决定。事实上,正是由该性质以及Bezier曲线的端点性质出发推导出了Bezier基函数。
4\. 对称性
Bezier曲线具有对称性,即保持控制多边形的顶点位置不变,仅仅把它们的顺序颠倒一下,将下标为k的控制点Pk改为下标为n-k的控制点Pn-k时,曲线保持不变,只是走向相反而已。
5\. 凸包性
Bezier曲线各点均落在控制多边形各顶点构成的凸包之中,这里的凸包指的是包含所有顶点的最小凸多边形。Bezier曲线的凸包性保证了曲线随控制点平稳前进而不会振荡。
6\. 几何不变性
Bezier曲线的形状仅与控制多边形各顶点的相对位置有关,而与坐标系的选择无关,即具有几何不变性。
7\. 变差减少性
Bezier曲线的变差减少性是指如果控制多边形是一个平面图形,则该平面内的任意直线与该Bezier曲线的交点个数不多于该直线与控制多边形的交点个数;如果控制多边形不是平面图形,则任意平面与Bezier曲线的交点个数不会超过它与控制多边形的交点个数。变差减少性反映了Bezier曲线比控制多边形波动得少,即比控制多边形更加光滑。</pre>
大学计算机图形学免修了,现在想想是亏了。
DNSPod开始支持IPV6了
可以支持IPV6,牛掰
AGG手册示例像素渲染器之bland部分在BCB下的编译问题
这个例子是描画阳光的光谱。rgba 类包含有 4 个浮点数的颜色部分(包括alpha),这个类有一个静态函数 from_wavelength ,以及相应的构造函数。rgba8 可以用 rgba 来构造(在 AGG 中这是一个常见的策略,也就是任何的颜色类型都可以用 rgba 来构造)。
#include <stdio.h>
#include <string.h>
#include “agg_pixfmt_rgb24.h”
enum
{
frame_width = 320,
frame_height = 200
};
// Writing the buffer to a .PPM file, assuming it has
// RGB-structure, one byte per color component
//————————————————–
bool write_ppm(const unsigned char buf,
unsigned width,
unsigned height,
const char file_name)
{
FILE fd = fopen(file_name, “wb”);
if(fd)
{
fprintf(fd, “P6 %d %d 255 “, width, height);
fwrite(buf, 1, width height * 3, fd);
fclose(fd);
return true;
}
return false;
}
int main()
{
//——————–
// Allocate the buffer.
// Clear the buffer, for now “manually”
// Create the rendering buffer object
// Create the Pixel Format renderer
// Create one line (span) of type rgba8.
// Fill the buffer using blend_color_span
// Write the buffer to agg_test.ppm
// Free memory
unsigned char buffer = new unsigned char[frame_width frame_height 3];
memset(buffer, 255, frame_width frame_height 3);
agg::rendering_buffer rbuf(buffer,
frame_width,
frame_height,
frame_width 3);
agg::pixfmt_rgb24 pixf(rbuf);
agg::rgba8 span[frame_width];
unsigned i;
for(i = 0; i < frame_width; ++i)
{
agg::rgba c(380.0 + 400.0 * i / frame_width, 0.8);
span[i] = agg::rgba8(c);
}
for(i = 0; i < frame_height; ++i)
{
pixf.blend_color_hspan(0, i, frame_width, span, 0); // 这里编译无法通过 需要改为 pixf.blend_color_hspan(0,i,frame_width,span,0,255);
}
write_ppm(buffer, frame_width, frame_height, “agg_test.ppm”);
delete [] buffer;
return 0;
}
看注释部分:
这里会发生两个问题
1.手册使用为2.4版本的AGG,在2.5中,增加了Cover参数,所以会发生缺少参数提示:
[BCC32 Error] Unit1.cpp(152): E2193 Too few parameters in call to ‘agg::pixfmt_rgb24::blend_color_hspan(int,int,unsigned int,const agg::rgba8 ,const unsigned char ,unsigned char)’
2.这个示例没有使用Covers,所以Covers参数设0,最后新增的Cover需要设为大于0的值,否则还是会看不到内容。设为255,就能看到示例的效果。
但将该代码调整为
pixf.blend_color_hspan(0, i, frame_width, span , 0 , 255);
仍然出现了如下错误
[BCC32 Fatal Error] agg_pixfmt_rgb.h(235): F1004 Internal compiler error at 0xaa3dd09 with base 0xa9d0000 ,
提示错误定位到了”agg_pixfmt_rgb.h”,在第235行。class pixfmt_alpha_blend_rgb中的
AGG_INLINE void copy_or_blend_pix(value_type* p, const color_type& c){
{
if (c.a)
{
if(c.a == base_mask)
{
p[order_type::R] = c.r;
p[order_type::G] = c.g;
p[order_type::B] = c.b;
}
else
{
m_blender.blend_pix(p, c.r, c.g, c.b, c.a); // 需要修改成 m_blender.blend_pix(p, c.r, c.g, c.b, c.a, 0);
}
}
}
m_blender在这个示例中原型是agg::pixfmt_rgb24,他的定义是
typedef pixfmt_alpha_blend_rgb<blender_rgb<rgba8, order_rgb>, rendering_buffer> pixfmt_rgb24; //—-pixfmt_rgb24
所以,我们查看blend_rgb这个类
static AGG_INLINE void blend_pix(value_type p,
unsigned cr, unsigned cg, unsigned cb,
unsigned alpha,
unsigned cover=0)
{
p[Order::R] += (value_type)(((cr - p[Order::R]) alpha) >> base_shift);
p[Order::G] += (value_type)(((cg - p[Order::G]) alpha) >> base_shift);
p[Order::B] += (value_type)(((cb - p[Order::B]) alpha) >> base_shift);
}
发现没有,这里cover这个参数是使用了default参数0,由于是模板调用,BCB2010的编译器在编译时发生了F1004错误,其实是编译器的一个BUG。了解了这个,只需要在头文件中把 m_blender.blend_pix(p, c.r, c.g, c.b, c.a); 修改成 m_blender.blend_pix(p, c.r, c.g, c.b, c.a, 0); 把这个默认参数补上,问题就解决了。
下面贴上我的运行结果:
如何在BCB2010上编译AGG库
AGG相对于GDI+,拥有跨平台的优势,在学习的角度看,复用性更高。
由于新项目基于BCB2010,于是尝试在这个平台做些实例。
AGG有Dephi版本,AGG@PAS ,可以在D2009&D2010使用。
这里使用的是C++的2.5版本。
源码下载以后,可以直接在BCB2010建立LIB项目或者DLL项目,然后加入src目录所有CPP文件,设置Include目录。如果打算使用SDL,则配置好SDL环境后,也要加入agg-2.5\src\platform\sdl下的CPP。如果不需要使用platform,这个目录下的可以不加入,或者只加入win32下的CPP,MacOS、X11等可以不加入。此外,与src同目录的font_freetype、font_win32_tt、gpc也要加入。这样,就可以正确编译出Lib文件。
程序员与BUG
你不能对一个程序员说:你的代码有bug。他的第一反应是:1,你的环境有问题吧;2,傻逼你会用吗。如果你委婉地说:你这个程序和预期的有点不一致,你看看是不是我的使用方法有问题。他本能地会想:操,是不是出bug了!