﻿<?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++博客-Shihira</title><link>http://www.cppblog.com/Shihira/</link><description>Open source - 开放源代码 - 開放原始碼 - オープンソース - 오픈 소스 - Отворен код - متن‌باز</description><language>zh-cn</language><lastBuildDate>Wed, 08 Apr 2026 23:28:33 GMT</lastBuildDate><pubDate>Wed, 08 Apr 2026 23:28:33 GMT</pubDate><ttl>60</ttl><item><title>卷积与平滑滤波器的图像处理应用</title><link>http://www.cppblog.com/Shihira/archive/2015/08/12/211542.html</link><dc:creator>Shihira</dc:creator><author>Shihira</author><pubDate>Tue, 11 Aug 2015 16:35:00 GMT</pubDate><guid>http://www.cppblog.com/Shihira/archive/2015/08/12/211542.html</guid><wfw:comment>http://www.cppblog.com/Shihira/comments/211542.html</wfw:comment><comments>http://www.cppblog.com/Shihira/archive/2015/08/12/211542.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Shihira/comments/commentRss/211542.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Shihira/services/trackbacks/211542.html</trackback:ping><description><![CDATA[<div><div><h1>卷积的介绍</h1> <p>卷积<em>（convolution）</em>是泛函分析里的一个概念，不过泛函分析一般都是数学系才学的，计算机系的学生大多在概率统计课本里了解到。它分为两种形式，一个是离散形式，一个是连续（积分）形式。在图像处理中我们更关心离散卷积，不过也先看看积分形式的卷积。现在假设我们有两个函数<img src="http://latex.codecogs.com/gif.latex?f%28x%29" alt="f(x)" />和<img src="http://latex.codecogs.com/gif.latex?g%28x%29" alt="g(x)" />，这里<img src="http://latex.codecogs.com/gif.latex?g%28x%29" alt="g(x)" />又叫做<strong>平滑函数</strong>或者<strong>卷积核</strong>，那么它们在连续空间的卷积是：</p> <img src="http://latex.codecogs.com/gif.latex?%28f*g%29%28x%29=%5Cint_%7B-%5Cinfty%7D%5E%7B%5Cinfty%7Df%28t%29g%28x-t%29dt" alt="(f*g)(x)=\int_{-\infty}^{\infty}f(t)g(x-t)dt" style="display: block; margin: 20px; margin-left: auto; margin-right: auto;" /> <p>一般我们有一个这样的结论，就是当<img src="http://latex.codecogs.com/gif.latex?f%28x%29" alt="f(x)" />经过足够多次相同平滑函数<img src="http://latex.codecogs.com/gif.latex?g%28x%29" alt="g(x)" />卷积，就会足够接近高斯函数，也就是正态分布的函数形式。卷积就是一种平滑操作，这说明高斯函数就是&#8220;最平滑的函数&#8221;。引入热力学中熵的概念，高斯函数就是拥有最高熵的函数，最稳定的状态，以至于自然界大多数的统计规律都呈现出正态分布：</p> <img src="http://latex.codecogs.com/gif.latex?%28%28%5Ccdots%28%28f*g%29*g%29%5Ccdots%29*g%29%28x%29%20%5Crightarrow%20%5Cfrac%201%7B%5Csigma%5Csqrt%7B2%5Cpi%7D%7D%20e%5E%7B-x%5E2/%7B%5Csigma%5E2%7D%7D" alt="((\cdots((f*g)*g)\cdots)*g)(x) \rightarrow \frac 1{\sigma\sqrt{2\pi}} e^{-x^2/{\sigma^2}}" style="display: block; margin: 20px; margin-left: auto; margin-right: auto;" /> <p>下面介绍离散形式的卷积。这卷积，首先是由有限项的多项式体现。神奇的是，而它们的乘积就是卷积。首先我们设有两个多项式<img src="http://latex.codecogs.com/gif.latex?p%20=%20a_0%20+%20a_1%20x%20+%20a_2%20x%5E2" alt="p = a_0 + a_1 x + a_2 x^2" />以及<img src="http://latex.codecogs.com/gif.latex?q%20=%20b_0%20+%20b_1%20x%20+%20b_2%20x%5E2%20+%20b_3%20x%5E3" alt="q = b_0 + b_1 x + b_2 x^2 + b_3 x^3" />。计算它们的乘积：</p> <img src="http://latex.codecogs.com/gif.latex?%5Cbegin%7Balign*%7D%0Ar%20=%20p%5Ccdot%20q%20&amp;=%20%28a_0%20b_0%29%20%5C%5C%0A&amp;+%20%28a_0%20b_1%20+%20a_1%20b_0%29%20x%20%5C%5C%0A&amp;+%20%28a_0%20b_2%20+%20a_1%20b_1+%20a_2%20b_0%29%20x%5E2%20%5C%5C%0A&amp;+%20%28a_0%20b_3%20+%20a_1%20b_2%20+%20a_2%20b_1%29%20x%5E3%20%5C%5C%0A&amp;+%20%28a_1%20b_3%20+%20a_2%20b_2%29%20x%5E4%20%5C%5C%0A&amp;+%20%28a_2%20b_3%29%20x%5E5%0A%5Cend%7Balign*%7D" alt="\begin{align*} r = p\cdot q &amp;= (a_0 b_0) \\ &amp;+ (a_0 b_1 + a_1 b_0) x \\ &amp;+ (a_0 b_2 + a_1 b_1+ a_2 b_0) x^2 \\ &amp;+ (a_0 b_3 + a_1 b_2 + a_2 b_1) x^3 \\ &amp;+ (a_1 b_3 + a_2 b_2) x^4 \\ &amp;+ (a_2 b_3) x^5 \end{align*}" style="display: block; margin: 20px; margin-left: auto; margin-right: auto;" /> <p>再引入离散形式卷积（向量卷积）的定义，大家比较一下这个定义和上面多项式的计算。稍微说明一下，中括号的意义是<strong>p[n]代表向量第n个元素</strong>。将两个多项式的系数写成向量形式然后进行向量卷积，也就是例如<img src="http://latex.codecogs.com/gif.latex?p%20=%20%5Ba_0,%20a_1,%20a_2%5D" alt="p = [a_0, a_1, a_2]" />，而没定义的地方当作0。可以发现，两者是完全一致的：</p> <img src="http://latex.codecogs.com/gif.latex?%5Cbegin%7Balign*%7D%0A%28p%20*%20q%29%5Bn%5D%20&amp;=%20%5Csum_%7Bm=-%5Cinfty%7D%5E%5Cinfty%20p%5Bm%5D%5Ccdot%20q%5Bn-m%5D%20%5C%5C%0Ar%5B1%5D%20&amp;=%20%5Csum_%7Bm=0%7D%5E1%20%20p%5Bm%5D%5Ccdot%20q%5B1-m%5D%20&amp;&amp;=%20a_0%20b_1%20+%20a_1%20b_0%20%5C%5C%0Ar%5B2%5D%20&amp;=%20%5Csum_%7Bm=0%7D%5E2%20%20p%5Bm%5D%5Ccdot%20q%5B2-m%5D%20&amp;&amp;=%20a_0%20b_2%20+%20a_1%20b_1%20+%20a_2%20b_0%20%5C%5C%0A&amp;%5Ccdots%0A%5Cend%7Balign*%7D" alt="\begin{align*} (p * q)[n] &amp;= \sum_{m=-\infty}^\infty p[m]\cdot q[n-m] \\ r[1] &amp;= \sum_{m=0}^1  p[m]\cdot q[1-m] &amp;&amp;= a_0 b_1 + a_1 b_0 \\ r[2] &amp;= \sum_{m=0}^2  p[m]\cdot q[2-m] &amp;&amp;= a_0 b_2 + a_1 b_1 + a_2 b_0 \\ &amp;\cdots \end{align*}" style="display: block; margin: 20px; margin-left: auto; margin-right: auto;" /> <blockquote><p>知道了多项式的乘积就是其相应的卷积，我们甚至可以直接得出两个幂级数卷积的结果。因为泰勒级数就是幂级数的一种，所以我们可以将几乎所有的连续函数转换成离散形式，避免了繁复的积分运算：比如我们希望得到 <img src="http://latex.codecogs.com/gif.latex?r%28x%29%20=%20p%28x%29%20*%20q%28x%29" alt="r(x) = p(x) * q(x)" />，其中<img src="http://latex.codecogs.com/gif.latex?p%28x%29%20=%20%5Csum%20a_i%20x%5Ei,%5C%20%20q%28x%29%20=%20%5Csum%20b_i%20x%5Ei" alt="p(x) = \sum a_i x^i,\  q(x) = \sum b_i x^i" />，只需要简单地计算这两个级数的<strong>柯西乘积</strong>，所得结果就是<img src="http://latex.codecogs.com/gif.latex?r%28x%29" alt="r(x)" />的卷积。当然了，这是后话，与本文的主题无关。</p></blockquote> <h1>卷积与图像处理</h1> <p>在开始讲图像处理之前，我希望先理解一下卷积的整个过程是怎样的。从上面的公式看得还是有点懵懵懂懂，从直觉上去理解一下很有必要。观察卷积的公式以及下面的图片，这个过程可以看作，当你想求一个r[n]的时候：</p> <blockquote><p>你先把卷积核q叠在p上面，<strong>尽量</strong>使左端靠近（如果左对齐就再好不过了），然后看看在<strong>[0, n]内</strong>p, q重叠的部分是从哪里到哪里，分别写成向量，那么r[n]就等于其中一个向量与另一个向量的<strong>逆序</strong>的内积。</p></blockquote> <p>比如当n = 2时，两个向量是<code>[a_0, a_1, a_2]</code>和<code>[b_2, b_1, b_0]</code>；n = 4时，两个向量是<code>[a_1, a_2, a_3, a_4]</code>和<code>[b_3, b_2, b_1, b_0]</code>。至于求内积，一定难不倒你。下图说明了这一点：</p> <img src="http://latex.codecogs.com/gif.latex?%5Cbegin%7Balign*%7D%0A&amp;&amp;%20a_0%20%20%20%20&amp;&amp;%20a_1%20%20%20%20&amp;&amp;%20a_2%20%20%20%20&amp;&amp;%20a_3%20%20%20%20&amp;&amp;%20a_4%20%5C%5C%0A&amp;&amp;%20a_0b_0%20&amp;&amp;%20a_0b_1%20&amp;&amp;%20a_0b_2%20&amp;&amp;%20a_0b_3%20%5C%5C%0A&amp;&amp;%20%20%20%20%20%20%20%20&amp;&amp;%20a_1b_0%20&amp;&amp;%20a_1b_1%20&amp;&amp;%20a_1b_2%20&amp;&amp;%20a_1b_3%20%5C%5C%0A&amp;&amp;%20%20%20%20%20%20%20%20&amp;&amp;%20%20%20%20%20%20%20%20&amp;&amp;%20a_2b_0%20&amp;&amp;%20a_2b_1%20&amp;&amp;%20a_2b_2%20&amp;&amp;%20a_2b_3%20%5C%5C%0A&amp;&amp;%20%20%20%20%20%20%20%20&amp;&amp;%20%20%20%20%20%20%20%20&amp;&amp;%20%20%20%20%20%20%20%20&amp;&amp;%20a_3b_0%20&amp;&amp;%20a_3b_1%20&amp;&amp;%20a_3b_2%20&amp;&amp;%20a_3b_3%20%5C%5C%0A&amp;&amp;%20%20%20%20%20%20%20%20&amp;&amp;%20%20%20%20%20%20%20%20&amp;&amp;%20%20%20%20%20%20%20%20&amp;&amp;%20%20%20%20%20%20%20%20&amp;&amp;%20a_4b_0%20&amp;&amp;%20a_4b_1%20&amp;&amp;%20a_4b_2%20&amp;&amp;%20a_4b_3%20%5C%5C%0A%5Chline%0A&amp;&amp;%20c_0%20%20%20%20&amp;&amp;%20c_1%20%20%20%20&amp;&amp;%20c_2%20%20%20%20&amp;&amp;%20c_3%20%20%20%20&amp;&amp;%20c_4%20%20%20%20&amp;&amp;%20c_5%20%20%20%20&amp;&amp;%20c_6%20%20%20%20&amp;&amp;%20c_7%0A%5Cend%7Balign*%7D" alt="\begin{align*} &amp;&amp; a_0    &amp;&amp; a_1    &amp;&amp; a_2    &amp;&amp; a_3    &amp;&amp; a_4 \\ &amp;&amp; a_0b_0 &amp;&amp; a_0b_1 &amp;&amp; a_0b_2 &amp;&amp; a_0b_3 \\ &amp;&amp;        &amp;&amp; a_1b_0 &amp;&amp; a_1b_1 &amp;&amp; a_1b_2 &amp;&amp; a_1b_3 \\ &amp;&amp;        &amp;&amp;        &amp;&amp; a_2b_0 &amp;&amp; a_2b_1 &amp;&amp; a_2b_2 &amp;&amp; a_2b_3 \\ &amp;&amp;        &amp;&amp;        &amp;&amp;        &amp;&amp; a_3b_0 &amp;&amp; a_3b_1 &amp;&amp; a_3b_2 &amp;&amp; a_3b_3 \\ &amp;&amp;        &amp;&amp;        &amp;&amp;        &amp;&amp;        &amp;&amp; a_4b_0 &amp;&amp; a_4b_1 &amp;&amp; a_4b_2 &amp;&amp; a_4b_3 \\ \hline &amp;&amp; c_0    &amp;&amp; c_1    &amp;&amp; c_2    &amp;&amp; c_3    &amp;&amp; c_4    &amp;&amp; c_5    &amp;&amp; c_6    &amp;&amp; c_7 \end{align*}" style="display: block; margin: 20px; margin-left: auto; margin-right: auto;" /> <p>上面是对某一点上卷积的理解。对整个域的卷积，则可以看成是将卷积核（除了开头几个外）不停向右移动，每移动一格就将重叠部分拿出来求内积。</p> <p>这时我们可以把图像处理和卷积联系起来了。图像处理是，将一副&#8220;源图像&#8221;<em>（Source）</em>，通过一些算法，变成一副&#8220;目标图像&#8221;<em>（Destination）</em>。当我们进行平滑处理的时候，用到一个叫做滤波器<em>（filter）</em>的 东西，也叫做滤镜。想想我们现实生活中放大镜是怎么用的：拿着放大镜，从报纸的左上角开始，一直扫啊扫到右下角，扫的过程中一直望着放大镜和报纸的重叠区 域（其实就是望着放大镜，因为它比报纸小多了），这样你就浏览完了一张放大过的报纸。平滑滤镜也是同样的使用方法，从源图的左上角开始扫到右下角，扫的过 程中一直取出重叠部分进行<strong>内积</strong>计算，然后将结果存放到目标图像中 &#8212;&#8212; 显然这个操作跟卷积是一致的，只不过定义在二维空间内。</p> <p>为了方便量化表示，我们把图像抽象成定义在<img src="http://latex.codecogs.com/gif.latex?R%20%5Ccap%20%5B0,%201%5D" alt="R \cap [0, 1]" /> 数环内的二维矩阵，其意义是<strong>灰度值</strong>，颜色信息我们暂且忽略。卷积核，也就是滤波器同样也是定义在<img src="http://latex.codecogs.com/gif.latex?R%20%5Ccap%20%5B0,%201%5D" alt="R \cap [0, 1]" /> 内的二维矩阵。这样，二维的卷积我们这样定义它的离散形式：</p> <img src="http://latex.codecogs.com/gif.latex?%5Ctext%7BDest%7D%5Bi,%20j%5D%20=%20%5Csum_%7By=-%5Cinfty%7D%5E%5Cinfty%20%5Csum_%7Bx=-%5Cinfty%7D%5E%5Cinfty%20%5Ctext%7BSrc%7D%5By,x%5D%20%5Ccdot%20%5Ctext%7BKer%7D%5Bi%20-%20y,%20j%20-%20x%5D" alt="\text{Dest}[i, j] = \sum_{y=-\infty}^\infty \sum_{x=-\infty}^\infty \text{Src}[y,x] \cdot \text{Ker}[i - y, j - x]" style="display: block; margin: 20px; margin-left: auto; margin-right: auto;" /> <p>我们的卷积核大小并不是无限的，它一个半径r，这样它的大小就是2r+1。规定了这个r使得，当|x| &gt; r 或 |y| &gt; r，都有Ker[y, x] = 0。规定过大小之后，由 <code>|i-y| &lt; r; |j-x| &lt; r</code>得到 <strong><code>i-r &lt; y &lt; i+r; j-r &lt; x &lt; j+r</code></strong>。同时我们规定Dest和Src的大小是<img src="http://latex.codecogs.com/gif.latex?m%20%5Ctimes%20n" alt="m \times n" />。于是我们得到了滤波器的算法：</p> <img src="http://latex.codecogs.com/gif.latex?%5Ctext%7BDest%7D%5Bi,%20j%5D%20=%20%5Csum_%7By=%5Cmax%5C%7B0,i-r%5C%7D%7D%5E%7B%5Cmin%5C%7Bi+r,n%5C%7D%7D%20%5Cleft%28%20%5Csum_%7Bx=%5Cmax%5C%7B0,j-r%5C%7D%7D%5E%7B%5Cmin%5C%7Bj+r,m%5C%7D%7D%20%5Ctext%7BSrc%7D%5By,%20x%5D%20%5Ccdot%20%5Ctext%7BKer%7D%5Bi%20-%20y,%20j%20-%20x%5D%20%5Cright%29" alt="\text{Dest}[i, j] = \sum_{y=\max\{0,i-r\}}^{\min\{i+r,n\}} \left( \sum_{x=\max\{0,j-r\}}^{\min\{j+r,m\}} \text{Src}[y, x] \cdot \text{Ker}[i - y, j - x] \right)" style="display: block; margin: 20px; margin-left: auto; margin-right: auto;" /> <h1>高斯滤波器</h1> <div imagebubble"=""> <img src="http://upload-images.jianshu.io/upload_images/610338-54f1c66e805cdc4c.gif?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="二维的高斯函数（俗称避孕套函数）" data-original-src="http://upload-images.jianshu.io/upload_images/610338-54f1c66e805cdc4c.gif" /><br /><div>二维的高斯函数（俗称避孕套函数）</div> </div> <p>高斯滤波器是最常用的平滑滤波器之一，在Photoshop里面它被用作<strong>高斯模糊滤镜</strong>。高斯滤波器的定义很经典，就是简单地把正态分布离散开来。二维形式只是单纯把x替代成(x<sup>2</sup> + y<sup>2</sup>)，然后修改系数令实数域上的积分为1：</p> <img src="http://latex.codecogs.com/gif.latex?%5Cbegin%7Balign*%7D%0A%5Ctext%7BKer%7D_1%5Bx%5D%20&amp;=%20%5Cfrac%201%7B%5Csigma%5Csqrt%7B2%5Cpi%7D%7D%20e%5E%7B-x%5E2/%7B%5Csigma%5E2%7D%7D%20%5C%5C%0A%5Ctext%7BKer%7D_2%5Bi,%20j%5D%20&amp;=%20%5Cfrac%201%7B2%5Csigma%5E2%5Cpi%7D%20e%5E%7B-%28i%5E2+j%5E2%29/%7B%5Csigma%5E2%7D%7D%0A%5Cend%7Balign*%7D" alt="\begin{align*} \text{Ker}_1[x] &amp;= \frac 1{\sigma\sqrt{2\pi}} e^{-x^2/{\sigma^2}} \\ \text{Ker}_2[i, j] &amp;= \frac 1{2\sigma^2\pi} e^{-(i^2+j^2)/{\sigma^2}} \end{align*}" style="display: block; margin: 20px; margin-left: auto; margin-right: auto;" /> <p>也许你已经发现了一个这样的规律，这一规律，这在更高维上仍然是满足的，也就是在连续空间里同样满足。这将成为我们优化算法的关键。将这个规律代回到二维离散卷积的公式里，因为y在第二个连加中相当于常数系数可以提出来，我们发现：</p> <img src="http://latex.codecogs.com/gif.latex?%5Cbegin%7Balign*%7D%0A%5Ctext%7BKer%7D_2%5Bi,%20j%5D%20&amp;=%20%5Ctext%7BKer%7D_1%5Bi%5D%20%5Ccdot%20%5Ctext%7BKer%7D_1%5Bj%5D%20%5C%5C%0A%5Ctext%7BDest%7D%5Bi,%20j%5D%20&amp;=%20%5Csum_%7By=-%5Cinfty%7D%5E%5Cinfty%20%5Csum_%7Bx=-%5Cinfty%7D%5E%5Cinfty%20%5Ctext%7BSrc%7D%5By,x%5D%20%5Ccdot%20%5Ctext%7BKer%7D_2%5Bi%20-%20y,%20j%20-%20x%5D%20%5C%5C%0A&amp;=%20%5Csum_%7By=-%5Cinfty%7D%5E%5Cinfty%20%5Csum_%7Bx=-%5Cinfty%7D%5E%5Cinfty%20%5Ctext%7BSrc%7D%5By,x%5D%20%5Ccdot%20%5Ctext%7BKer%7D_1%5Bi-y%5D%20%5Ccdot%20%5Ctext%7BKer%7D_1%5Bj-x%5D%5C%5C%0A&amp;=%20%5Csum_%7By=-%5Cinfty%7D%5E%5Cinfty%20%5Cleft%28%20%5Csum_%7Bx=-%5Cinfty%7D%5E%5Cinfty%20%5Ctext%7BSrc%7D%5By,x%5D%20%5Ccdot%20%5Ctext%7BKer%7D_1%5Bj-x%5D%5Cright%29%20%5Ctext%7BKer%7D_1%5Bi-y%5D%0A%5Cend%7Balign*%7D" alt="\begin{align*} \text{Ker}_2[i, j] &amp;= \text{Ker}_1[i] \cdot \text{Ker}_1[j] \\ \text{Dest}[i, j] &amp;= \sum_{y=-\infty}^\infty \sum_{x=-\infty}^\infty \text{Src}[y,x] \cdot \text{Ker}_2[i - y, j - x] \\ &amp;= \sum_{y=-\infty}^\infty \sum_{x=-\infty}^\infty \text{Src}[y,x] \cdot \text{Ker}_1[i-y] \cdot \text{Ker}_1[j-x]\\ &amp;= \sum_{y=-\infty}^\infty \left( \sum_{x=-\infty}^\infty \text{Src}[y,x] \cdot \text{Ker}_1[j-x]\right) \text{Ker}_1[i-y] \end{align*}" style="display: block; margin: 20px; margin-left: auto; margin-right: auto;" /> <p>如果x连加所表示是卷积是从右上角开始按照文字书写顺序从左到右，然后从上到下的顺序进行一维卷积，那么y连加表示的卷积就是先从上到下，再从左到有的顺序卷积。在OpenCV提供的数据结构的基础上，不用imgproc提供的算法，我写了一个示例：</p><p><br /></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;cflags:&nbsp;-lopencv_highgui&nbsp;-lopencv_core</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; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">iostream</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">cmath</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">opencv2</span><span style="color: #000000; ">/</span><span style="color: #000000; ">highgui</span><span style="color: #000000; ">/</span><span style="color: #000000; ">highgui.hpp</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;cv;<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">namespace</span><span style="color: #000000; ">&nbsp;std;<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;title&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">gaussian-filter</span><span style="color: #000000; ">"</span><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; ">Mat&nbsp;kernelMatrix(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;radius,&nbsp;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&nbsp;sigma)<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">14</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;d&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;radius&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">2</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mat&nbsp;kernel(</span><span style="color: #000000; ">2</span><span style="color: #000000; ">,&nbsp;d,&nbsp;CV_64F);<br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&nbsp;coef&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;i&nbsp;</span><span style="color: #000000; ">&lt;=</span><span style="color: #000000; ">&nbsp;radius;&nbsp;i</span><span style="color: #000000; ">++</span><span style="color: #000000; ">)&nbsp;{<br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;f(x)&nbsp;=&nbsp;1/(sigma&nbsp;*&nbsp;sqrt(2&nbsp;pi))&nbsp;*&nbsp;e&nbsp;^&nbsp;-x^2/(2&nbsp;s^2)</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;dx&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;radius;<br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&nbsp;dx_2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;dx&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;dx;<br /></span><span style="color: #008080; ">22</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&nbsp;w&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;pow(M_E,&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;dx_2&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #000000; ">2</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;sigma&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;sigma));<br /></span><span style="color: #008080; ">23</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">24</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;coef&nbsp;</span><span style="color: #000000; ">+=</span><span style="color: #000000; ">&nbsp;w;<br /></span><span style="color: #008080; ">25</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kernel.at</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;i)&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;w;<br /></span><span style="color: #008080; ">26</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kernel.at</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;d&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;w;<br /></span><span style="color: #008080; ">27</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;when&nbsp;you&nbsp;used&nbsp;values&nbsp;from&nbsp;i&nbsp;to&nbsp;j&nbsp;(j&gt;i),&nbsp;the&nbsp;sum&nbsp;of&nbsp;them&nbsp;is:<br /></span><span style="color: #008080; ">28</span>&nbsp;<span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;kernel[1,&nbsp;j]&nbsp;-&nbsp;(i&nbsp;?&nbsp;kernel[1,&nbsp;i-1]&nbsp;:&nbsp;0)</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">29</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kernel.at</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;i)&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;coef;<br /></span><span style="color: #008080; ">30</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">31</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">32</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;radius&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;&nbsp;i&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;d;&nbsp;i</span><span style="color: #000000; ">++</span><span style="color: #000000; ">)&nbsp;{<br /></span><span style="color: #008080; ">33</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;coef&nbsp;</span><span style="color: #000000; ">+=</span><span style="color: #000000; ">&nbsp;kernel.at</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;i);<br /></span><span style="color: #008080; ">34</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kernel.at</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;i)&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;coef;<br /></span><span style="color: #008080; ">35</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">36</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">37</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;kernel;<br /></span><span style="color: #008080; ">38</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">39</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">40</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">41</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;convolution(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Mat</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;img,&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;Mat</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;kernel,&nbsp;Mat</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;output,&nbsp;</span><span style="color: #0000FF; ">bool</span><span style="color: #000000; ">&nbsp;t&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">)<br /></span><span style="color: #008080; ">42</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">43</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;y&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;x&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;&nbsp;y&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;img.rows;&nbsp;x&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(</span><span style="color: #000000; ">++</span><span style="color: #000000; ">x</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">img.cols)</span><span style="color: #000000; ">?</span><span style="color: #000000; ">&nbsp;x&nbsp;:&nbsp;(y</span><span style="color: #000000; ">++</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">))&nbsp;{<br /></span><span style="color: #008080; ">44</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Vec3d&nbsp;r(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">45</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">46</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;ideal&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;x&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">(kernel.cols&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">2</span><span style="color: #000000; ">),<br /></span><span style="color: #008080; ">47</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ran_beg&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;max(ideal,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;ideal,<br /></span><span style="color: #008080; ">48</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ran_end&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;min(ideal&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;kernel.cols,&nbsp;img.cols)&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;ideal;<br /></span><span style="color: #008080; ">49</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">50</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;ran_beg;&nbsp;i&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;ran_end;&nbsp;i</span><span style="color: #000000; ">++</span><span style="color: #000000; ">)&nbsp;{<br /></span><span style="color: #008080; ">51</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&nbsp;weight&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;kernel.at</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;i);<br /></span><span style="color: #008080; ">52</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Vec3b&nbsp;pixel&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;img.at</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Vec3b</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(y,&nbsp;ideal&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;i);<br /></span><span style="color: #008080; ">53</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">54</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r[</span><span style="color: #000000; ">0</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">+=</span><span style="color: #000000; ">&nbsp;pixel[</span><span style="color: #000000; ">0</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;weight;<br /></span><span style="color: #008080; ">55</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">+=</span><span style="color: #000000; ">&nbsp;pixel[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;weight;<br /></span><span style="color: #008080; ">56</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r[</span><span style="color: #000000; ">2</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">+=</span><span style="color: #000000; ">&nbsp;pixel[</span><span style="color: #000000; ">2</span><span style="color: #000000; ">]&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;weight;<br /></span><span style="color: #008080; ">57</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">58</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">59</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&nbsp;coef&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;kernel.at</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;ran_end&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">60</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(ran_beg)&nbsp;coef&nbsp;</span><span style="color: #000000; ">-=</span><span style="color: #000000; ">&nbsp;kernel.at</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">double</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;ran_beg&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">61</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">62</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;output.at</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Vec3b</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(t</span><span style="color: #000000; ">?</span><span style="color: #000000; ">x:y,&nbsp;t</span><span style="color: #000000; ">?</span><span style="color: #000000; ">y:x)&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Vec3b(<br /></span><span style="color: #008080; ">63</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;saturate_cast</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">uchar</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(r[</span><span style="color: #000000; ">0</span><span style="color: #000000; ">]</span><span style="color: #000000; ">/</span><span style="color: #000000; ">coef),<br /></span><span style="color: #008080; ">64</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;saturate_cast</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">uchar</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(r[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">]</span><span style="color: #000000; ">/</span><span style="color: #000000; ">coef),<br /></span><span style="color: #008080; ">65</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;saturate_cast</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">uchar</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">(r[</span><span style="color: #000000; ">2</span><span style="color: #000000; ">]</span><span style="color: #000000; ">/</span><span style="color: #000000; ">coef));<br /></span><span style="color: #008080; ">66</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">67</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">68</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">69</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">70</span>&nbsp;<span style="color: #000000; "></span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;main()<br /></span><span style="color: #008080; ">71</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">72</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;namedWindow(title,&nbsp;WINDOW_AUTOSIZE);<br /></span><span style="color: #008080; ">73</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">74</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">const</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;r&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">10</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">75</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">76</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mat&nbsp;img&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;imread(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">ai-sample.jpg</span><span style="color: #000000; ">"</span><span style="color: #000000; ">),<br /></span><span style="color: #008080; ">77</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kernel&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;kernelMatrix(r,&nbsp;(r&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0.3</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0.8</span><span style="color: #000000; ">);<br /></span><span style="color: #008080; ">78</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">79</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mat&nbsp;product_v&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Mat(img.cols,&nbsp;img.rows,&nbsp;img.type());<br /></span><span style="color: #008080; ">80</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mat&nbsp;product_h&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Mat(img.rows,&nbsp;img.cols,&nbsp;img.type());<br /></span><span style="color: #008080; ">81</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">82</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;convolution(img,&nbsp;kernel,&nbsp;product_v);<br /></span><span style="color: #008080; ">83</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;convolution(product_v,&nbsp;kernel,&nbsp;product_h);<br /></span><span style="color: #008080; ">84</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">85</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imshow(title,&nbsp;product_h);<br /></span><span style="color: #008080; ">86</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">(;&nbsp;waitKey(</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;);<br /></span><span style="color: #008080; ">87</span>&nbsp;<span style="color: #000000; "><br /></span><span style="color: #008080; ">88</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;destroyWindow(title);<br /></span><span style="color: #008080; ">89</span>&nbsp;<span style="color: #000000; ">}</span></div><p><br /></p><img src="http://upload-images.jianshu.io/upload_images/610338-6d8a7ba9a3985876.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="渲染效果图" data-original-src="http://upload-images.jianshu.io/upload_images/610338-6d8a7ba9a3985876.png" /><br /><div imagebubble"=""><div>渲染效果图</div> </div> </div></div><img src ="http://www.cppblog.com/Shihira/aggbug/211542.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Shihira/" target="_blank">Shihira</a> 2015-08-12 00:35 <a href="http://www.cppblog.com/Shihira/archive/2015/08/12/211542.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浮点数简介</title><link>http://www.cppblog.com/Shihira/archive/2015/01/02/209380.html</link><dc:creator>Shihira</dc:creator><author>Shihira</author><pubDate>Fri, 02 Jan 2015 06:38:00 GMT</pubDate><guid>http://www.cppblog.com/Shihira/archive/2015/01/02/209380.html</guid><wfw:comment>http://www.cppblog.com/Shihira/comments/209380.html</wfw:comment><comments>http://www.cppblog.com/Shihira/archive/2015/01/02/209380.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Shihira/comments/commentRss/209380.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Shihira/services/trackbacks/209380.html</trackback:ping><description><![CDATA[<div>
<div>
<div>
<div>
<h2>内存中的储存形式(IEEE-745)</h2>
<pre style="font-size: 0.85em; font-family: Consolas,Inconsolata,Courier,monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas,Inconsolata,Courier,monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; background-color: #f8f8f8; border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid #cccccc; padding: 0.5em 0.7em; display: block ! important;">Address 3 &nbsp; &nbsp; &nbsp; &nbsp;2 &nbsp; &nbsp; &nbsp; &nbsp;1 &nbsp; &nbsp; &nbsp; &nbsp;0 <br />Content SEEEEEEE EBBBBBBB BBBBBBBB BBBBBBBB </code></pre>
<p style="margin: 1.2em 0px ! important;">其中的字母分别代表:</p>
<ul style="margin: 1.2em 0px;padding-left: 2em;">
     <li style="margin: 0.5em 0px;">S(Significand):1 - 正负号<img alt="(-1)^S" name="4f943fc1-46c0-42b8-852f-2ab52da5d07b" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/4f943fc1-46c0-42b8-852f-2ab52da5d07b.png?resizeSmall&amp;width=832" /></li>
     <li style="margin: 0.5em 0px;">E(Exponent):8 - 指数部分</li>
     <li style="margin: 0.5em 0px;">B(Base):23 - 底数部分</li>
