テキストから升目状の図を描く
裁ち合わせの問題の図を描くために,以下のようなテキスト入力で,同じ文字の箇所を同じ色にした升目状の図を描くプログラムを作成してみた.
AAAAABBBBBFFF AMAEABDBDBDJF AAAEABDBDBDJF HHHEEEDDDDDJF GGHECECCCKIJF GHHECECLCKIJI GGGGCCCLCKIII
プログラム char2svg.pl
SVG (Scalable Vector Graphics)用のPerlライブラリ libsvg-perlを利用した.
Ubuntuでは,「apt-get install libsvg-perl 」でインストールできる.マニュアルは「man SVG::Manual」で参照できる.
#!/usr/bin/perl use strict; use SVG; use Getopt::Std; $| = 1; use vars qw($opt_h $opt_w $opt_c); &getopts("hw:c"); if ($opt_h) { &usage(); } my @colors = ( "#ff0000", "#00ff00", "#0000ff", # A B C "#ffff00", "#ff00ff", "#00ffff", # D E F "#c08000", "#c00080", "#80c000", # G H I "#00c080", "#8000c0", "#0080c0", # J K L "#c04040", "#40c040", "#4040c0", # M N O "#808000", "#800080", "#008080", # P Q R "#800000", "#008000", "#000080", # S T U ); my ($rows, $cols, @data); my (%region); &read_data(); my (@hline, @vline); foreach my $i (1 .. $rows-2) { foreach my $j (1 .. $cols-2) { my $c = $data[$i][$j]; next if &empty($c); if ($data[$i][$j] ne $data[$i-1][$j]) { $hline[$i][$j]{$c}++; } if ($data[$i][$j] ne $data[$i+1][$j]) { $hline[$i+1][$j]{$c}++; } if ($data[$i][$j] ne $data[$i][$j-1]) { $vline[$i][$j]{$c}++; } if ($data[$i][$j] ne $data[$i][$j+1]) { $vline[$i][$j+1]{$c}++; } } } my $width = $opt_w || 640; my $size = int($width / $cols); $width = $size * $cols; my $height = $size * $rows; my %color; my $k = 0; foreach my $c (sort keys %region) { $color{$c} = $colors[$k % scalar(@colors)]; $k++; } &write_svg(); exit 0; sub usage { print "Usage: $0 [options]\n"; print "-h : Help\n"; exit(1); } sub read_data { @data = (); $rows = 0; $cols = 0; while (<>) { chomp; my @x = split(//, $_); if (@x > $cols) { $cols = @x; } foreach my $c (@x) { if (! &empty($c)) { $region{$c}++; } } $data[$rows] = \@x; $rows++; } if (! &empty_row(\@data, 0, $cols)) { unshift(@data, []); $rows++; } if (! &empty_row(\@data, $rows-1, $cols)) { push(@data, []); $rows++; } if (! &empty_col(\@data, $rows, 0)) { foreach my $i (0 .. $rows-1) { unshift(@{$data[$i]}, " "); } $cols++; } if (! &empty_col(\@data, $rows, $cols-1)) { foreach my $i (0 .. $rows-1) { push(@{$data[$i]}, " "); } $cols++; } foreach my $i (0 .. $rows-1) { foreach my $j (0 .. $cols-1) { if (&empty($data[$i][$j])) { $data[$i][$j] = " "; } } } } sub write_svg { my $svg = SVG->new("width"=>$width, "height"=>$height, "-encoding"=>"UTF-8"); if ($opt_c) { foreach my $i (0 .. $rows-1) { foreach my $j (0 .. $cols-1) { my $c = $data[$i][$j]; next if &empty($c); my $x = $size * $j; my $y = $size * $i; my $color = $color{$c}; $svg->rect(x=>$x, y=>$y, width=>$size, height=>$size, style=>{fill=>$color, stroke=>"none",}); } } } foreach my $i (0 .. $rows-1) { foreach my $j (0 .. $cols-1) { my $c = $data[$i][$j]; my $x1 = $size * $j; my $y1 = $size * $i; my ($x2, $y2) = ($x1+$size, $y1); if ($hline[$i][$j]) { $svg->line(x1=>$x1, y1=>$y1, x2=>$x2, y2=>$y2, style=>"fill:none; stroke:#000000; stroke-width:1"); } elsif (! &empty($c)) { $svg->line(x1=>$x1+1, y1=>$y1, x2=>$x2-1, y2=>$y2, style=>"fill:none; stroke:#c0c0c0; stroke-width:1"); } ($x2, $y2) = ($x1, $y1+$size); if ($vline[$i][$j]) { $svg->line(x1=>$x1, y1=>$y1, x2=>$x2, y2=>$y2, style=>"fill:none; stroke:#000000; stroke-width:1"); } elsif (! &empty($c)) { $svg->line(x1=>$x1, y1=>$y1+1, x2=>$x2, y2=>$y2-1, style=>"fill:none; stroke:#c0c0c0; stroke-width:1"); } } } print $svg->xmlify, "\n"; } sub empty_row { my ($d, $i, $cols) = @_; foreach my $j (0 .. $cols-1) { if (! &empty($d->[$i][$j])) { return 0; } } return 1; } sub empty_col { my ($d, $rows, $j) = @_; foreach my $i (0 .. $rows-1) { if (! &empty($d->[$i][$j])) { return 0; } } return 1; } sub empty { my ($c) = @_; return ! $c || $c eq " "; }
使い方
以下の内容のテキストファイル file.in を作成する.
AAAAABBBBBFFF AMAEABDBDBDJF AAAEABDBDBDJF HHHEEEDDDDDJF GGHECECCCKIJF GHHECECLCKIJI GGGGCCCLCKIII J HHH BBB E E CCC AAA FFF GGG DDD J H B E E C A F G G M D J KHH BBB EEE CCC AAA F GII DDD J K B E C A A F G I D J KLL BBB E CCC AAA F III DDD
char2svg.plのプログラムを上の入力に対して実行する.
$ char2svg.pl -c file.in >file.svg
作成されたSVGファイルをInkscape等で開けば,編集できる.
また,以下のようにすればPNGファイルに変換できる.
$ inkscape -z -e file.png file.svg