﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-兔子的技术博客-随笔分类-框架/图像/算法</title><link>http://www.cppblog.com/flyinghare/category/11699.html</link><description>兔子</description><language>zh-cn</language><lastBuildDate>Fri, 12 Apr 2013 09:26:17 GMT</lastBuildDate><pubDate>Fri, 12 Apr 2013 09:26:17 GMT</pubDate><ttl>60</ttl><item><title>网络游戏的对时以及同步问题</title><link>http://www.cppblog.com/flyinghare/archive/2013/04/12/199370.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Fri, 12 Apr 2013 04:20:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2013/04/12/199370.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/199370.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2013/04/12/199370.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/199370.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/199370.html</trackback:ping><description><![CDATA[<div style="clear: both; color: #333333; font-family: 'trebuchet ms', verdana, helvetica, arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><p style="margin-top: 10px; margin-bottom: 10px;">大多数实时网络游戏，将 server 的时间和 client 的时间校对一致是可以带来许多其他系统设计上的便利的。这里说的对时，并非去调整 client 的 os 中的时钟，而是把 game client 内部的逻辑时间调整跟 server 一致即可。</p><p style="margin-top: 10px; margin-bottom: 10px;">一个粗略的对时方案可以是这样的，client 发一个数据包给 server，里面记录下发送时刻。server 收到后，立刻给这个数据包添加一个server 当前时刻信息，并发还给 client 。因为大部分情况下，game server 不会立刻处理这个包，所以，可以在处理时再加一个时刻。两者相减，client 可以算得包在 server 内部耽搁时间。</p><p style="margin-top: 10px; margin-bottom: 10px;">client 收到 server 发还的对时包时，因为他可以取出当初发送时自己附加的时刻信息，并知道当前时刻，也就可以算出这个数据包来回的行程时间。这里，我们假定数据包来回时间相同，那么把 server 通知的时间，加上行程时间的一半，则可以将 client 时间和 server 时间校对一致。</p></div><div id="more" style="clear: both; color: #333333; font-family: 'trebuchet ms', verdana, helvetica, arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #ffffff;"><p style="margin-top: 10px; margin-bottom: 10px;">这个过程用 udp 协议做比用 tcp 协议来的好。因为 tcp 协议可能因为丢包重发引起教大误差，而 udp 则是自己控制，这个误差要小的多。只是，现在网络游戏用 tcp 协议实现要比 udp 有优势的多，我们也不必为对时另起一套协议走 udp 。</p><p style="margin-top: 10px; margin-bottom: 10px;">一般的解决方法用多次校对就可以了。因为，如果双方时钟快慢一致的情况下，对时包在网络上行程时间越短，就一定表明误差越小。这个误差是不会超过包来回时间的一半的。我们一旦在对时过程中得到一个很小的行程时间，并在我们游戏逻辑的时间误差允许范围内，就不需要再校对了。</p><p style="margin-top: 10px; margin-bottom: 10px;">或者校对多次，发现网络比较稳定（虽然网速很慢），也可以认为校对准确。这种情况下，潜在的时间误差可能比较大。好在，一般，我们在时间敏感的包上都会携带时间戳。当双方时间校对误差很小的时候，client 发过来的时间戳是不应该早于 server 真实时刻的。（当时间校对准确后，server 收到的包上的时间戳加上数据包单行时间，应该等于 server 当前时刻）</p><p style="margin-top: 10px; margin-bottom: 10px;">一旦 server 发现 client 的包&#8220;提前&#8221;收到了，只有一种解释：当初校对时间时糟糕的网络状态带来了很多的时间误差，而现在的网络状态要明显优于那个时候。这时，server 应该勒令 client 重新对时。同理，client 发现 server 的数据包&#8220;提前&#8221;到达，也可以主动向 server 重新对时。</p><p style="margin-top: 10px; margin-bottom: 10px;">一个良好的对时协议的设定，在协议上避免 client 时间作弊（比如加速器，或者减速器）是可行的。这里不讨论也不分析更高级的利用游戏逻辑去时间作弊的方式，我们给数据包打上时间戳的主要目的也非防止时间作弊。</p><p style="margin-top: 10px; margin-bottom: 10px;">校对时间的一般用途是用来实现更流畅的战斗系统和位置同步。因为不依赖网络传输的统一时间参照标准可以使游戏看起来更为实时。</p><p style="margin-top: 10px; margin-bottom: 10px;">首先谈谈位置同步。</p><p style="margin-top: 10px; margin-bottom: 10px;">好的位置同步一定要考虑网络延迟的影响，所以，简单把 entity 的坐标广播到 clients 不是一个好的方案。我们应该同步的是一个运动矢量以及时间信息。既，无论是 client 还是 server ，发出和收到的信息都应该是每个 entity 在某个时刻的位置和运动方向。这样，接收方可以根据收到的时刻，估算出 entity 的真实位置。对于 server 一方的处理，只要要求 client 按一个频率(一般来说战斗时 10Hz 即可，而非战斗状态或 player 不改变运动状态时可以更低) 给它发送位置信息。server 可以在网络状态不好的情况下依据最近收到的包估算出现在 player 位置。而 client 发出的每次 player 位置信息，都应该被 server 信任，用来去修正上次的估算值。而 server 要做的只是抽查，或交给另一个模块去校验数据包的合法性（防止作弊）。</p><p style="margin-top: 10px; margin-bottom: 10px;">在 server 端，每个 entity 的位置按 10Hz 的频率做离散运动即可。</p><p style="margin-top: 10px; margin-bottom: 10px;">client 因为涉及显示问题，玩家希望看到的是 entity 的连续运动，所以处理起来麻烦一点。server 发过来的位置同步信息也可能因为网络延迟晚收到。client 同样根据最近收到的包做估算，但是再收到的包和之前已经收到的信息估算结果不同的时候，应该做的是运动方向和速度的修正，尽可能的让下次的估算更准确。</p><p style="margin-top: 10px; margin-bottom: 10px;">关于战斗指令同步，我希望是给所有战斗指令都加上冷却时间和引导时间，这正是 wow 的设计。这样，信任 client 的时间戳，就可以得到 client 准确的指令下达时间。引导时间（或者是公共冷却时间）可以充当网络延迟时间的缓冲。当然我们现在的设计会更复杂一些，这里不再列出。对于距离敏感的技能，例如远程攻击和范围魔法，我们的设计是有一个模糊的 miss 判定公式，解决距离边界的判定问题。</p><p style="margin-top: 10px; margin-bottom: 10px;">这里， server 对攻击目标的位置做估算的时候，可以不按上次发出包的运动方向去做位置估计，而选择用最有利于被攻击者的运动方向来做。这样，可以减少网络状况差的玩家的劣势。</p><p style="margin-top: 10px; margin-bottom: 10px;">对于 PVE 的战斗，甚至可以做更多的取舍，达到游戏流畅的效果。比如一个网络状态差的玩家去打 npc，他攻击 npc 的时刻，npc 是处于攻击范围之内的。但是由于网络延迟，数据包被 server 收到的时候，npc 已经离开。这个时候 server 可以以 client 的逻辑来将 npc 拉会原来的坐标。</p><p style="margin-top: 10px; margin-bottom: 10px;">虽然，这样做，可能会引起其他玩家（旁观者） client 上表现的不同。但是，网络游戏很多情况下是不需要严格同步的。在不影响主要游戏逻辑的情况下，player 的手感更为重要。</p></div>转自：<a href="http://blog.codingnow.com/2006/04/sync.html#comments">http://blog.codingnow.com/2006/04/sync.html#comments</a><img src ="http://www.cppblog.com/flyinghare/aggbug/199370.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2013-04-12 12:20 <a href="http://www.cppblog.com/flyinghare/archive/2013/04/12/199370.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> (转) cocos2dX 多线程</title><link>http://www.cppblog.com/flyinghare/archive/2012/10/15/193327.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Mon, 15 Oct 2012 10:01:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2012/10/15/193327.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/193327.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2012/10/15/193327.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/193327.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/193327.html</trackback:ping><description><![CDATA[最近使用Cocos2d-x开发游戏，发现Cocos2d-x的内存管理采用Objective-C的机制，大喜过望。因为只要坚持Objective-C的原则&#8220;谁创建谁释放，谁备份谁释放&#8221;的原则即可确保内存使用不易出现Bug。<br style="word-wrap: break-word; " />但是因为本身开放的游戏需要使用到多线程技术，导致测试的时候总是莫名其妙的导致空指针错误。而且是随机出现，纠结了2天无果后，开始怀疑Cocos2d-X的内存本身管理可能存在问题。怀着这样的想法，<br style="word-wrap: break-word; " />一步一步的调试，发现经常出现指针异常的变量总是在调用autorelease后一会就莫名其妙再使用的时候就抛异常。狠下心，在它的析构函数里面断点+Log输出信息。发现对象被释放了。一时也很迷糊，因为对象只是<br style="word-wrap: break-word; " />autorelease,并没有真正释放，是谁导致它释放的？<br style="word-wrap: break-word; " /><br style="word-wrap: break-word; " />然后就去看了CCAutoreleasePool的源码，发现存在Cocos2d-X的内存管理在多线程的情况下存在如下问题<br style="word-wrap: break-word; " /><br style="word-wrap: break-word; " /><img src="http://www.cppblog.com/images/cppblog_com/flyinghare/cocos2d_autorelease.png" width="575" height="256" alt="" /><br style="word-wrap: break-word; " /><br />如图：thread 1和thread 2是独立的两个线程，它们之间存在CPU分配的交叉集，我们在time 1的时候push一个autorelease的自动释放池，在该线程的末尾，即time 3的时候pop它。同理在thread 2的线程里面，在time 2的时候push一个自动释放池，在time 4的时候释放它，即Pop.<br style="word-wrap: break-word; " />此时我们假设在thread 2分配得到CPU的时候有一个对象obj自动释放，即obj-autorelease().<strong style="word-wrap: break-word; ">那么在time 3的时候会发生是么事情呢？</strong><br style="word-wrap: break-word; " /><strong style="word-wrap: break-word; ">答案很简单，就是obj在time 3的时候就被释放了，而我们期望它在time 4的时候才释放。所以就导致我上面说的，在多线程下面，cocos2d-x的autorelease变量会发生莫名其妙的指针异常。</strong><br style="word-wrap: break-word; " /><br style="word-wrap: break-word; " /><br style="word-wrap: break-word; " /><strong style="word-wrap: break-word; ">解决办法：</strong>在PoolManager给每个线程根据pthread_t的线程id生成一个CCArray的stack的嵌套管理自动释放池。源码如下<br style="word-wrap: break-word; " />所以我在Push的时候根据当前线程的pthread_t的线程id生成一个CCArray的stack来存储该线程对应的Autoreleasepool的嵌套对象<br style="word-wrap: break-word; " />源码如下<br style="word-wrap: break-word; " /><br style="word-wrap: break-word; color: #444444; font-family: Tahoma, Simsun; background-color: #ffffff; " />&nbsp; &nbsp;<table cellspacing="0" style="word-wrap: break-word; empty-cells: show; border-collapse: collapse; border-style: solid; border-color: #e3edf5; table-layout: auto; width: 801px; "><tbody style="word-wrap: break-word; "><tr style="word-wrap: break-word; "><td style="word-wrap: break-word; font-size: 14px; padding: 4px; border-style: solid; border-color: #e3edf5; overflow: hidden; "><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">1</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">2</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">3</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">4</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">5</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">6</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">7</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">8</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">9</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">10</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">11</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">12</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">13</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">14</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">15</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">16</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">17</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">18</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">19</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">20</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">21</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">22</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">23</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">24</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">25</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">26</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">27</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">28</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">29</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">30</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">31</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">32</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">33</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">34</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">35</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">36</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">37</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">38</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">39</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">40</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">41</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">42</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">43</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">44</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">45</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">46</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">47</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">48</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">49</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">50</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">51</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">52</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">53</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">54</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">55</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">56</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">57</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">58</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">59</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">60</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">61</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">62</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">63</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">64</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">65</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">66</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">67</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">68</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">69</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">70</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">71</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">72</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">73</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">74</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">75</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">76</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">77</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">78</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">79</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">80</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">81</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">82</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">83</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">84</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">85</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">86</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">87</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">88</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">89</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">90</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">91</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">92</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">93</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">94</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">95</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">96</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">97</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">98</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">99</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">100</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">101</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">102</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">103</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">104</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">105</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">106</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">107</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">108</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">109</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">110</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">111</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">112</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">113</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">114</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">115</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">116</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">117</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">118</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">119</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">120</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">121</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">122</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">123</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">124</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">125</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">126</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">127</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">128</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">129</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">130</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">131</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">132</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">133</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">134</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">135</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">136</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">137</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">138</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">139</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">140</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">141</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">142</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">143</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">144</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">145</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">146</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">147</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">148</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">149</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">150</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">151</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">152</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">153</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">154</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">155</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">156</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">157</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">158</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">159</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">160</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">161</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">162</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">163</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">164</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">165</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">166</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">167</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">168</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">169</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">170</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">171</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">172</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">173</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">174</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">175</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">176</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">177</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">178</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">179</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">180</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">181</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">182</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">183</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">184</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">185</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">186</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">187</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">188</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">189</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">190</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">191</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">192</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">193</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">194</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">195</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">196</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">197</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">198</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">199</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">200</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">201</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">202</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">203</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">204</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">205</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">206</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">207</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">208</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">209</p><p align="right" style="word-wrap: break-word; margin: 0px; padding: 0px; ">210</p></td><td style="word-wrap: break-word; font-size: 14px; padding: 4px; border-style: solid; border-color: #e3edf5; overflow: hidden; "><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">//--------------------------------------------------------------------</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">//</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">// CCPoolManager</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">//</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">//--------------------------------------------------------------------</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">/////【diff - begin】- by layne//////</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">CCPoolManager* CCPoolManager::sharedPoolManager()</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">{</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; if (s_pPoolManager == NULL)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; {</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;s_pPoolManager = new CCPoolManager();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; }</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; return s_pPoolManager;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">}</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">void CCPoolManager::purgePoolManager()</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">{</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; CC_SAFE_DELETE(s_pPoolManager);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">}</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">CCPoolManager::CCPoolManager()</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">{</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; m_pReleasePoolStack = new CCArray();&nbsp; &nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; m_pReleasePoolStack-&gt;init();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; m_pCurReleasePool = 0;</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; m_pReleasePoolMultiStack = new CCDictionary();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">}</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">CCPoolManager::~CCPoolManager()</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">{</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; finalize();</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; // we only release the last autorelease pool here</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; m_pCurReleasePool = 0;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; m_pReleasePoolStack-&gt;removeObjectAtIndex(0);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; CC_SAFE_DELETE(m_pReleasePoolStack);</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; finalize();</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; CC_SAFE_DELETE(m_pReleasePoolMultiStack);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">}</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">void CCPoolManager::finalize()</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">{</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; if(m_pReleasePoolMultiStack-&gt;count() &gt; 0)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; {</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;//CCAutoreleasePool* pReleasePool;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;CCObject* pkey = NULL;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;CCARRAY_FOREACH(m_pReleasePoolMultiStack-&gt;allKeys(), pkey)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;{</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if(!pkey)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; break;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;CCInteger *key = (CCInteger*)pkey;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;CCArray *poolStack = (CCArray *)m_pReleasePoolMultiStack-&gt;objectForKey(key-&gt;getValue());</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;CCObject* pObj = NULL;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;CCARRAY_FOREACH(poolStack, pObj)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;{</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; if(!pObj)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;break;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; CCAutoreleasePool* pPool = (CCAutoreleasePool*)pObj;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; pPool-&gt;clear();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; }</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">}</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">void CCPoolManager::push()</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">{</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; CCAutoreleasePool* pPool = new CCAutoreleasePool();&nbsp; &nbsp;&nbsp; &nbsp; //ref = 1</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; m_pCurReleasePool = pPool;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; m_pReleasePoolStack-&gt;addObject(pPool);&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; //ref = 2</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; pPool-&gt;release();&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;//ref = 1</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; pthread_mutex_lock(&amp;m_mutex);</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; CCArray* pCurReleasePoolStack = getCurReleasePoolStack();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; CCAutoreleasePool* pPool = new CCAutoreleasePool();&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;//ref = 1</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; pCurReleasePoolStack-&gt;addObject(pPool);&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; //ref = 2</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; pPool-&gt;release();&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; //ref = 1&nbsp; &nbsp;</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; pthread_mutex_unlock(&amp;m_mutex);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">}</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">void CCPoolManager::pop()</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">{</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; if (! m_pCurReleasePool)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; {</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;return;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; }</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; int nCount = m_pReleasePoolStack-&gt;count();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; m_pCurReleasePool-&gt;clear();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; if(nCount &gt; 1)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; {</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;m_pReleasePoolStack-&gt;removeObjectAtIndex(nCount-1);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;//&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;if(nCount &gt; 1)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;//&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;{</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;//&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; m_pCurReleasePool = m_pReleasePoolStack-&gt;objectAtIndex(nCount - 2);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;//&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; return;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;//&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;}</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;m_pCurReleasePool = (CCAutoreleasePool*)m_pReleasePoolStack-&gt;objectAtIndex(nCount - 2);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; }</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; /*m_pCurReleasePool = NULL;*/</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; pthread_mutex_lock(&amp;m_mutex);&nbsp; &nbsp;</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; CCArray* pCurReleasePoolStack = getCurReleasePoolStack();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; CCAutoreleasePool* pCurReleasePool = getCurReleasePool();&nbsp; &nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; if (pCurReleasePoolStack &amp;&amp; pCurReleasePool)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; {</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;int nCount = pCurReleasePoolStack-&gt;count();</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;pCurReleasePool-&gt;clear();</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;if(nCount &gt; 1)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;{</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;pCurReleasePoolStack-&gt;removeObject(pCurReleasePool);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;}</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; }</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; pthread_mutex_unlock(&amp;m_mutex);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">}</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">void CCPoolManager::removeObject(CCObject* pObject)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">{</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; CCAssert(m_pCurReleasePool, "current auto release pool should not be null");</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; m_pCurReleasePool-&gt;removeObject(pObject);</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; pthread_mutex_lock(&amp;m_mutex);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; CCAutoreleasePool* pCurReleasePool = getCurReleasePool();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; CCAssert(pCurReleasePool, "current auto release pool should not be null");</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; pCurReleasePool-&gt;removeObject(pObject);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; pthread_mutex_unlock(&amp;m_mutex);&nbsp; &nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">}</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">void CCPoolManager::addObject(CCObject* pObject)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">{</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; getCurReleasePool()-&gt;addObject(pObject);</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; pthread_mutex_lock(&amp;m_mutex);&nbsp; &nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; CCAutoreleasePool* pCurReleasePool = getCurReleasePool(true);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; CCAssert(pCurReleasePool, "current auto release pool should not be null");</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; pCurReleasePool-&gt;addObject(pObject);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; pthread_mutex_unlock(&amp;m_mutex);&nbsp; &nbsp;&nbsp;&nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">}</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">CCArray* CCPoolManager::getCurReleasePoolStack()</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">{</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; CCArray* pPoolStack = NULL;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; pthread_t tid = pthread_self();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; if(m_pReleasePoolMultiStack-&gt;count() &gt; 0)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; {</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;pPoolStack = (CCArray*)m_pReleasePoolMultiStack-&gt;objectForKey((int)tid);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; }</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; if (!pPoolStack) {</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;pPoolStack = new CCArray();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;m_pReleasePoolMultiStack-&gt;setObject(pPoolStack, (int)tid);</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;pPoolStack-&gt;release();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; }</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; return pPoolStack;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">}</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">CCAutoreleasePool* CCPoolManager::getCurReleasePool(bool autoCreate)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">{</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; if(!m_pCurReleasePool)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; {</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;push();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; }</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; CCAssert(m_pCurReleasePool, "current auto release pool should not be null");</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; //&nbsp; &nbsp; return m_pCurReleasePool;</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; CCAutoreleasePool* pReleasePool = NULL;</p><br style="word-wrap: break-word; " /><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; CCArray* pPoolStack = getCurReleasePoolStack();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; if(pPoolStack-&gt;count() &gt; 0)</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; {</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;pReleasePool = (CCAutoreleasePool*)pPoolStack-&gt;lastObject();</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; }</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; if (!pReleasePool &amp;&amp; autoCreate) {</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;CCAutoreleasePool* pPool = new CCAutoreleasePool();&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;//ref = 1</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;pPoolStack-&gt;addObject(pPool);&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; //ref = 2</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;pPool-&gt;release();&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; //ref = 1</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;pReleasePool = pPool;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; }</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">&nbsp; &nbsp; return pReleasePool;</p><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">}</p><br style="word-wrap: break-word; " /><p align="left" style="word-wrap: break-word; margin: 0px; padding: 0px; ">/////【diff - end】- by layne//////</p></td></tr></tbody></table><br style="word-wrap: break-word; " /><br style="word-wrap: break-word; " /><br style="word-wrap: break-word; " /><br style="word-wrap: break-word; color: #444444; font-family: Tahoma, Simsun; background-color: #ffffff; " /><br style="word-wrap: break-word; " /><br style="word-wrap: break-word; " />转自：<a href="http://www.ityran.com/thread-3364-1-1.html">http://www.ityran.com/thread-3364-1-1.html</a><img src ="http://www.cppblog.com/flyinghare/aggbug/193327.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2012-10-15 18:01 <a href="http://www.cppblog.com/flyinghare/archive/2012/10/15/193327.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跑步的好处</title><link>http://www.cppblog.com/flyinghare/archive/2012/05/15/174954.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Tue, 15 May 2012 03:36:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2012/05/15/174954.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/174954.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2012/05/15/174954.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/174954.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/174954.html</trackback:ping><description><![CDATA[<span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">1.告别臃肿身材。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">许多人开始跑步就是因为减肥，跑步确实减肥的最好运动方式，跑步每分钟比起其他运动燃烧更多的卡路里。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">2.防止你的骨骼，肌肉退化。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">我们的骨骼是和你的身体需求相互协调的。长期坐在显示器前的我们让我们的骨骼越来越脆弱。而长期的，经常的运动会使你的骨骼保持健康。更进一步说就是防止我们身体内部老化的更快。经常的高强度锻炼，例如跑步，被证明可以促进人体荷尔蒙的生长，荷尔蒙就是那些名人为了看起来更年轻而持续注射的药剂。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">3.抵抗疾病&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">跑步可以降低得中风和乳腺癌的风险。经常的跑步已经成为医生对那些容易引发或在已经处在早期的骨质疏松，糖尿病，高血压病人的治疗建议。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">4.维持并提高总体的身体水平。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">跑步是是人们可以采取的最好的锻炼身体的运动。它可以提高胆固醇,降低血液凝块的危险，锻炼你的50%的经常处于闲置状态的肺。跑步还可以通过增加你的淋巴细胞来增强你的免疫力。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">5.让你更加自信。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">慢跑像其他一些单人运动一样，它可以增强你的自信心。跑步让你完成一次又一次的尝试，让你变得更强大，更加肯定自己。他让你真实的越过某个山峰，穿过某个障碍.在意识到你的身体已经更加强壮，更加有用，你会得到被赋予力量和自由的感觉。自信更是那些通过跑步成功的减肥并得到自己心中理想身材的跑步者的宝贵财富。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">6.放松自己，减轻压力。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">慢跑可以转移聂注意力，沐浴在路旁的风景中，你的烦恼一定会消失殆尽。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">长跑适合那些正处在一堆头疼，恼人的烦心事的人。还有比在两个小时的长跑中，清理的的头脑、舒缓自己的神经更好的主意了吗。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">如果你此时觉得异常压抑，何不快跑一下呢，之后你会一个好的心情。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">7.著名的&#8220;跑步者高峰体验&#8221;&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">包括释放压力，慢跑被证明提高你的心态。跑步，特别在户外和旅行中,会使身体释放一种物质让你产生一种幸福愉悦感（跑步者高峰体验）或者就是快乐的感觉。跑步已经被采用了多年来治疗临床抑郁症，上瘾等。更少的压力，更少的压抑，更少的疲劳，更少的混乱，经过一段时间的经常跑步，病人很快就有了变化。跑步让他们有了注意的对象，让他们看到了除了他们消极的状态和沉溺的事务，还有一些美好的东西的存在。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">8.锻炼你的头脑。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">像对你的身体有所帮助一样，跑步同样对你的头脑很有帮助。通过在跑步中克服一系列的障碍，你学会了专注和决心.在经历那些你几乎要放弃的长跑或其他项目后你会发现：你在跑步过程中产生的意志和体魄的增强让你在其他方面有着同样的专注和决心。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">9.增强合作精神。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">又是一个非常值得去做的好处。这点好处或许让很多人感到惊奇，因为人们认为跑步不可能得到这种益处，仅仅由于跑步是单人运动。但是跑步确实有时涉及到互相合作。旅行跑步，特别是在那些路况不好的地方，需要极大的合作意识。这些路面经常会有一些 障碍如石头、灌木让跑步进行的很困难。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">10.随时随地，简单。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">不是很多的运动可以在任何地方，几乎不需要设备的。我敢肯定古代希腊人会争辩说甚至是鞋子和衣服也不需要。今天，我们只是需要一双好点的跑步鞋然后就可以出发了。从市中心到郊区,整个世界的地方等待你的探索。经常出差吗？你的旅行箱里肯定会有空间来装你的运动鞋的。这个世界就是你的健身房，去再次发现它吧。&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">Here are some tips for how to make running a practice:&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">Be consistent in your running program. Plan your weekly workout schedule and stick to it. This will teach you persistence.&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">Know which focuses you'll use during every run. This will teach you planning and mindfulness, and improve your mind/body connection.&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">Constantly practice relaxing your muscles. This will help to relieve tension and train you to relax no matter what activity you're doing.&nbsp;</span><br style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; " /><span style="color: #111111; font-family: Arial, Helvetica, sans-serif; font-size: 13px; background-color: #ffffff; ">At the end of your run, spend a few minutes doing an "end-of-run review." Ask yourself how well you did with keeping your focuses, how your body felt during the run. What did you come away with that will help your next run? Then, the next time you go out for a run, you'll have something to work on that you brought forward from your last run. In this way you'll build a healthy, growing and sustainable running program.&nbsp;</span>&nbsp;<br />转自：<a href="http://www.douban.com/group/topic/20749798/">http://www.douban.com/group/topic/20749798/</a><img src ="http://www.cppblog.com/flyinghare/aggbug/174954.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2012-05-15 11:36 <a href="http://www.cppblog.com/flyinghare/archive/2012/05/15/174954.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>调用D3D的 CreateDevice 函数后导致 COleDateTime::GetCurrentTime() 失败</title><link>http://www.cppblog.com/flyinghare/archive/2010/07/21/120944.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Wed, 21 Jul 2010 03:49:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2010/07/21/120944.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/120944.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2010/07/21/120944.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/120944.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/120944.html</trackback:ping><description><![CDATA[<div>当执行以下代码后，将导致&nbsp;COleDateTime::GetCurrentTime() 失败<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(FAILED(g_pD3D</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">CreateDevice(D3DADAPTER_DEFAULT,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DDEVTYPE_HAL,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hWnd,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DCREATE_SOFTWARE_VERTEXPROCESSING</span><span style="COLOR: #000000">,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">d3dpp,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">g_pd3dDevice)))<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;FALSE;<br>&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br>这是 <span style="COLOR: #000000">CreateDevice 函数修改了系统的浮点运算精度，只要加上 D3DCREATE_FPU_PRESERVE 选项即可解决，修改后的代码如下：<br><span class=Apple-style-span style="WORD-SPACING: 0px; FONT: medium/23px 微软雅黑; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span class=Apple-style-span style="FONT-SIZE: 12px; COLOR: rgb(68,68,68); LINE-HEIGHT: 20px; FONT-FAMILY: 'Microsoft Yahei', Verdana, Simsun">
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(FAILED(g_pD3D</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">CreateDevice(D3DADAPTER_DEFAULT,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DDEVTYPE_HAL,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hWnd,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;D3DCREATE_SOFTWARE_VERTEXPROCESSING&nbsp;</span><span style="COLOR: #000000">|</span><span style="COLOR: #000000">&nbsp;<span style="COLOR: red">D3DCREATE_FPU_PRESERVE</span>,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">d3dpp,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">g_pd3dDevice)))<br>&nbsp;&nbsp;&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;FALSE;<br>&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<h4 class=beTitle id=subjcns!F962D4854A8233D!396 style="FONT-WEIGHT: normal; FONT-SIZE: 12px; MARGIN: 0px 0px 5px; COLOR: rgb(68,68,68); LINE-HEIGHT: 18px">&nbsp;</h4>
</span></span></span><br></div>
参考资料：<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://topameng.spaces.live.com/Blog/cns!F962D4854A8233D!396.entry?wa=wsignin1.0&amp;sa=56810441">http://topameng.spaces.live.com/Blog/cns!F962D4854A8233D!396.entry?wa=wsignin1.0&amp;sa=56810441</a>
<div>&nbsp;<a href="http://visual-c.itags.org/visual-c-c++/56481/">http://visual-c.itags.org/visual-c-c++/56481/</a><br><br><span class=Apple-style-span style="WORD-SPACING: 0px; FONT: medium/23px 微软雅黑; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span class=Apple-style-span style="FONT-SIZE: 12px; COLOR: rgb(68,68,68); LINE-HEIGHT: 20px; FONT-FAMILY: 'Microsoft Yahei', Verdana, Simsun">
<h4 class=beTitle id=subjcns!F962D4854A8233D!396 style="FONT-WEIGHT: normal; FONT-SIZE: 12px; MARGIN: 0px 0px 5px; COLOR: rgb(68,68,68); LINE-HEIGHT: 18px">D3DCREATE_FPU_PRESERVE</h4>
<div class=bvMsg id=msgcns!F962D4854A8233D!396 style="OVERFLOW-Y: hidden; OVERFLOW-X: hidden; WIDTH: 820px; LINE-HEIGHT: 20px; TEXT-OVERFLOW: ellipsis">
<p style="MARGIN: 0px 0px 1.35em; LINE-HEIGHT: 20px">&nbsp; 在FPU中，却存在着三种运算精度：single precision(24bits)，double precision(53bits)(一般应用程序启动时的精度)，double extended precision(64bits，很少用)。FPU的默认精度是53bits的double precision。D3D的CreateDevice函数会将FPU的运算精度改成24bits。除非指定了D3DCREATE_FPU_PRESERVE参数，否则不能你的应用程序浮点精度也会降低。<br style="LINE-HEIGHT: 20px">&nbsp; 悲剧的是你不能确认dx或者其他程序是否给你切换回来，感觉有些dx版本有bug，即使设置D3DCREATE_FPU_PRESERVE也不会切换回来。这是我们需要手动切换<br style="LINE-HEIGHT: 20px">&nbsp;&nbsp;&nbsp; unsigned int uiFloat;<br style="LINE-HEIGHT: 20px">&nbsp;&nbsp;&nbsp; _controlfp_s(&amp;uiFloat, 0, 0);<br style="LINE-HEIGHT: 20px">&nbsp;&nbsp;&nbsp; _controlfp_s(0, _PC_53, MCW_PC);&nbsp; //切换到double精度</p>
<p style="MARGIN: 0px 0px 1.35em; LINE-HEIGHT: 20px">&nbsp;&nbsp;&nbsp; .......<br style="LINE-HEIGHT: 20px">&nbsp;&nbsp;&nbsp; _controlfp_s(0, uiFloat, MCW_PC);&nbsp; //切换到原来的精度</p>
</div>
</span></span></div>
<img src ="http://www.cppblog.com/flyinghare/aggbug/120944.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2010-07-21 11:49 <a href="http://www.cppblog.com/flyinghare/archive/2010/07/21/120944.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GDI+ 综述 </title><link>http://www.cppblog.com/flyinghare/archive/2009/11/11/100746.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Wed, 11 Nov 2009 14:42:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2009/11/11/100746.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/100746.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2009/11/11/100746.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/100746.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/100746.html</trackback:ping><description><![CDATA[转自：<a href="http://www.cnblogs.com/xingd/archive/2008/03/02/1088087.html">http://www.cnblogs.com/xingd/archive/2008/03/02/1088087.html</a><br><br>
<p><font face=Verdana>系列前面的两篇文章写的内容太简单了，本文对我理解的GDI+做一个综述，不再涉及代码细节。<br><br>GDI+中共有三种坐标，全局坐标、页面坐标和设备坐标。在GDI+的绘图调用中，传入的坐标位于全局坐标内，全局坐标经由全局变换转换到页面坐标，页面坐标再通过页面变换计算出设备坐标。</font></p>
<p><font face=Verdana>全局变换通过Graphics.Transform指定，其类型为Matrix。GDI+中的矩阵为3x3浮点矩阵，可以通过Matrix类的方法和属性来修改全局变换，也可以通过Graphics类上的TranslateTransform等方法来设定。页面变换通过Graphics类的PageUnit和PageScale来设定坐标单位和缩放倍数。</font></p>
<p><font face=Verdana>Point, Size, Rectangle是GDI+中常用的度量类型，并且都具有对应的float类型。Color则代表了32位A8R8G8B8的颜色。这一些都是基本的值类型，在实际使用的时候，要牢记其值类型的特征，类似o.Size.Width = 100的代码是没有作用的，因为.Width = 100是作用在了o.Size返回的临时变量上了，对于o的状态没有任何影响。</font></p>
<p><font face=Verdana>GraphicsPath，Region, Image则是GDI+中的一些资源性的类型，在使用完成后要尽快Dispose。GraphicsPath是一系列连续的线，包含直线和曲线。Region则表示封闭的一个区域，这个区域的边界可以由GraphicsPath来描述。Image表示一个图形，其中表现像素组成的位图的派生类为Bitmap，表现失量绘图指令组成的图形的派生类为Metafile。计算机屏幕最擅长展现两维的数据，因此Rectangle视为最简单的一种Region，并且应用面也非常广泛，计算包含整个Region的Rectangle也是非常常见的一种操作。</font></p>
<p><font face=Verdana>Brush用来填充一个Region，填充时可以使用单色填充，可以使用纹理（图片）填充，也可以使用线型填充和渐变填充，.NET中封充的GDI+提供了SolidBrush，TextureBrush，HatchBrush，LinearGradientBrush和PathGradientBrush类。Brush也是需要及时Dispose的，对于SolidBrush，可使用SystemBrushes和Brushes中的静态属性，获取预定义的Brush对表，免去Dispose的麻烦。</font></p>
<p><font face=Verdana>Pen是用来画线的，GDI+的线是有宽度的，也就有其内部区域，因此GDI+中的Pen需要一个Brush实例来构造。同样SystemPens和Pens中提供了预定义的单色Pen实例。</font></p>
<p><font face=Verdana>此外Font对象用来实现GDI+中不同字体的输出，Graphics类提供了一个MeasureString方法计算一段字符串绘制出来时占据的区域大小。</font></p>
<p><font face=Verdana>Graphics类提供了一系列Draw...方法，使用特定的Pen来绘制一定的形状，Fill...系列则使用特定的Brush来填充指定区域。</font></p>
<p><font face=Verdana>Graphics的Clip属性通过一个Region类的实例指定GDI+有效绘制区域，这是一个基础信息，Graphics的属性ClipBounds，IsClipEmpty，IsVisibleClipEmpty，VisibleClipBounds均基于Clip属性，并且为只读的。</font></p>
<p><font face=Verdana>CompositingQuality，InterpolationMode，PixelOffsetMode，SmoothingMode，TextRenderingHint用来控制绘制输出质量，质量越高，速度越慢。CompositingMode用来启用Alpha Blend，TextContrast控制文本输出时的Gamma值，RenderingOrigin用来控制8bit/16bit色深时的色彩拌动和Hatch Brush的起始点。<br><br>这些内容对之后的Minesweeper内容足够了，如果有问题，欢迎在评论中提出。</font></p>
<img src ="http://www.cppblog.com/flyinghare/aggbug/100746.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2009-11-11 22:42 <a href="http://www.cppblog.com/flyinghare/archive/2009/11/11/100746.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>四大图像库</title><link>http://www.cppblog.com/flyinghare/archive/2009/11/05/100178.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Thu, 05 Nov 2009 01:26:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2009/11/05/100178.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/100178.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2009/11/05/100178.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/100178.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/100178.html</trackback:ping><description><![CDATA[<div>转自：<a href="http://blog.chinaunix.net/u/24948/showart_408317.html">http://blog.chinaunix.net/u/24948/showart_408317.html</a><br><br>四大图像库的使用感受:OpenCV/FreeImage/CImg/CxImage <br>对OpenCV的印象：功能十分的强大，而且支持目前先进的图像处理技术，体系十分完善，操作手册很详细，手册首先给大家补计算机视觉的知识，几乎涵盖了近10年内的主流算法；然后将图像格式和矩阵运算，然后将各个算法的实现函数。我用它来做了一个Harris角点检测器和Canny边缘检测器，总共就花了一个小时（第一次用OpenCV）。而且该库显示图像极其方便，两句话就可以。但该库似乎不大稳定，对32F和16S、8U的图像数据支持上bug重重。我用cvFilter2D函数进行线性滤波，屡屡出错，后来一查原来是大bug。后来用cvmGet来取矩阵元素也是频繁出错，仔细检查了N遍确保程序没问题之后在yahoogroup上找到答案：仍然是bug。。。但好歹该库是开放的，所以自己可以修改；而且支持CVS。另外该库用的是IPL矩阵库，速度奇快～～<br><br>对CxImage考察的印象：该开发包完全开放源代码，图像封装为一个类，功能极为强大，与Windows、MFC支持极好，支持图像的多种操作（线性滤波、中值滤波、直方图操作、旋转缩放、区域选取、阈值处理、膨胀腐蚀、alpha混合等等），支持从文件、内存或者win32api定义的位图图像格式中读取图像，支持将图像显示在任意窗口，功能可谓很强大了，而且对像素的操作很方便，另外还有一个界面很强的demo，可以直接在上面进行二次开发，推荐使用！<br>缺点：里面的子库很多，用起来可能较麻烦；而且感觉速度稍慢，不如后面提到的freeimage<br>但功能真的十分强大啊！<br><br>CImg：就一个.h文件所以用起来很简明，但感觉功能上不如CxImage。可以与CxImage配合使用，因为CImg提供了基于lapack的矩阵运算函数和完善的线性滤波卷积函数，同时CImg做像素运算还是很方便的。另外，独有Display类可以方便的实现各种显示，包括显示图像、打字、画线等等。还有，该库有个基于光流的多尺度图像配准例子，很好<br><br>FreeImage：C语言的体系，大量使用指针运算速度可以保证，内含先进的多种插值算法。另外独有的支持meta exif信息的读取。该库最大的特点就是比较简练，只把重点放在对各种格式图像的读取写入支持上，没有显示部分，实际编程的时候还是需要调用API函数进行显示<br><br>OpenCV 参考手册</div>
<div><a href="http://www.assuredigit.com/incoming/sourcecode/opencv/chinese_docs/ref/opencvref_cv_chinese.htm"><u><font color=#800080>http://www.assuredigit.com/incoming/sourcecode/opencv/chinese_docs/ref/opencvref_cv_chinese.htm</font></u></a><br><br><br>深度图像理解<br><a href="http://blog.csdn.net/thirdapple/category/117113.aspx"><u><font color=#0066cc>http://blog.csdn.net/thirdapple/category/117113.aspx</font></u></a></div>
<div><br><br>中国图形图像网<br><a href="http://www.image2003.com/"><font color=#479299><u>http://www.image2003.com</u></font></a></div>
<div><br><br>图象算法大全：<br><a href="http://www.machinevisionshow.cn/search/c07tuxiangsuanfa.htm"><u><font color=#0066cc>http://www.machinevisionshow.cn/search/c07tuxiangsuanfa.htm</font></u></a><br></div>
<div><br>一个边缘识别算法代码<br><a href="http://www.moon-soft.com/download/soft/2157.htm"><u><font color=#0066cc>http://www.moon-soft.com/download/soft/2157.htm</font></u></a></div>
<div><br></div>
<table style="BORDER-COLLAPSE: collapse" borderColor=#bbf0ff cellSpacing=0 cellPadding=0 width="100%" align=center border=1>
    <tbody>
        <tr>
            <td background=../../templates/newblue/images/bg_line.gif height=28><strong>网友评论</strong></td>
        </tr>
        <tr>
            <td align=middle>
            <table style="COLOR: #0066cc; BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr height=25>
                        <td width=120>&nbsp;<strong> 本站网友</strong> </td>
                        <td style="COLOR: #0066cc" align=right width=360>时间：2008-03-15 23:58:05 IP地址：219.225.53.★</td>
                    </tr>
                    <tr>
                        <td colSpan=3 height=5></td>
                    </tr>
                    <tr>
                        <td colSpan=3>
                        <table style="COLOR: #666666; BORDER-COLLAPSE: collapse; WORD-WRAP: break-word" cellSpacing=0 cellPadding=0 width=480 border=0>
                            <tbody>
                                <tr height=30>
                                    <td vAlign=top width=20><strong></strong></td>
                                    <td vAlign=top width=480>
                                    <pre style="MARGIN: 0px; COLOR: #666666; LINE-HEIGHT: 150%" wrap="break-word">CImg&nbsp;是一个用C++编写的开源数字图像处理库。<br>
                                    &nbsp;<br>
                                    作者介绍<br>
                                    &nbsp;<br>
                                    作者David&nbsp;Tschumperl&#233;，&nbsp;之前是法国La&nbsp;Rochelle大学的一名教授，现受雇于CNRS&nbsp;图像组。据说作者从1998年写博士论文时就开始写这个库。作者主页：http://www.greyc.ensicaen.fr/~dtschump/&nbsp;，里面有更多关于作者本人的消息。<br>
                                    &nbsp;<br>
                                    库的特点<br>
                                    &nbsp;<br>
                                    这个库与一般的类库最大的不同点在于，不像其他的图像处理类库，CImg所有的代码都包含在一个文件中（CImg.h）。库的设计使用了C++模板技术，支持多种数据类型，且库的设计机器简单明了。库包含了这几个模块：首先是CImg类，这是库的主体，基本上基于图像的操作都在这个类里实现了。第二个是CImgDisplay类，该类用于显示处理后的图像。我们在用c++处理图像时，总是要花好多功夫在图像的显示上，CImgDisplay的设计就是为解决这个问题而写的。有了它，我们可以像用Matlab一样方便的显示图像。第三个重要的类是CImgList该类主要为处理序列图像。<br>
                                    &nbsp;<br>
                                    该库还有一个特点是可移植性，同时支持Windows和linux，FreeBSD等等。<br>
                                    &nbsp;<br>
                                    该库支持多种图像格式的读取与保存，不过个人认为，除了bmp文件外，读取其他文件时都是先用ImageMagic的convert程序转换格式在读取，所以速度很慢。读取bmp文件很快。<br>
                                    &nbsp;<br>
                                    如何使用<br>
                                    &nbsp;<br>
                                    在该库发布的下载文件中包含了很多演示程序。要使用它，首先将下载下来的CImg.h文件拷贝到你的编译器搜索的include文件夹中，然后在源代码写上：<br>
                                    &nbsp;<br>
                                    #include&nbsp;"CImg.h"<br>
                                    using&nbsp;namespace&nbsp;cimg_library;<br>
                                    &nbsp;<br>
                                    <br>
                                    &nbsp;<br>
                                    就这么简单，你就可以使用所有的库函数。<br>
                                    下面是作者给的一个例子：<br>
                                    <br>
                                    #include&nbsp;"CImg.h"<br>
                                    &nbsp;&nbsp;using&nbsp;namespace&nbsp;cimg_library;<br>
                                    <br>
                                    &nbsp;&nbsp;int&nbsp;main()&nbsp;{<br>
                                    &nbsp;&nbsp;&nbsp;&nbsp;CImg&lt;unsigned&nbsp;char&gt;&nbsp;image("lena.jpg"),&nbsp;visu(500,400,1,3,0);<br>
                                    &nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;unsigned&nbsp;char&nbsp;red[]&nbsp;=&nbsp;{&nbsp;255,0,0&nbsp;},&nbsp;green[]&nbsp;=&nbsp;{&nbsp;0,255,0&nbsp;},&nbsp;blue[]&nbsp;=&nbsp;{&nbsp;0,0,255&nbsp;};<br>
                                    &nbsp;&nbsp;&nbsp;&nbsp;image.blur(2.5);<br>
                                    &nbsp;&nbsp;&nbsp;&nbsp;CImgDisplay&nbsp;main_disp(image,"Click&nbsp;a&nbsp;point"),&nbsp;draw_disp(visu,"Intensity&nbsp;profile");<br>
                                    &nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;(!main_disp.is_closed&nbsp;&amp;&amp;&nbsp;!draw_disp.is_closed)&nbsp;{<br>
                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;main_disp.wait();<br>
                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(main_disp.button&nbsp;&amp;&amp;&nbsp;main_disp.mouse_y&gt;=0)&nbsp;{<br>
                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;const&nbsp;int&nbsp;y&nbsp;=&nbsp;main_disp.mouse_y;<br>
                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visu.fill(0).draw_graph(image.get_crop(0,y,0,0,image.dimx()-1,y,0,0),red,1,255,0);<br>
                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visu.draw_graph(image.get_crop(0,y,0,1,image.dimx()-1,y,0,1),green,1,255,0);<br>
                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visu.draw_graph(image.get_crop(0,y,0,2,image.dimx()-1,y,0,2),blue,1,255,0).display(draw_disp);<br>
                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
                                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
                                    &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;0;<br>
                                    &nbsp;&nbsp;}<br>
                                    <br>
                                    &nbsp;<br>
                                    <br>
                                    你可以直接将上面的源代码保存到一个.cpp文件然后编译查看效果。当然，在项目所在文件夹中必须包含有图片lena.jpg。<br>
                                    <br>
                                    技术支持<br>
                                    <br>
                                    该库有非常详细的文档说明随源代码一起发布。http://cimg.sourceforge.net/index.shtml&nbsp;这是sourceforge上该项目的主页，有论坛，我觉得作者非常认真负责，经常在上面为网友解答问题，详细细致。<br></pre>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/flyinghare/aggbug/100178.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2009-11-05 09:26 <a href="http://www.cppblog.com/flyinghare/archive/2009/11/05/100178.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>高斯模糊资料收集</title><link>http://www.cppblog.com/flyinghare/archive/2009/09/30/97651.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Wed, 30 Sep 2009 06:11:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2009/09/30/97651.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/97651.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2009/09/30/97651.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/97651.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/97651.html</trackback:ping><description><![CDATA[GIL图像处理（高斯模糊）：<a href="http://www.cppprog.com/2009/0305/76_8.html">http://www.cppprog.com/2009/0305/76_8.html</a><br><br>高斯平滑 高斯模糊 高斯滤波器：<a href="http://blog.csdn.net/hhygcy/archive/2009/07/07/4329056.aspx">http://blog.csdn.net/hhygcy/archive/2009/07/07/4329056.aspx</a><br><br><a class=singleposttitle id=ctl03_TitleUrl href="http://www.cnblogs.com/hoodlum1980/archive/2008/03/03/1088567.html"><u><font color=#800080>对Photoshop高斯模糊滤镜的算法总结</font></u></a> ：<a href="http://www.cnblogs.com/hoodlum1980/archive/2008/03/03/1088567.html">http://www.cnblogs.com/hoodlum1980/archive/2008/03/03/1088567.html</a>
<img src ="http://www.cppblog.com/flyinghare/aggbug/97651.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2009-09-30 14:11 <a href="http://www.cppblog.com/flyinghare/archive/2009/09/30/97651.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>BMP文件结构及图像每行字节计算方法</title><link>http://www.cppblog.com/flyinghare/archive/2009/09/27/97376.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Sun, 27 Sep 2009 08:00:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2009/09/27/97376.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/97376.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2009/09/27/97376.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/97376.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/97376.html</trackback:ping><description><![CDATA[转自：<a href="http://hi.baidu.com/kennlee/blog/item/52375eca63394743f31fe7d8.html">http://hi.baidu.com/kennlee/blog/item/52375eca63394743f31fe7d8.html</a><br>
<p><font size=3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1. BMP文件组成 <br><br>　　BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。文件头主要包含文件的大小、文件类型、图像数据偏离文件头的长度等信息；位图信息头包含图象的尺寸信息、图像用几个比特数值来表示一个像素、图像是否压缩、图像所用的颜色数等信息。颜色信息包含图像所用到的颜色表，显示图像时需用到这个颜色表来生成调色板，但如果图像为真彩色，既图像的每个像素用24个比特来表示，文件中就没有这一块信息，也就不需要操作调色板。文件中的数据块表示图像的相应的像素值，需要注意的是：图像的像素值在文件中的存放顺序为从左到右，从下到上，也就是说，在BMP文件中首先存放的是图像的最后一行像素，最后才存储图像的第一行像素，但对与同一行的像素，则是按照先左边后右边的的顺序存储的；另外一个需要读者朋友关注的细节是：文件存储图像的每一行像素值时，如果存储该行像素值所占的字节数为4的倍数，则正常存储，否则，需要在后端补0，凑足4的倍数。 <br><br>　　2. BMP文件头 <br><br>　　BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。其结构定义如下: <br><br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span>&nbsp;<span style="COLOR: #000000">typedef&nbsp;</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;tagBITMAPFILEHEADER<br></span><span style="COLOR: #008080">2</span>&nbsp;<span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">3</span>&nbsp;<span style="COLOR: #000000">WORD&nbsp;bfType;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位图文件的类型，必须为&#8220;BM&#8221;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">4</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">DWORD&nbsp;bfSize;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位图文件的大小，以字节为单位</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">5</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">WORD&nbsp;bfReserved1;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位图文件保留字，必须为0</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">6</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">WORD&nbsp;bfReserved2;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位图文件保留字，必须为0</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">7</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">DWORD&nbsp;bfOffBits;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位图数据的起始位置，以相对于位图文件头的偏移量表示，以字节为单位</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">8</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">}&nbsp;BITMAPFILEHEADER；该结构占据14个字节。&nbsp;</span></div>
<p><br><br>　　3. 位图信息头 <br><br>　　BMP位图信息头数据用于说明位图的尺寸等信息。其结构如下：<br><br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #000000">typedef&nbsp;</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;tagBITMAPINFOHEADER{<br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #000000">DWORD&nbsp;biSize;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;本结构所占用字节数</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">LONG&nbsp;biWidth;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位图的宽度，以像素为单位</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">LONG&nbsp;biHeight;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位图的高度，以像素为单位</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">WORD&nbsp;biPlanes;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;目标设备的平面数不清，必须为1</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">WORD&nbsp;biBitCount</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;每个像素所需的位数，必须是1(双色),&nbsp;4(16色)，8(256色)或24(真彩色)之一</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">DWORD&nbsp;biCompression;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位图压缩类型，必须是&nbsp;0(不压缩),1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">DWORD&nbsp;biSizeImage;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位图的大小，以字节为单位</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">LONG&nbsp;biXPelsPerMeter;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位图水平分辨率，每米像素数</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">LONG&nbsp;biYPelsPerMeter;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位图垂直分辨率，每米像素数</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">DWORD&nbsp;biClrUsed;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位图实际使用的颜色表中的颜色数</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">DWORD&nbsp;biClrImportant;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位图显示过程中重要的颜色数</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">}&nbsp;BITMAPINFOHEADER；该结构占据40个字节。&nbsp;</span></div>
<p><br><br>　　注意：对于BMP文件格式，在处理单色图像和真彩色图像的时候，无论图象数据多么庞大，都不对图象数据进行任何压缩处理，一般情况下，如果位图采用压缩格式，那么16色图像采用RLE4压缩算法，256色图像采用RLE8压缩算法。<br><br>　　4. 颜色表 <br><br>　　颜色表用于说明位图中的颜色，它有若干个表项，每一个表项是一个RGBQUAD类型的结构，定义一种颜色。RGBQUAD结构的定义如下: <br><br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span>&nbsp;<span style="COLOR: #000000">typedef&nbsp;</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;tagRGBQUAD&nbsp;{<br></span><span style="COLOR: #008080">2</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;BYTErgbBlue;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;蓝色的亮度(值范围为0-255)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">3</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;BYTErgbGreen;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;绿色的亮度(值范围为0-255)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">4</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;BYTErgbRed;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;红色的亮度(值范围为0-255)</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">5</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;BYTErgbReserved;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;保留，必须为0</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">6</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">}&nbsp;RGBQUAD;&nbsp;</span></div>
<p><br><br>　　颜色表中RGBQUAD结构数据的个数由BITMAPINFOHEADER 中的biBitCount项来确定，当biBitCount=1,4,8时，分别有2,16,256个颜色表项，当biBitCount=24时，图像为真彩色，图像中每个像素的颜色用三个字节表示，分别对应R、G、B值，图像文件没有颜色表项。位图信息头和颜色表组成位图信息，BITMAPINFO结构定义如下:<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">2</span>&nbsp;<span style="COLOR: #000000">typedef&nbsp;</span><span style="COLOR: #0000ff">struct</span><span style="COLOR: #000000">&nbsp;tagBITMAPINFO&nbsp;{<br></span><span style="COLOR: #008080">3</span>&nbsp;<span style="COLOR: #000000">BITMAPINFOHEADER&nbsp;bmiHeader;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;位图信息头</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">4</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">RGBQUAD&nbsp;bmiColors[</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">];&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;颜色表</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">5</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000">}&nbsp;BITMAPINFO;&nbsp;</span></div>
<p><br><br>　　注意：RGBQUAD数据结构中，增加了一个保留字段rgbReserved，它不代表任何颜色，必须取固定的值为&#8220;0&#8221;，同时，RGBQUAD结构中定义的颜色值中，红色、绿色和蓝色的排列顺序与一般真彩色图像文件的颜色数据排列顺序恰好相反，既：若某个位图中的一个像素点的颜色的描述为&#8220;00，00，ff，00&#8221;，则表示该点为红色，而不是蓝色。<br><br>　　5. 位图数据 <br><br>　　位图数据记录了位图的每一个像素值或该对应像素的颜色表的索引值，图像记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。这种格式我们又称为Bottom_Up位图，当然与之相对的还有Up_Down形式的位图，它的记录顺序是从上到下的，对于这种形式的位图，也不存在压缩形式。位图的一个像素值所占的字节数：当biBitCount=1时，8个像素占1个字节；当biBitCount=4时，2个像素占1个字节；当biBitCount=8时，1个像素占1个字节；当biBitCount=24时,1个像素占3个字节，此时图像为真彩色图像。当图像不是为真彩色时，图像文件中包含颜色表，位图的数据表示对应像素点在颜色表中相应的索引值，当为真彩色时，每一个像素用三个字节表示图像相应像素点彩色值，每个字节分别对应R、G、B分量的值，这时候图像文件中没有颜色表。上面我已经讲过了，<strong>Windows规定图像文件中一个扫描行所占的字节数必须是4的倍数(即以字为单位),不足的以0填充</strong>，图像文件中一个扫描行所占的字节数计算方法：<br><br></font></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataSizePerLine</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(biWidth</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;biBitCount</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">31</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">8</span><span style="COLOR: #000000">；</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;一个扫描行所占的字节数&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;2</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;3</span>&nbsp;<span style="COLOR: #000000">或者<br></span><span style="COLOR: #008080">&nbsp;4</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataSizePerLine</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(biWidth</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;biBitCount</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">31</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">32</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">；</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;一个扫描行所占的字节数&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;5</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;6</span>&nbsp;<span style="COLOR: #000000">(如果biBitCount&nbsp;</span><span style="COLOR: #000000">==</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">8</span><span style="COLOR: #000000">&nbsp;或24)&nbsp;<br></span><span style="COLOR: #008080">&nbsp;7</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;8</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataSizePerLine</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(biWidth</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">；</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;一个扫描行所占的字节数&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;9</span>&nbsp;<span style="COLOR: #008000"></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">10</span>&nbsp;<span style="COLOR: #000000">或<br></span><span style="COLOR: #008080">11</span>&nbsp;<span style="COLOR: #000000"><br></span><span style="COLOR: #008080">12</span>&nbsp;<span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataSizePerLine</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(biWidth</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">3</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">4</span><span style="COLOR: #000000">；</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;一个扫描行所占的字节数&nbsp;<br></span><span style="COLOR: #008080">13</span>&nbsp;<span style="COLOR: #008000"></span></div>
<p><br><font size=3>　　位图数据的大小按下式计算(不压缩情况下)：<br><br>　　DataSize= DataSizePerLine* biHeight。 <br><br>　　上述是BMP文件格式的说明，搞清楚了以上的结构，就可以正确的操作图像文件，对它进行读或写操作了。<br></font></p>
<img src ="http://www.cppblog.com/flyinghare/aggbug/97376.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2009-09-27 16:00 <a href="http://www.cppblog.com/flyinghare/archive/2009/09/27/97376.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DirectShow中常见的RGB/YUV格式</title><link>http://www.cppblog.com/flyinghare/archive/2009/09/27/97374.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Sun, 27 Sep 2009 07:53:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2009/09/27/97374.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/97374.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2009/09/27/97374.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/97374.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/97374.html</trackback:ping><description><![CDATA[转自：<a href="http://www.sharp-i.net/cn/articles/article/The_RGB_YUV_format_in_DirectShow.htm">http://www.sharp-i.net/cn/articles/article/The_RGB_YUV_format_in_DirectShow.htm</a><br><br>
<p align=left><span><span>　　</span>计算机彩色显示器显示色彩的原理与彩色电视机一样，都是采用<span>R</span>（<span>Red</span>）、<span>G</span>（<span>Green</span>）、<span>B</span>（<span>Blue</span>）相加混色的原理：通过发射出三种不同强度的电子束，使屏幕内侧覆盖的红、绿、蓝磷光材料发光而产生色彩。这种色彩的表示方法称为<span>RGB</span>色彩空间表示（它也是多媒体计算机技术中用得最多的一种色彩空间表示方法）。</span><span><br></span><span>　　</span><span>根据三基色原理，任意一种色光<span>F</span>都可以用不同分量的<span>R</span>、<span>G</span>、<span>B</span>三色相加混合而成。</span><span><br></span><span>F = r [ R ] + g [ G ] + b [ B ]</span><span><br></span><span>　　</span><span>其中，<span>r</span>、<span>g</span>、<span>b</span>分别为三基色参与混合的系数。当三基色分量都为<span>0</span>（最弱）时混合为黑色光；而当三基色分量都为<span>k</span>（最强）时混合为白色光。调整<span>r</span>、<span>g</span>、<span>b</span>三个系数的值，可以混合出介于黑色光和白色光之间的各种各样的色光。</span><span><br></span><span>那么<span>YUV</span>又从何而来呢？在现代彩色电视系统中，通常采用三管彩色摄像机或彩色<span>CCD</span>摄像机进行摄像，然后把摄得的彩色图像信号经分色、分别放大校正后得到<span>RGB</span>，再经过矩阵变换电路得到亮度信号<span>Y</span>和两个色差信号<span>R</span>－<span>Y</span>（即<span>U</span>）、<span>B</span>－<span>Y</span>（即<span>V</span>），最后发送端将亮度和色差三个信号分别进行编码，用同一信道发送出去。这种色彩的表示方法就是所谓的<span>YUV</span>色彩空间表示。</span><span><br></span><span>采用<span>YUV</span>色彩空间的重要性是它的亮度信号<span>Y</span>和色度信号<span>U</span>、<span>V</span>是分离的。如果只有<span>Y</span>信号分量而没有<span>U</span>、<span>V</span>分量，那么这样表示的图像就是黑白灰度图像。彩色电视采用<span>YUV</span>空间正是为了用亮度信号<span>Y</span>解决彩色电视机与黑白电视机的兼容问题，使黑白电视机也能接收彩色电视信号。</span><span><br></span><span>　　</span><span>YUV</span><span>与<span>RGB</span>相互转换的公式如下（<span>RGB</span>取值范围均为<span>0-255</span>）：</span><span><br><br></span><span>Y = 0.299R + 0.587G + 0.114B</span><span><br></span><span>U = -0.147R - 0.289G + 0.436B</span><span><br></span><span>V = 0.615R - 0.515G - 0.100B</span><span><br><br></span><span>R = Y + 1.14V</span><span><br></span><span>G = Y - 0.39U - 0.58V</span><span><br></span><span>B = Y + 2.03U</span><span><br><br></span><span>　　</span><span>在<span>DirectShow</span>中，常见的<span>RGB</span>格式有<span>RGB1</span>、<span>RGB4</span>、<span>RGB8</span>、<span>RGB565</span>、<span>RGB555</span>、<span>RGB24</span>、<span>RGB32</span>、<span>ARGB32</span>等；常见的<span>YUV</span>格式有<span>YUY2</span>、<span>YUYV</span>、<span>YVYU</span>、<span>UYVY</span>、<span>AYUV</span>、<span>Y41P</span>、<span>Y411</span>、<span>Y211</span>、<span>IF09</span>、<span>IYUV</span>、<span>YV12</span>、<span>YVU9</span>、<span>YUV411</span>、<span>YUV420</span>等。作为视频媒体类型的辅助说明类型（<span>Subtype</span>），它们对应的<span>GUID</span>见表<span>2.3</span>。</span><span><br><br></span><span>　　</span><span>表<span>2.3 </span>常见的<span>RGB</span>和<span>YUV</span>格式</span><span><br><br></span><span>GUID &nbsp;&nbsp;&nbsp;</span><span>格式描述</span><span><br></span><span>MEDIASUBTYPE_RGB1&nbsp;&nbsp;&nbsp;&nbsp;2</span><span>色，每个像素用<span>1</span>位表示，需要调色板</span><span><br></span><span>MEDIASUBTYPE_RGB4&nbsp;&nbsp;&nbsp;&nbsp;16</span><span>色，每个像素用<span>4</span>位表示，需要调色板</span><span><br></span><span>MEDIASUBTYPE_RGB8&nbsp;&nbsp;&nbsp;&nbsp;256</span><span>色，每个像素用<span>8</span>位表示，需要调色板</span><span><br></span><span>MEDIASUBTYPE_RGB565&nbsp;&nbsp;&nbsp;&nbsp;</span><span>每个像素用<span>16</span>位表示，<span>RGB</span>分量分别使用<span>5</span>位、<span>6</span>位、<span>5</span>位</span><span><br></span><span>MEDIASUBTYPE_RGB555&nbsp;&nbsp;&nbsp;&nbsp;</span><span>每个像素用<span>16</span>位表示，<span>RGB</span>分量都使用<span>5</span>位（剩下的<span>1</span>位不用）</span><span><br></span><span>MEDIASUBTYPE_RGB24&nbsp;&nbsp;&nbsp;&nbsp;</span><span>每个像素用<span>24</span>位表示，<span>RGB</span>分量各使用<span>8</span>位</span><span><br></span><span>MEDIASUBTYPE_RGB32&nbsp;&nbsp;&nbsp;&nbsp;</span><span>每个像素用<span>32</span>位表示，<span>RGB</span>分量各使用<span>8</span>位（剩下的<span>8</span>位不用）</span><span><br></span><span>MEDIASUBTYPE_ARGB32&nbsp;&nbsp;&nbsp;&nbsp;</span><span>每个像素用<span>32</span>位表示，<span>RGB</span>分量各使用<span>8</span>位（剩下的<span>8</span>位用于表示<span>Alpha</span>通道值）</span><span><br></span><span>MEDIASUBTYPE_YUY2&nbsp;&nbsp;&nbsp;&nbsp;YUY2</span><span>格式，以<span>4:2:2</span>方式打包</span><span><br></span><span>MEDIASUBTYPE_YUYV&nbsp;&nbsp;&nbsp;&nbsp;YUYV</span><span>格式（实际格式与<span>YUY2</span>相同）</span><span><br></span><span>MEDIASUBTYPE_YVYU&nbsp;&nbsp;&nbsp;&nbsp;YVYU</span><span>格式，以<span>4:2:2</span>方式打包</span><span><br></span><span>MEDIASUBTYPE_UYVY&nbsp;&nbsp;&nbsp;&nbsp;UYVY</span><span>格式，以<span>4:2:2</span>方式打包</span><span><br></span><span>MEDIASUBTYPE_AYUV&nbsp;&nbsp;&nbsp;&nbsp;</span><span>带<span>Alpha</span>通道的<span>4:4:4 YUV</span>格式</span><span><br></span><span>MEDIASUBTYPE_Y41P&nbsp;&nbsp;&nbsp;&nbsp;Y41P</span><span>格式，以<span>4:1:1</span>方式打包</span><span><br></span><span>MEDIASUBTYPE_Y411&nbsp;&nbsp;&nbsp;&nbsp;Y411</span><span>格式（实际格式与<span>Y41P</span>相同）</span><span><br></span><span>MEDIASUBTYPE_Y211&nbsp;&nbsp;&nbsp;&nbsp;Y211</span><span>格式</span><span><br></span><span>MEDIASUBTYPE_IF09&nbsp;&nbsp;&nbsp;&nbsp;IF09</span><span>格式</span><span><br></span><span>MEDIASUBTYPE_IYUV&nbsp;&nbsp;&nbsp;&nbsp;IYUV</span><span>格式</span><span><br></span><span>MEDIASUBTYPE_YV12&nbsp;&nbsp;&nbsp;&nbsp;YV12</span><span>格式</span><span><br></span><span>MEDIASUBTYPE_YVU9&nbsp;&nbsp;&nbsp;&nbsp;YVU9</span><span>格式</span><span><br><br></span><span>　　</span><span>下面分别介绍各种<span>RGB</span>格式。</span><span><br><br></span><span>　　<span>RGB1</span>、<span>RGB4</span>、<span>RGB8</span>都是调色板类型的<span>RGB</span>格式，在描述这些媒体类型的格式细节时，通常会在<span>BITMAPINFOHEADER</span>数据结构后面跟着一个调色板（定义一系列颜色）。它们的图像数据并不是真正的颜色值，而是当前像素颜色值在调色板中的索引。以<span>RGB1</span>（<span>2</span>色位图）为例，比如它的调色板中定义的两种颜色值依次为<span>0x000000</span>（黑色）和<span>0xFFFFFF</span>（白色），那么图像数据<span>001101010111&#8230;</span>（每个像素用<span>1</span>位表示）表示对应各像素的颜色为：黑黑白白黑白黑白黑白白白<span>&#8230;</span>。</span><span><br><br></span><span>　　<span>RGB565</span>使用<span>16</span>位表示一个像素，这<span>16</span>位中的<span>5</span>位用于<span>R</span>，<span>6</span>位用于<span>G</span>，<span>5</span>位用于<span>B</span>。程序中通常使用一个字（<span>WORD</span>，一个字等于两个字节）来操作一个像素。当读出一个像素后，这个字的各个位意义如下：</span><span><br></span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>高字节<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>低字节</span><span><br></span><span>R R R R R G G G&nbsp;&nbsp;&nbsp;&nbsp; G G G B B B B B</span><span><br></span><span>可以组合使用屏蔽字和移位操作来得到<span>RGB</span>各分量的值：</span><span><br><br></span><span>#define RGB565_MASK_RED&nbsp;&nbsp;&nbsp;&nbsp;0xF800</span><span><br></span><span>#define RGB565_MASK_GREEN&nbsp;&nbsp;0x07E0</span><span><br></span><span>#define RGB565_MASK_BLUE&nbsp;&nbsp; 0x001F</span><span><br></span><span>R = (wPixel &amp; RGB565_MASK_RED) &gt;&gt; 11;&nbsp;&nbsp; // </span><span>取值范围<span>0-31<span><br></span>G = (wPixel &amp; RGB565_MASK_GREEN) &gt;&gt; 5;&nbsp;&nbsp;// </span>取值范围<span>0-63</span></span><span><br></span><span>B =&nbsp;&nbsp;wPixel &amp; RGB565_MASK_BLUE;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span>取值范围<span>0-31</span></span><span><br><br></span><span>　　<span>RGB555</span>是另一种<span>16</span>位的<span>RGB</span>格式，<span>RGB</span>分量都用<span>5</span>位表示（剩下的<span>1</span>位不用）。使用一个字读出一个像素后，这个字的各个位意义如下：</span><span><br></span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span><span>高字节<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>低字节</span><span><br></span><span>X R R R R G G&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; G G G B B B B B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>（<span>X</span>表示不用，可以忽略）</span><span><br></span><span>可以组合使用屏蔽字和移位操作来得到<span>RGB</span>各分量的值：</span><span><br><br></span><span>#define RGB555_MASK_RED&nbsp;&nbsp;&nbsp;&nbsp;0x7C00</span><span><br></span><span>#define RGB555_MASK_GREEN&nbsp;&nbsp;0x03E0</span><span><br></span><span>#define RGB555_MASK_BLUE&nbsp;&nbsp; 0x001F</span><span><br></span><span>R = (wPixel &amp; RGB555_MASK_RED) &gt;&gt; 10;&nbsp;&nbsp; // </span><span>取值范围<span>0-31<span><br></span>G = (wPixel &amp; RGB555_MASK_GREEN) &gt;&gt; 5;&nbsp;&nbsp;// </span>取值范围<span>0-31</span></span><span><br></span><span>B =&nbsp;&nbsp;wPixel &amp; RGB555_MASK_BLUE;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span>取值范围<span>0-31</span></span><span><br><br></span><span>　　<span>RGB24</span>使用<span>24</span>位来表示一个像素，<span>RGB</span>分量都用<span>8</span>位表示，取值范围为<span>0-255</span>。注意在内存中<span>RGB</span>各分量的排列顺序为：<span>BGR BGR BGR&#8230;</span>。通常可以使用<span>RGBTRIPLE</span>数据结构来操作一个像素，它的定义为：</span><span><br><br></span><span>typedef struct tagRGBTRIPLE { </span><span><br></span><span>&nbsp;&nbsp;BYTE rgbtBlue;&nbsp;&nbsp;&nbsp;&nbsp;// </span><span>蓝色分量</span><span><br></span><span>&nbsp;&nbsp;BYTE rgbtGreen;&nbsp;&nbsp; // </span><span>绿色分量</span><span><br></span><span>&nbsp;&nbsp;BYTE rgbtRed;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span>红色分量</span><span><br></span><span>} RGBTRIPLE;</span><span><br><br></span><span>　　<span>RGB32</span>使用<span>32</span>位来表示一个像素，<span>RGB</span>分量各用去<span>8</span>位，剩下的<span>8</span>位用作<span>Alpha</span>通道或者不用。（<span>ARGB32</span>就是带<span>Alpha</span>通道的<span>RGB32</span>。）注意在内存中<span>RGB</span>各分量的排列顺序为：<span>BGRA BGRA BGRA&#8230;</span>。通常可以使用<span>RGBQUAD</span>数据结构来操作一个像素，它的定义为：</span><span><br><br></span><span>typedef struct tagRGBQUAD {</span><span><br></span><span>&nbsp;&nbsp;BYTE&nbsp;&nbsp;&nbsp;&nbsp;rgbBlue;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// </span><span>蓝色分量</span><span><br></span><span>&nbsp;&nbsp;BYTE&nbsp;&nbsp;&nbsp;&nbsp;rgbGreen;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span>绿色分量</span><span><br></span><span>&nbsp;&nbsp;BYTE&nbsp;&nbsp;&nbsp;&nbsp;rgbRed;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span><span>红色分量</span><span><br></span><span>&nbsp;&nbsp;BYTE&nbsp;&nbsp;&nbsp;&nbsp;rgbReserved;&nbsp;&nbsp;// </span><span>保留字节（用作<span>Alpha</span>通道或忽略）</span><span><br></span><span>} RGBQUAD;</span><span><br><br></span><span>　　　</span><span>下面介绍各种<span>YUV</span>格式。<span>YUV</span>格式通常有两大类：打包（<span>packed</span>）格式和平面（<span>planar</span>）格式。前者将<span>YUV</span>分量存放在同一个数组中，通常是几个相邻的像素组成一个宏像素（<span>macro-pixel</span>）；而后者使用三个数组分开存放<span>YUV</span>三个分量，就像是一个三维平面一样。表<span>2.3</span>中的<span>YUY2</span>到<span>Y211</span>都是打包格式，而<span>IF09</span>到<span>YVU9</span>都是平面格式。（注意：在介绍各种具体格式时，<span>YUV</span>各分量都会带有下标，如<span>Y0</span>、<span>U0</span>、<span>V0</span>表示第一个像素的<span>YUV</span>分量，<span>Y1</span>、<span>U1</span>、<span>V1</span>表示第二个像素的<span>YUV</span>分量，以此类推。）</span><span><br><br></span><span>　　　</span><span>YUY2</span><span>（和<span>YUYV</span>）格式为每个像素保留<span>Y</span>分量，而<span>UV</span>分量在水平方向上每两个像素采样一次。一个宏像素为<span>4</span>个字节，实际表示<span>2</span>个像素。（<span>4:2:2</span>的意思为一个宏像素中有<span>4</span>个<span>Y</span>分量、<span>2</span>个<span>U</span>分量和<span>2</span>个<span>V</span>分量。）图像数据中<span>YUV</span>分量排列顺序如下：</span><span><br></span><span>Y0 U0 Y1 V0&nbsp;&nbsp;&nbsp;&nbsp;Y2 U2 Y3 V2 &#8230;</span><span><br><br></span><span>　　<span>YVYU</span>格式跟<span>YUY2</span>类似，只是图像数据中<span>YUV</span>分量的排列顺序有所不同：</span><span><br></span><span>Y0 V0 Y1 U0&nbsp;&nbsp;&nbsp;&nbsp;Y2 V2 Y3 U2 &#8230;</span><span><br><br></span><span>　　<span>UYVY</span>格式跟<span>YUY2</span>类似，只是图像数据中<span>YUV</span>分量的排列顺序有所不同：</span><span><br></span><span>U0 Y0 V0 Y1&nbsp;&nbsp;&nbsp;&nbsp;U2 Y2 V2 Y3 &#8230;</span><span><br><br></span><span>　　<span>AYUV</span>格式带有一个<span>Alpha</span>通道，并且为每个像素都提取<span>YUV</span>分量，图像数据格式如下：</span><span><br></span><span>A0 Y0 U0 V0&nbsp;&nbsp;&nbsp;&nbsp;A1 Y1 U1 V1 &#8230;</span><span><br><br></span><span>　　<span>Y41P</span>（和<span>Y411</span>）格式为每个像素保留<span>Y</span>分量，而<span>UV</span>分量在水平方向上每<span>4</span>个像素采样一次。一个宏像素为<span>12</span>个字节，实际表示<span>8</span>个像素。图像数据中<span>YUV</span>分量排列顺序如下：</span><span><br></span><span>U0 Y0 V0 Y1&nbsp;&nbsp;&nbsp;&nbsp;U4 Y2 V4 Y3&nbsp;&nbsp;&nbsp;&nbsp;Y4 Y5 Y6 Y8 &#8230; </span><span><br><br></span><span>　　<span>Y211</span>格式在水平方向上<span>Y</span>分量每<span>2</span>个像素采样一次，而<span>UV</span>分量每<span>4</span>个像素采样一次。一个宏像素为<span>4</span>个字节，实际表示<span>4</span>个像素。图像数据中<span>YUV</span>分量排列顺序如下：</span><span><br></span><span>Y0 U0 Y2 V0&nbsp;&nbsp;&nbsp;&nbsp;Y4 U4 Y6 V4 &#8230;</span><span><br><br></span><span>　　<span>YVU9</span>格式为每个像素都提取<span>Y</span>分量，而在<span>UV</span>分量的提取时，首先将图像分成若干个<span>4 x 4</span>的宏块，然后每个宏块提取一个<span>U</span>分量和一个<span>V</span>分量。图像数据存储时，首先是整幅图像的<span>Y</span>分量数组，然后就跟着<span>U</span>分量数组，以及<span>V</span>分量数组。<span>IF09</span>格式与<span>YVU9</span>类似。</span><span><br><br></span><span>　　<span>IYUV</span>格式为每个像素都提取<span>Y</span>分量，而在<span>UV</span>分量的提取时，首先将图像分成若干个<span>2 x 2</span>的宏块，然后每个宏块提取一个<span>U</span>分量和一个<span>V</span>分量。<span>YV12</span>格式与<span>IYUV</span>类似。</span><span><br><br></span><span>　　<span>YUV411</span>、<span>YUV420</span>格式多见于<span>DV</span>数据中，前者用于<span>NTSC</span>制，后者用于<span>PAL</span>制。<span>YUV411</span>为每个像素都提取<span>Y</span>分量，而<span>UV</span>分量在水平方向上每<span>4</span>个像素采样一次。<span>YUV420</span>并非<span>V</span>分量采样为<span>0</span>，而是跟<span>YUV411</span>相比，在水平方向上提高一倍色差采样频率，在垂直方向上以<span>U/V</span>间隔的方式减小一半色差采样。</span></p>
<img src ="http://www.cppblog.com/flyinghare/aggbug/97374.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2009-09-27 15:53 <a href="http://www.cppblog.com/flyinghare/archive/2009/09/27/97374.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网狐棋牌游戏服务端架构设计原理</title><link>http://www.cppblog.com/flyinghare/archive/2009/09/20/96772.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Sun, 20 Sep 2009 05:52:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2009/09/20/96772.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/96772.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2009/09/20/96772.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/96772.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/96772.html</trackback:ping><description><![CDATA[<p>转自：<a href="http://blog.csdn.net/dotnet90/archive/2009/05/05/4152401.aspx">http://blog.csdn.net/dotnet90/archive/2009/05/05/4152401.aspx</a><br><br>基本设计概念和处理流程</p>
<p>调用模型</p>
<p>利用面向对象思想多态性,调用方保存着被调用方的基础接口指针(一般称呼为 钩子),调用方直接调用接口指针里面方法,方法具体实现逻辑由</p>
<p>该接口的派生类实现.示意图:</p>
<p>&nbsp;<img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/flyinghare/image001.gif" width=504 height=208></p>
<p><br>基于事件驱动的数据处理模型</p>
<p>为系统功能设计，需要处理网络事件数据SocketEvent，数据库事件数据DatabaseEvent，定时器事件数据TimerEvent等，为此建立数据队列服</p>
<p>务QueueService,为每一队列建立多个子线程QueueServiceThread处理。数据队列服务提供添加事件数据方法AddToQueue，设置数据队列服务钩</p>
<p>子SetQueueServiceSink，让数据队列服务钩子QueueServiceSink做具体逻辑事件数据处理。<br>示意图:</p>
<p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/flyinghare/image002.gif" width=584 height=208><br>再者，根据网络,数据库等特定功能，构建网络，数据库等管理服务，实现数据队列服务钩子QueueServiceSink方法，调度事件数据执行外部处</p>
<p>理接口，外部处理接口具体由二次开发用户实现。示意图:</p>
<p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/flyinghare/image003.gif" width=516 height=166></p>
<p>事件数据设计</p>
<p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/flyinghare/Event.gif" width=511 height=292></p>
<p><br>框架体系设计</p>
<p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/flyinghare/image004.gif" width=696 height=476></p>
<p>功能模块划分</p>
<p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/flyinghare/FrameWork.gif" width=537 height=397></p>
<p>数据队列服务QueueService模块设计</p>
<p>&nbsp;&nbsp;&nbsp; 基本设计概念</p>
<p>&nbsp;&nbsp;&nbsp; 建立一个内存链表，保存事件数据，对外部提供方法往链表添加事件数据并通知线程，同时启动多个处理线程，从数据链表里获取事件数据，执行外部钩子方法进行处理.线程事件通知采用完成端口技术.</p>
<p>&nbsp;&nbsp; 类与接口设计</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 接口设计</p>
<p>&nbsp;<img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/flyinghare/22.jpg" width=541 height=694></p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/dotnet90/archive/2009/05/05/4152401.aspx">http://blog.csdn.net/dotnet90/archive/2009/05/05/4152401.aspx</a></p>
<img src ="http://www.cppblog.com/flyinghare/aggbug/96772.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2009-09-20 13:52 <a href="http://www.cppblog.com/flyinghare/archive/2009/09/20/96772.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>顶点坐标变换（3）</title><link>http://www.cppblog.com/flyinghare/archive/2009/09/16/96404.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Wed, 16 Sep 2009 04:15:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2009/09/16/96404.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/96404.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2009/09/16/96404.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/96404.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/96404.html</trackback:ping><description><![CDATA[<p>转自：<a href="http://www.cppblog.com/lovedday/archive/2008/05/02/48628.html">http://www.cppblog.com/lovedday/archive/2008/05/02/48628.html</a><strong><br><br>世界变换</strong></p>
<p>世界变换就是将物体顶点坐标从模型空间转换到世界空间。在模型空间里，顶点位置坐标依据模型的本地坐标系的原点而定，在世界空间里，所有模型的顶点共用一个原点，即世界坐标系原点。事实上，世界变换就是将一个模型从本地空间重新定位到世界空间内。从模型空间到世界空间的转换实际上就是对模型进行平移、旋转、缩放以及它们的任意组合变换。</p>
<p>使用三维模型制作软件，例如3dmax，制作三维模型时，首先需要为模型设定一个坐标系，模型上的顶点坐标就是设定的模型自身坐标系下的坐标，这个坐标系也就是上面提到的本地坐标系或模型空间。</p>
<p>&nbsp;</p>
<p><strong>1、世界变换矩阵</strong></p>
<p>在处理三维图像的应用程序中，可使用世界变换完成一个物体（确切的说是一个坐标或一系列坐标）的平移、旋转和缩放。当然也可以完成这三种变换的任意组合。具体的方法就是通过下式：</p>
<p><img height=111 src="http://www.cppblog.com/images/cppblog_com/changingnow/6923/o_world_matrix.jpg" width=344 border=0></p>
<p>将任意一点P(x, y, z)转换到p'(x', y', z')，上式也可以表示为以下形式：</p>
<p>p'(x', y', z') = P(x, y, z) . M<sub>world</sub></p>
<p>M<sub>world</sub>就是世界变换矩阵。也就是它实现了物体的平移、旋转、缩放和它们的复合变换。在定义好世界变换矩阵后，调用函数IDirect3DDevice9::SetTransform()并指定第一个参数为D3DTS_WORLD，第二个参数为相应的世界变换矩阵即可。</p>
<p>&nbsp;</p>
<p><strong>2、平移</strong></p>
<p>可以通过下式（也就是下面的平移变换矩阵）：</p>
<p><img height=108 src="http://www.cppblog.com/images/cppblog_com/changingnow/6923/o_translation_matrix.jpg" width=292 border=0></p>
<p>将点（x, y, z）沿x、y和z轴分别移动T<sub>x</sub>、T<sub>y</sub>、T<sub>z</sub>，到另一点（x'，y'，z'）。很显然，只要得到了这个平移矩阵，平移工作就可以完成。</p>
<p>为方便起见，D3DX扩展函数库d3dx9.lib提供了函数D3DXMatrixTranslation()，用它可以很方便地生成一个平移世界矩阵。该函数的声明如下:</p>
<p><font color=#004040>Builds a matrix using the specified offsets.</font></p>
<pre class=syntax><font color=#004040><strong>D3DXMATRIX * D3DXMatrixTranslation(</strong><br>  <strong>D3DXMATRIX *</strong> <em>pOut</em><strong>,</strong><br>  <strong>FLOAT</strong> <em>x</em><strong>,</strong><br>  <strong>FLOAT</strong> <em>y</em><strong>,</strong><br>  <strong>FLOAT</strong> <em>z</em><br><strong>)</strong>;</font></pre>
<h4><font color=#004040>Parameters</font></h4>
<dl>
<dt><font color=#004040><em>pOut</em> </font>
<dd><font color=#004040>[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation. </font>
<dt><font color=#004040><em>x</em> </font>
<dd><font color=#004040>[in] X-coordinate offset. </font>
<dt><font color=#004040><em>y</em> </font>
<dd><font color=#004040>[in] Y-coordinate offset. </font>
<dt><font color=#004040><em>z</em> </font>
<dd><font color=#004040>[in] Z-coordinate offset. </font></dd></dl>
<h4><font color=#004040>Return Values</font></h4>
<p><font color=#004040>Pointer to a <strong>D3DXMATRIX</strong> structure that contains a translated transformation matrix.</font></p>
<h4><font color=#004040>Remarks</font></h4>
<p><font color=#004040>The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMATRIXTranslation can be used as a parameter for another function.</font></p>
<p>&nbsp;</p>
<p><strong>3、旋转</strong></p>
<p>与平移类似，使用下面的四阶矩阵可以将点（x, y, z）绕x轴旋转&#952;角，到新点（x', y', z'）:</p>
<p><img height=117 src="http://www.cppblog.com/images/cppblog_com/changingnow/6923/o_rotate_x_matrix.jpg" width=321 border=0></p>
<p>绕y轴旋转&#952;角时的矩阵为：</p>
<p><img height=113 src="http://www.cppblog.com/images/cppblog_com/changingnow/6923/o_rotate_y_matrix.jpg" width=303 border=0></p>
<p>绕z轴旋转&#952;角时的矩阵为：</p>
<p><img height=114 src="http://www.cppblog.com/images/cppblog_com/changingnow/6923/o_rotate_z_matrix.jpg" width=327 border=0></p>
<p>&#952;指旋转角度，单位是弧度，具体是指沿着旋转轴的指向（即正方向）向坐标原点看去顺指针旋转过的角度。</p>
<p>同样可以使用D3DX扩展函数库d3dx9.lib提供的函数D3DXMatrixRotationX()、D3DXMatrixRotationY()和D3DXMatrixRotationZ()方便地创建旋转矩阵，这三个函数的声明如下，因声明类似，只列出D3DXMatrixRotationX()的使用说明:</p>
<p><font color=#004040>Builds a matrix that rotates around the x-axis.</font></p>
<pre class=syntax><font color=#004040><strong>D3DXMATRIX * D3DXMatrixRotationX(</strong><br>  <strong>D3DXMATRIX *</strong> <em>pOut</em><strong>,</strong><br>  <strong>FLOAT</strong> <em>Angle</em><br><strong>)</strong>;</font></pre>
<h4><font color=#004040>Parameters</font></h4>
<dl>
<dt><font color=#004040><em>pOut</em> </font>
<dd><font color=#004040>[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation. </font>
<dt><font color=#004040><em>Angle</em> </font>
<dd><font color=#004040>[in] Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin. </font></dd></dl>
<h4><font color=#004040>Return Values</font></h4>
<p><font color=#004040>Pointer to a <strong>D3DXMATRIX</strong> structure rotated around the x-axis.</font></p>
<h4><font color=#004040>Remarks</font></h4>
<p><font color=#004040>The return value for this function is the same value returned in the pOut parameter. In this way, the <strong>D3DXMatrixRotationX</strong> function can be used as a parameter for another function.</font></p>
<p>&nbsp;</p>
<p><strong>4、缩放</strong></p>
<p>使用下面的四阶矩阵可以将点（x, y, z）在x、y、z轴上各缩放Sx、Sy、Sz，到另一点（x', y', z'）。</p>
<p><img height=119 src="http://www.cppblog.com/images/cppblog_com/changingnow/6923/o_scale_matrix.jpg" width=274 border=0></p>
<p>同样，可以使用Direct3D扩展实用库中的函数D3DXMatrixScaling()来生成缩放矩阵，该函数的声明如下：</p>
<p><font color=#004040>Builds a matrix that scales along the x-axis, the y-axis, and the z-axis.</font></p>
<pre class=syntax><font color=#004040><strong>D3DXMATRIX * D3DXMatrixScaling(</strong><br>  <strong>D3DXMATRIX *</strong> <em>pOut</em><strong>,</strong><br>  <strong>FLOAT</strong> <em>sx</em><strong>,</strong><br>  <strong>FLOAT</strong> <em>sy</em><strong>,</strong><br>  <strong>FLOAT</strong> <em>sz</em><br><strong>)</strong>;</font></pre>
<h4><font color=#004040>Parameters</font></h4>
<dl>
<dt><font color=#004040><em>pOut</em> </font>
<dd><font color=#004040>[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation. </font>
<dt><font color=#004040><em>sx</em> </font>
<dd><font color=#004040>[in] Scaling factor that is applied along the x-axis. </font>
<dt><font color=#004040><em>sy</em> </font>
<dd><font color=#004040>[in] Scaling factor that is applied along the y-axis. </font>
<dt><font color=#004040><em>sz</em> </font>
<dd><font color=#004040>[in] Scaling factor that is applied along the z-axis. </font></dd></dl>
<h4><font color=#004040>Return Values</font></h4>
<p><font color=#004040>Pointer to the scaling transformation <strong>D3DXMATRIX</strong>.</font></p>
<h4><font color=#004040>Remarks</font></h4>
<p><font color=#004040>The return value for this function is the same value returned in the pOut parameter. In this way, the <strong>D3DXMatrixScaling</strong> function can be used as a parameter for another function.</font></p>
<p>&nbsp;</p>
<p><strong>5、矩阵连接与复合变换</strong></p>
<p>在大多数情况下，Direct3D中的物体需要进行的世界变换不止一个，而往往是多个世界变换的组合，这时可以使用矩阵连接来实现这种复合变换。因为矩阵的一个优点是通过矩阵的相乘，将两个或更多矩阵的作用合并在一起实现。为了先后实现一个模型的旋转和移动，不需要使用两个矩阵，可以将旋转矩阵和平移矩阵相乘得到一个复合矩阵以实现所有功能。这个过程叫做矩阵连接（matrix concatention），可以用下面的公式表示：</p>
<p>C = M<sub>1</sub> * M<sub>2</sub> * ... * M<sub>n-1</sub> * M<sub>n</sub></p>
<p>在这个公式里，C是实现复合变换的复合矩阵，从M<sub>1</sub>到M<sub>n</sub>是只能实现某一种世界变换的单独矩阵（individual matrices）。大多数情况下是两到三个矩阵连接，但这个数量没有限制。</p>
<p>使用函数D3DXMatrixMultiply() 可完成矩阵的乘法，该函数的说明如下：</p>
<p><font color=#004040>Determines the product of two matrices.</font></p>
<pre class=syntax><font color=#004040><strong>D3DXMATRIX * D3DXMatrixMultiply(</strong><br>  <strong>D3DXMATRIX *</strong> <em>pOut</em><strong>,</strong><br>  <strong>CONST D3DXMATRIX *</strong> <em>pM1</em><strong>,</strong><br>  <strong>CONST D3DXMATRIX *</strong> <em>pM2</em><br><strong>)</strong>;</font></pre>
<h4><font color=#004040>Parameters</font></h4>
<dl>
<dt><font color=#004040><em>pOut</em> </font>
<dd><font color=#004040>[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation. </font>
<dt><font color=#004040><em>pM1</em> </font>
<dd><font color=#004040>[in] Pointer to a source <strong>D3DXMATRIX</strong> structure. </font>
<dt><font color=#004040><em>pM2</em> </font>
<dd><font color=#004040>[in] Pointer to a source <strong>D3DXMATRIX</strong> structure. </font></dd></dl>
<h4><font color=#004040>Return Values</font></h4>
<p><font color=#004040>Pointer to a <strong>D3DXMATRIX</strong> structure that is the product of two matrices.</font></p>
<h4><font color=#004040>Remarks</font></h4>
<p><font color=#004040>The result represents the transformation M1 followed by the transformation M2 (Out = M1 * M2).</font></p>
<p><font color=#004040>The return value for this function is the same value returned in the pOut parameter. In this way, the <strong>D3DXMatrixMultiply</strong> function can be used as a parameter for another function.</font></p>
<p>矩阵pOut表示最终的复合变换，也就是先进行矩阵pM1表示的变换，然后又进行矩阵pM2表示的变换。</p>
<p><font color=#800000>在矩阵的乘法中，顺序是很关键的。无论要创建什么样的世界变换矩阵，记住从左到右的原则才能确保实现想要的效果，也就是说，一个复合矩阵的视觉效果是按从左到右的顺序各单独矩阵视觉效果的组合。</font>假设一个物体先绕y轴旋转，然后把它移动到场景内的另一个位置。为实现这个效果，首先创建一个旋转矩阵R<sub>y</sub>，然后乘以一个平移矩阵T<sub>w</sub>：</p>
<p>W = R<sub>y</sub> * T<sub>w</sub></p>
<p>在这个公式里，R<sub>y</sub>表示绕y轴的旋转矩阵，T<sub>w</sub>实现世界坐标系内的一次平移。<font color=#800000>矩阵的乘法不满足交换律。</font>如果将这两个矩阵以相反的顺序相乘，效果是先平移，然后旋转。</p>
<img src ="http://www.cppblog.com/flyinghare/aggbug/96404.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2009-09-16 12:15 <a href="http://www.cppblog.com/flyinghare/archive/2009/09/16/96404.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：图象处理常用特效算法</title><link>http://www.cppblog.com/flyinghare/archive/2009/09/08/95538.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Tue, 08 Sep 2009 02:14:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2009/09/08/95538.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/95538.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2009/09/08/95538.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/95538.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/95538.html</trackback:ping><description><![CDATA[<p>原文：<a href="http://blog.csdn.net/alin0725/archive/2007/03/28/1543860.aspx">http://blog.csdn.net/alin0725/archive/2007/03/28/1543860.aspx</a><br><br>１．图像的逆反处理算法</p>
<p>逆反处理的算法如下：<br>设r，g，b分别为源图像像素f（i，j）的红，绿，蓝分量值，rr，gg，bb分别为处理后像素g（i，j）的红，绿，蓝分量值。则<br>rr=255-r<br>gg=255-g<br>bb=255-b</p>
<p><br>２.图像的平滑处理</p>
<p>算法如下：<br>平滑处理是指将源图像的每一个像素的颜色值由其相邻n*n个像素的平均值来代替。<br>例如，对于3*3点阵而言，设原图像某像素的值为f（i，j），平滑处理后该像素的值为g（i，j），则：<br>g(i,j)=(f(i,j)+f(i-1,j)+f(i+1,j)+f(i-1,j-1)+f(i,j-1)+f(i+1,j-1)+<br>f(i-1,j+1)+f(i,j+1)+f(i+1,j+1))/9<br>注意：该算法不能平滑图像边界的像素。</p>
<p>３. 图象的霓虹处理</p>
<p>算法：<br>对于3*3点阵，首先计算原图象像素f(i,j)的红，绿，蓝分量与相同行f（i+1，j）及同列f(i,j+1)相邻象素的梯度，即差的平方之和的平方根，然后将梯度值作为处理后的象素g(i,j)的红，绿，蓝分量值。<br>设r1,g1,b1分别为原图象象素f(i,j)的红，绿，蓝分量值，r2,g2,b2分别为相同行相邻象素f(i+1,j)的红，绿，蓝分量值，r3,g3,b3分别为同列相邻象素f(i,j+1)的红，绿，蓝分量值，rr,gg,bb为处理后象素g(i,j)的红，绿，蓝分量值，则：<br>rr1=(r1-r2)^2&nbsp; rr2=(r1-r3)^2<br>gg1=(g1-g2)^2&nbsp; gg2=(g1-g3)^2<br>bb1=(b1-b2)^2&nbsp; bb2(b1-b3)^2<br>rr=2*(rr1+rr2)^0.5<br>gg=2*(gg1+gg2)^0.5<br>bb=2*(bb1+bb2)^0.5</p>
<p>４.图象的锐化处理</p>
<p>锐化处理的算法：<br>计算原图像像素f(i,j)的像素值与该像素与相邻像素f(i-1,j-1)像素值之差的绝对值得百分比之和，作为处理后图像像素g(i,j)的像素值。例如，设r1,g1,b1分别为f(i,j)的红、绿、蓝分量值，r2,g2,b2分别为f(i-1,j-1)的红、绿、蓝分量值，rr,gg,bb分别为g(i,j)的红、绿、蓝分量值，则：<br>rr=r1+0.25*abs(r1-r2)<br>gg=g1+0.25*abs(g1-g2)<br>bb=b1+0.25*abs(b1-b2)</p>
<p>５. 图像的浮雕处理</p>
<p>算法：<br>位图图像的浮雕处理的算法是：<br>g(i,j)=f(i,j)-f(i-1,j)+常数<br>式中，g(i,j)为处理后图像的像素值，f(i,j)为原图像的像素值，f(i-1,j)为前一个相邻像素的值。常数一般取128，即<br>rr=r1-r2+128<br>gg=g1-g2+128<br>bb=b1-b2+128<br>式中，r1,g1,b1分别为原图像的像素f(i,j)的红、绿、蓝分量值；r2,g2,b2分别为前一个相邻像素f(i-1,j)的红、绿、蓝分量值，rr,gg,bb,分别为处理后图像的像素g(i,j)的红、绿、蓝分量值.</p>
<p>６.图像的镶嵌处理</p>
<p>镶嵌处理算法如下：<br>镶嵌处理后的图像每一小矩阵内的所有像素值都取此矩阵内原图像各像素值之和的平均值。例如，对于3*3的子域：<br>g(i,j)=(f(i,j)+f(i-1,j)+f(i+1,j)+f(i-1,j-1)+f(i+1,j-1)+f(i-1,j+1)+f(i,j+1)+f(i+1,j+1))/9<br>则取：<br>g(i-1,j)=g(i,j)<br>g(i+1,j)=g(i,j)<br>g（i,j-1）=g(i,j)<br>g(i,j+1)=g(i,j)<br>g(i,j+1)=g(i,j)<br>g(i-1,j-1)=g(i,j)<br>g(i-1,j+1)=g(i,j)<br>g(i+1,j-1)=g(i,j)<br>g(i+1,j+1)=g(i,j)</p>
<p>７.图像的灰度处理</p>
<p>彩色图像灰度处理的算法如下：<br>c=tuxing.GetPixel(i,j)<br>r=c.R<br>g=c.G<br>b=c.B<br>rr=g(r 64)*64<br>gg=(g 64)*64<br>bb=(b 64)*64</p>
<p>８.图像缩小处理</p>
<p>以坐标原点为中心，将图像个像素坐标的X分量和Y分量分别乘以Sx，Sy，则可使图像进行整体放大和缩小。这时，<br>X'=X*Sx<br>Y'=Y*Sy<br>当Sx=Sy时，作相似变换;<br>当Sx!=Sy时，产生变形。</p>
<p>９.图像的平移处理</p>
<p>图像的平移变换是将图形上的点（x,y)在x方向（水平方向）和y方向（垂直方向）<br>分别移动dx和dy,则变换后点(x',y')坐标值为：<br>x'=x+dx<br>y'=y+dy</p>
<p><br>１０.图像的旋转变换</p>
<p>二维图像的旋转变换是以原点为中心，将点（x,y）旋转a角度而得到新的坐标（x',y'）的变换称为旋转变换。其数学表达式为：<br>x'=x*cosa-y*sina<br>y'=x*sina+y*cosa</p>
<p><br>１１.二维图像的对称变换</p>
<p>二维图像对称变换有以下几种情况.<br>1.以x轴为对称得对称变换。<br>以x轴为对称得点(x,y)的对称点(x',y')坐标为：<br>x'=x<br>y'=-y<br>2.以y轴为对称得对称变换。<br>以y轴为对称的点（x,y）的对称点(x',y')坐标为：<br>x'=-x<br>y'=y<br>3.以原点为对称的对称变换。<br>以原点为对称得点（x,y）的对称点（x',y'）坐标为：<br>x'=-x<br>y'=-y<br>对图像的每一个像素依据二维图形几何变换公式进行计算后，在进行图像显示，则可得到图像的几何变换。</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/alin0725/archive/2007/03/28/1543860.aspx">http://blog.csdn.net/alin0725/archive/2007/03/28/1543860.aspx</a></p>
<img src ="http://www.cppblog.com/flyinghare/aggbug/95538.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2009-09-08 10:14 <a href="http://www.cppblog.com/flyinghare/archive/2009/09/08/95538.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：使用FreeType实现矢量字体的粗体、斜体、描边、阴影效果</title><link>http://www.cppblog.com/flyinghare/archive/2009/09/07/95461.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Mon, 07 Sep 2009 07:24:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2009/09/07/95461.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/95461.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2009/09/07/95461.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/95461.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/95461.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 原文：http://www.cppblog.com/mybios/archive/2009/08/01/91869.html前言：Freetype是一个跨平台、开源的字体渲染器，网上很多文章介绍，本人就不啰嗦了。本文重点在于实现文章标题所属的各种效果，不是Freetype的基本使用方法介绍文档，所以对于Freetype不熟悉的同学们请先学习下Freetype的基本用法，才可以使用本文中所提...&nbsp;&nbsp;<a href='http://www.cppblog.com/flyinghare/archive/2009/09/07/95461.html'>阅读全文</a><img src ="http://www.cppblog.com/flyinghare/aggbug/95461.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2009-09-07 15:24 <a href="http://www.cppblog.com/flyinghare/archive/2009/09/07/95461.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：GDI+ 在Delphi程序的应用 -- 文字描边与阴影扩展</title><link>http://www.cppblog.com/flyinghare/archive/2009/09/07/95445.html</link><dc:creator>会飞的兔子</dc:creator><author>会飞的兔子</author><pubDate>Mon, 07 Sep 2009 02:53:00 GMT</pubDate><guid>http://www.cppblog.com/flyinghare/archive/2009/09/07/95445.html</guid><wfw:comment>http://www.cppblog.com/flyinghare/comments/95445.html</wfw:comment><comments>http://www.cppblog.com/flyinghare/archive/2009/09/07/95445.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/flyinghare/comments/commentRss/95445.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/flyinghare/services/trackbacks/95445.html</trackback:ping><description><![CDATA[<p>原文：<a href="http://blog.csdn.net/maozefa/archive/2008/08/04/2767721.aspx">http://blog.csdn.net/maozefa/archive/2008/08/04/2767721.aspx</a><br><br>&nbsp;&nbsp; [b]自从文章[/b]《GDI+ 在Delphi程序的应用 -- 可调节的文字阴影特效》发表后，不少人问我怎样实现文字描边。由于我只是个业余编程爱好者，加上文化底蕴差，只要涉及算法和编程理论方面的东西，我就无能为力了，所以直到目前，我也不知道具体的描边算法是怎样的（网上搜索过N次，也没找到答案，可能这方面的东西是要卖钱的）。</p>
<p>&nbsp;&nbsp;&nbsp; 因问得人多了，有时我也思索和研究一下，总算找了个方法可以实现，虽然同专业的图像软件（如PhotoShop）文字描边效果相比差强人意，但可以凑合凑合，作为研究心得，将代码贴在这里备查。</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; 在《GDI+ 在Delphi程序的应用 -- 可调节的文字阴影特效》一文的内容的基础上，对文字阴影效果代码进行了改进和扩充，扩充的功能有2点：一是由原来只能产生黑色阴影扩充为任意颜色阴影；二是可以对阴影进行扩展。有了这2个功能，利用阴影效果也就可以进行文字描边了，推而广之，也可实现图像的描边。下面是具体的代码内容：</p>
<p>&nbsp;</p>
<p>// 备份图像。Data: GDI+位图数据，32位ARGB格式; Dest: 备份目标; Color: 阴影颜色 <br><br>procedure BackImage(Data: TBitmapData; Dest: Pointer; Color: TARGB); <br>asm <br>&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; esi <br>&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; edi </p>
<p>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; esi, [eax + 16]&nbsp;&nbsp; // esi = Data.Scan0 <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; edi, edx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // esi = Dest <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; edx, ecx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // edx = Color &amp; 0xffffff <br>&nbsp;&nbsp;&nbsp; and&nbsp;&nbsp;&nbsp;&nbsp; edx, 0FFFFFFh <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, [eax]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ecx = Data.Height * Data.Width <br>&nbsp;&nbsp;&nbsp; imul&nbsp;&nbsp;&nbsp; ecx, [eax + 4] <br>&nbsp;&nbsp;&nbsp; cld </p>
<p>&nbsp; @Loop:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // for (; ecx &gt;= 0; ecx --) <br>&nbsp;&nbsp;&nbsp; or&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [esi], edx <br>&nbsp;&nbsp;&nbsp; movsd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; *edi++ = *esi++ &amp; 0xff000000 | edx <br>&nbsp;&nbsp;&nbsp; loop&nbsp;&nbsp;&nbsp; @Loop </p>
<p>&nbsp;&nbsp;&nbsp; pop&nbsp;&nbsp;&nbsp;&nbsp; edi <br>&nbsp;&nbsp;&nbsp; pop&nbsp;&nbsp;&nbsp;&nbsp; esi <br>end; </p>
<p>// 扩展。Data: GDI+位图数据，32位ARGB格式; Source: 复制的源 <br>// ExpMatrix: 卷积矩阵; MatrixSize：矩阵大小 <br>procedure MakeExpand(Data: TBitmapData; Source, ExpMatrix: Pointer; <br>&nbsp;&nbsp;&nbsp; MatrixSize: LongWord); <br>var <br>&nbsp; Radius, mSize, rSize: LongWord; <br>&nbsp; x, y: LongWord; <br>&nbsp; Width, Height: Integer; <br>&nbsp; Matrix: Pointer; <br>&nbsp; Stride: LongWord; <br>asm <br>&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; esi <br>&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; edi <br>&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; ebx </p>
<p>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; esi, edx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // esi = Source <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; edi, [eax + 16]&nbsp;&nbsp; // edi = Data.Scan0 + 3 (Alpha byte) <br>&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp; edi, 3 <br>&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp; ecx, 3 <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; Matrix, ecx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Matrix = ExpMatrix + 3 (Alpha byte) <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, MatrixSize <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; edx, ecx <br>&nbsp;&nbsp;&nbsp; dec&nbsp;&nbsp;&nbsp;&nbsp; ecx <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ebx, [eax] <br>&nbsp;&nbsp;&nbsp; sub&nbsp;&nbsp;&nbsp;&nbsp; ebx, ecx <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; Width, ebx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Width = Data.Width - (MatrixSize - 1) <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ebx, [eax + 4] <br>&nbsp;&nbsp;&nbsp; sub&nbsp;&nbsp;&nbsp;&nbsp; ebx, ecx <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; Height, ebx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Height = Data.Height - (MatrixSize - 1) <br>&nbsp;&nbsp;&nbsp; shr&nbsp;&nbsp;&nbsp;&nbsp; ecx, 1 <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; Radius, ecx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Radius = MatrixSize / 2 <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; eax, [eax + 8] <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; Stride, eax <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; mSize, eax <br>&nbsp;&nbsp;&nbsp; shl&nbsp;&nbsp;&nbsp;&nbsp; edx, 2 <br>&nbsp;&nbsp;&nbsp; sub&nbsp;&nbsp;&nbsp;&nbsp; mSize, edx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // mSize = Data.Stride - MatrixSize * 4 <br>&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp; eax, 4 <br>&nbsp;&nbsp;&nbsp; imul&nbsp;&nbsp;&nbsp; eax, ecx <br>&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp; eax, 3 <br>&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp; esi, eax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // esi = esi + (Data.Stride * Radius + Radius * 4 + 3) <br>&nbsp;&nbsp;&nbsp; shl&nbsp;&nbsp;&nbsp;&nbsp; ecx, 3 <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; rSize, ecx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // rSize = Radius * 2 * 4 </p>
<p>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; y, 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // for (y = 0; y &lt; Height; y ++) <br>&nbsp; @yLoop:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // { <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; x, 0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; for (x = 0; x &lt; Width; x ++) <br>&nbsp; @xLoop:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp; test&nbsp;&nbsp;&nbsp; [esi], 0ffh&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; if (*esi != 0) <br>&nbsp;&nbsp;&nbsp; jz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @NextPixel&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp; test&nbsp;&nbsp;&nbsp; [esi - 4], 0ffh <br>&nbsp;&nbsp;&nbsp; jz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @001 <br>&nbsp;&nbsp;&nbsp; test&nbsp;&nbsp;&nbsp; [esi + 4], 0ffh <br>&nbsp;&nbsp;&nbsp; jz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @001 <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ebx, Stride <br>&nbsp;&nbsp;&nbsp; test&nbsp;&nbsp;&nbsp; [esi + ebx], 0ffh <br>&nbsp;&nbsp;&nbsp; jz&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @001 <br>&nbsp;&nbsp;&nbsp; neg&nbsp;&nbsp;&nbsp;&nbsp; ebx <br>&nbsp;&nbsp;&nbsp; test&nbsp;&nbsp;&nbsp; [esi + ebx], 0ffh <br>&nbsp;&nbsp;&nbsp; jnz&nbsp;&nbsp;&nbsp;&nbsp; @NextPixel <br>&nbsp; @001: <br>&nbsp;&nbsp;&nbsp; push&nbsp;&nbsp;&nbsp; edi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Save(edi) <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ebx, Matrix&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ebx = Matrix <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; edx, MatrixSize&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (I = 0; I &lt; MatrixSize; I ++) <br>&nbsp; @Loop3:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; ecx, MatrixSize&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (J = 0; J &lt;= MatrixSize; J ++) <br>&nbsp; @Loop4:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; al, [ebx]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *edi = max(*ebx, *edi) <br>&nbsp;&nbsp;&nbsp; cmp&nbsp;&nbsp;&nbsp;&nbsp; al, [edi] <br>&nbsp;&nbsp;&nbsp; jb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @002 <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; [edi], al <br>&nbsp; @002: <br>&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp; edi, 4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; edi += 4 <br>&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp; ebx, 4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ebx += 4 <br>&nbsp;&nbsp;&nbsp; loop&nbsp;&nbsp;&nbsp; @Loop4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp; edi, mSize&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; edi += mSize <br>&nbsp;&nbsp;&nbsp; dec&nbsp;&nbsp;&nbsp;&nbsp; edx <br>&nbsp;&nbsp;&nbsp; jnz&nbsp;&nbsp;&nbsp;&nbsp; @Loop3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; pop&nbsp;&nbsp;&nbsp;&nbsp; edi&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Reset(edi) <br>&nbsp; @NextPixel:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp; edi, 4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; edi += 4 <br>&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp; esi, 4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; esi += 4 <br>&nbsp;&nbsp;&nbsp; inc&nbsp;&nbsp;&nbsp;&nbsp; x <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; eax, x <br>&nbsp;&nbsp;&nbsp; cmp&nbsp;&nbsp;&nbsp;&nbsp; eax, Width <br>&nbsp;&nbsp;&nbsp; jl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @xLoop&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp; esi, rSize <br>&nbsp;&nbsp;&nbsp; add&nbsp;&nbsp;&nbsp;&nbsp; edi, rSize <br>&nbsp;&nbsp;&nbsp; inc&nbsp;&nbsp;&nbsp;&nbsp; y <br>&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp; eax, y <br>&nbsp;&nbsp;&nbsp; cmp&nbsp;&nbsp;&nbsp;&nbsp; eax, Height <br>&nbsp;&nbsp;&nbsp; jl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @yLoop&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // } </p>
<p>&nbsp;&nbsp;&nbsp; pop&nbsp;&nbsp;&nbsp;&nbsp; ebx <br>&nbsp;&nbsp;&nbsp; pop&nbsp;&nbsp;&nbsp;&nbsp; edi <br>&nbsp;&nbsp;&nbsp; pop&nbsp;&nbsp;&nbsp;&nbsp; esi <br>end; </p>
<p>procedure GdipShadow(Data: TBitmapData; Buf: Pointer; Radius: LongWord); <br>var <br>&nbsp; Gauss: array of Integer; <br>&nbsp; Q: Double; <br>&nbsp; x, y, n, z: Integer; <br>&nbsp; p: PInteger; <br>begin <br>&nbsp; // 根据半径计算高斯模糊矩阵 <br>&nbsp; Q := Radius / 2; <br>&nbsp; if Q = 0 then Q := 0.1; <br>&nbsp; n := Radius shl 1 + 1; <br>&nbsp; SetLength(Gauss, n * n); <br>&nbsp; p := @Gauss[0]; <br>&nbsp; z := 0; <br>&nbsp; for x := -Radius to Radius do <br>&nbsp;&nbsp;&nbsp; for y := -Radius to Radius do <br>&nbsp;&nbsp;&nbsp; begin <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p^ := Round(Exp(-(x * x + y * y) / (2.0 * Q * Q)) / (2.0 * PI * Q * Q) * 1000.0); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Inc(z, p^); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Inc(p); <br>&nbsp;&nbsp;&nbsp; end; <br>&nbsp; MakeShadow(Data, Buf, Gauss, n, z); <br>end; </p>
<p>procedure GdipBorder(Data: TBitmapData; Buf: Pointer; Expand: LongWord; Color: TARGB); <br>var <br>&nbsp; bmp: TGpBitmap; <br>&nbsp; bg: TGpGraphics; <br>&nbsp; Data1: TBitmapData; <br>&nbsp; Size: Integer; <br>begin <br>&nbsp; Size := Expand shl 1 + 1; <br>&nbsp; bmp := TGpBitmap.Create(Size, Size, pf32bppARGB); <br>&nbsp; bg := TGpGraphics.Create(bmp); <br>&nbsp; try <br>&nbsp;&nbsp;&nbsp; // 制造一个直径=Size，消除锯齿后的圆作为描边（或扩展）的位图画笔 <br>&nbsp;&nbsp;&nbsp; bg.SmoothingMode := smAntiAlias; <br>&nbsp;&nbsp;&nbsp; bg.PixelOffsetMode := pmHalf; <br>&nbsp;&nbsp;&nbsp; bg.FillEllipse(Brushs[Color], 0, 0, Size, Size); <br>&nbsp;&nbsp;&nbsp; Data1 := bmp.LockBits(GpRect(0, 0, Size, Size), [imRead], pf32bppARGB); <br>&nbsp;&nbsp;&nbsp; try <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 用位图画笔扩展图像 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MakeExpand(Data, Buf, Data1.Scan0, Size); <br>&nbsp;&nbsp;&nbsp; finally <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bmp.UnlockBits(Data1); <br>&nbsp;&nbsp;&nbsp; end; <br>&nbsp; finally <br>&nbsp;&nbsp;&nbsp; bg.Free; <br>&nbsp;&nbsp;&nbsp; bmp.Free; <br>&nbsp; end; <br>end; </p>
<p>procedure DrawShadow(const g: TGpGraphics; const Bitmap: TGpBitmap; <br>&nbsp;&nbsp;&nbsp; const layoutRect: TGpRectF; ShadowSize, Distance: LongWord; <br>&nbsp;&nbsp;&nbsp; Angle: Single; Color: TARGB; Expand: LongWord); <br>var <br>&nbsp; dr, sr: TGpRectF; <br>&nbsp; Data: TBitmapData; <br>&nbsp; Buf: Pointer; <br>&nbsp; SaveScan0: Pointer; <br>begin <br>&nbsp; Data := Bitmap.LockBits(GpRect(0, 0, Bitmap.Width, Bitmap.Height), <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [imRead, imWrite], pf32bppARGB); <br>&nbsp; GetMem(Buf, Data.Height * Data.Stride); <br>&nbsp; try <br>&nbsp;&nbsp;&nbsp; BackImage(Data, Buf, Color); <br>&nbsp;&nbsp;&nbsp; if Expand &gt; ShadowSize then <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Expand := ShadowSize; <br>&nbsp;&nbsp;&nbsp; if Expand &lt;&gt; 0 then&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 处理文字阴影扩展 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if Expand &lt;&gt; ShadowSize then <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SaveScan0 := Data.Scan0; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Data.Scan0 := Buf; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GdipBorder(Data, SaveScan0, Expand, Color); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Data.Scan0 := SaveScan0; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end else <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GdipBorder(Data, Buf, Expand, Color); <br>&nbsp;&nbsp;&nbsp; if Expand &lt;&gt; ShadowSize then&nbsp;&nbsp; // 处理文字阴影效果 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GdipShadow(Data, Buf, ShadowSize - Expand); <br>&nbsp; finally <br>&nbsp;&nbsp;&nbsp; FreeMem(Buf); <br>&nbsp;&nbsp;&nbsp; Bitmap.UnlockBits(Data); <br>&nbsp; end; <br>&nbsp; sr := GpRect(0.0, 0.0, Data.Width, Data.Height); <br>//&nbsp; sr := GpRect(0.0, 0.0, layoutRect.Width + ShadowSize * 2 + 2, <br>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; layoutRect.Height + ShadowSize * 2 + 2); <br>&nbsp; dr := GpRect(layoutRect.Point, sr.Size); <br>&nbsp; // 根据角度计算阴影位图在目标画布的偏移量 <br>&nbsp; Offset(dr, Cos(PI * Angle / 180) * Distance - ShadowSize - 1, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sin(PI * Angle / 180) * Distance - ShadowSize - 1); <br>&nbsp; // 输出阴影位图到目标画布 <br>&nbsp; g.DrawImage(Bitmap, dr, sr.X, sr.Y, sr.Width, sr.Height, utPixel); <br>end; </p>
<p>// 计算并输出文字阴影效果 <br>// g: 文字输出的画布; str要输出的文字; font: 字体; layoutRect: 限定的文字输出范围 <br>// ShadowSize: 阴影大小; Distance: 阴影距离; <br>// Angle: 阴影输出角度(左边平行处为0度。顺时针方向) <br>// ShadowAlpha: 阴影文字的不透明度; format: 文字输出格式 <br>procedure DrawShadowString(const g: TGpGraphics; const str: WideString; <br>&nbsp;&nbsp;&nbsp; const font: TGpFont; const layoutRect: TGpRectF; <br>&nbsp;&nbsp;&nbsp; ShadowSize, Distance: LongWord; Angle: Single = 60; <br>&nbsp;&nbsp;&nbsp; Color: TARGB = $C0000000; Expand: LongWord = 0; <br>&nbsp;&nbsp;&nbsp; const format: TGpStringFormat = nil); overload; <br>var <br>&nbsp; Bmp: TGpBitmap; <br>&nbsp; Bg: TGpGraphics; <br>begin <br>&nbsp; // 建立透明的32位ARGB阴影位图，大小为layoutRect长、宽度 + ShadowSize * 2 + 2 <br>&nbsp; Bmp := TGpBitmap.Create(Round(layoutRect.Width + 0.5) + ShadowSize shl 1 + 2, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Round(layoutRect.Height + 0.5) + ShadowSize shl 1 + 2, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pf32bppARGB); <br>&nbsp; Bg := TGpGraphics.Create(Bmp); <br>&nbsp; try <br>&nbsp;&nbsp;&nbsp; Bg.TextRenderingHint := thAntiAlias; <br>&nbsp;&nbsp;&nbsp; // 以Color不透明度的黑色画刷，在ShadowSize + 1处输出文字到位图画布。 <br>&nbsp;&nbsp;&nbsp; // 方便黑色以外的阴影颜色替换（直接用Color画，模糊处理后很难看） <br>&nbsp;&nbsp;&nbsp; Bg.DrawString(str, font, Brushs[Color and $FF000000], <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GpRect(ShadowSize + 1, ShadowSize + 1, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; layoutRect.Width, layoutRect.Height), format); <br>&nbsp;&nbsp;&nbsp; DrawShadow(g, Bmp, layoutRect, ShadowSize, Distance, Angle, Color, Expand); <br>&nbsp; finally <br>&nbsp;&nbsp;&nbsp; Bg.Free; <br>&nbsp;&nbsp;&nbsp; Bmp.Free; <br>&nbsp; end; <br>end; </p>
<p>// 计算并输出文字阴影效果，除以输出点origin替代上面布局矩形外，其他参数同上 <br>procedure DrawShadowString(const g: TGpGraphics; const str: WideString; <br>&nbsp;&nbsp;&nbsp; const font: TGpFont; const origin: TGpPointF; <br>&nbsp;&nbsp;&nbsp; ShadowSize, Distance: LongWord; Angle: Single = 60; <br>&nbsp;&nbsp;&nbsp; Color: TARGB = $C0000000; Expand: LongWord = 0; <br>&nbsp;&nbsp;&nbsp; const format: TGpStringFormat = nil); overload; <br>begin <br>&nbsp; DrawShadowString(g, str, font, g.MeasureString(str, font, origin, format), <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ShadowSize, Distance, Angle, Color, Expand, format); <br>end;<br>&nbsp;&nbsp;&nbsp; 上面代码中MakeShadow过程的代码在《GDI+ 在Delphi程序的应用 -- 可调节的文字阴影特效》一文中，本文没有贴出。由于代码中已经有了较详细的注释，故不再解释。下面贴出测试代码：</p>
<p><br>procedure TextPaint(g: TGpGraphics); <br>var <br>&nbsp; brush: TGpLinearGradientBrush; <br>&nbsp; font: TGpFont; <br>&nbsp; fontFamily: TGpFontFamily; <br>&nbsp; r: TGpRect; <br>begin <br>&nbsp; fontFamily := TGpFontFamily.Create({'Times New Roman'}'华文行楷'); <br>&nbsp; font := TGpFont.Create(fontFamily, 55, [fsBold], utPixel); <br>&nbsp; r := GpRect(Form1.PaintBox1.ClientRect); <br>&nbsp; brush := TGpLinearGradientBrush.Create(r, kcBlue, kcAliceBlue, 90); <br>&nbsp; g.FillRectangle(Brush, r); </p>
<p>&nbsp; DrawShadowString(g, '文字阴影特效', font, GpPoint(10, r.Height / 3), 5, 10, 60, $C0000000, 1); <br>&nbsp; DrawShadowString(g, '文字阴影特效', font, GpPoint(10, r.Height / 3), 1, 0, 60, $FFFF0000, 1); </p>
<p>//&nbsp; DrawShadowString(g, '文字阴影特效', font, GpPoint(10, r.Height / 3), 5, 12, 60, $C0000000, 1); <br>//&nbsp; DrawShadowString(g, '文字阴影特效', font, GpPoint(10, r.Height / 3), 2, 3, 60, $FFc00000, 1); <br>&nbsp; g.TextRenderingHint := thAntiAlias; <br>&nbsp; g.DrawString('文字阴影特效', font, Brushs.White, 10, r.Height / 3); <br>&nbsp; font.Free; <br>&nbsp; fontFamily.Free; <br>&nbsp; Brush.Free; <br>end;<br>&nbsp;&nbsp;&nbsp; 以下是测试代码效果图，图一和图二都是文字描边（1个像素的边框）加阴影效果，其中图一没进行阴影扩展，即上面的15行的代码最后一个参数为0，图二是加了1个像素的阴影扩展效果（上述代码的&#8220;正宗&#8221;输出）：</p>
<p>&nbsp;图一</p>
<p>&nbsp;<img height=97 alt="" src="http://www.cppblog.com/images/cppblog_com/flyinghare/52-1.jpg" width=390 border=0></p>
<p>图二</p>
<p>&nbsp;<img height=97 alt="" src="http://www.cppblog.com/images/cppblog_com/flyinghare/52-2.jpg" width=390 border=0></p>
<p>&nbsp;&nbsp;&nbsp; 利用改进的阴影效果，不仅可实现文字描边，也可显示类似立体文字的效果（改变显示距离），上面测试代码中，被注释的2句代码输出效果如下：</p>
<p>&nbsp;</p>
<p>图三<br></p>
<p><img height=97 alt="" src="http://www.cppblog.com/images/cppblog_com/flyinghare/52-3.jpg" width=390 border=0><br>&nbsp;&nbsp;&nbsp; 至于图像的描边，似乎没有文字的描边效果好，究其原因，主要是图像的轮廓看起来好像是圆润平滑的，其实有很多半影锯齿，在Photoshop中，通过先选区后描边，可能对选区边缘作了处理，所以效果相当好（专业的软件，肯定有很好的算法）。下面是我对一张小图片作的描边处理代码和输出效果图：</p>
<p>// 图像描边 <br>// g: 文字输出的画布; Image: 图像; x, y: 图像输出原点 <br>// BorderWidth: 总的边框宽度; Color: 边框颜色; <br>// Expand: 边框扩散大小; Attributes: 图像显示属性 <br>procedure DrawImageBorder(const g: TGpGraphics; const Image: TGpImage; <br>&nbsp;&nbsp;&nbsp; x, y: Single; BorderWidth: LongWord; Color: TARGB = kcWhite; <br>&nbsp;&nbsp;&nbsp; Expand: LongWord = 0; const Attributes: TGpImageAttributes = nil); <br>var <br>&nbsp; Bmp: TGpBitmap; <br>&nbsp; Bg: TGpGraphics; <br>&nbsp; ColorMatrix: TColorMatrix; <br>&nbsp; Attr: TGpImageAttributes; <br>&nbsp; layoutRect: TGpRectF; <br>begin <br>&nbsp; Bmp := TGpBitmap.Create(Image.Width + BorderWidth shl 1 + 2, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Image.Height + BorderWidth shl 1 + 2, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pf32bppARGB); <br>&nbsp; Bg := TGpGraphics.Create(Bmp); <br>&nbsp; Attr := Attributes; <br>&nbsp; if Attr = nil then <br>&nbsp;&nbsp;&nbsp; Attr := TGpImageAttributes.Create; <br>&nbsp; try <br>&nbsp;&nbsp;&nbsp; FillChar(ColorMatrix, Sizeof(TColorMatrix), 0); <br>&nbsp;&nbsp;&nbsp; ColorMatrix[3, 3] := 1; <br>&nbsp;&nbsp;&nbsp; ColorMatrix[4, 4] := 1; <br>&nbsp;&nbsp;&nbsp; // 利用颜色矩阵将图像输出为黑色，以便边框颜色替换 <br>&nbsp;&nbsp;&nbsp; Attr.SetColorMatrix(ColorMatrix); <br>&nbsp;&nbsp;&nbsp; layoutRect := GpRect(x, y, Image.Width, Image.Height); <br>&nbsp;&nbsp;&nbsp; Bg.DrawImage(Image, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GpRect(BorderWidth + 1, BorderWidth + 1, layoutRect.Width, layoutRect.Height), <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0, 0, layoutRect.Width, layoutRect.Height, utPixel, Attr); <br>&nbsp;&nbsp;&nbsp; DrawShadow(g, Bmp, layoutRect, BorderWidth, 0, 0, Color, BorderWidth - Expand); <br>&nbsp; finally <br>&nbsp;&nbsp;&nbsp; if Attributes &lt;&gt; nil then <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Attr.ClearColorMatrix <br>&nbsp;&nbsp;&nbsp; else <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Attr.Free; <br>&nbsp;&nbsp;&nbsp; Bg.Free; <br>&nbsp;&nbsp;&nbsp; Bmp.Free; <br>&nbsp; end; <br>end; </p>
<p>procedure ImagePaint(g: TGpGraphics); <br>var <br>&nbsp; brush: TGpLinearGradientBrush; <br>&nbsp; r: TGpRect; <br>&nbsp; Image: TGpImage; <br>&nbsp; Attributes: TGpImageAttributes; <br>begin <br>&nbsp; r := GpRect(Form1.PaintBox1.ClientRect); <br>&nbsp; brush := TGpLinearGradientBrush.Create(r, kcBlue, kcAliceBlue, 90); <br>&nbsp; g.FillRectangle(Brush, r); <br>&nbsp; Image := TGpImage.Create('..\..\Media\Watermark.bmp'); <br>&nbsp; // 画原图 <br>&nbsp; g.TranslateTransform(20, r.Height / 3); <br>&nbsp; g.DrawImage(Image, 0, 0, Image.Width, Image.Height); <br>&nbsp; // 设置图像透明色 <br>&nbsp; Attributes := TGpImageAttributes.Create; <br>&nbsp; Attributes.SetColorKey($ff00ff00, $ff00ff00); <br>&nbsp; // 画2个像素的描边图 <br>&nbsp; g.TranslateTransform(Image.Width + 20, 0); <br>&nbsp; DrawImageBorder(g, Image, 0, 0, 2, kcWhite, 0, Attributes); <br>&nbsp; g.DrawImage(Image, GpRect(0.0, 0, Image.Width, Image.Height), <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0, 0.0, Image.Width, Image.Height, utPixel, Attributes); <br>&nbsp; // 画5个像素的描边图，其中扩散3像素 <br>&nbsp; g.TranslateTransform(Image.Width + 20, 0); <br>&nbsp; DrawImageBorder(g, Image, 0, 0, 5, kcWhite, 3, Attributes); <br>&nbsp; g.DrawImage(Image, GpRect(0.0, 0, Image.Width, Image.Height), <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0, 0.0, Image.Width, Image.Height, utPixel, Attributes); <br>&nbsp; Attributes.Free; <br>&nbsp; Brush.Free; <br>&nbsp; Image.Free; <br>end; </p>
<p>&nbsp;<img height=94 alt="" src="http://www.cppblog.com/images/cppblog_com/flyinghare/52-4.jpg" width=330 border=0></p>
<p>&nbsp;</p>
<p>图四</p>
<p>&nbsp;&nbsp;&nbsp; 上面的效果图中，左边是原图，中间是2个像素的描边图，右边是5个像素的描边图，其中有3像素的模糊扩散。从图中可以看出，我以$ff00ff00为透明色处理图像四个角后，在中间和右边的描边图中，还是很明显的看到四个角有很淡的绿色，正是这个原因，在中间图的圆角描边有明显的锯齿。</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; 最后作几点说明：</p>
<p>&nbsp;&nbsp;&nbsp; 1、本文纯属业余学习和研究的心得，并非什么正宗的算法；</p>
<p>&nbsp;&nbsp;&nbsp; 2、因为本文代码是学习时即兴写的，并非优化代码，而且是以过程形式出现的，有兴趣的朋友可以自己进行优化改进，写成类或者元件更好（由于算法和功能都不是很完善，所以我没写成类的形式）；</p>
<p>&nbsp;&nbsp;&nbsp; 3、例子中的GDI+版本系本人自己改写的，与网上流通的版本不完全兼容，如需使用本版本，请参照《GDI+ for VCL基础 -- GDI+ 与 VCL 》一文的下载地址，并请留意后面的修改说明。</p>
<p>&nbsp;&nbsp;&nbsp; 4、如有好的建议，请来信：<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#109;&#97;&#111;&#122;&#101;&#102;&#97;&#64;&#104;&#111;&#116;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;">maozefa@hotmail.com</a></p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; 更新(2008-8-5 12:50)：在MakeExpand过程中，是按图象逐点用位图画笔矩阵填充的，每个像素点都要进行矩阵大小的操作，最小的1像素扩展的矩阵大小为3 * 3，可见扩展速度是不大理想的。今天对代码作了一点修改，对每个象素点都进行了判断，如果是边界像素，则作画笔矩阵填充，否则直接跳过，这样一来，速度应该提高不少（没作测试，增加的代码用红色标出，有兴趣者可以测试）。</p>
<p>&nbsp;<br>原作者相关文章：<br><a title="GDI+ 在Delphi程序的应用 -- 可调节的文字阴影特效" href="http://blog.csdn.net/maozefa/archive/2007/12/17/1944451.aspx">GDI+ 在Delphi程序的应用 -- 可调节的文字阴影特效</a><br><a title="GDI+在Delphi程序的应用 &#8211; Photoshop色相/饱和度/明度功能" href="http://blog.csdn.net/maozefa/archive/2009/05/07/4157466.aspx">GDI+在Delphi程序的应用 &#8211; Photoshop色相/饱和度/明度功能</a></p>
<img src ="http://www.cppblog.com/flyinghare/aggbug/95445.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/flyinghare/" target="_blank">会飞的兔子</a> 2009-09-07 10:53 <a href="http://www.cppblog.com/flyinghare/archive/2009/09/07/95445.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>