</ul>
<p style="margin: 1.2em 0px ! important;">这样, 整个浮点数表示起来就是:</p>
<p style="margin: 1.2em 0px ! important;"><img alt="(-1)^S \times 1.BBBBBBBBBBBBBBBBBBBBBBB \times 2 ^{EEEEEEEE - 01111111}" name="d5a7553b-beea-4ec5-be84-38434cb8f811" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/d5a7553b-beea-4ec5-be84-38434cb8f811.png?resizeSmall&amp;width=832" /></p>
<h2>N进制的小数</h2>
<p style="margin: 1.2em 0px ! important;">看到10进制的小数, 小数点是用来分隔指数正负位的:</p>
<p style="margin: 1.2em 0px ! important;"><img alt="123.456" name="f19cf11c-9bbd-4579-ab0d-38aca2c03bf5" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/f19cf11c-9bbd-4579-ab0d-38aca2c03bf5.png?resizeSmall&amp;width=832" /><br clear="none" />
<img alt="= 1 \times 10^2 + 2 \times 10^1 + 3 \times 10^0 + 4 \times 10^{-1} + 5 \times 10^{-2} + 6 \times 10^{-3}" name="5c8f2017-66c5-4e8c-b3f4-c5d7af5bd422" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/5c8f2017-66c5-4e8c-b3f4-c5d7af5bd422.png?resizeSmall&amp;width=832" /></p>
<p style="margin: 1.2em 0px ! important;">推广到N进制, 形式是完全相同的, 这里用二进制做一个例子:</p>
<p style="margin: 1.2em 0px ! important;"><img alt="(101.0101)_2" name="9b964ef0-2b66-47a3-bf3b-6034f1399e36" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/9b964ef0-2b66-47a3-bf3b-6034f1399e36.png?resizeSmall&amp;width=832" /><br clear="none" />
<img alt="= 2^2 + 2^0 + 2^{-2} + 2^{-4}" name="6f79a2c5-604c-4044-8ed8-79e195e19324" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/6f79a2c5-604c-4044-8ed8-79e195e19324.png?resizeSmall&amp;width=832" /><br clear="none" />
<img alt="= 4+1+{1 \over 4}+{1 \over 16}" name="b2eea789-a281-42f0-a308-33a9a316d321" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/b2eea789-a281-42f0-a308-33a9a316d321.png?resizeSmall&amp;width=832" /><br clear="none" />
<img alt="= 5.3125" name="06cb8f45-bd55-4d89-9829-d104d04675e7" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/06cb8f45-bd55-4d89-9829-d104d04675e7.png?resizeSmall&amp;width=832" /></p>
<h2>构造一个浮点数</h2>
<p style="margin: 1.2em 0px ! important;">以12.625为例子. 首先我们推算一下它的二进制形式是什么. 如我们所知, 整数部分和小数部分的位置是恒定不变的, 因为它们是否小于1这个性质, 无论在什么进制之下都不会改变. 首先算整数部分:</p>
<p style="margin: 1.2em 0px ! important;"><img alt="12 \div 2 = 6 \cdots 0" name="92f68c9f-f8e4-4fa5-aace-7c49f7400ef3" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/92f68c9f-f8e4-4fa5-aace-7c49f7400ef3.png?resizeSmall&amp;width=832" /><br clear="none" />
<img alt="6 \div 2 = 3 \cdots 0" name="0b788b1d-fdc0-4e0a-ab78-5488502ad8b1" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/0b788b1d-fdc0-4e0a-ab78-5488502ad8b1.png?resizeSmall&amp;width=832" /><br clear="none" />
<img alt="3 \div 2 = 1 \cdots 1" name="f7f6f374-94ef-4bdf-b6f9-431e3d0ee838" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/f7f6f374-94ef-4bdf-b6f9-431e3d0ee838.png?resizeSmall&amp;width=832" /><br clear="none" />
<img alt="1 \div 2 = 0 \cdots 1" name="1e4cda93-2816-416a-ab2d-b51d66501d4a" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/1e4cda93-2816-416a-ab2d-b51d66501d4a.png?resizeSmall&amp;width=832" /><br clear="none" />
<img alt="\therefore \ (12)_10 = (1100)_2" name="9463af4e-69bf-4588-b077-bc01dcf9a233" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/9463af4e-69bf-4588-b077-bc01dcf9a233.png?resizeSmall&amp;width=832" /></p>
<p style="margin: 1.2em 0px ! important;">小数部分(不知道是否注意到, 小数部分只有是2^n的和才有可能被表示成不循环小数. 诸如0.7, 0.3都是二进制的无限循环小数):</p>
<p style="margin: 1.2em 0px ! important;"><img alt="0.625 \times 2 = 1 + 0.25" name="65a180e0-735d-45ba-b563-f3b71456843d" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/65a180e0-735d-45ba-b563-f3b71456843d.png?resizeSmall&amp;width=832" /><br clear="none" />
<img alt="0.25 \times 2 = 0 + 0.5" name="fde2d47d-b280-4846-b995-4a9d8ed31dc3" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/fde2d47d-b280-4846-b995-4a9d8ed31dc3.png?resizeSmall&amp;width=832" /><br clear="none" />
<img alt="0.5 \times 2 = 1" name="80991657-d983-4356-89d3-5513077712c7" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/80991657-d983-4356-89d3-5513077712c7.png?resizeSmall&amp;width=832" /><br clear="none" />
<img alt="\therefore \ (0.625)_{10} = (0.101)_2" name="8d4c77f3-67ba-4e1c-bcaa-607afcc6e14a" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/8d4c77f3-67ba-4e1c-bcaa-607afcc6e14a.png?resizeSmall&amp;width=832" /></p>
<p style="margin: 1.2em 0px ! important;">这样, 我们得到了一个二进位的小数1100.101, 并且化成IEEE-745标准形式:</p>
<p style="margin: 1.2em 0px ! important;"><img alt="1100.101 = 1.100101 \times 2^{00000011 + 01111111 - 01111111}" name="aaf4f83b-de41-415c-a845-766387dbd563" src="https://www.evernote.com/shard/s375/sh/a4e4ed3a-af3e-4855-90ba-56daef650054/219cbab4fc64ceb3acdccab81292dfba/res/aaf4f83b-de41-415c-a845-766387dbd563.png?resizeSmall&amp;width=832" /></p>
<pre style="font-size: 0.85em; font-family: Consolas,Inconsolata,Courier,monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas,Inconsolata,Courier,monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; background-color: #f8f8f8; border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid #cccccc; padding: 0.5em 0.7em; display: block ! important;">Address 3 &nbsp; &nbsp; &nbsp; &nbsp;2 &nbsp; &nbsp; &nbsp; &nbsp;1 &nbsp; &nbsp; &nbsp; &nbsp;0 <br />Content SEEEEEEE EBBBBBBB BBBBBBBB BBBBBBBB <br />Value &nbsp; 01000001 01001010 00000000 00000000 <br />Hex &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 41 &nbsp; &nbsp; &nbsp; 4A &nbsp; &nbsp; &nbsp; 00 &nbsp; &nbsp; &nbsp; 00 </code></pre>
<p style="margin: 1.2em 0px ! important;">现在我们得到了一个整数0x414A0000, 把它输出出来看看是多少:</p>
<pre style="font-size: 0.85em; font-family: Consolas,Inconsolata,Courier,monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas,Inconsolata,Courier,monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid #eaeaea; background-color: #f8f8f8; border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid #cccccc; padding: 0.5em 0.7em; display: block ! important;">$ cat test.c <br />#include &lt;stdio.h&gt; <br />int main() <br />{ <br />&nbsp;&nbsp; union { <br />&nbsp;&nbsp; &nbsp;&nbsp; unsigned long u; <br />&nbsp;&nbsp; &nbsp;&nbsp; float f; <br />&nbsp;&nbsp; } u; <br />&nbsp;&nbsp; u.u = 0x414a0000; <br />&nbsp;&nbsp; printf("%f\n", u.f); <br />&nbsp;&nbsp; return 0;<br />}<br /><br />$ ./test <br />12.625000 </code></pre>
<div title="MDH:PGRpdj4jIyDlhoXlrZjkuK3nmoTlgqjlrZjlvaLlvI8oSUVFRS03NDUpPGJyPjxicj5gYGA8YnI+ QWRkcmVzcyAzJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IDImbmJz cDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgMSZuYnNwOyZuYnNwOyZuYnNw OyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyAwPGJyPkNvbnRlbnQgU0VFRUVFRUUgRUJCQkJCQkIg QkJCQkJCQkIgQkJCQkJCQkI8YnI+YGBgPGJyPjxicj7lhbbkuK3nmoTlrZfmr43liIbliKvku6Po oag6PGJyPjxicj4tIFMoU2lnbmlmaWNhbmQpOjEgLSDmraPotJ/lj7ckKC0xKV5TJDxicj4tIEUo RXhwb25lbnQpOjggLSDmjIfmlbDpg6jliIY8YnI+LSBCKEJhc2UpOjIzIC0g5bqV5pWw6YOo5YiG PGJyPjxicj7ov5nmoLcsIOaVtOS4qua1rueCueaVsOihqOekuui1t+adpeWwseaYrzo8YnI+PGJy PiQoLTEpXlMgXHRpbWVzIDEuQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkIgXHRpbWVzIDIgXntFRUVF RUVFRSAtIDAxMTExMTExfSQ8YnI+PGJyPiMjIE7ov5vliLbnmoTlsI/mlbA8YnI+PGJyPueci+WI sDEw6L+b5Yi255qE5bCP5pWwLCDlsI/mlbDngrnmmK/nlKjmnaXliIbpmpTmjIfmlbDmraPotJ/k vY3nmoQ6PGJyPjxicj4kMTIzLjQ1NiQ8YnI+JD0gMSBcdGltZXMgMTBeMiArIDIgXHRpbWVzIDEw XjEgKyAzIFx0aW1lcyAxMF4wICsgNCBcdGltZXMgMTBeey0xfSArIDUgXHRpbWVzIDEwXnstMn0g KyA2IFx0aW1lcyAxMF57LTN9JDxicj48YnI+5o6o5bm/5YiwTui/m+WItiwg5b2i5byP5piv5a6M 5YWo55u45ZCM55qELCDov5nph4znlKjkuozov5vliLblgZrkuIDkuKrkvovlrZA6PGJyPjxicj4k KDEwMS4wMTAxKV8yJDxicj4kPSAyXjIgKyAyXjAgKyAyXnstMn0gKyAyXnstNH0kPGJyPiQ9IDQr MSt7MSBcb3ZlciA0fSt7MSBcb3ZlciAxNn0kPGJyPiQ9IDUuMzEyNSQ8YnI+PGJyPiMjIOaehOmA oOS4gOS4qua1rueCueaVsDxicj48YnI+5LulMTIuNjI15Li65L6L5a2QLiDpppblhYjmiJHku6zm jqjnrpfkuIDkuIvlroPnmoTkuozov5vliLblvaLlvI/mmK/ku4DkuYguIOWmguaIkeS7rOaJgOef pSwg5pW05pWw6YOo5YiG5ZKM5bCP5pWw6YOo5YiG55qE5L2N572u5piv5oGS5a6a5LiN5Y+Y55qE LCDlm6DkuLrlroPku6zmmK/lkKblsI/kuo4x6L+Z5Liq5oCn6LSoLCDml6DorrrlnKjku4DkuYjo v5vliLbkuYvkuIvpg73kuI3kvJrmlLnlj5guIOmmluWFiOeul+aVtOaVsOmDqOWIhjo8YnI+PGJy PiQxMiBcZGl2IDIgPSA2IFxjZG90cyAwJDxicj4kNiBcZGl2IDIgPSAzIFxjZG90cyAwJDxicj4k MyBcZGl2IDIgPSAxIFxjZG90cyAxJDxicj4kMSBcZGl2IDIgPSAwIFxjZG90cyAxJDxicj4kXHRo ZXJlZm9yZSBcICgxMilfMTAgPSAoMTEwMClfMiQ8YnI+PGJyPuWwj+aVsOmDqOWIhijkuI3nn6Xp gZPmmK/lkKbms6jmhI/liLAsIOWwj+aVsOmDqOWIhuWPquacieaYrzJebueahOWSjOaJjeacieWP r+iDveiiq+ihqOekuuaIkOS4jeW+queOr+Wwj+aVsC4g6K+45aaCMC43LCAwLjPpg73mmK/kuozo v5vliLbnmoTml6DpmZDlvqrnjq/lsI/mlbApOjxicj48YnI+JDAuNjI1IFx0aW1lcyAyID0gMSAr IDAuMjUkPGJyPiQwLjI1IFx0aW1lcyAyID0gMCArIDAuNSQ8YnI+JDAuNSBcdGltZXMgMiA9IDEk PGJyPiRcdGhlcmVmb3JlIFwgKDAuNjI1KV97MTB9ID0gKDAuMTAxKV8yJDxicj48YnI+6L+Z5qC3 LCDmiJHku6zlvpfliLDkuobkuIDkuKrkuozov5vkvY3nmoTlsI/mlbAxMTAwLjEwMSwg5bm25LiU 5YyW5oiQSUVFRS03NDXmoIflh4blvaLlvI86PGJyPjxicj4kMTEwMC4xMDEgPSAxLjEwMDEwMSBc dGltZXMgMl57MDAwMDAwMTEgKyAwMTExMTExMSAtIDAxMTExMTExfSQ8YnI+PGJyPmBgYDxicj5B ZGRyZXNzIDMmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgMiZuYnNw OyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyAxJm5ic3A7Jm5ic3A7Jm5ic3A7 Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IDA8YnI+Q29udGVudCBTRUVFRUVFRSBFQkJCQkJCQiBC QkJCQkJCQiBCQkJCQkJCQjxicj5WYWx1ZSZuYnNwOyZuYnNwOyAwMTAwMDAwMSAwMTAwMTAxMCAw MDAwMDAwMCAwMDAwMDAwMDxicj5IZXgmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJz cDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgNDEmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJz cDsmbmJzcDsgNEEmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgMDAmbmJzcDsm bmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgMDA8YnI+YGBgPGJyPjxicj7njrDlnKjmiJHk u6zlvpfliLDkuobkuIDkuKrmlbTmlbAweDQxNEEwMDAwLCDmiorlroPovpPlh7rlh7rmnaXnnIvn nIvmmK/lpJrlsJE6PGJyPjxicj5gYGA8YnI+JCBjYXQgdGVzdC5jPGJyPiNpbmNsdWRlICZsdDtz dGRpby5oJmd0Ozxicj48YnI+aW50IG1haW4oKSB7PGJyPiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNw OyZuYnNwOyZuYnNwOyZuYnNwOyB1bmlvbiB7PGJyPiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZu YnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyB1bnNpZ25lZCBsb25nIHU7 PGJyPiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNw OyZuYnNwOyZuYnNwOyBmbG9hdCBmOzxicj4mbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsm bmJzcDsmbmJzcDsgfSB1Ozxicj4mbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsm bmJzcDsgdS51ID0gMHg0MTRhMDAwMDs8YnI+Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7 Jm5ic3A7Jm5ic3A7IHByaW50ZigiJWZcbiIsIHUuZik7PGJyPiZuYnNwOyZuYnNwOyZuYnNwOyZu YnNwOyZuYnNwOyZuYnNwOyZuYnNwOyByZXR1cm4gMDs8YnI+fTxicj48YnI+JCAuL3Rlc3Q8YnI+ MTIuNjI1MDAwPGJyPmBgYDxicj48L2Rpdj4=" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0;">&#8203;</div>
</div>
</div>
</div>
</div><img src ="http://www.cppblog.com/Shihira/aggbug/209380.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Shihira/" target="_blank">Shihira</a> 2015-01-02 14:38 <a href="http://www.cppblog.com/Shihira/archive/2015/01/02/209380.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TypeGame: 为Vim加上打字练习功能</title><link>http://www.cppblog.com/Shihira/archive/2014/08/16/typegame-vim.html</link><dc:creator>Shihira</dc:creator><author>Shihira</author><pubDate>Sat, 16 Aug 2014 13:11:00 GMT</pubDate><guid>http://www.cppblog.com/Shihira/archive/2014/08/16/typegame-vim.html</guid><wfw:comment>http://www.cppblog.com/Shihira/comments/208039.html</wfw:comment><comments>http://www.cppblog.com/Shihira/archive/2014/08/16/typegame-vim.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/Shihira/comments/commentRss/208039.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Shihira/services/trackbacks/208039.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 这是本文作者所写的一个小小的Vim插件，小到都不必为它新开一个Github项目。如果曾经玩过金山打字的朋友肯定对这个不陌生，无非两行，上行对照，下行打字。这个Vim脚本模拟了这个方式，也因此它即使名为Game，其实挺无趣的囧rz=3&nbsp;&nbsp;<a href='http://www.cppblog.com/Shihira/archive/2014/08/16/typegame-vim.html'>阅读全文</a><img src ="http://www.cppblog.com/Shihira/aggbug/208039.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Shihira/" target="_blank">Shihira</a> 2014-08-16 21:11 <a href="http://www.cppblog.com/Shihira/archive/2014/08/16/typegame-vim.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows API 字符编码转换以及一些解释和心得</title><link>http://www.cppblog.com/Shihira/archive/2013/10/28/200124.html</link><dc:creator>Shihira</dc:creator><author>Shihira</author><pubDate>Mon, 28 Oct 2013 14:49:00 GMT</pubDate><guid>http://www.cppblog.com/Shihira/archive/2013/10/28/200124.html</guid><wfw:comment>http://www.cppblog.com/Shihira/comments/200124.html</wfw:comment><comments>http://www.cppblog.com/Shihira/archive/2013/10/28/200124.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cppblog.com/Shihira/comments/commentRss/200124.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Shihira/services/trackbacks/200124.html</trackback:ping><description><![CDATA[<div>
<p><span style="font-size: 12pt;">我在解决乱码上面实际走了不少弯路，做了很多实验，查了很多资料。在这里做下笔记，希望后来者可以明白，少走些弯路。</span></p>
<p>
</p>
<h3>从最熟悉的两种字符编码说起<br />
</h3>
<p>
<span style="font-size: 12pt;">除了一些旧的、没有考虑到兼容性的网页还在用gbk做编码外，大部分的网页都已经用utf-8做编码了。但是最令人头疼的是，windows的控制台是很不好显示utf-8的。有明君为我大C++写了两个函数，是正确的、好用的<strike>（除了用std::string做返回值让我等效率党有点觉得不爽之外&#8230;&#8230;还是挺方便的）</strike>.</span></p>
</div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000; ">#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />
#include&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">windows.h</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />
</span><span style="color: #0000FF; ">using</span><span style="color: #000000; ">&nbsp;std::</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">;<br />
<br />
</span><span style="color: #008000; ">//</span><span style="color: #008000; ">gbk&nbsp;转&nbsp;utf8</span><span style="color: #008000; "><br />
</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&nbsp;GBKToUTF8(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;strGBK)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&nbsp;strOutUTF8&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">""</span><span style="color: #000000; ">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;WCHAR&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;str1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;n&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;MultiByteToWideChar(CP_ACP,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;strGBK.c_str(),&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;NULL,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;str1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;WCHAR[n];<br />
&nbsp;&nbsp;&nbsp;&nbsp;MultiByteToWideChar(CP_ACP,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;strGBK.c_str(),&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;str1,&nbsp;n);<br />
&nbsp;&nbsp;&nbsp;&nbsp;n&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;WideCharToMultiByte(CP_UTF8,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;str1,&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;NULL,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;NULL,&nbsp;NULL);<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;str2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">[n];<br />
&nbsp;&nbsp;&nbsp;&nbsp;WideCharToMultiByte(CP_UTF8,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;str1,&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;str2,&nbsp;n,&nbsp;NULL,&nbsp;NULL);<br />
&nbsp;&nbsp;&nbsp;&nbsp;strOutUTF8&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;str2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;delete[]str1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;str1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NULL;<br />
&nbsp;&nbsp;&nbsp;&nbsp;delete[]str2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;str2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;NULL;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;strOutUTF8;<br />
}<br />
<br />
</span><span style="color: #008000; ">//</span><span style="color: #008000; ">utf-8&nbsp;转&nbsp;gbk</span><span style="color: #008000; "><br />
</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&nbsp;UTF8ToGBK(</span><span style="color: #0000FF; ">const</span><span style="color: #000000; "> </span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&amp;</span><span style="color: #000000; ">&nbsp;strUTF8)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;len&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;MultiByteToWideChar(CP_UTF8,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;strUTF8.c_str(),&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;NULL,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;</span><span style="color: #0000FF; ">short</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;wszGBK&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;unsigned&nbsp;</span><span style="color: #0000FF; ">short</span><span style="color: #000000; ">[len&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">];<br />
&nbsp;&nbsp;&nbsp;&nbsp;memset(wszGBK,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;len&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">2</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">2</span><span style="color: #000000; ">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;MultiByteToWideChar(CP_UTF8,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;(LPCTSTR)strUTF8.c_str(),&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;wszGBK,&nbsp;len);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;len&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;WideCharToMultiByte(CP_ACP,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;wszGBK,&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;NULL,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;NULL,&nbsp;NULL);<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">szGBK&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">char</span><span style="color: #000000; ">[len&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">];<br />
&nbsp;&nbsp;&nbsp;&nbsp;memset(szGBK,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;len&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;WideCharToMultiByte(CP_ACP,</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;wszGBK,&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;szGBK,&nbsp;len,&nbsp;NULL,&nbsp;NULL);<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">strUTF8&nbsp;=&nbsp;szGBK;</span><span style="color: #008000; "><br />
</span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;std::</span><span style="color: #0000FF; ">string</span><span style="color: #000000; ">&nbsp;strTemp(szGBK);<br />
&nbsp;&nbsp;&nbsp;&nbsp;delete[]szGBK;<br />
&nbsp;&nbsp;&nbsp;&nbsp;delete[]wszGBK;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;strTemp;<br />
}</span></div>
<p>
<span style="font-size: 12pt;">这玩意儿不跨平台，因为它用到了windows api。我之所以把它放到跨平台编程上面来，是因为字符编码这东西只有到跨平台的时候才显得坑爹。</span></p>
<br />
<h3>接着我是不是要介绍那俩函数一下？</h3>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;MultiByteToWideChar(<br />
&nbsp;&nbsp;_In_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UINT&nbsp;CodePage,&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">代码页是Windows下字符编码的叫法，gbk是936，utf-8是65001，CP_ACP是ANSI</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />
&nbsp;&nbsp;_In_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;dwFlags,&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">选项标志，转换类型，设0就行了</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />
&nbsp;&nbsp;_In_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPCSTR&nbsp;lpMultiByteStr,&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">多字节字符串</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />
&nbsp;&nbsp;_In_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;cbMultiByte,&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">字符串要处理的长度，如果是-1函数就会处理整个字符串</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />
&nbsp;&nbsp;_Out_opt_&nbsp;&nbsp;LPWSTR&nbsp;lpWideCharStr,&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">输出的宽字符串缓存，如果为空就返回需要的宽字符串长度</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />
&nbsp;&nbsp;_In_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;cchWideChar&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">宽字符串缓存的长度，当然如果宽字符串为空，这个设0就可以了</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />
);<br />
<br />
</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;WideCharToMultiByte(<br />
&nbsp;&nbsp;_In_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UINT&nbsp;CodePage,<br />
&nbsp;&nbsp;_In_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;dwFlags,<br />
&nbsp;&nbsp;_In_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPCWSTR&nbsp;lpWideCharStr,<br />
&nbsp;&nbsp;_In_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;cchWideChar,<br />
&nbsp;&nbsp;_Out_opt_&nbsp;&nbsp;LPSTR&nbsp;lpMultiByteStr,<br />
&nbsp;&nbsp;_In_&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;cbMultiByte,&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">前面的基本与MultiByteToWideChar都相同，就不解释了</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />
&nbsp;&nbsp;_In_opt_&nbsp;&nbsp;&nbsp;LPCSTR&nbsp;lpDefaultChar,&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">填0即可</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />
&nbsp;&nbsp;_Out_opt_&nbsp;&nbsp;LPBOOL&nbsp;lpUsedDefaultChar&nbsp;</span><span style="color: #008000; ">/*</span><span style="color: #008000; ">填0即可</span><span style="color: #008000; ">*/</span><span style="color: #000000; "><br />
);<br />
</span></div>
<p><span style="font-size: 12pt;">这两个函数分别是将多字节字符串转换为宽字符字符串 和 将宽字符字符串转换为多字节字符串（在此处晕倒的童鞋们我没有对不起你们&#8230;&#8230;是M$那家伙对不起你们）。我早就说过Windows API 的界面不友好，这么多不知道干嘛吗用的参数，全部填0就对了。要是iconv()，它貌似只有4个参数，这才是好的榜样。</span></p>
<p><br />
</p>
<h3>宽字符？多字节？</h3>
<p><span style="font-size: 12pt;">这是Windows给它们起的名字，让人摸不着头脑。</span></p>
<p>
</p>
<p>
</p>
<ul>
     <li>
     <p><span style="font-size: 12pt;">宽字符：就是<strong style="font-size: 12pt;">Unicode</strong>。它雷打不动地用2个字节（0x0000 - 0xFFFF），表示所有我们平常能见到的字符，具体的表格见：<a href="http://unicode-table.com">http://unicode-table.com</a></span></p>
     </li>
</ul>
<p>
</p>
<ul>
     <li>
     <p><span style="font-size: 12pt;">多字节：就是除了Unicode外<strong style="font-size: 12pt;">其他</strong>的。我们熟悉的gbk, utf-8, big5，统统归入多字节。</span></p>
     </li>
</ul>
<p>
</p>
<p>
</p>
<p><span style="font-size: 12pt;">宽字符之所以叫做宽字符，是因为它是一个宽一点的字符。那什么是短字符&#8230;&#8230;就是ascii了，1个字节1个字符绝对够短，而且只能表示256个西欧字符。宽字符呢，是2个字节1个字符。宽一点，但还是可以识别到一个字符是哪里的。而多字节呢，就是它在计算机里表示成多个字节，但是没有办法识别那里到那里是一个字符。</span></p>
<p>
</p>
<p><span style="font-size: 12pt;">我不喜欢这两个函数的命名。如果按照Python的命名，</span><span style="color: #000000; font-size: 12pt;">MultiByteToWideChar 应该叫 decode(解码)，WideCharToMultiByte 应该叫 encode(编码)。</span></p>
<p><br />
</p>
<h3>所以呢？</h3>
<p><span style="font-size: 12pt;">如你所见，多字节无法准确识别字符的长度，处理起来就会很麻烦。而宽字符大多时候虽然比多字节多耗费一点空间，但是处理起来方便。比如正则表达式处理，引擎是基于字符去匹配的，宽字符可以两个字节两个字节跳着匹配，而多字节就会匹配错误。</span></p>
<p>
</p>
<p><span style="font-size: 12pt;">比如有一个词&#8220;</span><span style="color: #008080; font-size: 12pt;">程序</span><span style="font-size: 12pt;">&#8221;=0xB3</span><span style="color: #0000ff; font-size: 12pt;">CCD0</span><span style="font-size: 12pt;">F2(gbk)，我想匹配&#8220;</span><span style="color: #008080; font-size: 12pt;">绦</span><span style="font-size: 12pt;">&#8221;=0x</span><span style="color: #0000ff; font-size: 12pt;">CCD0</span><span style="font-size: 12pt;">(gbk)，正则库会替我把中间那两个字节匹配了。用在C里用wchar_t，C++里用std::wstring，我们可以很准确的，无错误地匹配到我们想要的子串，因为引擎在迭代的时候是逐字（而不是逐字节）进行比较的。</span></p>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008080; ">1</span>&nbsp;<span style="color: #008000;">&gt;&gt;&gt;</span><span style="color: #000000; ">&nbsp;str1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #800000; ">绦</span><span style="color: #800000; ">"</span><span style="color: #000000; "><br />
</span><span style="color: #008080; ">2</span>&nbsp;<span style="color: #000000; "></span><span style="color: #008000;">&gt;&gt;&gt;</span><span style="color: #000000; ">&nbsp;str2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #800000; ">"</span><span style="color: #800000; ">程序</span><span style="color: #800000; ">"</span><span style="color: #000000; "><br />
</span><span style="color: #008080; ">3</span>&nbsp;<span style="color: #000000; "></span><span style="color: #008000;">&gt;&gt;&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">&nbsp;re.findall(str1,&nbsp;str2)<br />
</span><span style="color: #008080; ">4</span>&nbsp;<span style="color: #000000; ">[</span><span style="color: #800000; ">'</span><span style="color: #800000; ">\xcc\xd0</span><span style="color: #800000; ">'</span><span style="color: #000000; ">]<br />
</span><span style="color: #008080; ">5</span>&nbsp;<span style="color: #000000; "></span><span style="color: #008000;">&gt;&gt;&gt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">print</span><span style="color: #000000; ">&nbsp;re.findall(str1.decode(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">gbk</span><span style="color: #800000; ">"</span><span style="color: #000000; ">),&nbsp;str2.decode(</span><span style="color: #800000; ">"</span><span style="color: #800000; ">gbk</span><span style="color: #800000; ">"</span><span style="color: #000000; ">))<br />
</span><span style="color: #008080; ">6</span>&nbsp;<span style="color: #000000; ">[]</span></div>
<p><strong><span style="font-size: 12pt;">所以在处理字符串的时候，但凡要处理中文，要先把用户给的字符串解码成Unicode。处理完之后显示出来或者保存，再编码成需要的charset。</span></strong></p>
<h4><br style="color: #333333;" />
<span></span></h4>
<h4><span style="color: #333333; font-size: 10pt;"><em>Appendix</em></span></h4>
<p><em style="color: #333333; font-size: 10pt;">在不同的地方用不同的编码：</em></p>
<ul>
     <li><em style="color: #333333; font-size: 10pt;">网络文本（如网页）传输一般用utf-8，因为有少量中文，而大部分是英文。</em></li>
     <li><em style="color: #333333; font-size: 10pt;">在保存为本地文件的时候，应该保存为Unicode，因为本地存储资源丰富，且可以节省时间，实时解码毕竟也是O(N^2)啊。</em></li>
     <li><em style="color: #333333; font-size: 10pt;">显示出来应该用系统的编码，中文Windows为gbk，繁体Windows为Big5，Linux一律为UTF-8。</em></li>
     <li><em style="color: #333333; font-size: 10pt;">源代码里的少量中文串尽量用<em style="color: #ff6600;">"\x????\x????"</em>来表示，如果有大量中文建议用gettext或者资源之类的以外挂的方式读入。</em></li>
     <li><em style="color: #333333; font-size: 10pt;">Qt内部使用Unicode，所以编写Qt应用时显示文字直接传递宽字符串即可。</em></li>
     <li><em style="color: #333333; font-size: 10pt;">NTFS的文件名、路径都是用<strike>GBK</strike>UTF16LE编码的，所以如果Windows下用户输入的是路径就无需解码了。</em></li>
</ul>
<p><br />
</p><img src ="http://www.cppblog.com/Shihira/aggbug/200124.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Shihira/" target="_blank">Shihira</a> 2013-10-28 22:49 <a href="http://www.cppblog.com/Shihira/archive/2013/10/28/200124.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AGG入门（八） - 渲染</title><link>http://www.cppblog.com/Shihira/archive/2012/08/01/185867.html</link><dc:creator>Shihira</dc:creator><author>Shihira</author><pubDate>Wed, 01 Aug 2012 12:01:00 GMT</pubDate><guid>http://www.cppblog.com/Shihira/archive/2012/08/01/185867.html</guid><wfw:comment>http://www.cppblog.com/Shihira/comments/185867.html</wfw:comment><comments>http://www.cppblog.com/Shihira/archive/2012/08/01/185867.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Shihira/comments/commentRss/185867.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Shihira/services/trackbacks/185867.html</trackback:ping><description><![CDATA[<h3>一、引言</h3>
<div>让我们来看一看渲染具体的流程图吧：</div>
<div><img src="http://www.cppblog.com/images/cppblog_com/shihira/20120724-1.png" border="0" alt="" width="392" height="713" /><br />
<div><strong>上面提到了几个概念，再解释一下：</strong></div>
<div>
<ul>
     <li>顶点源（Vertex Source）：用顶点的方式描述矢量图形；</li>
     <li>光栅化（Resterizer）：它的作用是把顶点源所描绘的图形与像素对应起来，可以说类似于Photoshop上的矢量蒙版；</li>
     <li>扫描线（Scanline）：扫描线的作用就是为扫描线渲染器提供一个扫描的方式和区域，使渲染器有序地填充；</li>
     <li>扫描线渲染器（Scanline Renderer）：分实色和自定义渲染器两类，实色只允许你用单一的颜色去进行渲染，而自定则可做得多姿多彩，比如渐变、位图；它相当于GDI里的画刷。</li>
</ul>
</div>
<div></div>
<h3>二、工作</h3>
<div>这次我们以一个自制的顶点源与椭圆组合作为渲染对象，用宝蓝色的实色渲染器进行渲染；<br />
<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#include&nbsp;&lt;agg_ellipse.h&gt;<br /><br /><span style="color: #008000; ">//................</span><span style="color: #008000; "><br /></span><br /><span style="color: #0000FF; ">class</span>&nbsp;triangle_path&nbsp;{<br /><span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;triangle_path()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;tmp_array[4][3]={<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{0&nbsp;&nbsp;,&nbsp;250,&nbsp;agg::path_cmd_move_to},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{500,&nbsp;250,&nbsp;agg::path_cmd_line_to},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{250,&nbsp;500,&nbsp;agg::path_cmd_line_to},<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{0&nbsp;&nbsp;,&nbsp;&nbsp;&nbsp;0,&nbsp;agg::path_cmd_stop}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memcpy(m_points[0],&nbsp;tmp_array[0],&nbsp;<span style="color: #0000FF; ">sizeof</span>(m_points));<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;vertex(<span style="color: #0000FF; ">double</span>&nbsp;*x,&nbsp;<span style="color: #0000FF; ">double</span>*&nbsp;y)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*x&nbsp;=&nbsp;m_points[m_step][0];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*y&nbsp;=&nbsp;m_points[m_step][1];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;r&nbsp;=&nbsp;m_points[m_step][2];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_step++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;r;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;rewind(<span style="color: #0000FF; ">int</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m_step&nbsp;=&nbsp;0;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><span style="color: #0000FF; ">private</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;m_step;<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;m_points[4][3];<br />};<br /><br /><span style="color: #008000; ">//......</span><span style="color: #008000; ">&nbsp;in&nbsp;class&nbsp;the_application</span><span style="color: #008000; "><br /></span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;on_draw()<br />&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ren_bas.reset_clipping(<span style="color: #0000FF; ">true</span>);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ren_bas.clear(agg::rgba8(255,&nbsp;255,&nbsp;255));<br />&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;agg::ellipse&nbsp;ellipse(250,&nbsp;125,&nbsp;125,&nbsp;125);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;triangle_path&nbsp;triangle;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rasterizer.reset();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rasterizer.add_path(triangle);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rasterizer.add_path(ellipse);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;agg::render_scanlines_aa_solid(rasterizer,&nbsp;scanline,&nbsp;ren_bas,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;agg::rgba8(45,&nbsp;108,&nbsp;155));&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">注意：函数名中的scanline是复数！！</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;}</div></div><div><div style="width: auto !important; margin: 0px !important; border-top-left-radius: 0px !important; border-top-right-radius: 0px !important; border-bottom-right-radius: 0px !important; border-bottom-left-radius: 0px !important; background-image: none !important; border: 0px !important; bottom: auto !important; float: none !important; height: auto !important; left: auto !important; line-height: 1.1em !important; outline: 0px !important; overflow: visible !important; position: relative !important; right: auto !important; text-align: left !important; top: auto !important; vertical-align: baseline !important; box-sizing: content-box !important; font-family: Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace !important; font-size: 1em !important; min-height: inherit !important; ">
</div>
</div>
</div>
<div><h3>三、解释</h3><div>先看on_draw函数：我们先定义了两个顶点源，一个是椭圆，另一个是自制的三角形；先把rasterizer重置，清除上次重绘留下的光栅信息；我们再在光栅中添加这两个顶点源，用渲染器渲染，就是了；</div><div>你可能感到奇怪：为什么没有扫描线渲染器的定义呢？其实在<span style="color: #ff0000; ">render_scanlines_aa_solid</span>里，就已经帮你定义好了实色渲染器。把render_scanlines_aa_solid展开成：</div></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;"><div><div>agg::<span style="color: #ff0000; ">renderer_scanline_aa_solid</span>&lt;agg::renderer_base&lt;agg::pixfmt_rgb24&gt;&gt; renderer_scanline(ren_bas);</div></div><div><div>renderer_scanline.color(agg::rgba8(45, 108, 155, cover));</div></div><div><div>agg::render_scanlines(rasterizer, scanlines, renderer_scanline);</div></div></blockquote><div><div>效率是一样的，只不过函数版本更加简洁。</div><div>顶点源的定义，结合上一节的知识和agg_basics.h中关于path_commands_e和path_flags_e的定义，应该是可以理解的；</div></div><img src ="http://www.cppblog.com/Shihira/aggbug/185867.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Shihira/" target="_blank">Shihira</a> 2012-08-01 20:01 <a href="http://www.cppblog.com/Shihira/archive/2012/08/01/185867.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AGG入门（七） - 顶点源</title><link>http://www.cppblog.com/Shihira/archive/2012/07/24/183919.html</link><dc:creator>Shihira</dc:creator><author>Shihira</author><pubDate>Tue, 24 Jul 2012 08:30:00 GMT</pubDate><guid>http://www.cppblog.com/Shihira/archive/2012/07/24/183919.html</guid><wfw:comment>http://www.cppblog.com/Shihira/comments/183919.html</wfw:comment><comments>http://www.cppblog.com/Shihira/archive/2012/07/24/183919.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/Shihira/comments/commentRss/183919.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Shihira/services/trackbacks/183919.html</trackback:ping><description><![CDATA[<h3>一、修改模板</h3>
<div>现在终于进入了真正的矢量绘图阶段，我们的模版也需要有所改变；至于为什么，有什么作用，以后会说到；<br />包含下面的头文件，并且在the_application类中添加两个成员。</div>
<div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><span style="color: #008000; ">//</span><span style="color: #008000; ">扫描线和扫描线光栅器</span><span style="color: #008000; "><br />
</span>#include&nbsp;&lt;agg_scanline_u.h&gt;<br />
#include&nbsp;&lt;agg_rasterizer_scanline_aa.h&gt;<br />
<br />
<span style="color: #0000FF; ">private</span>:<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">扫描线和扫描线光栅器</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;agg::scanline_u8&nbsp;scanline;<br />
&nbsp;&nbsp;&nbsp;&nbsp;agg::rasterizer_scanline_aa&lt;&gt;&nbsp;rasterizer;</div>
</div>
<div>
<p><br />
</p>
<h3>&nbsp;二、顶点源</h3>
<p>&nbsp;</p>
<div>顶点源（Vertex Source）不是一个类，而是一种类的模式。这种类里面有rewind()函数和vertex()函数给AGG内部调用（没错，这就是它的定义）。类如其名，顶点源就是为绘图系统提供顶点信息的，大家能想象得出这两个函数的作用了吗？</div>
<div><strong>rewind()</strong>：回到最开始个步骤；</div>
<div><strong>vertex(double* x, double* y)</strong>：每调用一次，跳一个步骤（点），每一个步骤都输出顶点的x,y坐标（灰色字），以及这个坐标的绘图命令（紫色字）；<br />
<img src="http://www.cppblog.com/images/cppblog_com/shihira/5.png" border="0" alt="" width="296" height="256" /></div>
<div></div>
<h3>三、内置顶点源</h3>
<div>AGG内置了大量的顶点源，我们可以直接调用，他们包括：</div>
<div><strong>agg::path_storage</strong></div>
<div><strong>agg::arc</strong></div>
<div><strong>agg::rounded_rect</strong></div>
<div><strong>agg::ellipse</strong></div>
<div><strong>agg::curve3</strong></div>
<div><strong>agg::curve4 ......</strong></div>
<div>等等，为什么没有线、点顶点源？其实，path_storage已经内置了画线函数、画弧函数、画贝塞尔曲线函数，你可以用path_storage创造几乎任何的图形。至于画点，copy_pixel()或者用椭圆吧&#8230;&#8230;</div>
<div></div>
<h3>四、路径储存器</h3>
<div>Path storage 是用来管理路径、画复杂图形的。在上面可以任意添加直线、曲线、其他路径。</div>
<h4>头文件</h4>
<div><span style="color: #0000ff; ">#include</span> &lt;agg_path_storage.h&gt;</div>
<h4>类型定义</h4>
<div><span style="color: #0000ff; ">typedef</span> path_base&lt;vertex_block_storage&lt;<span style="color: #0000ff; ">double</span>&gt; &gt; path_storage;</div>
<h4>基本成员函数</h4>
<div>
<ul>
     <li><strong>move_to()</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;添加命令为 path_cmd_move_to 的顶点，意为下一条线从这个点开始画；</li>
     <li><strong>line_to()</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;添加命令为 path_cmd_line_to 的顶点，意为画线到这个点；</li>
     <li><strong>arc_to(double rx, double ry, double angle, bool large_arc_flag, bool sweep_flag, double x, double y)</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;添加一条弧路径，画轴长为rx, ry，角度为angle，优/劣弧，顺逆时针，终点在(x,y)。</li>
     <li><strong>curve3_to()</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;添加贝塞尔曲线，参数为一个控制点和终点的坐标</li>
     <li><strong>curve4_to()</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;添加贝塞尔曲线，参数为两个控制点和终点的坐标</li>
     <li><strong>join_path()</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;添加一个顶点源，即组合</li>
     <li><strong>vertex(unsigned idx, double* x, double* y)<br />
     last_vertex(double* x, double* y)<br />
     vertex(double* x, double* y)</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;取顶点位置，前者为已知步骤，后两者为顺序或倒序获取</li>
     <li><strong>modify_vertex()<br />
     modify_command()</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;修改步骤为idx的顶点坐标和命令</li>
</ul>
</div>
<div></div>
<h3>五、其他顶点源</h3>
<div>其他顶点源就不一一介绍了，只列出其头文件和构造函数：</div>
<div>
<ul>
     <li><span style="color: #0000ff; ">#include &lt;agg_ellipse.h&gt;</span><br />
     <strong>ellipse(double x, double y, double rx, double ry, unsigned num_steps=0, bool cw=false)</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;圆心(x, y)和长短半轴分别为rx, ry，步骤数位num_steps（无用），cw决定相交地方是否空出</li>
     <li><span style="color: #0000ff; ">#include &lt;agg_arc.h&gt;</span><br />
     <strong>arc(double x, &nbsp;double y, double rx, double ry, double a1, double a2, bool ccw=true)</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;圆心为(x, y)和长短半轴分别为rx, ry，初始角度和终结角度为a1, a2</li>
     <li><span style="color: #0000ff; ">#include &lt;agg_curves.h&gt;</span><br />
     <strong>curve3(double x1, double y1, double x2, double y2, double x3, double y3)</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;三个点，分别为：初始点，控制点一，终结点</li>
     <li><span style="color: #0000ff; ">#include &lt;agg_curves.h&gt;</span><br />
     <strong>curve4(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;四个点，分别为：初始点，控制点一，控制点二，终结点</li>
     <li><span style="color: #0000ff; ">#include &lt;agg_rounded_rect.h&gt;</span><br />
     <strong>rounded_rect(double x1, double y1, double x2, double r)</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;对角点的坐标和圆角半径</li>
</ul>
</div>
<div></div>
<p><strong style="color: #993300; ">至于怎样把他们画在渲染内存上呢，我们下一篇会讲到。</strong><strong style="color: red; "><br />头文件也渐渐地多了起来，包含头文件时的工作量有点大；我特地列了一个头文件，里面已经包含了所有的AGG头文件，以后大家只需要包含它就好了。<br />下载处：</strong><a href="http://www.cppblog.com/Files/Shihira/agg.h.zip">http://www.cppblog.com/Files/Shihira/agg.h.zip</a><a href="http://www.cppblog.com/Files/Shihira/AGG.zip"></a></p>
</div><img src ="http://www.cppblog.com/Shihira/aggbug/183919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Shihira/" target="_blank">Shihira</a> 2012-07-24 16:30 <a href="http://www.cppblog.com/Shihira/archive/2012/07/24/183919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AGG入门（六） - 练习和细节</title><link>http://www.cppblog.com/Shihira/archive/2012/07/24/183618.html</link><dc:creator>Shihira</dc:creator><author>Shihira</author><pubDate>Tue, 24 Jul 2012 08:30:00 GMT</pubDate><guid>http://www.cppblog.com/Shihira/archive/2012/07/24/183618.html</guid><wfw:comment>http://www.cppblog.com/Shihira/comments/183618.html</wfw:comment><comments>http://www.cppblog.com/Shihira/archive/2012/07/24/183618.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/Shihira/comments/commentRss/183618.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Shihira/services/trackbacks/183618.html</trackback:ping><description><![CDATA[<div>学到目前为止，已经认识了六个类型：</div>
<div>
<ul>
     <li><strong>platform_support</strong></li>
     <li><strong>rendering_buffer</strong></li>
     <li><strong>rgba8</strong></li>
     <li><strong>pixfmt_rgb24</strong></li>
     <li><strong>rect_i</strong></li>
     <li><strong>renderer_base</strong></li>
</ul>
</div>
<div>现在来做些练习，看看有没有掌握学过的东西，并且灵活运用吧。</div>
<div></div>
<h3>一、基本框架</h3>
<div>这一节的程序都以这个框架为基础，都是在on_draw中稍微改动的：</div>
<div>
<div style="background-color: #eeeeee; font-size: 13px; border:1px solid #CCCCCC; border-left-color: #cccccc; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; padding-top: 4px; width: 98%; word-break: break-all; "><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->#include&nbsp;&lt;agg_pixfmt_rgb.h&gt;<br />
#include&nbsp;&lt;agg_renderer_base.h&gt;<br />
#include&nbsp;&lt;platform/agg_platform_support.h&gt;<br />
<br />
<span style="color: #0000FF; ">class</span>&nbsp;the_application&nbsp;:&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;agg::platform_support<br />
{<br />
<span style="color: #0000FF; ">public</span>:<br />
&nbsp;&nbsp;&nbsp;&nbsp;the_application(agg::pix_format_e&nbsp;format,&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;flip_y)&nbsp;:&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;agg::platform_support(format,&nbsp;flip_y),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pix_fmt(rbuf_window()),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ren_bas(pix_fmt)&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">初始化渲染器</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">virtual</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;on_draw()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;ren_bas.reset_clipping(true);
<div>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;ren_bas.clear(agg::rgba8(255, 255, 255));</div>
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<span style="color: #0000FF; ">private</span>:<br />
&nbsp;&nbsp;&nbsp;&nbsp;agg::pixfmt_rgb24&nbsp;pix_fmt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;agg::renderer_base&lt;agg::pixfmt_rgb24&gt;&nbsp;ren_bas;<br />
<br />
};<br />
<br />
<span style="color: #0000FF; ">int</span>&nbsp;agg_main(<span style="color: #0000FF; ">int</span>&nbsp;argc,&nbsp;<span style="color: #0000FF; ">char</span>*&nbsp;argv[])<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;the_application&nbsp;app(agg::pix_format_bgr24,&nbsp;<span style="color: #0000FF; ">true</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;app.caption("AGG&nbsp;Test");<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(app.init(500,&nbsp;500,&nbsp;agg::window_resize))&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;app.run();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;-1;<br />
}</div>
</div>
<h3>二、画线函数</h3>
<p>编写如下函数，实现在渲染缓存中画线的功能（无需反锯齿）：<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">inline void</span> stroke_line(<span style="color: #0000ff; ">int</span> x1, <span style="color: #0000ff; ">int</span> y1, <span style="color: #0000ff; ">int</span> x2, <span style="color: #0000ff; ">int</span> y2, agg::rgba8&amp; color);<br />
参数：<br />
</p>
<ul>
     <li>x1, y1, x2, y2分别是两个端点的坐标；</li>
     <li>color是颜色；</li>
</ul>
<p>&nbsp;</p>
<h3>三、画圆函数</h3>
<p>编写如下函数，实现在渲染缓存中画圆的功能（无需反锯齿）：<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff; ">void</span> stroke_round(<span style="color: #0000ff; ">int</span> r, <span style="color: #0000ff; ">int</span> C_x, <span style="color: #0000ff; ">int</span> C_y, agg::rgba8&amp; color, <span style="color: #0000ff; ">float </span>step = 0.01)
<br />
参数：<br />
</p>
<ul>
     <li>C_x,&nbsp;C_y&nbsp;是圆心的坐标；</li>
     <li>color是颜色；</li>
     <li>step是步长，也就是吧圆细分成1/step边形；
     </li>
</ul>
<p>&nbsp;</p>
<h3>四、答案</h3>
<div>
<p>
</p>
<ul>
     <li>画线函数<br />
     <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
     <br />
     Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
     http://www.CodeHighlighter.com/<br />
     <br />
     -->inline&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;stroke_line(<span style="color: #0000FF; ">int</span>&nbsp;x1,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;y1,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;x2,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;y2,&nbsp;agg::rgba8&amp;&nbsp;color)<br />
     {<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">double</span>&nbsp;precision&nbsp;=&nbsp;max(abs(x1&nbsp;-&nbsp;x2),&nbsp;abs(y1&nbsp;-&nbsp;y2));<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">精度，也就是画多少个点</span><span style="color: #008000; "><br />
     </span><br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">int</span>&nbsp;i=0;&nbsp;i&nbsp;&lt;=&nbsp;precision;&nbsp;i++)<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ren_bas.copy_pixel(&nbsp;x1&nbsp;+&nbsp;(&nbsp;x2&nbsp;-&nbsp;x1&nbsp;)&nbsp;/&nbsp;precision&nbsp;*&nbsp;i,&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">x</span><span style="color: #008000; "><br />
     </span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y1&nbsp;+&nbsp;(&nbsp;y2&nbsp;-&nbsp;y1&nbsp;)&nbsp;/&nbsp;precision&nbsp;*&nbsp;i,&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">y</span><span style="color: #008000; "><br />
     </span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;color);<br />
     }</div>
     </li>
     <li>画圆函数<br />
     <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
     <br />
     Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
     http://www.CodeHighlighter.com/<br />
     <br />
     --><span style="color: #0000FF; ">void</span>&nbsp;stroke_round(<span style="color: #0000FF; ">int</span>&nbsp;r,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;C_x,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;C_y,&nbsp;agg::rgba8&amp;&nbsp;color,&nbsp;<span style="color: #0000FF; ">float</span>&nbsp;step&nbsp;=&nbsp;0.01)<br />
     {<br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;prev_x&nbsp;=&nbsp;<span style="color: #0000FF; ">int</span>(r&nbsp;*&nbsp;cos(-0.01))&nbsp;+&nbsp;C_x,<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prev_y&nbsp;=&nbsp;<span style="color: #0000FF; ">int</span>(r&nbsp;*&nbsp;sin(-0.01))&nbsp;+&nbsp;C_y;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">保存上一个点</span><span style="color: #008000; "><br />
     </span><br />
     &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;x,&nbsp;y;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">保存当前的点</span><span style="color: #008000; "><br />
     </span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(<span style="color: #0000FF; ">double</span>&nbsp;rad&nbsp;=&nbsp;0;&nbsp;rad&nbsp;&lt;&nbsp;2&nbsp;*&nbsp;PI&nbsp;+&nbsp;step;&nbsp;rad+=&nbsp;step)&nbsp;{<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;=&nbsp;<span style="color: #0000FF; ">int</span>(r&nbsp;*&nbsp;cos(rad))&nbsp;+&nbsp;C_x;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y&nbsp;=&nbsp;<span style="color: #0000FF; ">int</span>(r&nbsp;*&nbsp;sin(rad))&nbsp;+&nbsp;C_y;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">计算弧度为rad时的坐标</span><span style="color: #008000; "><br />
     </span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stroke_line(x,&nbsp;y,&nbsp;prev_x,&nbsp;prev_y,&nbsp;color);<br />
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prev_x&nbsp;=&nbsp;x;&nbsp;prev_y&nbsp;=&nbsp;y;<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     }</div>
     </li>
</ul>
<p>可能有的人会觉得奇怪的是，为什么在画线函数中，不用pix_fmt.copy_pixel()而用ren_bas.copy_pixel()呢？因为，在pix_fmt中，混合器不进行检查，像素拷贝的时候会拷贝到剪裁区域以外，这样会造成很奇怪的情况，以至于如果写到了缓存以外，还会出现异常。注意，剪裁盒功能是基础渲染器级别才提供的，更加底层的操作，比如像素格式混合和直接操作缓存，高层次的渲染器是无从管理的。为了安全起见，建议少碰基础渲染器以下的工具&#8230;&#8230;</p>
</div>
<div>
</div><img src ="http://www.cppblog.com/Shihira/aggbug/183618.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Shihira/" target="_blank">Shihira</a> 2012-07-24 16:30 <a href="http://www.cppblog.com/Shihira/archive/2012/07/24/183618.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AGG入门（五） - 基础渲染器</title><link>http://www.cppblog.com/Shihira/archive/2012/07/24/183556.html</link><dc:creator>Shihira</dc:creator><author>Shihira</author><pubDate>Tue, 24 Jul 2012 08:29:00 GMT</pubDate><guid>http://www.cppblog.com/Shihira/archive/2012/07/24/183556.html</guid><wfw:comment>http://www.cppblog.com/Shihira/comments/183556.html</wfw:comment><comments>http://www.cppblog.com/Shihira/archive/2012/07/24/183556.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Shihira/comments/commentRss/183556.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Shihira/services/trackbacks/183556.html</trackback:ping><description><![CDATA[<div>基础渲染器（Base Renderer）是扫描线渲染器的基础，可以说，正常情况下，你绘画任何图形、做任何事，都需要通过它。而基础渲染器需要你以模版的形式提供像素格式的信息，他将会通过像素格式混合器来实现渲染。其实，基础渲染器比像素格式混合器多了剪裁盒的功能，其他混合、拷贝什么的和像素格式混合器是相似的，这里就不列出来了。</div><div></div><h3>矩形类</h3><div>AGG封装了一个专门表示矩形的模板类rect_base，方便矩形的操作。下面用rect_i说明一下。 &nbsp; &nbsp; &nbsp; &nbsp;</div><h4>头文件</h4><div><span style="color: #0000ff; ">#include</span> "agg_basics.h"</div><h4>类型定义</h4><div><span style="color: #0000ff; ">typedef</span> rect_base&lt;int&gt; rect_i;</div><h4>基本成员函数</h4><div><ul><li><span style="color: #000080; "><strong>rect_i(x1, y1, x2, y2)<br /></strong></span>&nbsp; &nbsp; &nbsp; &nbsp; 构造函数，给出最小和最大坐标；</li><li><strong><font color="#000080">normalize()<br /></font></strong>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;修正x1&gt;x2或y1&gt;y2的不合法矩形；</li><li><span style="color: #000080; "><strong>clip(rect_i&amp; r)</strong></span><br />&nbsp; &nbsp; &nbsp; &nbsp; 取当前矩形与r相交的区域矩形作为当前矩形；</li><li><span style="color: #000080; "><strong>is_valid()</strong></span><br />&nbsp; &nbsp; &nbsp; &nbsp; 检查矩形是否合法；</li><li><span style="color: #000080; "><strong>hit_test(int x, int y)<br /></strong></span>&nbsp; &nbsp; &nbsp; &nbsp; 检查(x, y)是否在矩形内；</li></ul></div><div></div><h3>基础渲染器</h3><h4>头文件</h4><div><span style="color: #0000ff; ">#include</span> "agg_renderer_base"</div><h4>类型定义</h4><div><span style="color: #0000ff; ">template</span>&lt;class PixelFormat&gt; class renderer_base</div><h4>基本成员函数</h4><div><ul><li><span style="color: #000080; "><strong>renderer_base(PixelFormat)<br /></strong></span>&nbsp; &nbsp; &nbsp; &nbsp; 构造函数，提供像素格式；</li><li><strong style="color: #000080; ">ren()<br /></strong>&nbsp; &nbsp; &nbsp; &nbsp; 返回像素格式对象；</li><li><span style="color: #000080; "><strong>clip_box(x1,y1,x2,y2)<br />clip_box_naked(x1,y1,x2,y2)<br /></strong></span>&nbsp; &nbsp; &nbsp; &nbsp; 设置当前剪裁盒为x1,y1,x2,y2围成的剪裁盒，前者检查剪裁盒是否合法，后者不检查。</li><li><span style="color: #000080; "><strong>reset_clipping(bool visibility)<br /></strong></span>&nbsp; &nbsp; &nbsp; &nbsp; 重置剪裁盒，visibility决定剪裁盒是铺满窗口（可视）还是0（不可视）；</li><li><span style="color: #000080; "><strong>clip_box()<br />xmin()<br />ymin()<br />xmax()<br />ymax()<br /></strong></span>&nbsp; &nbsp; &nbsp; &nbsp; 返回当前剪裁盒矩形、以及纵横坐标；</li><li><span style="color: #000080; "><strong>copy_from()<br />blend_from()<br /></strong></span>&nbsp; &nbsp; &nbsp; &nbsp; 可以比较方便地、以矩形方式拷贝和混合缓存里的图像了；</li></ul></div><img src ="http://www.cppblog.com/Shihira/aggbug/183556.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Shihira/" target="_blank">Shihira</a> 2012-07-24 16:29 <a href="http://www.cppblog.com/Shihira/archive/2012/07/24/183556.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AGG入门（四） - 渲染缓存和混合器</title><link>http://www.cppblog.com/Shihira/archive/2012/07/24/183204.html</link><dc:creator>Shihira</dc:creator><author>Shihira</author><pubDate>Tue, 24 Jul 2012 08:29:00 GMT</pubDate><guid>http://www.cppblog.com/Shihira/archive/2012/07/24/183204.html</guid><wfw:comment>http://www.cppblog.com/Shihira/comments/183204.html</wfw:comment><comments>http://www.cppblog.com/Shihira/archive/2012/07/24/183204.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Shihira/comments/commentRss/183204.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Shihira/services/trackbacks/183204.html</trackback:ping><description><![CDATA[<h3>一、上一节的代码</h3>
<div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->&nbsp; &nbsp; &nbsp; &nbsp; agg::rendering_buffer&nbsp;&amp;rbuf&nbsp;=&nbsp;rbuf_window();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;agg::pixfmt_rgb24&nbsp;pixf(rbuf);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;agg::renderer_base&lt;agg::pixfmt_rgb24&gt;&nbsp;renb(pixf);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;renb.clear(agg::rgba8(255,&nbsp;255,&nbsp;255));<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pixf.copy_pixel(20,&nbsp;20,&nbsp;agg::rgba8(0,&nbsp;0,&nbsp;255));</div>
</div>
<div></div>
<h3>二、渲染缓存</h3>
<img src="http://www.cppblog.com/images/cppblog_com/shihira/3.png" border="0" alt="" width="392" height="193" />
<div>渲染缓存保存着一个个像素，作为AGG的画布。它仅仅是一个内存块，用来储存像素信息，不提供任何绘图功能，只允许你读取和修改里面的数据。它也不告诉你里面的像素是灰度的、RGB的还是RGBA的，不告诉你从哪里到哪里是一个像素&#8212;&#8212;它只是用来管理内存数据的。</div>
<h4>头文件</h4>
<div><span style="color: #0000ff; ">#include</span> "platform/agg_platform_support.h"</div>
<h4>类型定义</h4>
<div><span style="color: #0000ff; ">typedef</span> row_accessor&lt;int8u&gt; rendering_buffer //int8u是8 bit无符号整形</div>
<h4>基本成员函数</h4>
<div>
<ul>
     <li><span style="color: #000080; "><strong>rendering_buffer</strong></span><span style="color: #000080; ">(int8u* buf, unsigned width, unsigned height, int stride)</span>&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;构造函数，指定事先分配好的内存块（到时就画到上面）首地址、宽高、一行的字节数（默认全部都是0）；</li>
     <li><span style="color: #000080; "><strong>row_ptr</strong>(int y)</span><br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;返回第y行的首地址；</li>
     <li><span style="color: #000080; "><strong>copy_from</strong>(void *buf)</span> <br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;从buf中拷贝像素；</li>
     <li><span style="color: #000080; "><strong>clear</strong>(int8u value)</span> <br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;用value清空缓存</li>
     <li><span style="color: #000080; "><strong>buf</strong>(), <strong>height</strong>(), <strong>weight</strong>(), <strong>stride</strong>()</span><br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;返回缓存首地址、宽高、一行的字节数；</li>
</ul>
</div>
<div><span style="color: red; ">注：代码中的rbuf_window()是platform_support的一个成员函数，用于返回platform_support一开始帮你申请的缓存引用。</span></div>
<div></div>
<h3>三、混合器</h3>
<div>混合器的存在是为了适应不同平台、不同需求下的不同像素格式。混合器有三种：<strong>agg::rgba</strong>，<strong>agg::rgba8</strong>和<strong>agg::rgba16</strong>，都是用来指定颜色的，rgba每个通道储存为double，rgba8为unsigned char，rgba16为int或long int；混合器起到的作用就像Win32API里的RGB和COLORREF宏。</div>
<h4>头文件</h4>
<div><span style="color: #0000ff; ">#include</span> "agg_pixfmt_rgba.h"</div>
<h4>类型定义</h4>
<div><span style="color: #0000ff; ">struct</span> rgba8; //对，你没有看错，是结构，不是类&#8230;&#8230;</div>
<h4>基本成员函数</h4>
<div>
<ul>
     <li><span style="color: #000080; "><strong>rgba8</strong>(unsigned r, unsigned g, unsigned b, unsigned a)</span> <br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;无须解释了吧，最大255；</li>
     <li><span style="color: #000080; "><strong>clear</strong>(), <strong>no_color</strong>()</span><br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;四个通道全部清零，也就是变没色咯；</li>
     <li><span style="color: #000080; "><strong>transparent</strong>()</span> <br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;alpha清零，变透明；</li>
     <li><span style="color: #000080; "><strong>opacity</strong>()</span><br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;返回透明度，用double表示；</li>
     <li><span style="color: #000080; "><strong>gradient</strong>(agg::rgba8 &amp;c, double k) </span><br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;颜色梯度，就是颜色变为从原先的颜色渐变为c，变化率为k；</li>
     <li><span style="color: #000080; "><strong>add</strong>(agg::rgba8 &amp;c, unsinged cover)</span> <br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;颜色叠加，叠加一个透明度为cover/255的颜色c；</li>
</ul>
</div>
<h4>成员变量</h4>
<div>
<ul>
     <li>r, g, b, a都是无符号整型；</li>
</ul>
</div>
<div></div>
<h3>四、像素格式混合器</h3>
<div><img src="http://www.cppblog.com/images/cppblog_com/shihira/4.png" border="0" alt="" width="445" height="251" /><br />
像素格式混合器的作用是直接操作像素（也就是缓存里保存的数据，但起码有个像素的样子），起到Win32API里的SetPixel()和GetPixel()的作用。像素格式由两个属性决定：混合器类型<strong>【agg::rgba8/agg::rgba16】</strong>、bgr/rgb/rgba/abgr顺序<strong>【agg::order_bgr/agg::order_rgb/agg::order_rgba/agg::order_abgr】</strong>&#8212;&#8212;这样，共8种像素格式，它们起名字的规则就是：</div>
<blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;">
<div><span style="color: #003300; ">agg::pixfmt_[order][bits*3];</span></div>
</blockquote>
<div>下面用最常用的agg::pixfmt_rgb24来解释：</div>
<h4>头文件</h4>
<div><span style="color: #0000ff; ">#include</span> "agg_pixfmt_rgb.h"</div>
<h4>类型定义</h4>
<div><span style="color: #0000ff; ">typedef</span> pixfmt_alpha_blend_rgb&lt;blender_rgb&lt;rgba8, &nbsp;order_rgb&gt;, rendering_buffer&gt; pixfmt_rgb24;</div>
<h4>基本成员函数</h4>
<div>
<ul>
     <li><span style="color: #000080; "><strong>pixfmt_rgb24</strong>(agg::rendering_buffer &amp;)&nbsp;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; 构造函数，指定缓存就好；</li>
     <li><span style="color: #000080; "><strong>blend_pixel</strong>(agg::rgba8&amp; c, int x, int y, int8u cover)</span> <br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;用颜色c以cover（覆盖率=透明度）的透明度混合像素(x, y)；</li>
     <li><span style="color: #000080; "><strong>copy_pixel</strong>(agg::rgba8&amp; c, int x, int y)，pixel(int x, int y)</span> <br />&nbsp; &nbsp; &nbsp; &nbsp; 这个就是相当于SetPixel()和GetPixel()了；</li>
     <li><span style="color: #000080; "><strong>copy_hline</strong>(int x, int y, unsigned len, agg::rgba8&amp; c)</span> <br />
     <span style="color: #000080; "><strong>copy_vline</strong>(int x, int y, unsigned len, agg::rgba8&amp; c)</span>&nbsp;&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;从(x, y)开始打横（竖）顺序设置len长度的像素；</li>
     <li><span style="color: #000080; "><strong>blend_hline</strong>(int x, int y， unsigned len, agg::rgba8&amp; c, int8u cover)<br />
     </span><span style="color: #000080; "><strong>blend_vline</strong>(int x, int y， unsigned len, agg::rgba8&amp; c, int8u cover)</span>&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;从(x, y)开始打横（竖）顺序混合len长度的像素；</li>
     <li><span style="color: #000080; "><strong>copy_solid_hspan</strong>(int x, int y， unsigned len, agg::rgba8* colors)</span> <br />
     <span style="color: #000080; "><strong>copy_solid_vspan</strong>(int x, int y， unsigned len, agg::rgba8* colors)<br />
     </span><span style="color: #000080; "><strong>blend_solid_hspan</strong>(int x, int y， unsigned len, agg::rgba8* colors, int8u* cover, int8u cover)<br />
     </span><span style="color: #000080; "><strong>blend_solid_vspan</strong>(int x, int y， unsigned len, agg::rgba8* colors, int8u* cover, int8u cover)</span><br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;同上两个，不过不是一个颜色，是一系列的颜色；</li>
     <li><span style="color: #000080; "><strong>for_each_pixel</strong>(void (*f)(agg::rgba8* color))</span><br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;每一像素执行一遍f；</li>
     <li><span style="color: #000080; "><strong>copy_from</strong>(agg::rendering_buffer &amp; from, int xdst, int ydst, int xsrc, int ysrc, unsigned len)<br />
     </span><span style="color: #000080; "><strong>blend_from</strong>(agg::rendering_buffer &amp; from, int xdst, int ydst, int xsrc, int ysrc, unsigned len[, unsigned cover])</span>&nbsp;&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;从缓存form中(xsrc, ysrc)顺序复制（混合）到当前缓存的(xdst, ydst)中；</li>
</ul>
</div>
<div>【其他函数和像素格式就要靠大家的举一反三，触类旁通了&#8230;&#8230;】</div>
<div>
</div>
<h3>五、结语</h3>
<div>上面说的三者关系是：混合器混合RGBA四个通道，像素格式混合器混合像素，像素格式混合器操作的结果是使渲染缓存里的数据发生变化，而混合器则不会，因为它的作用仅仅是表示颜色。</div><img src ="http://www.cppblog.com/Shihira/aggbug/183204.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Shihira/" target="_blank">Shihira</a> 2012-07-24 16:29 <a href="http://www.cppblog.com/Shihira/archive/2012/07/24/183204.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AGG入门（三） - 渲染器介绍</title><link>http://www.cppblog.com/Shihira/archive/2012/07/24/183117.html</link><dc:creator>Shihira</dc:creator><author>Shihira</author><pubDate>Tue, 24 Jul 2012 08:28:00 GMT</pubDate><guid>http://www.cppblog.com/Shihira/archive/2012/07/24/183117.html</guid><wfw:comment>http://www.cppblog.com/Shihira/comments/183117.html</wfw:comment><comments>http://www.cppblog.com/Shihira/archive/2012/07/24/183117.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Shihira/comments/commentRss/183117.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Shihira/services/trackbacks/183117.html</trackback:ping><description><![CDATA[<h3>一、看回AGG入门（二）时on_draw()虚函数里的代码：</h3>
<div>
<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->&nbsp; &nbsp; &nbsp; &nbsp; agg::rendering_buffer&nbsp;&amp;rbuf&nbsp;=&nbsp;rbuf_window();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;agg::pixfmt_rgb24&nbsp;pixf(rbuf);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;agg::renderer_base&lt;agg::pixfmt_rgb24&gt;&nbsp;renb(pixf);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;renb.clear(agg::rgba8(255,&nbsp;255,&nbsp;255));<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pixf.copy_pixel(20,&nbsp;20,&nbsp;agg::rgba8(0,&nbsp;0,&nbsp;255));</div>
</div>
<div></div>
<h3>二、渲染器</h3>
<h4>什么是渲染？</h4>
<div>渲染是把内存中的绘图指令真正执行的过程。比如说，绘制一条线段，在内存里只会保存着两个端点的坐标和线段的宽度，而渲染就把这两个端点转换为位图、缓存甚至显示屏上的一个个像素的数据。又比如说，纸飞机下面肯定是要有投影的了，但这个投影的质量，就由渲染器决定；线段是走样的（A），还是反走样的（B），靠的就是渲染器的指令了。<br />
<img src="http://www.cppblog.com/images/cppblog_com/shihira/20120713-1.png" border="0" alt="" width="392" height="193" /><br />
<img src="http://www.cppblog.com/images/cppblog_com/shihira/20120713-2.png" border="0" alt="" width="460" height="193" /></div>
<h4>AGG里的渲染器</h4>
<div>AGG分有多种渲染器。在AGG中，渲染器负责表现扫描线中的每个线段。在渲染器之前，AGG图形中的线段是没有颜色值的，只是位置、长度和 覆盖率（透明度）。渲染器赋于线段色彩，最终成为一幅完整的图像。其中最常用的是：</div>
<div>
<ul>
     <li>像素格式渲染器</li>
     <li>基础渲染器</li>
     <li>扫描线（反锯齿）渲染器</li>
</ul>
</div>
<div></div>
<h3>三、三种渲染器间的关系</h3>
<div>
<ul>
     <li>像素格式渲染器（PixelFormat Renderer）是最基础的渲染器，不需要任何其他渲染器的支持，所以可以直接声明；</li>
     <li>基础渲染器（Base Renderer）是中级渲染器，需要像素格式作为模版和像素格式渲染器的支持;</li>
     <li>扫描线渲染器（Scanline Renderer）是高级渲染器，需要基础渲染器作为模版和支持;</li>
</ul>
</div>
<div>（注：模版主要是为了获取像素格式的信息）</div>
<div></div>
<blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;">
<div>所以，除像素格式渲染器声明为：<br />
<span style="color: #008000; ">agg::class object(agg::rendering_buffer &amp;);</span><br />之外其他的渲染器都声明为：</div><div>
<span style="color: #008000; ">agg::class&lt;template&gt; object(template &amp;);</span></div>
</blockquote>
<div></div><img src ="http://www.cppblog.com/Shihira/aggbug/183117.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Shihira/" target="_blank">Shihira</a> 2012-07-24 16:28 <a href="http://www.cppblog.com/Shihira/archive/2012/07/24/183117.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>