Add tartans

This commit is contained in:
Neale Pickett 2009-11-13 18:09:22 -06:00
parent d4ac728d0f
commit ec72794f6e
26 changed files with 616 additions and 0 deletions

View File

@ -6,4 +6,5 @@ SubInclude TOP papers ;
SubInclude TOP projects ; SubInclude TOP projects ;
SubInclude TOP poems ; SubInclude TOP poems ;
SubInclude TOP src ; SubInclude TOP src ;
SubInclude TOP tartans ;
SubInclude TOP toys ; SubInclude TOP toys ;

View File

@ -19,3 +19,9 @@ pre {
padding: 1em; padding: 1em;
border: solid black 1px; border: solid black 1px;
} }
.figure {
float: right;
padding: 0.5em;
font-size: small;
}

44
tartans/Jamfile Normal file
View File

@ -0,0 +1,44 @@
SubDir TOP tartans ;
TARTAN_TMPL = $(SUBDIR)/tartan.m4 ;
TARTANTOMDWN = $(SUBDIR)/tartantomdwn ;
LOOM = $(SUBDIR)/loom.py ;
rule Tartan {
local tartans = [ FGristFiles $(1:S=.tartan) ] ;
for t in $(tartans) {
local png = $(t:S=.png:D=img:G=) ;
local mdwn = $(t:S=.mdwn) ;
TartanToMdwn $(mdwn) : $(t) ;
TartanToPng $(png) : $(t) ;
Webify $(mdwn) ;
Depends $(mdwn:S=.html) : $(png) ;
}
}
rule TartanToMdwn {
Depends $(1) : $(2) $(TARTAN_TMPL) $(TARTANTOMDWN) ;
Clean clean : $(1) ;
MakeLocate $(1) : $(LOCATE_TARGET) ;
SEARCH on $(2) = $(SEARCH_SOURCE) ;
}
rule TartanToPng {
Depends $(1) : $(2) $(LOOM) ;
Clean clean : $(1) ;
MakeLocate $(1) : $(LOCATE_TARGET) ;
SEARCH on $(2) = $(SEARCH_SOURCE) ;
}
actions TartanToMdwn {
$(TARTANTOMDWN) $(1:S=) < $(2) > $(1)
}
actions TartanToPng {
$(LOOM) < $(2) > $(1)
}
Webify index.mdwn ;
Tartan albuquerque armstrong az blackwatch buchanan co nm nmloe nv ok pjs pjs2 shrek tx ut wa ;

View File

