﻿<?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://cppblog.com/Shihira/category/19614.html</link><description>Open source - 开放源代码 - 開放原始碼 - オープンソース - 오픈 소스 - Отворен код - متن‌باز</description><language>zh-cn</language><lastBuildDate>Wed, 12 Aug 2015 01:20:42 GMT</lastBuildDate><pubDate>Wed, 12 Aug 2015 01:20:42 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>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><item><title>AGG入门（一） - 配置开发环境</title><link>http://www.cppblog.com/Shihira/archive/2012/07/24/183033.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/183033.html</guid><wfw:comment>http://www.cppblog.com/Shihira/comments/183033.html</wfw:comment><comments>http://www.cppblog.com/Shihira/archive/2012/07/24/183033.html#Feedback</comments><slash:comments>13</slash:comments><wfw:commentRss>http://www.cppblog.com/Shihira/comments/commentRss/183033.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Shihira/services/trackbacks/183033.html</trackback:ping><description><![CDATA[<div>AGG是一个高效的、高质量的、开源的矢量图形库，类似的有：GTK+的Cairo，Microsoft的GDI+。在三者中，AGG的性能是最高的（不讨论Skia和Direct2D，他们有OGL和DX的硬件加速，绘图速度根本不是一个档次的）。让我们细数一下他的优缺点：</div>
<div></div>
<div>
<ul>
     <li>优点：效率高，质量高（有反锯齿），功能强大，跨平台和平台GUI支持，&#8230;&#8230;</li>
     <li>缺点：没有硬件加速，文档少，门槛有那么点高，&#8230;&#8230;</li>
</ul>
</div>
<div>&nbsp;</div>
<div></div>
<h3>一、准备</h3>
<div></div>
<div>
<ul>
     <li>到 <a href="http://www.antigrain.com/download/index.html">http://www.antigrain.com/download/index.html</a>下载源码包。</li>
     <li>今天用Visual C++ 6.0来做IDE和编译器啦！要多经典有多经典。</li>
</ul>
</div>
<div>&nbsp;</div>
<div></div>
<h3>二、工作</h3>
<div></div>
<div>
<ol>
     <li>在VC6里新建一个工程&#8220;AGG&#8221;，类型为静态库Win32 Static Library<br />
     <img src="http://www.cppblog.com/images/cppblog_com/shihira/20120712-1.png" border="0" alt="" width="420" height="70" /><br />
     </li>
     <li>将下列源文件都加入工程：<br />
     <img src="http://www.cppblog.com/images/cppblog_com/shihira/20120712-2.png" border="0" alt="" width="466" height="102" /><br />
     </li>
     <ol>
         <li><span style="color: #008000; ">./src/ 目录下所有cpp文件【核心库】*</span></li>
         <li><span style="color: #008000; ">./src/ctrl/ 目录下所有cpp文件【控件库】*</span></li>
         <li><span style="color: #008000; ">./src/platform/ 下对应平台目录（win32）下的所有cpp文件【平台支持库】*</span></li>
         <li><span style="color: #008000; ">./font_freetype/ 下所有的cpp文件【Freetype字体支持库】</span></li>
         <li><span style="color: #008000; ">./font_win32_tt/ 下所有的cpp文件【Truetype字体支持库】*</span></li>
         <li><span style="color: #008000; ">./gpc/ 下所有的cpp文件【Generic Polygon Clipper裁切库】<br />
         </span></li>
     </ol>
     <li>将下列目录加入Tools（工具）菜单&#8211; Options（选项）菜单 &#8211; Directory（目录）选项卡中的Include Files目录列表中：<br />
     <img src="http://www.cppblog.com/images/cppblog_com/shihira/20120712-3.png" border="0" alt="" /><br />
     </li>
     <ol>
         <li><span style="color: #008000; ">./include/ *</span></li>
         <li><span style="color: #008000; ">./font_freetype/</span></li>
         <li><span style="color: #008000; ">./font_win32_tt/ *</span></li>
         <li><span style="color: #008000; ">./gpc/</span></li>
     </ol>
     <li>选择配置为Win32 Release，编译<br />
     <img src="http://www.cppblog.com/images/cppblog_com/shihira/20120712-4.png" border="0" alt="" width="418" height="64" /><br />
     </li>
     <li>编译成功后，Tools（工具）菜单&#8211; Options（选项）菜单 &#8211; Directory（目录）选项卡中的Library Files目录列表中加入 【工程所在目录】\Release\<br />
     <img src="http://www.cppblog.com/images/cppblog_com/shihira/20120712-5.png" border="0" alt="" width="426" height="57" /><br />
     </li>
     <li> 没有成功编译的童鞋，奖励已经编译好的AGG.lib一枚&#8230;&#8230;&nbsp;<a href="/Files/Shihira/AGG.zip">AGG.zip</a><a></a></li>
</ol>
</div>
<div></div>
<h3>三、测试</h3>
<div></div>
<div>
<ol>
     <li>新建一个Win32 Application 空工程，新建一源文件，加入下面的代码：<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_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><br />
     &nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;}<br />
     <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;&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(204,&nbsp;204,&nbsp;204));<br />
     &nbsp;&nbsp;&nbsp;&nbsp;}<br />
     <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_rgb24,&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>
     </li>
<li>在【工程】菜单 - 【设置】菜单 - 【连接】选项卡 - 【对象/库模块】文本框 中加入AGG.lib</li>
<li>编译运行，不出意外，可以得到下面的结果：<br />
     <img src="http://www.cppblog.com/images/cppblog_com/shihira/20120712-6.png" border="0" alt="" width="385" height="129" /><br /></li>
