Anti-Grain Geometry Tutorial
tutorial_layer.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_image_accessors.h>
18 #include <agg_pixfmt_rgba.h>
19 #include <agg_rasterizer_scanline_aa.h>
20 #include <agg_renderer_base.h>
21 #include <agg_renderer_scanline.h>
22 #include <agg_scanline_p.h>
23 #include <agg_span_allocator.h>
24 #include <agg_span_image_filter_rgba.h>
25 #include <agg_span_interpolator_linear.h>
26 
27 #include "path.h"
28 #include "writepng.h"
29 
32 
35 
36 template<class RBaseType1, class RBaseType2>
37 void
38 drawImage(RBaseType1& dst, RBaseType2& src, int x, int y, int width, int height)
39 {
40  typedef agg::span_interpolator_linear<agg::trans_affine> InterpolatorType;
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  // compute the matrix that would transform from the src
51  // to the dst drawing area
52  agg::trans_affine matrix;
53  matrix.scale(width / srcWidth, height / srcHeight);
54  matrix.translate(x, y);
55 
56  // from the matrix, compute the invert matrix. It will
57  // be the lookup of src pixels from the dst location.
58  agg::trans_affine invertMatrix (matrix);
59  invertMatrix.invert();
60 
61  InterpolatorType interpolator (invertMatrix);
62  ImageAccessorType ia (src.ren(), transparentWhiteColor);
63  SpanGeneratorType sg (ia, interpolator);
64 
65  double rect[] =
66  {
67  (double)x, (double)y,
68  (double)x + width, (double)y,
69  (double)x + width, (double)y + height,
70  (double)x, (double)y + height,
71  (double)x, (double)y
72  };
73 
74  // The target region to draw the image.
75  SimplePath path(rect, sizeof(rect) / sizeof(double));
76 
78  agg::scanline_p8 scanline;
79  SpanAllocatorType sa;
80 
81  ras.reset();
82  ras.add_path(path);
83  agg::render_scanlines_aa(ras, scanline, dst, sa, sg);
84 }
85 
86 
87 int
88 main (int argc, const char* argv[])
89 {
90  try
91  {
92  const int imageWidth = 400;
93  const int imageHeight = 400;
94 
95 
96  const int pixelSize = PixelFormat::pix_width;
97 
98  agg::rendering_buffer renderBuffer;
99  PixelFormat pixFmt;
100  RendererBaseType rBase;
101 
102  unsigned char *imageBuffer = new unsigned char[imageWidth * imageHeight * pixelSize];
103 
104  // Hook everything up
105  renderBuffer.attach (imageBuffer, imageWidth, imageHeight, imageWidth * pixelSize);
106  pixFmt.attach(renderBuffer);
107  rBase.attach(pixFmt);
108 
109  const agg::rgba8 transparentWhiteColor (0xff, 0xff, 0xff, 0);
110  const agg::rgba8 greenColor (0, 0xff, 0, 0x7f);
111  const agg::rgba8 redColor (0xff, 0, 0, 0x7f);
112 
113  // clear the buffer with transparent white color
114  rBase.clear(transparentWhiteColor);
115 
117  agg::scanline_p8 scanline;
118 
119  ras.auto_close(false);
120 
121  // draw a red semi-transparent square in the middle
122  {
123  double centerSquare[] =
124  {
125  100, 100,
126  300, 100,
127  300, 300,
128  100, 300,
129  100, 100
130  };
131 
132  SimplePath path (centerSquare, sizeof(centerSquare) / sizeof(double));
133 
134  ras.reset();
135  ras.add_path(path);
136 
137  agg::render_scanlines_aa_solid(ras, scanline, rBase, redColor);
138  }
139 
140  double square[] =
141  {
142  50, 50,
143  150, 50,
144  150, 150,
145  50, 150,
146  50, 50
147  };
148 
149  SimplePath path (square, sizeof(square) / sizeof(double));
150 
151  // draw a green semi-transparent square at top left
152  {
153  ras.reset();
154  ras.add_path(path);
155 
156  agg::render_scanlines_aa_solid(ras, scanline, rBase, greenColor);
157  }
158 
159  // draw a layer without PRE at top right
160  {
161  agg::rendering_buffer layerBuffer;
162  PixelFormat layerPixFmt;
163  RendererBaseType layerRBase;
164 
165  unsigned char *layerImageBuffer = new unsigned char[200 * 200 * pixelSize];
166 
167  // Hook everything up
168  layerBuffer.attach (layerImageBuffer, 200, 200, 200 * pixelSize);
169  layerPixFmt.attach(layerBuffer);
170  layerRBase.attach(layerPixFmt);
171 
172  double square[] =
173  {
174  50, 50,
175  150, 50,
176  150, 150,
177  50, 150,
178  50, 50
179  };
180 
181  SimplePath path (square, sizeof(square) / sizeof(double));
182 
183  ras.reset();
184  ras.add_path(path);
185 
186  agg::render_scanlines_aa_solid(ras, scanline, layerRBase, greenColor);
187 
188  drawImage (rBase, layerRBase, 200, 0, 200, 200);
189  }
190 
191  // draw a PRE layer at bottom left
192  {
193  agg::rendering_buffer layerBuffer;
194  PrePixelFormat layerPixFmt;
195  PreRendererBaseType layerRBase;
196 
197  unsigned char *layerImageBuffer = new unsigned char[200 * 200 * pixelSize];
198 
199  // Hook everything up
200  layerBuffer.attach (layerImageBuffer, 200, 200, 200 * pixelSize);
201  layerPixFmt.attach(layerBuffer);
202  layerRBase.attach(layerPixFmt);
203 
204  double square[] =
205  {
206  50, 50,
207  150, 50,
208  150, 150,
209  50, 150,
210  50, 50
211  };
212 
213  SimplePath path (square, sizeof(square) / sizeof(double));
214 
215  ras.reset();
216  ras.add_path(path);
217 
218  agg::render_scanlines_aa_solid(ras, scanline, layerRBase, greenColor);
219 
220  drawImage (rBase, layerRBase, 0, 200, 200, 200);
221  }
222 
223  // now write the image out for visualization
224  char fileName[1000] = { 0 };
225  if (argc > 1)
226  {
227  sprintf (fileName, "%s/", argv[1]);
228  }
229  strcat(fileName, "tutorial_layer.png");
230  writePng<RendererBaseType> (fileName, rBase);
231 
232  delete imageBuffer;
233  }
234  catch (TutorialException& ex)
235  {
236  printf ("%s\n", ex.getMessage());
237  return 1;
238  }
239  catch (...)
240  {
241  printf ("Unknown exception detected.\n");
242  return 1;
243  }
244 
245  return 0;
246 }