结婚就素那浮云啊

昨天我一同学打电话来说他十一号就要结婚了。当年刚毕业时和几个同学一起在水泥厂当电工,转眼已经是上个世纪的事了。比较熟的几个同学差不多都结婚了,有的孩子大约都有两岁了吧。而我自己呢?套先生的文章戏说起来便是:

我从乡下跑到城里,一转眼已经不少年了。其间耳闻目睹的所谓城里人的生活,算起来也很不少;但在我心里,都不留什么痕迹,倘要我寻出这些事的影响来说,便只是增长了我的坏脾气,——老实说,便是教我一天比一天的看不起人。

当然这些都是玩笑话了。城里人结婚其实是很恐怖的,比如前几天看到的这么个东东:

[转帖]结婚流程
1.婚礼筹备计划
1.1.决定婚礼日期、地点、仪式及婚宴方式
1.2.确定婚礼预算
1.3.草拟客人名单
1.4.召集好朋友讨论婚礼计划
1.5.确定伴郎、伴娘
1.6.确定主婚人、证婚人
1.7.成立婚礼筹备组
1.7.1.召开kick-off项目启动会
1.7.2.制定婚礼项目计划书
1.7.3.明确筹备组分工
2.婚礼前准备
  2.1.与婚礼的所有项目干系人沟通
  2.1.1.就婚礼筹备计划和进展与父母沟通
  2.1.2.发喜贴给亲友
  2.1.3.电话通知外地亲友
  2.1.4.网上发布结婚通知
  2.1.5.再次确认主、证婚人
  2.1.6.及时反馈亲友受邀信息
  2.1.7.对于重要亲友再次确认
  2.2.结婚物品采购
  2.2.1.新家布置用品
  2.2.1.1.家电、家具
  2.2.1.2.床上用品
  2.2.1.3.彩色气球
  2.2.1.4.彩灯(冷光)
  2.2.1.5.纱
  2.2.1.6.蜡烛
  2.2.1.7.胶布
  2.2.1.8.插线板
  2.2.1.9.其他物品
  2.2.2.婚礼用品订购
  2.2.2.1.新郎新娘婚纱礼服
  2.2.2.2.结婚戒指
  2.2.2.3.新娘化妆品
  2.2.2.4.喜贴、红包、喜字
  2.2.2.5.彩带、拉花、喷物
  2.2.2.6.烟、酒、饮料
  2.2.2.7.糖、花生、瓜子、茶叶
  2.2.2.8.录像带、胶卷
  2.2.2.9.预定鲜花
  2.2.2.10.预定蛋糕
  2.2.2.11.水果
  2.3.新郎新娘形象准备
  2.3.1.新娘开始皮肤保养
  2.3.2.新郎剪头发
  2.4.拍婚纱照
  2.4.1.挑选婚纱影楼
  2.4.2.预约拍摄日期
  2.4.3.拍照
  2.4.4.选片
  2.4.5.冲印或喷绘
  2.5.布置新房
  2.5.1.请清洁公司彻底打扫新房
  2.5.2.布置新房
  2.6.确定婚礼主持人
  2.6.1.就婚礼当天计划与设想与之沟通
  2.7.婚宴预约
  2.7.1.估计来宾人数
  2.7.2.估计酒席数量
  2.7.3.选择婚宴地点
  2.7.4.确认酒席菜单、价格
  2.7.5.确认婚宴现场的音响效果
  2.7.6.与酒店协调婚宴布置等细节
  2.7.7.预定酒席
  2.8.婚礼化妆预约
  2.8.1.选择化妆地点
  2.8.2.与发型师、化妆师沟通
  2.8.3.确认婚礼当天的造型
  2.8.4.预约化妆具体时间
  2.9.婚庆车辆预约
  2.9.1.确定婚车数量
  2.9.2.选定婚车司机
  2.9.3.预约扎彩车时间地点
  2.9.4.确定婚礼当天婚车行进路线及所需时间
  2.9.5.预约婚车
  2.10.婚庆摄像预约
  2.10.1.确定摄影社摄像数量
  2.10.2.选定婚礼当天摄影摄像人员
  2.10.3.安排摄影摄像分工
  2.10.4.准备摄影像器材和胶卷录像带
  2.10.5.预约摄影摄像
  2.11.其他
  2.11.1.调换崭新钞票
  2.11.2.确定滚床儿童
  2.11.3.为远道而来的亲友准备客房
