I had fun today playing with GD.pm and quilting patterns. In "nine blocks" there are 9 squares, whose contents are limited to 16 basic patterns and radial symetry.
Here's a sample output: 3x3
The idea comes from this guy who has done some amazing artistry with Flash programming. While he has open-sourced his code, I don't have access to Macromedia products so I built it from the specs on that web page.
I'm currently planning to print out a whole lot of them on a sheet of photographic paper, as a present for a quilter.
It's got problems with it, but it's a start.
#!/usr/bin/perl
# nineblocks.pl - create assorted quilt patterns using 16 graphical primitives
# and radial symetry.
# Copyright (C) 2004 Daniel Allen. It is distributed under the same
# terms as Perl itself. See the "Artistic License" in the Perl
# source code distribution for licensing terms.
# inspired by http://www.complexification.net/gallery/machines/nineblock/
use warnings;
use strict;
use GD;
my $XS = 20; # dimensions of squares in pixels
my $XN = $XS*5; # dimensions of nineblocks in pixels
my $dim = 10; # number of squares wide/tall
my $border = $XN/2;
my @squares = (
"",
".5,1 1,1 1,.5",
".5,.5 .5,1 1,.5",
"0,0 .5,.5 1,0",
"0,.5 1,.5, .5,0",
".5,.5 .5,1 1,1 1,.5",
".25,.25 .25,.75 .75,.75 .75,.25",
"0,1 .5,1 .5,.5 1,.5 1,0",
"0,.5 1,1 .5,0",
"0,0 .25,.5 .5,0 1,0 .75,.5 .5,0",
# "0,0 .25,.5 .5,0 1,0 .75,.5 .5,0 .5,1, + .25,.5 .75,.5",
"0,0 0,.5 1,1 .5,0",
".5,0 .5,1 1,1 1,0",
"0,.5 .5,1 1,.5 .5,0",
"0,0 .5,1 1,0",
"0,1 1,1 1,0",
"0,0 1,0 1,1 0,1"
);
my @centers = (
"",
".25,.25 .25,.75 .75,.75 .75,.25",
"0,.5 .5,1 1,.5 .5,0",
"0,0 1,0 1,1 0,1"
);
my $image = new GD::Image($dim * $XN, $dim * $XN);
my $white = $image->colorAllocate(255,255,255); # background
my $xpos = 0;
my $ypos = 0;
OUT: while (1) {
my $block = &nineblock(&r(3), &r(3), &r(15), &r(15), &r(3));
$image->copy($block, $xpos, $ypos, 0, 0, $XN, $XN);
$xpos += $XN;
if ($xpos > (($dim ) * $XN)) {
$xpos = 0;
$ypos += $XN;
if ($ypos > (($dim ) * $XN)) {
last OUT;
}
}
}
# nineblocks are at left-top corner of their background
# (which might be useful for colored backgrounds, but not for white)
#
# new background should be: + 2 * border - the total offset of each 9square
my $background = new GD::Image($dim*$XN + 2*$border - 2*$XN/5,
$dim*$XN + 2*$border - 2*$XN/5);
$white = $background->colorAllocate(255,255,255);
$background->copy($image, $border, $border, 0, 0, $dim * $XN, $dim * $XN);
&display($background);
sub r {
my ($max) = @_;
int rand $max;
}
sub nineblock {
# edgeRot = 0-3 ( times 90 degrees)
# cornerRot = 0-3
# edgeShape = 0-15
# cornerShape = 0-15
# centerShape = 0-3
my ($edgeRot, $cornerRot, $edgeShape, $cornerShape, $centerShape) = @_;
my $image = new GD::Image(3*$XS,3*$XS);
my $xpos = 0;
my @face = (&square($edgeRot, $squares[$edgeShape]),
&square($cornerRot, $squares[$cornerShape]));
my $center = &square(0, $centers[$centerShape]);
$image->copy($center,
$XS, $XS, 0, 0, $XS, $XS);
for (@face) {
my $square = $_;#6&square($_);
# $destimage->copy(srcImage, destX, destY, srcX, srcY, width, height)
#
# $destimage->copyResized(srcImage, destX, destY, srcX, srcY,
# destWidth, destHeight, srcWidth, srcHeight)
my $max = (2*$XS - $xpos);
$image->copy($square, $xpos, 0, 0, 0, $XS, $XS);
$image->copy($square->copyRotate90, 2*$XS, $xpos, 0, 0, $XS, $XS);
$image->copy($square->copyRotate180, $max, 2*$XS, 0, 0, $XS, $XS);
$image->copy($square->copyRotate270, 0, $max, 0, 0, $XS, $XS);
$xpos += $XS;
}
return $image;
}
sub square {
my ($rot, $points) = @_;
my $image = new GD::Image($XS,$XS);
my $polygon1 = new GD::Polygon;
#my $white = $image->colorAllocate(&r(255),0,&r(255));
my $white = $image->colorAllocate(255,255,255);
my $black = $image->colorAllocate(&r(255),0,&r(255));
#my $black = $image->colorAllocate(0,0,0);
&add_points($polygon1, $points);
$image->filledPolygon($polygon1, $black);
$image->flipVertical;
for (1 .. $rot) {
$image = $image->copyRotate90;
}
return $image;
}
sub add_points {
my ($poly, $points) = @_;
foreach my $pair (split /\s/, $points) {
$pair =~ /([\d.]+),([\d.]+)/;
$poly->addPt($1 * $XS, $2 * $XS);
}
}
sub display {
my ($image) = @_;
# 'display' program provided with ImageMagick
open OUTFILE, "| display -" or die "couldn't open display";
print OUTFILE $image->png;
close OUTFILE;
}