#!/usr/bin/perl -w use strict; use constant SIZE => 256; use constant SCALE => SIZE / 1024; # Edge definition (bezier curve control points in absolute coordinates). my @points = ( [100,900], [100,500],[600,300],[900,100], [1000,400],[700,600],[900,900], [600,1000],[500,900],[100,900] ); # Output image buffer. my $image = chr(0) x (SIZE * SIZE); # Interpolate between two values. sub interpolate($$$) { my ($a, $b, $t) = @_; return $a + ($b - $a) * $t; } # Syntactic sugar. sub min($$) { my ($a, $b) = @_; return $a < $b ? $a : $b; } sub max($$) { my ($a, $b) = @_; return $a > $b ? $a : $b; } # Draw outlined shape. sub draw_outline($) { my ($color) = @_; for(my $i = 0; $i + 3 < scalar @points; $i += 3) { my $x0 = SCALE * $points[$i][0]; my $x1 = SCALE * $points[$i + 1][0]; my $x2 = SCALE * $points[$i + 2][0]; my $x3 = SCALE * $points[$i + 3][0]; my $y0 = SCALE * $points[$i][1]; my $y1 = SCALE * $points[$i + 1][1]; my $y2 = SCALE * $points[$i + 2][1]; my $y3 = SCALE * $points[$i + 3][1]; for(my $j = 0; $j < (SIZE * 2); $j++) { my $t = $j / (SIZE * 2); my $x = interpolate(interpolate(interpolate($x0, $x1, $t), interpolate($x1, $x2, $t), $t), interpolate(interpolate($x1, $x2, $t), interpolate($x2, $x3, $t), $t), $t); my $y = interpolate(interpolate(interpolate($y0, $y1, $t), interpolate($y1, $y2, $t), $t), interpolate(interpolate($y1, $y2, $t), interpolate($y2, $y3, $t), $t), $t); my $ix = int($x); my $iy = int($y); if( $ix >= 0 && $ix < SIZE && $iy >= 0 && $iy < SIZE ) { substr($image, $iy * SIZE + $ix, 1) = $color; } } } } # Draw filled shape by scanlines. sub draw_scanlines() { my @ranges = (); for(my $i = 0; $i < SIZE; $i++) { push @ranges, [undef, undef]; } # Collect ranges. for(my $i = 0; $i + 3 < scalar @points; $i += 3) { my $x0 = SCALE * $points[$i][0]; my $x1 = SCALE * $points[$i + 1][0]; my $x2 = SCALE * $points[$i + 2][0]; my $x3 = SCALE * $points[$i + 3][0]; my $y0 = SCALE * $points[$i][1]; my $y1 = SCALE * $points[$i + 1][1]; my $y2 = SCALE * $points[$i + 2][1]; my $y3 = SCALE * $points[$i + 3][1]; for(my $j = 0; $j < SIZE * 2; $j++) { my $t = $j / (SIZE * 2); my $x = interpolate(interpolate(interpolate($x0, $x1, $t), interpolate($x1, $x2, $t), $t), interpolate(interpolate($x1, $x2, $t), interpolate($x2, $x3, $t), $t), $t); my $y = interpolate(interpolate(interpolate($y0, $y1, $t), interpolate($y1, $y2, $t), $t), interpolate(interpolate($y1, $y2, $t), interpolate($y2, $y3, $t), $t), $t); my $ix = int($x); my $iy = int($y); if( $ix >= 0 && $ix < SIZE && $iy >= 0 && $iy < SIZE ) { if( defined($ranges[$iy][0]) ) { $ranges[$iy][0] = min($ranges[$iy][0], $ix); $ranges[$iy][1] = max($ranges[$iy][1], $ix); } else { $ranges[$iy][0] = $ranges[$iy][1] = $ix; } } } } # Draw scanlines. for(my $y = 0; $y < SIZE; $y++) { if( defined($ranges[$y][0]) ) { my $w = $ranges[$y][1] - $ranges[$y][0] + 1; substr($image, $y * SIZE + $ranges[$y][0], $w) = chr(1) x $w; } } } draw_scanlines(); print "P1\n", SIZE, " ", SIZE, "\n"; for(my $y = 0; $y < SIZE; $y++) { foreach my $c (unpack "C*", substr($image, $y * SIZE, SIZE)) { print $c ? "0 " : "1 "; } print "\n"; }