3.婚礼前一天准备
  3.1.与婚礼的所有项目干系人沟通
  3.1.1.就婚礼准备工作完成情况与父母沟通
  3.1.2.就准备情况和婚礼当天分工与筹备组作最后沟通
  3.1.3.根据准备情况就婚礼当天仪式进程与主持人作最后沟通
  3.1.4.与伴郎伴娘再次沟通
  3.1.5.最后确认帮忙的亲友
  3.1.6.最后确认婚宴、车辆、摄影像、化妆等细节准备情况
  3.2.确认婚礼当天要发言人的准备情况
  3.2.1.主证婚人发言准备情况
  3.2.2.父母代表发言准备情况
  3.2.3.来宾代表发言准备情况
  3.2.4.抢亲时新娘提问准备
  3.2.5.新郎新娘在仪式上或闹洞房可能会遇到的问题
  3.3.最后确认婚礼当天所有物品准备情况
  3.3.1.最后试穿所有礼服
  3.3.2.将婚礼当天要穿的所有服装分装口袋
  3.3.3.准备两瓶假酒
  3.3.4.准备婚礼当天新郎新娘的快餐干粮
  3.3.5.最后检查所有物品并交于专人保管
  3.3.5.1.新娘的新鞋
  3.3.5.2.结婚证书
  3.3.5.3.戒指
  3.3.5.4.红包
  3.3.5.5.要佩戴的首饰
  3.3.5.6.新娘补妆盒
  3.3.5.7.糖、烟、酒、茶、饮料
  3.3.5.8.焰火道具
  3.4.新郎新娘特别准备
  3.4.1.新郎新娘反复熟悉婚礼程序
  3.4.2.预演背新娘动作
  3.4.3.预演婚礼进行台步
  3.4.4.预演交杯酒动作
  3.4.5.放松心情,互相鼓励
  3.4.6.注意睡眠,早点休息
  3.5.准备闹钟
  3.5.1确认一只正常工作的闹钟
  3.5.2将闹钟调到5点半
4.婚礼当天流程
  4.1.化妆
  4.1.1. 5:30 起床
  4.1.2. 7:00 新郎发型做好后到达新南门女方娘家附近等待
  4.1.3. 7:45 新娘妆完成,通知新郎
  4.1.4. 化妆师、美发师红包
  4.2.婚车
  4.2.1. 6:30 开始扎彩车
  4.2.2. 7:00 专车送新郎至新南门
  4.2.3. 7:30 彩车完成
  4.2.4. 7:45 专车送新娘回新南门娘家(8:30前到达)
  4.2.5. 9:00 所有婚车到达新南门
  4.2.6. 司机红包
  4.3.抢新娘
  4.3.1. 8:00 伴郎准备好鲜花、红包
  4.3.2. 8:30 新娘回到娘家,藏好新鞋
  4.3.3. 8:40 新郎带领兄弟们开始抢人
  4.3.4. 8:45 敲门、盘问、塞红包、挤门
  4.3.5. 8:55 新郎找新鞋,向女方家人承诺
  4.3.6. 9:00 彩带师到位气球到位
  4.3.7. 9:05 新郎背新娘出门,彩带,踩气球
  4.3.8. 9:10 车队出发
  4.4.迎新娘
  4.4.1. 10:00 车队到达化成小区男方家
  4.4.2 10:05 新郎抱新娘进门,彩带,踩气球
  4.4.3 10:10 小孩子滚床
  4.4.4 10:15 伴娘准备好茶
  4.4.5. 10:20 新娘给男方父母敬茶
  4.4.6 10:40 新郎新娘出发至酒店
  4.5.酒店准备
  4.5.1 10:00 将糖、烟、酒、茶、饮料等带至酒店
  4.5.2 10:10 最后检查酒席安排、音响、签到处等细节
  4.5.3 10:30 准备好新郎新娘迎宾香烟火柴糖
  4.5.4 10:45 彩带师到位酒店门口
  4.6.酒店迎宾
  4.6.1 10:50 新郎新娘到酒店,彩带
  4.6.2 11:00 签到处人员就位
  4.6.3 11:00 引导人员门口就位  
  4.6.4 11:00 新郎新娘伴郎伴娘门口迎宾
  4.7.婚礼仪式
  4.7.1. 12:15 主持人准备
  4.7.2 12:15 音响准备
  4.7.3 12:15 结婚证书、戒指准备
  4.7.4 12:15 气球、彩带到位
  4.7.8 12:20 奏乐,新人入场,彩带、踩气球
  主持人介绍
  主婚人致词
  证婚人宣读结婚证书
  新人父母上台
  新郎新娘交换戒指,三鞠躬
  新人给父母敬茶
  双方父母代表讲话
  双方父母退场
  新人开香槟、切蛋糕、喝交杯酒
  游戏
  4.7.9. 13:00 婚宴正式开始
  4.7.10. 13:00 新郎新娘退场、速食,新娘换礼服
  4.7.11. 13:15 新郎新娘逐桌敬酒
  4.7.12. 14:00 宴席结束,宾客与新人合影
  4.8.下午休息
  4.8.1. 14:00 宾客离开或到棋牌室娱乐
  4.8.2. 14:30 新郎新娘进餐、休息
  4.8.3. 14:30 清点所剩烟酒糖等
  4.8.4. 14:30 统计晚餐人数
  4.9.晚餐
  4.9.1. 17:00 通知酒店晚餐准备数量
  4.9.2. 18:00 请宾客进晚餐
  4.9.3.20:00 清点所有物品,离开酒店
  4.10. 闹洞房
  4.10.1. 21:00 开始闹洞房
  女方藏结婚证
  新郎找结婚证
  其它节目自由发挥
  4.10.2. 22:30 宾客离开
  4.11.摄像摄影
  4.11.1.摄像a从新娘化妆开始全程拍摄新娘
  4.11.2.摄像b从新郎抢亲开始全程拍摄新郎
  4.11.3.摄像c拍摄婚礼仪式全过程
  4.11.4.摄影适时拍摄
  4.11.5.摄影摄像人员红包