</ol>
</div><img src ="http://www.cppblog.com/Shihira/aggbug/183033.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/183033.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/183046.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/183046.html</guid><wfw:comment>http://www.cppblog.com/Shihira/comments/183046.html</wfw:comment><comments>http://www.cppblog.com/Shihira/archive/2012/07/24/183046.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/Shihira/comments/commentRss/183046.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Shihira/services/trackbacks/183046.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"><span style="background-color: #eeeeee; font-size: 13px; ">#include&nbsp;</span><span style="background-color: #eeeeee; font-size: 13px; ">&lt;</span><span style="background-color: #eeeeee; font-size: 13px; ">platform</span><span style="background-color: #eeeeee; font-size: 13px; ">/</span><span style="background-color: #eeeeee; font-size: 13px; ">agg_platform_support.h</span><span style="background-color: #eeeeee; font-size: 13px; ">&gt;</span><br />
#include&nbsp;&lt;agg_pixfmt_rgb.h&gt;<br />
#include&nbsp;&lt;agg_renderer_base.h&gt;<br />
#include&nbsp;&lt;stdio.h&gt;<br />
<br />
#include&nbsp;&lt;agg_path_storage.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;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<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;&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;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">virtual</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;on_mouse_button_down(<span style="color: #0000FF; ">int</span>&nbsp;x,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;y,&nbsp;unsigned&nbsp;flags)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(flags&nbsp;==&nbsp;agg::mouse_left)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">char</span>&nbsp;str[50];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sprintf(str,&nbsp;"Mouse&nbsp;location:(%d,&nbsp;%d)",&nbsp;x,&nbsp;y);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message(str);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">virtual</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;on_key(<span style="color: #0000FF; ">int</span>&nbsp;x,&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;y,&nbsp;unsigned&nbsp;key,&nbsp;unsigned&nbsp;flags)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(key&nbsp;==&nbsp;agg::key_return&nbsp;&amp;&amp;&nbsp;flags&nbsp;==&nbsp;agg::kbd_shift)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;img&nbsp;=&nbsp;0,&nbsp;states;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;states&nbsp;=&nbsp;create_img(0,&nbsp;500,&nbsp;500);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;states&nbsp;=&nbsp;load_img(img,&nbsp;"Steve-and-Bill.bmp");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;copy_img_to_window(img);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;update_window();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<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_rgb24,&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>如果不出意外，在窗口中点击鼠标左键将会出现对话框提示当前鼠标的位置，而按下Shift+Enter将会在窗口中显示在工作目录下的位图&#8220;Steve-and-Bill.bmp&#8221;；
<br />
<img src="http://www.cppblog.com/images/cppblog_com/shihira/20120717-1.png" border="0" alt="" width="527" height="548" /></div>
<h3>二、解释</h3>
<div>先看看头文件：platform/agg_platform_support.h，它里边定义了一个platform_support类&#8212;&#8212;它允许你建立一个窗口来测试你的图形，并用鼠标键盘去控制它。
<h4>类型</h4>
<div>
<ul>
     <li>class platform_support&nbsp;</li>
</ul>
</div>
<h4>主要成员函数</h4>
<div>
<ul>
     <li>platform_support(pix_format_e, bool) : 构造函数。设置窗口风格和y轴是否上下翻转；</li>
     <li>width() ：返回窗口的宽；</li>
     <li>height() ：返回窗口的高；</li>
     <li>caption([ const char* ]) ：设置标题或返回标题字符串；</li>
     <li>format() ： 返回窗口风格；</li>
     <li>message(const char*) ：弹出对话框（没有风格可选）；</li>
     <li>run() ：运行窗口；</li>
     <li>force_redraw() ：重绘窗口，调用on_draw()；</li>
     <li>update_window() ：更新窗口，既是把渲染缓存中已有的内容写入窗口，不调用on_draw()。</li>
     <li><strong>platform_support为我们提供了一个很好地绘图平台，它有一系列的函数可用于操作位图（BMP或PPM）：
     </strong>
     <ul>
         <li>create_img()：创建一个编号为idx的位图；</li>
         <li>save_img()：将位图idx保存到文件中；</li>
         <li>load_img()：从文件中加载位图到idx中；</li>
         <li>copy_img_to_window()：把idx拷贝到渲染缓存里；</li>
         <li>copy_img_to_img()：把idx拷贝到另一幅位图里；</li>
         <li>copy_window_to_img() ：将渲染缓存里的内容拷贝到位图。</li>
     </ul>
     </li>
</ul>
</div>
<h4>虚函数（一般都是些消息，要覆盖它以让消息循环调用）</h4>
<div>
<ul>
     <li>on_init() ：窗口初始化时调用；</li>
     <li>on_resize(int, int) ：改变大小时调用；</li>
     <li>on_idle() &nbsp;：空闲时调用；</li>
     <li>on_mouse_move(int, int, unsigned) ：鼠标移动时调用；</li>
     <li>on_mouse_button_down(int, int, unsigned) ：鼠标按下时调用；</li>
     <li>on_mouse_button_up(int, int, unsigned) &nbsp;：鼠标弹起时调用；</li>
     <li>on_key(int, int, unsigned, unsigned) &nbsp;：键盘打字时调用；</li>
     <li>on_draw() &nbsp;：窗口重绘时调用。</li>
</ul>
</div>
<div></div>
<div></div>
<h3>三、结语</h3>
<div>platform_support 的功能不仅仅是这么多，除此之外，他还能使用控件，等等。但很多时候，成熟的应用是不会使用它的，因为它封装了太多，虽然保证了跨平台性，却缺乏了自由性。platform_support 的主要作用是测试图像和修改图像，方便工作和移植&#8230;&#8230;还有，方便初学者入门&#8230;&#8230;</div>
<div></div>
</div>
</div><img src ="http://www.cppblog.com/Shihira/aggbug/183046.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/183046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>