Anti-Grain Geometry Tutorial
tutorial_blur.cpp
1 /*
2  * Copyright (c) 2019 Heng Yuan
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <cstring>
17 #include <agg_conv_stroke.h>
18 #include <agg_conv_transform.h>
19 #include <agg_ellipse.h>
20 #include <agg_pixfmt_rgba.h>
21 #include <agg_rasterizer_scanline_aa.h>
22 #include <agg_renderer_base.h>
23 #include <agg_renderer_scanline.h>
24 #include <agg_scanline_p.h>
25 #include <agg_span_allocator.h>
26 #include <agg_span_interpolator_linear.h>
27 #include <agg_span_gradient.h>
28 #include <agg_blur.h>
29 
30 #include "path.h"
31 #include "writepng.h"
32 
35 
36 template<class SrcPixelFormat>
37 void
38 drawIcon(SrcPixelFormat& pixFmt, int x, int y, int width, int height)
39 {
40  agg::rendering_buffer renBuffer;
41  SrcPixelFormat dstPixFmt (renBuffer);
42  dstPixFmt.attach (pixFmt, x, y , x + width - 1, y + height - 1);
43  agg::renderer_base<SrcPixelFormat> rBase (dstPixFmt);
44 
46  ras.auto_close(false);
47  agg::scanline_p8 scanline;
48 
49  // draw a purple circle
50  {
51  agg::ellipse circle (100, 100, 70, 70);
52 
53  agg::conv_stroke<agg::ellipse> strokePath (circle);
54 
55  double strokeWidth = 10.0;
56  strokePath.width(strokeWidth);
57  strokePath.line_cap(agg::butt_cap);
58  strokePath.line_join(agg::miter_join);
59  strokePath.miter_limit(strokeWidth);
60 
61  ras.reset();
62  ras.add_path(strokePath);
63  const agg::rgba8 purpleColor (0xee, 0, 0xcc, 0xcc);
64  agg::render_scanlines_aa_solid(ras, scanline, rBase, purpleColor);
65  }
66 
67  // draw a gradient button
68  {
69  typedef agg::gradient_linear_color<agg::rgba8> ColorFunctionType;
70  typedef agg::gradient_x GradientFunctionType;
71 
72  typedef agg::span_interpolator_linear<agg::trans_affine> InterpolatorType;
73  typedef agg::span_allocator<agg::rgba8> SpanAllocatorType;
75  InterpolatorType,
76  GradientFunctionType,
77  ColorFunctionType> SpanGradientType;
78 
79  agg::ellipse circle (30, 30, 30, 30);
80 
81  GradientFunctionType gradientFunction;
82  agg::trans_affine matrix;
83  matrix.translate (70, 70);
84 
85  agg::trans_affine invertMatrix (matrix);
86  invertMatrix.invert();
87  InterpolatorType interpolator (invertMatrix);
88 
89  ColorFunctionType colorFunction (agg::rgba8 (0xff, 0xd7, 0, 0xff),
90  agg::rgba8 (0xff, 0, 0, 0xff),
91  60);
92 
93  SpanGradientType sg (interpolator, gradientFunction, colorFunction, 0.0, 60.0);
94  SpanAllocatorType sa;
95 
96  agg::conv_transform<agg::ellipse> tp(circle, matrix);
97  ras.reset ();
98  ras.add_path(tp);
99 
100  agg::render_scanlines_aa(ras, scanline, rBase, sa, sg);
101  }
102 }
103 
104 template<class PixFormat, class BlurType>
105 void
106 blurImage(PixFormat& pixFmt, int x, int y, int width, int height, BlurType& blur, double radius)
107 {
108  agg::rendering_buffer renBuffer;
109  PixFormat subPixFmt (renBuffer);
110  subPixFmt.attach (pixFmt, x, y , x + width - 1, y + height - 1);
111  blur.blur (subPixFmt, radius);
112 }
113 
114 int
115 main (int argc, const char* argv[])
116 {
117  try
118  {
119  const int imageWidth = 800;
120  const int imageHeight = 200;
121 
123  ras.auto_close(false);
124 
125  agg::scanline_p8 scanline;
126 
127  const int pixelSize = PixelFormat::pix_width;
128 
129  const double PI = 3.14159265358979;
130 
131  unsigned char *imageBuffer = new unsigned char[imageWidth * imageHeight * pixelSize];
132  agg::rendering_buffer renderBuffer (imageBuffer, imageWidth, imageHeight, imageWidth * pixelSize);
133  PixelFormat pixFmt (renderBuffer);
134  RendererBaseType rBase (pixFmt);
135 
136  const agg::rgba8 whiteColor (0xff, 0xff, 0xff, 0xff);
137  rBase.clear(whiteColor);
138 
139  {
140  drawIcon (pixFmt, 0, 0, 200, 200);
141 
142  {
143  drawIcon (pixFmt, 200, 0, 200, 200);
145  blurImage (pixFmt, 200, 0, 200, 200, blur, 10);
146  }
147 
148  {
149  drawIcon (pixFmt, 400, 0, 200, 200);
151  blurImage (pixFmt, 400, 0, 200, 200, blur, 10);
152  }
153 
154  {
155  drawIcon (pixFmt, 600 + 5, 0 + 5, 200, 200);
157  blurImage (pixFmt, 600 + 5, 0 + 5, 200, 200, blur, 10);
158 
159  drawIcon (pixFmt, 600, 0, 200, 200);
160  }
161  }
162 
163  // now write the image out for visualization
164  char fileName[1000] = { 0 };
165  if (argc > 1)
166  {
167  sprintf (fileName, "%s/", argv[1]);
168  }
169  strcat(fileName, "tutorial_blur.png");
170  writePng<RendererBaseType> (fileName, rBase);
171 
172  delete imageBuffer;
173  }
174  catch (TutorialException& ex)
175  {
176  printf ("%s\n", ex.getMessage());
177  return 1;
178  }
179  catch (...)
180  {
181  printf ("Unknown exception detected.\n");
182  return 1;
183  }
184 
185  return 0;
186 }