Anti-Grain Geometry Tutorial
tutorial_alphamask.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_alpha_mask_u8.h>
21 #include <agg_pixfmt_amask_adaptor.h>
22 #include <agg_pixfmt_rgba.h>
23 #include <agg_rasterizer_scanline_aa.h>
24 #include <agg_renderer_base.h>
25 #include <agg_renderer_scanline.h>
26 #include <agg_scanline_p.h>
27 #include <agg_scanline_u.h>
28 #include <agg_span_allocator.h>
29 #include <agg_span_interpolator_linear.h>
30 #include <agg_span_gradient.h>
31 #include <agg_blur.h>
32 
33 #include "path.h"
34 #include "writepng.h"
35 
38 
39 template<class SrcPixelFormat>
40 void
41 drawIcon(SrcPixelFormat& pixFmt, int x, int y, int width, int height)
42 {
43  agg::rendering_buffer renBuffer;
44  SrcPixelFormat dstPixFmt (renBuffer);
45  dstPixFmt.attach (pixFmt, x, y , x + width - 1, y + height - 1);
46  agg::renderer_base<SrcPixelFormat> rBase (dstPixFmt);
47 
49  ras.auto_close(false);
50  agg::scanline_p8 scanline;
51 
52  // draw a purple circle
53  {
54  agg::ellipse circle (100, 100, 70, 70);
55 
56  agg::conv_stroke<agg::ellipse> strokePath (circle);
57 
58  double strokeWidth = 10.0;
59  strokePath.width(strokeWidth);
60  strokePath.line_cap(agg::butt_cap);
61  strokePath.line_join(agg::miter_join);
62  strokePath.miter_limit(strokeWidth);
63 
64  ras.reset();
65  ras.add_path(strokePath);
66  const agg::rgba8 purpleColor (0xee, 0, 0xcc, 0xcc);
67  agg::render_scanlines_aa_solid(ras, scanline, rBase, purpleColor);
68  }
69 
70  // draw a gradient button
71  {
72  typedef agg::gradient_linear_color<agg::rgba8> ColorFunctionType;
73  typedef agg::gradient_x GradientFunctionType;
74 
75  typedef agg::span_interpolator_linear<agg::trans_affine> InterpolatorType;
76  typedef agg::span_allocator<agg::rgba8> SpanAllocatorType;
78  InterpolatorType,
79  GradientFunctionType,
80  ColorFunctionType> SpanGradientType;
81 
82  agg::ellipse circle (30, 30, 30, 30);
83 
84  GradientFunctionType gradientFunction;
85  agg::trans_affine matrix;
86  matrix.translate (70, 70);
87 
88  agg::trans_affine invertMatrix (matrix);
89  invertMatrix.invert();
90  InterpolatorType interpolator (invertMatrix);
91 
92  ColorFunctionType colorFunction (agg::rgba8 (0xff, 0xd7, 0, 0xff),
93  agg::rgba8 (0xff, 0, 0, 0xff),
94  60);
95 
96  SpanGradientType sg (interpolator, gradientFunction, colorFunction, 0.0, 60.0);
97  SpanAllocatorType sa;
98 
99  agg::conv_transform<agg::ellipse> tp(circle, matrix);
100  ras.reset ();
101  ras.add_path(tp);
102 
103  agg::render_scanlines_aa(ras, scanline, rBase, sa, sg);
104  }
105 }
106 
107 template<class PixelFormat, class Path, class AlphaMaskType>
108 void
109 drawAMPath(PixelFormat& pixFmt, Path& path, const agg::rgba8& color, AlphaMaskType &alphaMask, int x, int y, int width, int height)
110 {
111  agg::rendering_buffer renBuffer;
112  PixelFormat subPixFmt (renBuffer);
113  subPixFmt.attach (pixFmt, x, y , x + width - 1, y + height - 1);
114 
116  typedef agg::renderer_base<AMPixelFormat> AMRendererBaseType;
117 
118  AMPixelFormat amPixFmt (subPixFmt, alphaMask);
119  AMRendererBaseType amRBase (amPixFmt);
121  amrs.color(color);
122 
124  ras.auto_close(false);
125  agg::scanline_p8 scanline;
126 
127  ras.reset();
128  ras.add_path(path);
129  agg::render_scanlines(ras, scanline, amrs);
130 }
131 
132 template<class PixFormat, class BlurType>
133 void
134 blurImage(PixFormat& pixFmt, int x, int y, int width, int height, BlurType& blur, double radius)
135 {
136  agg::rendering_buffer renBuffer;
137  PixFormat subPixFmt (renBuffer);
138  subPixFmt.attach (pixFmt, x, y , x + width - 1, y + height - 1);
139  blur.blur (subPixFmt, radius);
140 }
141 
142 int
143 main (int argc, const char* argv[])
144 {
145  try
146  {
147  const int imageWidth = 800;
148  const int imageHeight = 200;
149  const int iconWidth = 200;
150  const int iconHeight = 200;
151 
153  ras.auto_close(false);
154 
155  agg::scanline_p8 scanline;
156 
157  const int pixelSize = PixelFormat::pix_width;
158 
159  const double PI = 3.14159265358979;
160  const agg::rgba8 blackColor(0, 0, 0, 0xff);
161  const agg::rgba8 whiteColor (0xff, 0xff, 0xff, 0xff);
162  const agg::rgba8 transparentWhiteColor (0xff, 0xff, 0xff, 0);
163 
164  unsigned char *imageBuffer = new unsigned char[imageWidth * imageHeight * pixelSize];
165  agg::rendering_buffer renderBuffer (imageBuffer, imageWidth, imageHeight, imageWidth * pixelSize);
166  PixelFormat pixFmt (renderBuffer);
167  RendererBaseType rBase (pixFmt);
168  rBase.clear(whiteColor);
169 
170  unsigned char *iconBuffer = new unsigned char[iconWidth * iconHeight * pixelSize];
171  agg::rendering_buffer iconRenderBuffer (iconBuffer, iconWidth, iconHeight, iconWidth * pixelSize);
172  PixelFormat iconPixFmt (iconRenderBuffer);
173  RendererBaseType iconRBase (iconPixFmt);
174  iconRBase.clear(transparentWhiteColor);
175 
176  double square[] =
177  {
178  0, 0,
179  200, 0,
180  200, 200,
181  0, 200,
182  0, 0
183  };
184  SimplePath path (square, sizeof(square) / sizeof(double));
185 
186  {
187  drawIcon (pixFmt, 0, 0, 200, 200);
188 
189  drawIcon (iconPixFmt, 0, 0, 200, 200);
190 
191  typedef agg::alpha_mask_rgba32a AlphaMaskType;
192 
193  AlphaMaskType alphaMask (iconRenderBuffer);
194 
195  {
196  drawAMPath (pixFmt, path, blackColor, alphaMask, 200, 0, 200, 200);
197  }
198 
199  {
200  drawAMPath (pixFmt, path, blackColor, alphaMask, 400, 0, 200, 200);
202  blurImage (pixFmt, 400, 0, 200, 200, blur, 10);
203  }
204 
205  {
206  drawAMPath (pixFmt, path, blackColor, alphaMask, 600 + 5, 0 + 5, 200, 200);
208  blurImage (pixFmt, 600 + 5, 0 + 5, 200, 200, blur, 10);
209  drawIcon (pixFmt, 600, 0, 200, 200);
210  }
211  }
212 
213  // now write the image out for visualization
214  char fileName[1000] = { 0 };
215  if (argc > 1)
216  {
217  sprintf (fileName, "%s/", argv[1]);
218  }
219  strcat(fileName, "tutorial_alphamask.png");
220  writePng<RendererBaseType> (fileName, rBase);
221 
222  delete imageBuffer;
223  }
224  catch (TutorialException& ex)
225  {
226  printf ("%s\n", ex.getMessage());
227  return 1;
228  }
229  catch (...)
230  {
231  printf ("Unknown exception detected.\n");
232  return 1;
233  }
234 
235  return 0;
236 }