@ -0,0 +1,9 @@
Name: Albuquerque
Sett: R4 G24 B4 G10 B36 W6 R4 W4
Created by Ralph Stevenson Jr and Charles Hargis in 2005 for the city's
tricentennial anniversary (1706-2006). It is similar in design to the
[New Mexico tartan](nm), with a little less green, and white instead of
yellow, with a thicker center band.
[Bally Dun Celtic Treasures](http://www.ballydun.com/) sells this tartan.

2
tartans/armstrong.tartan Normal file
View File

@ -0,0 +1,2 @@
Name: Armstrong
Sett: G4 BK2 G60 BK24 B4 BK2 B2 BK2 B24 R6

6
tartans/az.tartan Normal file
View File

@ -0,0 +1,6 @@
Name: Arizona
Sett: W2 G3 R4 G28 B3 (963)8
Based on a jpeg I found on a geocities homepage. Surprisingly,
that jpeg was the only mention I could find on the net of what
the actual sett was for Arizona.

View File

@ -0,0 +1,4 @@
Name: Black Watch
Sett: B22 BK2 B2 BK2 B2 BK16 G16 BK2 G16 BK16 B16 BK2 B2BK2 G10 BK8 DB9 BK1 DB1
A standard.

4
tartans/buchanan.tartan Normal file
View File

@ -0,0 +1,4 @@
Name: Buchanan
Sett: Y8 BK2 Y8 BK2 B6 BK2 G8 B4 G8 BK2 B6 BK2 LR10 W2 LR10 BK2 B6 BK2 .
I typed in this one as an example of an asymmetric sett.

13
tartans/co.tartan Normal file
View File

@ -0,0 +1,13 @@
Name: Colorado
Sett: Y4 R6 (669)34 K40 G4 W6 LV6 W6 G22
Wikipedia lists the sett as `[Y/6] R4 MB26 K32 G4 W4 Lv4 W4 [G/44]`. I'm
not familiar with the [Color/Count] notation, the count appears to be
doubled, possibly to indicate the total count of that thread in the
mirror section.
[Colorado house joint resolution
97-1016](http://www.state.co.us/gov_dir/leg_dir/res/HJR1016.htm) makes
this official but doesn't provide a thread count. It speaks of
"cerulean blue" which I approximate with the unique (669) color.

88
tartans/design.cgi Executable file
View File

@ -0,0 +1,88 @@
#! /usr/bin/python
import cgitb; cgitb.enable()
import htmltmpl
import loom
import re
import sys
import cgi
import os
import rfc822
import urllib
import cStringIO as StringIO
var_re = re.compile('\$(\w+|{\w+})')
def fill_template(tmpl, **keywds):
def repl(match):
var = match.group(0)[1:]
var = var.strip('{}')
return keywds[var]
return var_re.sub(repl, tmpl)
def serve(s, c_t):
o = ('Content-type: %s\r\nContent-length: %d\r\n\r\n%s' %
(c_t, len(s), s))
sys.stdout.write(o)
f = cgi.FieldStorage()
s = f.getfirst('sett')
if s:
sett = loom.str_to_sett(s)
l = loom.tartan(sett)
p = StringIO.StringIO()
l.png(p)
serve(p.getvalue(), 'image/png')
else:
manager = htmltmpl.TemplateManager(precompile=0)
tmpl = manager.prepare('/home/neale/lib/wiki/templates/page.tmpl')
processor = htmltmpl.TemplateProcessor(html_escape=False)
t = os.environ.get('PATH_INFO', '').strip('/')
if not t:
t = f.getfirst('t', 'Unknown')
s = f.getfirst('s')
if t and not s:
try:
m = rfc822.Message(file('%s.tartan' % t))
t = m.get('Title', t)
s = m.get('Sett')
except IOError:
pass
if not t or not s:
# Default to Black Watch
t = 'Black Watch'
s = ('B22 BK2 B2 BK2 B2 BK16 G16 BK2 G16 BK16 B16 BK2 B2'
'BK2 G10 BK8 DB9 BK1 DB1')
s_st = s.replace(' ', '')
s_st = s_st.replace('\n' ,'')
content = '''
<ul style="background: white; float: right;">
<li><a href="design.cgi?sett=%(sett_compressed)s">image only</a></li>
<li><a href="/~neale/tartans">More tartans</a></li>
</ul>
<h2>woozle.org tartan designer</h2>
<form action="design" style="padding: 10px;">
<input name="t" value="%(tartan)s" />
<textarea name="s" rows="3" cols="40">%(sett)s</textarea> <br />
<input type="submit" value="Generate" />
</form>
<div style="background: url(design.cgi?sett=%(sett_compressed)s);
height: 400px;
border: solid black 40px;">
</div>
''' % {'tartan': t,
'sett': s,
'sett_compressed': urllib.quote(s_st)}
processor.set('title', t)
processor.set('content', content)
page = processor.process(tmpl)
serve(page, 'text/html')

22
tartans/index.mdwn Normal file
View File

@ -0,0 +1,22 @@
Title: Tartans
I like tartans, they appeal to my geeky need for symmetry and elegant
description.
<div class="figure">
<img src="img/nmloe.png" alt="tartan image" />
<br />
<a href="nmloe">
New Mexico Land Of Enchantment
</a>
<br />
LG8 LV32 R4 G32 LG32 Y4 LG4
</div>
I've written a [tartan designer](design) that will take a sett pattern
in modified xtartan format, and output a PNG image of said tartan. Below
are some tartans I've made with it.
If you have one you'd like to contribute to my database, or would like
the code that generates this stuff, feel free to [email
me](mailto:neale-tartan@woozle.org).

181
tartans/loom.py Executable file
View File

@ -0,0 +1,181 @@
#! /usr/bin/python
# coding: utf-8
import re
class Yarn:
"""A spool of yarn.
Color is specified as a 3-tuple (red, green, blue) of
saturation values ranging from 0.0 (no saturation) to
1.0 (full saturation).
"""
def __init__(self, r, g, b):
self.rgb = (r, g, b)
self.color = (int(r * 256), int(g * 256), int(b * 256))
def __repr__(self):
return '<Yarn %r>' % (self.rgb)
class Loom:
def __init__(self, warp):
self.warp = warp
self.fabric = []
def weave(self, yarn, up=1, down=1, skip=0, repeat=0):
offset = (len(self.fabric) / (repeat + 1)) * (skip + 1)
harnesses = up + down
row = []
for i in range(len(self.warp)):
j = (i + offset) % harnesses
if j < down:
row.append(self.warp[i])
else:
row.append(yarn)
self.fabric.append(row)
def plain_weave(self, yarn):
# AKA tabby weave, taffeta weave
self.weave(yarn)
def twill(self, yarn, up=2, down=2):
self.weave(yarn, up, down)
def satin_weave(self, yarn):
# 1/16, skip 4
self.weave(yarn, 1, 16, 4)
def basket_weave(self, yarn):
# 2/2, skip 1, repeat 1
self.weave(yarn, 2, 2, 1, 1)
class PNGLoom(Loom):
def png(self, outf, scale=1):
import Image
import array
imgstr = array.array('B')
for fr in self.fabric:
row = []
for c in fr:
for i in range(scale):
row.extend(c.color)
for i in range(scale):
imgstr.fromlist(row)
x = len(fr * scale)
y = len(self.fabric * scale)
img = Image.fromstring('RGB', (x, y), imgstr.tostring())
img.save(outf, 'PNG')
def ascii_test():
print 'Plain weave'
l = Loom('||||||||||||||||||||||||||||||||')
for i in range(16):
l.plain_weave('-')
for row in l.fabric:
print ' ', ''.join(row)
print 'Twill'
l = Loom('||||||||||||||||||||||||||||||||')
for i in range(16):
l.twill('-')
for row in l.fabric:
print ' ', ''.join(row)
print '2/1 twill'
l = Loom('||||||||||||||||||||||||||||||||')
for i in range(16):
l.twill('-', 2, 1)
for row in l.fabric:
print ' ', ''.join(row)
print 'Satin weave'
l = Loom('||||||||||||||||||||||||||||||||')
for i in range(16):
l.satin_weave('-')
for row in l.fabric:
print ' ', ''.join(row)
print 'Basketweave'
l = Loom('||||||||||||||||||||||||||||||||')
for i in range(16):
l.basket_weave('-')
for row in l.fabric:
print ' ', ''.join(row)
##
## Tartan junk
##
colors = {'R': Yarn(0.50, 0.00, 0.00), # Red
'G': Yarn(0.00, 0.30, 0.00), # Green
'B': Yarn(0.00, 0.00, 0.50), # Blue
'C': Yarn(0.00, 0.25, 0.25), # Cyan
'Y': Yarn(0.80, 0.80, 0.00), # Yellow
'P': Yarn(0.60, 0.00, 0.60), # Purple (?!)
'W': Yarn(0.60, 0.60, 0.60), # White
'K': Yarn(0.00, 0.00, 0.00), # Black
'BK': Yarn(0.00, 0.00, 0.00), # Black
'GR': Yarn(0.25, 0.25, 0.25), # Gray
'DB': Yarn(0.00, 0.00, 0.30), # Dark Blue
'LB': Yarn(0.00, 0.25, 0.60), # Light Blue
'LR': Yarn(0.60, 0.00, 0.00), # Light Red
'LG': Yarn(0.00, 0.60, 0.00), # Light Green
'LV': Yarn(0.50, 0.25, 0.60), # Lavender
'BR': Yarn(0.30, 0.25, 0.00), # Brown
'LGR': Yarn(0.60, 0.60, 0.60), # Light Gray
'LBR': Yarn(0.40, 0.40, 0.00), # Light Brown
}
sett_re = re.compile('([A-Za-z]{1,3}|\([A-Fa-f0-9]{3}\))(\d{1,3})')
def str_to_sett(s):
"""Convert an xtartan sett string into a sett tuple."""
sett = []
while s:
m = sett_re.search(s)
if not m:
break
cs = m.group(1)
if cs[0] == '(' and cs[-1] == ')':
ca = []
for a in cs[1:-1]:
ca.append(int(a+a, 16) / 256.0)
y = Yarn(*ca)
else:
y = colors[cs]
for i in range(int(m.group(2))):
sett.append(y)
s = s[m.end():]
if not s.endswith('.'):
o = sett[:]
o.reverse()
sett += o
return sett
def tartan(sett):
l = PNGLoom(sett)
for y in sett:
l.twill(y)
return l
if __name__ == '__main__':
import sys
for line in sys.stdin:
if line.startswith('Sett:'):
_, s = line.split(':', 1)
s = s.strip()
break
sett = str_to_sett(s)
l = tartan(sett)
l.png(sys.stdout, 1)

7
tartans/lstartans Executable file
View File

@ -0,0 +1,7 @@
#! /bin/sh
for i in "$@"; do
base=$(basename $i .tartan)
name=$(awk -F': ' '(/^Name:/) {print $2; exit;}' $i)
echo "* [$name]($base.html)"
done

10
tartans/nm.tartan Normal file
View File

@ -0,0 +1,10 @@
Name: New Mexico
Sett: R4 G24 B4 G16 B36 Y8 R4 Y4
Designed by Ralph Stevenson Jr, [officially recognized in 2003](nm-proc)
by the Secretary of State. It is similar in design to the [Albuquerque
tartan](albuquerque). I bought a scarf of this plaid from
Mr. Stevenson; it came with a photocopy of the tartan registration and a
few other documents.
[Bally Dun Celtic Treasures](http://www.ballydun.com/) sells this tartan.

7
tartans/nmloe.tartan Normal file
View File

@ -0,0 +1,7 @@
Name: New Mexico Land Of Enchantment
Sett: LG8 LV32 R4 G32 LG32 Y4 LG4
This isn't official but I think it's pretty. I just guessed at the
sett pattern but I think I got pretty close.
[Kathy Lare](http://www.kathyskilts.com/) is the sole source for this
fabric.

6
tartans/nv.tartan Normal file
View File

@ -0,0 +1,6 @@
Name: Nevada
Sett: W4 LGR16 B4 LGR8 B8 Y4 B4 R4 B20
Based on a terrible gif that is apparently a part of [Nevada Revised
Statute 235.130](http://leg.state.nv.us/NRS/NRS-235.html#NRS235Sec130).
Designed by Richard Zygmunt Pawlowski, approved May 8, 2001.

4
tartans/ok.tartan Normal file
View File

@ -0,0 +1,4 @@
Name: Oklahoma
Sett: R4 W8 LB64 Y6 BK16
Based on a photo on a web page.

7
tartans/pjs.tartan Normal file
View File

@ -0,0 +1,7 @@
Name: Neale's PJs
Sett: W7 C3 GR5 BK3 C5 BK3 C6 GR3 C5
This is an approximation of the pajamas I was wearing when I wrote the
tartan designer. They weren't actually a tartan. I guess modern
weavers feel they ought to show off the fact that they can do fancy
tricks with their looms.

5
tartans/pjs2.tartan Normal file
View File

@ -0,0 +1,5 @@
Name: Neale's PJs II
Sett: W3 G24 Y2 W2 G2 W2 G2 W1
More of my PJs. This one is an exact copy, I can count the threads
in this fabric.

6
tartans/shrek.tartan Normal file
View File

@ -0,0 +1,6 @@
Name: Shrek
Sett: LBR4 BR8 G16 R2 G16 BR32
I (Neale) created this based on Shrek's pants in a couple of frame grabs
from the movie. It appears to be different from the recently-released
"Shrek's Tartan".

21
tartans/tartan.m4 Normal file
View File

@ -0,0 +1,21 @@
Title: TARTAN Tartan
divert(1)
<div style="background: url(img/BASE.png);
height: 400px;
border: solid black 40px;
clear: both;">
</div>
I place this image in the public domain, in the hope that it will
increase interest in tartans and tartan design.
<form action="design.cgi">
<fieldset>
<legend>Tartan Designer</legend>
<label for="t">Name:</label> <input name="t" value="TARTAN" /> <br/>
<label for="s">Sett:</label> <input name="s" value="SETT" /> <br/>
<input type="submit" value="Design" />
</fieldset>
</form>
divert(0)

117
tartans/tartan.py Executable file
View File

@ -0,0 +1,117 @@
#! /usr/bin/python
import sys
import Image
import re
import array
colors = {'R': '\x88\x00\x00', # Red
'G': '\x00\x44\x00', # Green
'B': '\x00\x00\x44', # Blue
'C': '\x00\x44\x44', # Cyan
'Y': '\x99\x99\x00', # Yellow
'P': '\x99\x00\x99', # Purple (?!)
'W': '\x99\x99\x99', # White
'K': '\x00\x00\x00', # Black
'BK': '\x00\x00\x00', # Black
'GR': '\x44\x44\x44', # Gray
'DB': '\x00\x00\x55', # Dark Blue
'LB': '\x00\x44\x99', # Light Blue
'LR': '\x99\x00\x00', # Light Red
'LG': '\x00\x99\x00', # Light Green
'LV': '\x88\x44\x99', # Lavender
'BR': '\x55\x44\x00', # Brown
'LGR': '\x99\x99\x99', # Light Gray
'LBR': '\x66\x66\x00', # Light Brown
}
sett_re = re.compile('([A-Za-z]{1,3}|\([A-Fa-f0-9]{3}\))(\d{1,3})')
def str_to_sett(s):
"""Convert an xtartan sett string into a sett tuple."""
sett = []
while s:
m = sett_re.search(s)
if not m:
break
cs = m.group(1)
if cs[0] == '(' and cs[-1] == ')':
ca = array.array('B')
for a in cs[1:-1]:
ca.append(int(a+a, 16))
c = ca.tostring()
else:
c = colors[cs]
n = int(m.group(2))
sett.append((c, n))
s = s[m.end():]
if not s.endswith('.'):
o = sett[:]
o.reverse()
sett += o
return sett
class Loom:
"""Simulates a simple loom with only one weft color per row.
This probably does a simplistic weave too, I don't know enough about
weaving to say for sure. But I can imagine more complicated ways of
doing it.
"""
def __init__(self, warp):
self.warp = warp
self.cloth = []
self.row = 0
def weave(self, weft):
out = []
for i in range(len(self.warp)):
if (i + self.row) % 2 == 0:
out.append(weft)
else:
out.append(self.warp[i])
self.cloth.append(out)
self.row += 1
class Tartan:
def __init__(self, sett):
# Weave a whole pattern suitable for tiling. In other words, it
# does the mirroring for you.
if type(sett) == type(''):
sett = str_to_sett(sett)
warp = []
for c,n in sett:
warp += [c]*n
if False:
# Offset it to the center of the first dealie
o = sett[0][1] / 2
warp += warp[:o]
del warp[:o]
self.loom = Loom(warp)
for w in warp:
self.loom.weave(w)
rgbs = [''.join(x) for x in self.loom.cloth]
imgstr = ''.join(rgbs)
self.img = Image.fromstring('RGB',
(len(self.loom.cloth[1]),
len(self.loom.cloth)),
imgstr)
def png(self, fd):
self.img.save(fd, 'PNG')
if __name__ == '__main__':
sett = sys.argv[1]
t = Tartan(sett)
t.png(sys.stdout)

22
tartans/tartantomdwn Executable file
View File

@ -0,0 +1,22 @@
#! /bin/sh
header () {
while IFS=: read key val; do
tval=$(echo $val | sed "s/'/\&apos;/g")
case $key in
Name)
echo -n "TARTAN='$tval';"
;;
Sett)
echo -n "SETT='$tval'"
;;
"")
break
;;
esac
done
}
eval $(header)
m4 -DTARTAN="$TARTAN" -DSETT="$SETT" -DBASE="$1" tartan.m4 -

12
tartans/tx.tartan Normal file
View File

@ -0,0 +1,12 @@
Name: Texas Bluebonnet
Sett: G4 R2 B16 W2 R2 W2 LB16 W2 LB16 W2 Y1
Based off a jpeg at the [Texas Scottish Heritage
Society](http://www.txscot.com/BB_tartan.htm#bluebonnet). (Why did they
save it as a jpeg?) The first blue in their image was only 15 threads
wide, I figured that was a typographical mistake given every subsequent
blue was 16, even in the repeats.
According to the aforementioned web page, it was designed by June
Prescott McRoberts, and adopted as the official state tartan on May 25,
1989.

7
tartans/ut.tartan Normal file
View File

@ -0,0 +1,7 @@
Name: Utah
Sett: W1 B6 R6 B4 R6 G18 R6 W4
Kudos to Utah for putting the sett right into 1996's SB-13. This is the
tartan as specified by law. The [photograph on Utah's Online
Library](http://pioneer.utah.gov/utah_on_the_web/utah_symbols/tartan.html)
seems to have a final white threadcount of 3.

5
tartans/wa.tartan Normal file
View File

@ -0,0 +1,5 @@
Name: Washington State
Sett: W3 R6 B36 G72 LB6 BK6 Y2
Adopted 1991 by the spartan [RCW
1.20.110](http://apps.leg.wa.gov/rcw/default.aspx?cite=1.20.110).