5.婚礼项目结束
  5.1 23:00 伴郎伴娘率筹备组另寻别处进行项目总结

余世维就是大师啊

研究了几天的EXIF,昨天终于有一点成果了。于是休息了一下,把一个老片翻出来再看一遍–著名的法国喜剧片《虎口脱险》,这么多年过去了,再看还是那么爆笑,经典就是经典啊。

看完电影又看了一节余世维的讲座(时代光华版),老余的课就是好啊,虽然不敢说经典,但至少也算是最好的管理学讲座之一。

这节课里老余说了一个事很有意思:

他在雅思兰黛做副总的时候,有一次在一个口红调色师的桌上看到一个样品,随口说了一句:“这个颜色好看吗?”,那个调色立即对他说:“余副总,您为什么说这句话?第一,这个还是试验品,还没有定稿;第二,我是专业人员,如果余副总您认为您可以调得更好,那明天请您自己来调;第三,这个口红是给女人用的,听说余副总您是男人,我想我不用考虑您的意见吧?”老余立即向这位叫做Lancy的调色师道歉。

很久以前,在软件业曾经有过一次大的争论,某些人提出一个观点:国内软件业之所以没有大的发展,在于软件开发人员不服管理,并且用一个问题来质问所有的软件开发人员:你是否能服从一个技术不如你的人的管理?并由此炒作起所谓的“软件蓝领”概念,让一大批做培训的公司发了一笔财。

现在看来,那完全就是一个阴谋。这次运动的结果直接让所有失败的软件公司找到了背黑锅者–所有的开发人员。并最终实现了逐步降低开发人员薪资的目的,同时提高了所谓管理人员的薪。其实事实上,最应该承担这个责任的就是这些所谓的管理人员。

技术不行可以理解,问题他们管理也不行,这还不算,还要去干涉技术的事务。就像老余对那个调色师说废话那样,而老余能很快意识到这一点(当然也跟那个Lancy能据理力争有关),但软件业的大多数所谓管理者都做不到。

其实前面那个质问很好回答:不懂技术可以,但你至少要懂管理,并且不能干涉技术的事。

我们常常说到团队,按老余的话说,team有三个traits,不具备这个条件的就不能叫team,只能说是“一群男人和女人”(软件业里大概可以简称为“一群男人”^_^)。而我们那些所谓的管理者们大概连哪三个traits都不知道,还敢厚颜无耻地自称是一个team。

