Anti-Grain Geometry Tutorial
tutorial_image_2.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 <agg_conv_stroke.h>
17 #include <agg_conv_transform.h>
18 #include <agg_ellipse.h>
19 #include <agg_image_accessors.h>
20 #include <agg_path_storage.h>
21 #include <agg_pixfmt_rgba.h>
22 #include <agg_rasterizer_scanline_aa.h>
23 #include <agg_renderer_base.h>
24 #include <agg_renderer_scanline.h>
25 #include <agg_scanline_p.h>
26 #include <agg_span_allocator.h>
27 #include <agg_span_image_filter_rgba.h>
28 #include <agg_span_interpolator_linear.h>
29 
30 #include "path.h"
31 #include "writepng.h"
32 
35 
36 template<class Path>
37 void
38 drawImage(RendererBaseType& dst, RendererBaseType& src, const agg::trans_affine& matrix, Path& path)
39 {
40  typedef agg::span_interpolator_linear<agg::trans_affine> InterpolatorType;
41  typedef agg::image_accessor_clip<PixelFormat> ImageAccessorType;
43  typedef agg::span_allocator<agg::rgba8> SpanAllocatorType;
44 
45  const agg::rgba8 transparentWhiteColor (0xff, 0xff, 0xff, 0);
46 
47  double srcWidth = src.width();
48  double srcHeight = src.height();
49 
50  // from the matrix, compute the invert matrix. It will
51  // be the lookup of src pixels from the dst location.
52  agg::trans_affine invertMatrix (matrix);
53  invertMatrix.invert();
54 
55  InterpolatorType interpolator (invertMatrix);
56  ImageAccessorType ia (src.ren(), transparentWhiteColor);
57  SpanGeneratorType sg (ia, interpolator);
58 
60  agg::scanline_p8 scanline;
61  SpanAllocatorType sa;
62 
63  ras.reset();
64  ras.add_path(path);
65  agg::render_scanlines_aa(ras, scanline, dst, sa, sg);
66 }
67 
68 int
69 main (int argc, const char* argv[])
70 {
71  try
72  {
73  const int iconWidth = 200;
74  const int iconHeight = 200;
75  const int imageWidth = 800;
76  const int imageHeight = 200;
77 
78  const agg::rgba8 transparentWhiteColor (0xff, 0xff, 0xff, 0);
79  const agg::rgba8 whiteColor (0xff, 0xff, 0xff, 0xff);
80 
82  ras.auto_close(false);
83 
84  agg::scanline_p8 scanline;
85 
86  const int pixelSize = PixelFormat::pix_width;
87 
88  agg::rendering_buffer iconRenderBuffer;
89  PixelFormat iconPixFmt;
90  RendererBaseType iconRBase;
91 
92  const double PI = 3.14159265358979;
93 
94  unsigned char *iconImageBuffer = new unsigned char[iconWidth * iconHeight * pixelSize];
95 
97  // Draw a simple color wheel icon
99  {
100  iconRenderBuffer.attach (iconImageBuffer, iconWidth, iconHeight, iconWidth * pixelSize);
101  iconPixFmt.attach(iconRenderBuffer);
102  iconRBase.attach(iconPixFmt);
103 
104  iconRBase.clear(transparentWhiteColor);
105 
106  // draw a big white circle
107  {
108  agg::ellipse circle (100, 100, 95, 95);
109  ras.reset();
110  ras.add_path(circle);
111  agg::render_scanlines_aa_solid(ras, scanline, iconRBase, whiteColor);
112  }
113 
114  // draw a small color wheel
115  double triangle[] =
116  {
117  0, 0,
118  -20, -90,
119  20, -90,
120  0, 0
121  };
122  agg::rgba8 colors[] =
123  {
124  { 0xfe, 0xfe, 0x33, 0xff },
125  { 0xfb, 0x99, 0x02, 0xff },
126  { 0xfa, 0xbc, 0x02, 0xff },
127  { 0xfe, 0x27, 0x12, 0xff },
128  { 0xfd, 0x53, 0x08, 0xff },
129  { 0x86, 0x01, 0xaf, 0xff },
130  { 0xa7, 0x19, 0x4b, 0xff },
131  { 0x02, 0x47, 0xfe, 0xff },
132  { 0x3d, 0x01, 0xa4, 0xff },
133  { 0x66, 0xb0, 0x32, 0xff },
134  { 0x03, 0x91, 0xce, 0xff },
135  { 0xd0, 0xea, 0x2b, 0xff }
136  };
137  SimplePath path (triangle, sizeof(triangle) / sizeof(double));
138 
139  int numRotations = sizeof(colors) / sizeof(agg::rgba8);
140  for (int i = 0; i < numRotations; ++i)
141  {
142  agg::trans_affine matrix;
143  matrix.rotate( PI * 2 * i / numRotations);
144  matrix.translate(100, 100);
145  agg::conv_transform<SimplePath> tp (path, matrix);
146 
147  ras.reset();
148  ras.add_path(tp);
149 
150  agg::render_scanlines_aa_solid(ras, scanline, iconRBase, colors[i]);
151  }
152 
153  // draw a small white circle
154  {
155  agg::ellipse innerCircle (100, 100, 40, 40);
156  ras.reset();
157  ras.add_path(innerCircle);
158  agg::render_scanlines_aa_solid(ras, scanline, iconRBase, whiteColor);
159  }
160 
161  // now write the icon out for visualization
162  char fileName[1000] = { 0 };
163  if (argc > 1)
164  {
165  sprintf (fileName, "%s/", argv[1]);
166  }
167  strcat(fileName, "tutorial_image_icon.png");
168  writePng<RendererBaseType> (fileName, iconRBase);
169  }
170 
171  agg::rendering_buffer renderBuffer;
172  PixelFormat pixFmt;
173  RendererBaseType rBase;
174 
175  // Allocate a 100 x 100 rgba buffer
176  unsigned char *imageBuffer = new unsigned char[imageWidth * imageHeight * pixelSize];
177 
178  // Hook everything up
179  renderBuffer.attach (imageBuffer, imageWidth, imageHeight, imageWidth * pixelSize);
180  pixFmt.attach(renderBuffer);
181  rBase.attach(pixFmt);
182 
183  const agg::rgba8 greenColor (0, 0xff, 0, 0xff);
184 
185  // clear the buffer with green color
186  rBase.clear(greenColor);
187 
189  // Stamp the image icon
191  {
192  double rect[] =
193  {
194  0, 0,
195  0, 200,
196  200, 200,
197  200, 0,
198  0, 0
199  };
200  // draw the image as is at left
201  {
202  SimplePath rectPath (rect, sizeof(rect) / sizeof(double));
203  agg::trans_affine matrix;
204  drawImage (rBase, iconRBase, matrix, rectPath);
205  }
206 
207  // create a donut shape
208  agg::path_storage path;
209  {
210  agg::ellipse outerRing (100, 100, 100, 100);
211  path.concat_path(outerRing);
212  path.arrange_orientations(0, agg::path_flags_cw);
213 
214  agg::path_storage tmpPath;
215  agg::ellipse innerRing (100, 100, 35, 35);
216  tmpPath.concat_path(innerRing);
217  tmpPath.arrange_orientations(0, agg::path_flags_ccw);
218  path.concat_path(tmpPath);
219  }
220 
221  // draw the icon image with a hole in the middle
222  {
223  agg::trans_affine matrix;
224  matrix.translate(200, 0);
225  agg::conv_transform<agg::path_storage> tp (path, matrix);
226  drawImage (rBase, iconRBase, matrix, tp);
227  }
228 
229  // draw a sheared donut
230  {
231  double shx = -2.0;
232  agg::trans_affine matrix(1.0, 0.0, shx, 1.0, 0.0, 0.0);
233  matrix.translate(700, 0);
234  agg::conv_transform<agg::path_storage> tp (path, matrix);
235  drawImage (rBase, iconRBase, matrix, tp);
236  }
237  }
238 
239  // now write the image out for visualization
240  char fileName[1000] = { 0 };
241  if (argc > 1)
242  {
243  sprintf (fileName, "%s/", argv[1]);
244  }
245  strcat(fileName, "tutorial_image_2.png");
246  writePng<RendererBaseType> (fileName, rBase);
247 
248  delete iconImageBuffer;
249  delete imageBuffer;
250  }
251  catch (TutorialException& ex)
252  {
253  printf ("%s\n", ex.getMessage());
254  return 1;
255  }
256  catch (...)
257  {
258  printf ("Unknown exception detected.\n");
259  return 1;
260  }
261 
262  return 0;
263 }