AGG (Anti-Grain Geometry) の agg::render_scanlines を使って図形描画のシンプルなサンプルを書いてみた。


#include <stdio.h>
#include <string.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>
 
bool write_ppm(const unsigned char* buf, int width, int height, const char* file_name){
  FILE* fd = fopen(file_name, "wb");
  if(fd){
    fprintf(fd, "P6 %d %d\n", width, height);
    fprintf(fd, "255\n");
    int num = width * height;
    for(int i=0; i<num; i++){
      fwrite(buf, 1, 3, fd);
      buf+=4;
    }
    fclose(fd);
    return true;
  }
  return false;
}
 
void print_bytes(const unsigned char* buf, int width, int height){
  for(int y=0; y<height; y++){
    for(int x=0; x<width; x++){
      int i = (width * y + x) * 4;
      printf("%03d,%03d = %3d,%3d,%3d,%3d\n", x, y, buf[i], buf[i+1], buf[i+2], buf[i+3]);
    }
  }
}
 
int main(){
 
  int frame_width = 400;
  int frame_height = 300;
  int bytes_per_pixel = 4;
 
  agg::int8u* buffer = new agg::int8u[frame_width * frame_height * bytes_per_pixel];
  memset(buffer, 255, frame_width * frame_height * bytes_per_pixel);
 
  agg::rendering_buffer rbuf(buffer, frame_width, frame_height, frame_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);
  }
 
  print_bytes(buffer, frame_width, frame_height);
  write_ppm(buffer, frame_width, frame_height, "agg_render_scanlines.ppm");
 
  delete [] buffer;
  return 0;
}

コンパイルして実行。


$ g++ -I/usr/local/include/agg2 -L/usr/local/lib -lagg ./aggrendererscanlines.cpp
$ ./a.out

出力された ppm 画像を ToyViewer for Mac OS X という画像ビューアで表示したところ。

Anti-Grain Geometry (libagg): agg::render_scanlines

Anti-Grain Geometry - agg_math_stroke.h によると線描画の形状パラメータは以下のようになってる。


    //-------------------------------------------------------------line_cap_e
    enum line_cap_e
    {
        butt_cap,
        square_cap,
        round_cap
    };
 
    //------------------------------------------------------------line_join_e
    enum line_join_e
    {
        miter_join         = 0,
        miter_join_revert  = 1,
        round_join         = 2,
        bevel_join         = 3,
        miter_join_round   = 4
    };
 
 
    //-----------------------------------------------------------inner_join_e
    enum inner_join_e
    {
        inner_bevel,
        inner_miter,
        inner_jag,
        inner_round
    };

ちなみに、環境。

- Mac OS X Snow Leopard
- GCC 4.2.1
- AGG 2.5


$ uname -mrsv
Darwin 10.8.0 Darwin Kernel Version 10.8.0: Tue Jun  7 16:33:36 PDT 2011; root:xnu-1504.15.3~1/RELEASE_I386 i386
 
$ gcc --version
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
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.
 
$ ls -la /usr/local/include/ | grep agg
lrwxr-xr-x   1 hoge    admin   33 12 27 16:50 agg2 -> ../Cellar/libagg/2.5/include/agg2

Ref.
- Anti-Grain Geometry -
- Anti-Grain Geometry - Conversion Pipeline Demonstration
- Anti-Grain Geometry - agg_renderer_scanline.h
- Anti-Grain Geometry - agg_conv_stroke.h

tags: agg

Posted by NI-Lab. (@nilab)