class Potracer::Trace

This class represents a trace of a Potracer::Bitmap

Public Class Methods

bitmap(bmp, width = nil, height = nil, map = 'RGB', &block) click to toggle source

Trace a bitmap

Attributes

  • bmp - mapped to a Potracer::Bitmap either a multi-dimensional array of bits or a string of image data

  • width - width of the image to be mapped if bmp is a string

  • height - height of the image to be mapped if bmp is a string

  • map - pixel data format if bmp is a string

  • block - optional block called to report trace progress

Example

require 'ruby-progressbar'

pbar = ProgressBar.create(title: 'Tracing')
Potracer::Trace.bitmap(bits) do |percent|
  pbar.progress = percent
end
pbar.finish
# File lib/potracer.rb, line 53
def self.bitmap(bmp, width = nil, height = nil, map = 'RGB', &block)
  trace = new
  params = Potracer::Params.new
  bits = make_bits(bmp, width, height, map)

  if block_given?
    trace.trace(bits, params, &block)
  else
    trace.trace(bits, params)
  end
  trace
end

Public Instance Methods

to_a click to toggle source

Convert the traced bitmap to an array in the form:

[
  {:area=>25, :sign=>"+", :parts=> [
    [:moveto, 0.0, 2.5],
    [:curveto, 0.0, 0.5, 0.5, 0.0, 2.5, 0.0],
    [:curveto, 4.5, 0.0, 5.0, 0.5, 5.0, 2.5],
    [:curveto, 5.0, 4.5, 4.5, 5.0, 2.5, 5.0],
    [:curveto, 0.5, 5.0, 0.0, 4.5, 0.0, 2.5]
  ]},
  {:area=>9, :sign=>"-", :parts=> [
    [:moveto, 4.0, 2.5],
    [:curveto, 4.0, 1.6749999999999998, 3.325, 1.0, 2.5, 1.0],
    [:curveto, 1.6749999999999998, 1.0, 1.0, 1.6749999999999998, 1.0, 2.5],
    [:curveto, 1.0, 3.325, 1.6749999999999998, 4.0, 2.5, 4.0],
    [:curveto, 3.325, 4.0, 4.0, 3.325, 4.0, 2.5]
  ]}
]
static VALUE
trace_as_array (VALUE klass)
{
  VALUE rpath, rparts;
  VALUE result = rb_ary_new();
  potrace_path_t *path;
  int i, num_segments, *tag;
  potrace_dpoint_t (*c)[3];
  potrace_state_t *trace = NULL;
  Data_Get_Struct(klass, potrace_state_t, trace);

  if (trace->status == POTRACE_STATUS_OK) {
    path = trace->plist;
    while (path != NULL) {
      rparts = rb_ary_new();
      num_segments = path->curve.n;
      tag = path->curve.tag;
      c = path->curve.c;
      MOVE_TO(rparts, c[num_segments-1][2]);
      for (i = 0; i < num_segments; i++) {
        switch (tag[i]) {
        case POTRACE_CORNER:
          LINE_TO(rparts, c[i][1]);
          LINE_TO(rparts, c[i][2]);
          break;
        case POTRACE_CURVETO:
          CURVE_TO(rparts, c[i]);
          break;
        }
      }
      rpath = rb_hash_new();
      rb_hash_aset(rpath, STRSYM("area"), rb_int_new(path->area));
      rb_hash_aset(rpath, STRSYM("sign"), rb_str_new2(path->sign == '+' ? "+" : "-"));
      rb_hash_aset(rpath, STRSYM("parts"), rparts);
      rb_ary_push(result, rpath);
      path = path->next;
    }
  }

  return result;
}
to_svg click to toggle source

Render the traced bitmap as an SVG

Example

bmp = Potracer::Bitmap.new(5, 5, [
  [1, 1, 1, 1, 1],
  [1, 0, 0, 0, 1],
  [1, 0, 0, 0, 1],
  [1, 0, 0, 0, 1],
  [1, 1, 1, 1, 1]
])
params = Potracer::Params.new
trace = Potracer::Trace.new
trace.trace(bmp, params).to_svg # =>
# <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="5" height="5">
#   <path fill-rule="evenodd" fill="rgb(0,0,0)" d="M 0.000000 2.500000 C 0.000000 0.500000 0.500000 0.000000 2.500000 0.000000C 4.500000 0.000000 5.000000 0.500000 5.000000 2.500000C 5.000000 4.500000 4.500000 5.000000 2.500000 5.000000C 0.500000 5.000000 0.000000 4.500000 0.000000 2.500000M 4.000000 2.500000 C 4.000000 1.675000 3.325000 1.000000 2.500000 1.000000C 1.675000 1.000000 1.000000 1.675000 1.000000 2.500000C 1.000000 3.325000 1.675000 4.000000 2.500000 4.000000C 3.325000 4.000000 4.000000 3.325000 4.000000 2.500000" />
# </svg>"
static VALUE
trace_as_svg (VALUE klass)
{
  FILE *out = tmpfile();
  char *out_buffer;
  long size;
  VALUE svg;
  potrace_path_t *path;
  int i, num_segments, *tag;
  potrace_dpoint_t (*c)[3];
  potrace_state_t *trace = NULL;
  Data_Get_Struct(klass, potrace_state_t, trace);

  fprintf(out, "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\"");
  fprintf(out, " width=\"%d\" height=\"%d\">",
          NUM2INT(rb_iv_get(klass, "@width")),
          NUM2INT(rb_iv_get(klass, "@height")));
  fprintf(out, "<path fill-rule=\"evenodd\" fill=\"rgb(0,0,0)\" d=\"");
  if (trace->status == POTRACE_STATUS_OK) {
    path = trace->plist;
    while (path != NULL) {
      num_segments = path->curve.n;
      tag = path->curve.tag;
      c = path->curve.c;
      SVG_MOVE_TO(out, c[num_segments-1][2]);
      for (i = 0; i < num_segments; i++) {
        switch (tag[i]) {
        case POTRACE_CORNER:
          SVG_LINE_TO(out, c[i][1]);
          SVG_LINE_TO(out, c[i][2]);
          break;
        case POTRACE_CURVETO:
          SVG_CURVE_TO(out, c[i]);
          break;
        }
      }
      path = path->next;
    }
  }
  fprintf(out, "\" /></svg>");

  size = ftell(out);
  out_buffer = ALLOC_N(char, size);
  rewind(out);
  fread(out_buffer, 1, size, out);
  fclose(out);
  svg = rb_str_new(out_buffer, size);
  xfree(out_buffer);
  return svg;
}
trace(bitmap = nil, params = nil, &block) click to toggle source

Trace the given bitmap

Attributes

  • bitmap - an instance of Potracer::Bitmap. If not given the +@bitmap+ is used.

  • params - an instance of Potracer::Params. If not given +@params+ is used.

  • block - optional block called to report trace progress

# File lib/potracer.rb, line 23
def trace(bitmap = nil, params = nil, &block)
  if block_given?
    do_trace(bitmap || @bitmap, params || @params, &block)
  else
    do_trace(bitmap || @bitmap, params || @params)
  end
end