而一个team之所以是team,很大的原因在于team leader。一个leader要领导别人,用的是权力,按老余的分法有五种:三种弱权,两种强权。那些所谓的管理者大概从来也不知道他们所用的都是弱权,所以他们才会管不住手下。

呵呵,这篇文字里出现最多的词就是“老余说”,所以这个不能算偶的随笔了,只能算是偶学习老余的课程所记的笔记^_^

BTW:以上未详细说的部分请自行参考余世维时代光华版讲座,我要再说老余要告我的^_^

MS DevDay 2004就素那浮云啊

昨天没去参加MS DevDay 2004挺可惜的,我都收到了MS的确认函了,没办法,公司事多,昨天还加班了两个小时,累S淫鸟。

今天听一个去参加的朋友说,每人都送一张光盘,带Together for VS.net,好爽啊。而且据说李维做的讲座也相当不错,很值得一听,真是亏大了。

现在看来,Borland和MS走得越来越近了,Black.Stone离开Borland,JBuilder看样子也希望不大了。前两天大致看了一下Eclipse,感觉上比JBuilder舒服,至少可以打上简体中文的语言包,看着都舒服的说。

现在看来,Borland也就剩一个Together还值点钱,干脆Borland的董事会把Together卖给MS,把本钱捞回来,然后把其它产品都拿来开源了,散伙完事,对大家都有好处。^_^

在家里用IE5.5写的格式跟在公司用IE6写的不一样啊,还要来改一下:)

自娱自乐

今天是愚人节,孤独的人的节日同样也是孤独的。连个可以作弄的人都没有,只好给人乱发一些短信。无聊啊无聊

今天开始,公司的午餐改在旁边的软件园餐厅去吃了,环境虽然还好,菜却不怎么样,最关键的是:诺大的一个餐厅里,连个像样的MM都看不到,影响食欲啊。

今天把自己写的那个相册软件升了一下级,也不知道除了我自己,还有没有别人在用:P 不过这个东东本来就是为了自己管理图片方便而写的,自己用着好就行了:)就如同现在这个BLOG,也不知道有几个人会看,但是我照样会继续写“博”下去一样,自己写着开心就好。

今天已经是四月了,CSDN已经很久没去了,论坛上吵吵闹闹的日子已经离得很远了,原来那帮子了色虽然还没离开CSDN,不过也很少在那出没了,大家都有事要忙,IT业的日子一天比一天难混了,工作压力下哪里还有空灌水。不过个人专栏还是要维护的,一会要把那篇线性插值的文章COPY过去。技术文章一般是没多少人看的。

古人云:敝帚自珍。大概就是指我这种情况吧,才写了不到一个月的BLOG,就开始想要怎么备份的问题:P

如此考试

朋友“李木勺”的GF要考计算机二级,昨天问了我几个C语言的题目,本来我想我怎么说用C也用了快十年了,写的程序也有几万行了,应该没有什么问题吧。虽然我知道这类考试通常都是很BT的,毕竟我也考过高程的考试,没想到还是出乎我的意料。

比如这一题:

