Anti-Grain Geometry Tutorial
tutorial_image_1.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_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_image_filter_rgba.h>
27 #include <agg_span_interpolator_linear.h>
28 
29 #include "path.h"
30 #include "writepng.h"
31 
34 
35 void
36 drawImage(RendererBaseType& dst, RendererBaseType& src, int x, int y, int width, int height)
37 {
38  typedef agg::span_interpolator_linear<agg::trans_affine> InterpolatorType;
39  typedef agg::image_accessor_clip<PixelFormat> ImageAccessorType;
41  typedef agg::span_allocator<agg::rgba8> SpanAllocatorType;
42 
43  const agg::rgba8 transparentWhiteColor (0xff, 0xff, 0xff, 0);
44 
45  double srcWidth = src.width();
46  double srcHeight = src.height();
47 
48  // compute the matrix that would transform from the src
49  // to the dst drawing area
50  agg::trans_affine matrix;
51  matrix.scale(width / srcWidth, height / srcHeight);
52  matrix.translate(x, y);
53 
54  // from the matrix, compute the invert matrix. It will
55  // be the lookup of src pixels from the dst location.
56  agg::trans_affine invertMatrix (matrix);
57  invertMatrix.invert();
58 
59  InterpolatorType interpolator (invertMatrix);
60  ImageAccessorType ia (src.ren(), transparentWhiteColor);
61  SpanGeneratorType sg (ia, interpolator);
62 
63  double rect[] =
64  {
65  (double)x, (double)y,
66  (double)x + width, (double)y,
67  (double)x + width, (double)y + height,
68  (double)x, (double)y + height,
69  (double)x, (double)y
70  };
71 
72  // The target region to draw the image.
73  SimplePath path(rect, sizeof(rect) / sizeof(double));
74 
76  agg::scanline_p8 scanline;
77  SpanAllocatorType sa;
78 
79  ras.reset();
80  ras.add_path(path);
81  agg::render_scanlines_aa(ras, scanline, dst, sa, sg);
82 }
83 
84 int
85 main (int argc, const char* argv[])
86 {
87  try
88  {
89  const int iconWidth = 200;
90  const int iconHeight = 200;
91  const int imageWidth = 400;
92  const int imageHeight = 400;
93 
94  const agg::rgba8 transparentWhiteColor (0xff, 0xff, 0xff, 0);
95  const agg::rgba8 whiteColor (0xff, 0xff, 0xff, 0xff);
96 
98  ras.auto_close(false);
99 
100  agg::scanline_p8 scanline;
101 
102  const int pixelSize = PixelFormat::pix_width;
103 
104  agg::rendering_buffer iconRenderBuffer;
105  PixelFormat iconPixFmt;
106  RendererBaseType iconRBase;
107 
108  const double PI = 3.14159265358979;
109  // Allocate a 50 x 50 rgba buffer
110  unsigned char *iconImageBuffer = new unsigned char[iconWidth * iconHeight * pixelSize];
111 
113  // Draw a simple color wheel icon
115  {
116  iconRenderBuffer.attach (iconImageBuffer, iconWidth, iconHeight, iconWidth * pixelSize);
117  iconPixFmt.attach(iconRenderBuffer);
118  iconRBase.attach(iconPixFmt);
119 
120  iconRBase.clear(transparentWhiteColor);
121 
122  // draw a big white circle
123  {
124  agg::ellipse circle (100, 100, 95, 95);
125  ras.reset();
126  ras.add_path(circle);
127  agg::render_scanlines_aa_solid(ras, scanline, iconRBase, whiteColor);
128  }
129 
130  // draw a small color wheel
131  double triangle[] =
132  {
133  0, 0,
134  -20, -90,
135  20, -90,
136  0, 0
137  };
138  agg::rgba8 colors[] =
139  {
140  { 0xfe, 0xfe, 0x33, 0xff },
141  { 0xfb, 0x99, 0x02, 0xff },
142  { 0xfa, 0xbc, 0x02, 0xff },
143  { 0xfe, 0x27, 0x12, 0xff },
144  { 0xfd, 0x53, 0x08, 0xff },
145  { 0x86, 0x01, 0xaf, 0xff },
146  { 0xa7, 0x19, 0x4b, 0xff },
147  { 0x02, 0x47, 0xfe, 0xff },
148  { 0x3d, 0x01, 0xa4, 0xff },
149  { 0x66, 0xb0, 0x32, 0xff },
150  { 0x03, 0x91, 0xce, 0xff },
151  { 0xd0, 0xea, 0x2b, 0xff }
152  };
153  SimplePath path (triangle, sizeof(triangle) / sizeof(double));
154 
155  int numRotations = sizeof(colors) / sizeof(agg::rgba8);
156  for (int i = 0; i < numRotations; ++i)
157  {
158  agg::trans_affine matrix;
159  matrix.rotate( PI * 2 * i / numRotations);
160  matrix.translate(100, 100);
161  agg::conv_transform<SimplePath> tp (path, matrix);
162 
163  ras.reset();
164  ras.add_path(tp);
165 
166  agg::render_scanlines_aa_solid(ras, scanline, iconRBase, colors[i]);
167  }
168 
169  // draw a small white circle
170  {
171  agg::ellipse innerCircle (100, 100, 40, 40);
172  ras.reset();
173  ras.add_path(innerCircle);
174  agg::render_scanlines_aa_solid(ras, scanline, iconRBase, whiteColor);
175  }
176 
177  // now write the icon out for visualization
178  char fileName[1000] = { 0 };
179  if (argc > 1)
180  {
181  sprintf (fileName, "%s/", argv[1]);
182  }
183  strcat(fileName, "tutorial_image_icon.png");
184  writePng<RendererBaseType> (fileName, iconRBase);
185  }
186 
187  agg::rendering_buffer renderBuffer;
188  PixelFormat pixFmt;
189  RendererBaseType rBase;
190 
191  // Allocate a 100 x 100 rgba buffer
192  unsigned char *imageBuffer = new unsigned char[imageWidth * imageHeight * pixelSize];
193 
194  // Hook everything up
195  renderBuffer.attach (imageBuffer, imageWidth, imageHeight, imageWidth * pixelSize);
196  pixFmt.attach(renderBuffer);
197  rBase.attach(pixFmt);
198 
199  const agg::rgba8 greenColor (0, 0xff, 0, 0xff);
200 
201  // clear the buffer with green color
202  rBase.clear(greenColor);
203 
205  // Stamp the image icon
207  {
208  drawImage (rBase, iconRBase, 0, 0, 25, 25);
209  drawImage (rBase, iconRBase, 25, 25, 50, 50);
210  drawImage (rBase, iconRBase, 75, 75, 100, 100);
211  drawImage (rBase, iconRBase, 175, 175, 200, 200);
212  }
213 
214  // now write the image out for visualization
215  char fileName[1000] = { 0 };
216  if (argc > 1)
217  {
218  sprintf (fileName, "%s/", argv[1]);
219  }
220  strcat(fileName, "tutorial_image_1.png");
221  writePng<RendererBaseType> (fileName, rBase);
222 
223  delete iconImageBuffer;
224  delete imageBuffer;
225  }
226  catch (TutorialException& ex)
227  {
228  printf ("%s\n", ex.getMessage());
229  return 1;
230  }
231  catch (...)
232  {
233  printf ("Unknown exception detected.\n");
234  return 1;
235  }
236 
237  return 0;
238 }