AGG (Anti-Grain Geometry, libagg) には PNG を入出力する機能が無いので、そこだけ cairo の力を借りる。

cairo_surface_t を agg::rendering_buffer に接続して AGG の描画結果が cairo_surface_t のバッファに入るようにし、 cairo_surface_write_to_png で PNG ファイルを生成する。

以下、 [ヅ] agg::render_scanlines を使った図形描画のシンプルなサンプル のコードをベースにしてcairoでPNGを出力するサンプルコード。


#include <string>
#include <cairo/cairo.h>
#include <agg_color_rgba.h>
#include <agg_rendering_buffer.h>
#include <agg_pixfmt_rgb.h>
#include <agg_pixfmt_rgba.h>
#include <agg_renderer_base.h>
#include <agg_renderer_scanline.h>
#include <agg_rasterizer_scanline_aa.h>
#include <agg_scanline_p.h>
#include <agg_path_storage.h>
#include <agg_conv_stroke.h>
 
int main(){
 
  int width = 400;
  int height = 300;
  int bytes_per_pixel = 4;
 
  // create cairo surface  
  cairo_surface_t* surface;
  surface  = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
  unsigned char* data = cairo_image_surface_get_data(surface);
 
  // agg rendering buffer attaches cairo surface  
  agg::rendering_buffer rbuf;
  rbuf.attach(data, width, height, width * bytes_per_pixel);  
  
  agg::pixfmt_rgba32 pixf(rbuf);
  agg::renderer_base<agg::pixfmt_rgba32> rbase(pixf);
  agg::renderer_scanline_aa_solid<agg::renderer_base<agg::pixfmt_rgba32> > rs(rbase);
 
  rbase.clear(agg::rgba8(255, 255, 255));
  agg::rgba8 red(255, 0, 0, 255);
  agg::rgba8 green(0, 255, 0, 255);
  agg::rgba8 blue(0, 0, 255, 100);
  agg::rgba8 purple(255, 0, 255, 100);
 
  // fill polygon
  {
    agg::path_storage path;
    path.move_to(200,  50);
    path.line_to(100, 200);
    path.line_to(100, 250);
    path.line_to(150, 200);
    path.close_polygon();
    agg::rasterizer_scanline_aa<> ras;
    agg::scanline_p8 sl;
    ras.add_path(path);
    rs.color(agg::rgba8(0,255,0,100));
    agg::render_scanlines(ras, sl, rs);
  }
 
  // draw polygon
  {
    agg::path_storage path;
    path.move_to(150,  50);
    path.line_to(150, 200);
    path.line_to(300, 150);
    path.close_polygon();
    agg::conv_stroke<agg::path_storage> stroke(path);
    stroke.width(5.0);
    stroke.line_cap(agg::butt_cap);
    stroke.line_join(agg::miter_join);
    stroke.inner_join(agg::inner_miter);
    stroke.miter_limit(4.0);
    agg::rasterizer_scanline_aa<> ras;
    agg::scanline_p8 sl;
    ras.add_path(stroke);
    rs.color(agg::rgba8(0,0,255,100));
    agg::render_scanlines(ras, sl, rs);
  }
 
  // draw polyline
  {
    agg::path_storage path;
    path.move_to(100, 100);
    path.line_to(200, 100);
    path.line_to(200, 200);
    agg::conv_stroke<agg::path_storage> stroke(path);
    stroke.width(10.0);
    stroke.line_cap(agg::round_cap);
    stroke.line_join(agg::round_join);
    stroke.inner_join(agg::inner_round);
    agg::rasterizer_scanline_aa<> ras;
    agg::scanline_p8 sl;
    ras.add_path(stroke);
    rs.color(agg::rgba8(255,0,0,100));
    agg::render_scanlines(ras, sl, rs);
  }
 
  // save image
  std::string path = "aggcairo.png";
  cairo_status_t status = cairo_surface_write_to_png(surface, path.c_str());
 
  // delete cairo surface
  cairo_surface_destroy(surface);
 
  return 0;
}

コンパイルして実行。


$ g++ -I/usr/local/include/agg2 -I/usr/local/Cellar/cairo/1.10.2/include -L/usr/local/lib -L/usr/local/Cellar/cairo/1.10.2/lib -lagg -lcairo ./aggcairopng.cpp
$ ./a.out 

出力されたPNG画像ファイル。

AGG and cairo output a png file.

今回の環境は Mac OS X Lion.


$ uname -mrsv
Darwin 11.2.0 Darwin Kernel Version 11.2.0: Tue Aug  9 20:54:00 PDT 2011; root:xnu-1699.24.8~1/RELEASE_X86_64 x86_64
 
$ g++ --version
i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
$ brew info libagg
libagg 2.5
http://www.antigrain.com
Depends on: pkg-config, sdl
/usr/local/Cellar/libagg/2.5 (147 files, 2.3M)
http://github.com/mxcl/homebrew/commits/master/Library/Formula/libagg.rb
 
$ brew info cairo
cairo 1.10.2
http://cairographics.org/
 
This formula is keg-only.
Mac OS X already provides this program and installing another version in
parallel can cause all kinds of trouble.
 
The Cairo provided by Leopard is too old for newer software to link against.
 
Depends on: pkg-config, pixman
/usr/local/Cellar/cairo/1.10.2 (91 files, 6.5M)
http://github.com/mxcl/homebrew/commits/master/Library/Formula/cairo.rb

Ref.
- Anti-Grain Geometry -
- cairographics.org

tags: cairo agg

Posted by NI-Lab. (@nilab)