main()
{int a=2,b=-1,c=2;
if(a if(belse c++;
printf(“%dn”,c);}

该程序输出多少?

看看这出题的人写的什么程序,完全是有意对读程序的人造成误解,故意降低程序的可读性,当然也有可能是他根本不知道什么叫编程风格,按老郑的说法就是:“在中国,所谓的考试就是一群水平不如你的人,背着你看了答案以后,编了一些问题来折磨你”(大致如此,记不准确了)。

这就是中国的所谓人才选拔的考核。记得有人说过:国外的考试总是拿最常用的内容来考,以检验你学会了没有;国内的考试总是拿最不可能用到的内容来考,以证明你没有学会,或者说存心让你出丑。

比如下面这题就很典型:

若变量a,i已经正确定义,且i已正确赋值,合法的语句是:A;a==1    B,++1
   C,a=a++=5  D,a=int(i) 

有这样的教育者和考核者,不难想象中国软件业现状的成因了。

软件的目标

昨天与朋友讨论myIE,一扯就扯到那个原作者头上了(关于这个作者是什么人物,myIE的开发初衷等问题就不在这里扯了),以及那个导致SourceForge被封(当时和它一起被封的还有Google)的软件FreeNet。

单纯从技术角度上说,这两个软件算是相当不错的,那些开发人员的能力也是很强的,只是其目的不妥。我不禁感慨:“人还是需要有精神寄托的”,他们能做出这样东东,在于他们有着非常明确的目的性,在此驱动下,他们才能很好地达到目标。

其实失败的软件开发在很大程度上是因为目标不明确或与最终用户的目标不一致而造成的。

当然的确有些白痴用户自己都不知道自己想干嘛,这也正是目前软件开发所面临的困境之一。正好今天看到一篇非常精屁的文章:

http://www.eping.net/fourm/dispbbs.asp?boardID=13&ID=1259&page=1

正如文章中所说的那样,用户有用户的思维定式,所以一些很重要的事情被认为是理所当然而没有被提出(至少是没有被准确地提出),而造成了开发人员的误解,直接埋下了最后造成软件项目失败的隐患。

所以,只有解决了如何准确全面地获取用户的需求并为开发人员建立明确的目标的问题,软件项目才有可能获得成功。

然而目前国内的软件企业中,承担这部分职责的人好像都很失职,因为有开发人员为他们顶缸(反正软件项目成功的,功劳是他们的,失败了,责任是开发人员的),他们只要坐在这个位子捣捣浆糊就行了,难怪现在人人都想往“管理”上靠。这个现在看来已经成为目前国内软件业发展的一个瓶颈了。

精与杂

昨天读Andrei Alexandrescu那本著名的《Modern C++ Design》(《C++设计新思维》这个中文译名大概老侯取的吧,反正我是不太喜欢)的时候,偶然看到译者之一的於春景的序里说到:他是三年前(此书于2003年出版,照算此处应该是指2000年)开始接触template的,不觉大寒。

想当年与朋友“太可怕”在福州琢磨着自己写一个template library时(那时还不知道有STL,后来知道STL后就作罢了),大概还是98年吧。时至今日,忽然发现自己的C++水平居然一直都没有大的长进。这些年来,为了混饭吃,什么方面的软件都要做,结果下来终于发现会的多,精的少。

这个於春景我是知道的,他的网名叫做lostmouse,我手上有一个Scott.Meyers的《Effective C++》的电子版就是lostmose做的,手上还有一本他译的书《C++网络编程(卷1)》(Douglas C.Schmidt的《C++ Network Programming Volume 1》)。相信他的C++功力已经相当不俗了,在他面前,我大概只有汗的份。

“业精于勤,技精于专”果然是所言非虚啊。

用线性插值算法实现图像缩放

用线性插值算法实现图像缩放

 

猛禽[Mental Studio](个人专栏)(BLOG)

http://mental.8gua.me

 

Windows中做过图像方面程序的人应该都知道WindowsGDI有一个API函数:StretchBlt,对应在VCL中是TCanvas类的StretchDraw方法。它可以很简单地实现图像的缩放操作。但问题是它是用了速度最快,最简单但效果也是最差的“最近邻域法”,虽然在大多数情况下,它也够用了,但对于要求较高的情况就不行了。

不久前我做了一个小玩意儿(见《人个信息助理之我的相册》),用于管理我用DC拍的一堆照片,其中有一个插件提供了缩放功能,目前的版本就是用了StretchDraw,有时效果不能令人满意,我一直想加入两个更好的:线性插值法和三次样条法。经过研究发现三次样条法的计算量实在太大,不太实用,所以决定就只做线性插值法的版本了。

从数字图像处理的基本理论,我们可以知道:图像的变形变换就是源图像到目标图像的坐标变换。简单的想法就是把源图像的每个点坐标通过变形运算转为目标图像的相应点的新坐标,但是这样会导致一个问题就是目标点的坐标通常不会是整数,而且像放大操作会导致目标图像中没有被源图像的点映射到,这是所谓“向前映射”方法的缺点。所以一般都是采用“逆向映射”法。

但是逆向映射法同样会出现映射到源图像坐标时不是整数的问题。这里就需要“重采样滤波器”。这个术语看起来很专业,其实不过是因为它借用了电子信号处理中的惯用说法(在大多数情况下,它的功能类似于电子信号处理中的带通滤波器),理解起来也不复杂,就是如何确定这个非整数坐标处的点应该是什么颜色的问题。前面说到的三种方法:最近邻域法,线性插值法和三次样条法都是所谓的“重采样滤波器”。

所谓“最近邻域法”就是把这个非整数坐标作一个四舍五入,取最近的整数点坐标处的点的颜色。而“线性插值法”就是根据周围最接近的几个点(对于平面图像来说,共有四点)的颜色作线性插值计算(对于平面图像来说就是二维线性插值)来估计这点的颜色,在大多数情况下,它的准确度要高于最近邻域法,当然效果也要好得多,最明显的就是在放大时,图像边缘的锯齿比最近邻域法小非常多。当然它同时还带业个问题:就是图像会显得比较柔和。这个滤波器用专业术语来说(呵呵,卖弄一下偶的专业^_^)叫做:带阻性能好,但有带通损失,通带曲线的矩形系数不高。至于三次样条法我就不说了,复杂了一点,可自行参考数字图像处理方面的专业书籍,如本文的参考文献。

再来讨论一下坐标变换的算法。简单的空间变换可以用一个变换矩阵来表示:

[x’,y’,w’]=[u,v,w]*T

其中:x’,y’为目标图像坐标,u,v为源图像坐标,w,w’称为齐次坐标,通常设为1T为一个3X3的变换矩阵。

这种表示方法虽然很数学化,但是用这种形式可以很方便地表示多种不同的变换,如平移,旋转,缩放等。对于缩放来说,相当于:

[Su  0  0]

[x, y, 1] = [u, v, 1] * | 0  Sv  0 |

[0   0  1]

其中Su,Sv分别是X轴方向和Y轴方向上的缩放率,大于1时放大,大于0小于1时缩小,小于0时反转。

矩阵是不是看上去比较晕?其实把上式按矩阵乘法展开就是:

{ x = u * Su

{ y = v * Sv

就这么简单。^_^

有了上面三个方面的准备,就可以开始编写代码实现了。思路很简单:首先用两重循环遍历目标图像的每个点坐标,通过上面的变换式(注意:因为是用逆向映射,相应的变换式应该是:u = x / Su v = y / Sv)取得源坐标。因为源坐标不是整数坐标,需要进行二维线性插值运算:

P = n*b*PA + n * ( 1 – b )*PB + ( 1 – n ) * b * PC + ( 1 – n ) * ( 1 – b ) * PD

其中:nv(映射后相应点在源图像中的Y轴坐标,一般不是整数)下面最接近的行的Y轴坐标与v的差;同样b也类似,不过它是X轴坐标。PA-PD分别是(u,v)点周围最接近的四个(左上,右上,左下,右下)源图像点的颜色(用TCanvasPixels属性)。P(u,v)点的插值颜色,即(x,y)点的近似颜色。

这段代码我就不写的,因为它的效率实在太低:要对目标图像的每一个点的RGB进行上面那一串复杂的浮点运算。所以一定要进行优化。对于VCL应用来说,有个比较简单的优化方法就是用TBitmapScanLine属性,按行进行处理,可以避免Pixels的像素级操作,对性能可以有很大的改善。这已经是算是用VCL进行图像处理的基本优化常识了。不过这个方法并不总是管用的,比如作图像旋转的时候,这时需要更多的技巧。

无论如何,浮点运算的开销都是比整数大很多的,这个也是一定要优化掉的。从上面可以看出,浮点数是在变换时引入的,而变换参数Su,Sv通常就是浮点数,所以就从它下手优化。一般来说,Su,Sv可以表示成分数的形式:

Su = ( double )Dw / Sw; Sv = ( double )Dh / Sh

其中Dw, Dh为目标图像的宽度和高度,Sw, Sh为源图像的宽度和高度(因为都是整数,为求得浮点结果,需要进行类型转换)。

将新的Su, Sv代入前面的变换公式和插值公式,可以导出新的插值公式:

因为:

b = 1 – x * Sw % Dw / ( double )Dw;  n = 1 – y * Sh % Dh / ( double )Dh

设:

B = Dw – x * Sw % Dw; N = Dh – y * Sh % Dh

则:

b = B / ( double )Dw; n = N / ( double )Dh

用整数的BN代替浮点的b, n,转换插值公式:

P = ( B * N * ( PA – PB – PC + PD ) + Dw * N * PB + DH * B * PC + ( Dw * Dh – Dh * B – Dw * N ) * PD ) / ( double )( Dw * Dh )

这里最终结果P是浮点数,对其四舍五入即可得到结果。为完全消除浮点数,可以用这样的方法进行四舍五入:

P = ( B * N … * PD + Dw * Dh / 2 ) / ( Dw * Dh )

这样,P就直接是四舍五入后的整数值,全部的计算都是整数运算了。

简单优化后的代码如下:

int __fastcall TResizeDlg::Stretch_Linear(Graphics::TBitmap * aDest, Graphics::TBitmap * aSrc)

{

    int sw = aSrc->Width – 1, sh = aSrc->Height – 1, dw = aDest->Width – 1, dh = aDest->Height – 1;

    int B, N, x, y;

    int nPixelSize = GetPixelSize( aDest->PixelFormat );

    BYTE * pLinePrev, *pLineNext;

    BYTE * pDest;

    BYTE * pA, *pB, *pC, *pD;

    for ( int i = 0; i <= dh; ++i )

    {

        pDest = ( BYTE * )aDest->ScanLine[i];

        y = i * sh / dh;

        N = dh – i * sh % dh;

        pLinePrev = ( BYTE * )aSrc->ScanLine[y++];

        pLineNext = ( N == dh ) ? pLinePrev : ( BYTE * )aSrc->ScanLine[y];

        for ( int j = 0; j <= dw; ++j )

        {

            x = j * sw / dw * nPixelSize;

            B = dw – j * sw % dw;

            pA = pLinePrev + x;

            pB = pA + nPixelSize;

            pC = pLineNext + x;

            pD = pC + nPixelSize;

            if ( B == dw )

            {

                pB = pA;

                pD = pC;

            }

            for ( int k = 0; k < nPixelSize; ++k )

                *pDest++ = ( BYTE )( int )(

                    ( B * N * ( *pA++ – *pB – *pC + *pD ) + dw * N * *pB++

                    + dh * B * *pC++ + ( dw * dh – dh * B – dw * N ) * *pD++

                    + dw * dh / 2 ) / ( dw * dh )

                );

        }

    }

    return 0;

}

应该说还是比较简洁的。因为宽度高度都是从0开始算,所以要减一,GetPixelSize是根据PixelFormat属性来判断每个像素有多少字节,此代码只支持2432位色的情况(对于1516位色需要按位拆开因为不拆开的话会在计算中出现不期望的进位或借位,导致图像颜色混乱处理较麻烦;对于8位及8位以下索引色需要查调色板,并且需要重索引,也很麻烦,所以都不支持;但8位灰度图像可以支持)。另外代码中加入一些在图像边缘时防止访问越界的代码。

通过比较,在PIII-733的机器上,目标图像小于1024×768的情况下,基本感觉不出速度比StretchDraw有明显的慢(用浮点时感觉比较明显)。效果也相当令人满意,不论是缩小还是放大,图像质量比StretchDraw方法有明显提高。

不过由于采用了整数运算,有一个问题必须加以重视,那就是溢出的问题:由于式中的分母是dw * dh,而结果应该是一个Byte8位二进制数,有符号整数最大可表示31位二进制数,所以dw * dh的值不能超过23位二进制数,即按2:1的宽高比计算目标图像分辨率不能超过4096*2048。当然这个也是可以通过用无符号数(可以增加一位)及降低计算精度等方法来实现扩展的,有兴趣的朋友可以自己试试。

当然这段代码还远没有优化到极致,而且还有很多问题没有深入研究,比如抗混叠(anti-aliasing)等,有兴趣的朋友可以自行参考相关书籍研究,如果你有什么研究成果,非常欢迎你为我的程序编写插件实现。

 

[Mental Studio]猛禽

2004-3-28

参考文献:

崔屹《数字图像处理技术与应用》电子工业出版社,1997

春游

昨天有朋友讨论要在这个春天出游,在研究要去什么地方玩的时候,我一下就想到了扬州。

春风十里扬州路,卷上珠帘总不如。

十年一觉扬州梦,赢得青楼薄倖名。

二十四桥明月夜,玉人何处教吹箫?

淮左名都,竹西佳处,解鞍少驻初程。
过春风十里,尽荠麦青青。
自胡马窥江去后,废池乔木,犹厌言兵。
渐黄昏,清角吹寒,都在空城。
杜郎俊赏,算而今、重到须惊。
纵豆蔻词工,青楼梦好,难赋深情。
二十四桥仍在,波心荡、冷月无声。
念桥边红药,年年知为谁生。

西西,我的BLOG名称就来自这里。