Half tone stencilling with 30% less repeditive strain injury

The process I came up with is pretty straight forward

  1. get an image
  2. crop to 4:3 or any other neat golden mean which you can find a canvas for
  3. reduce to a small number of pixels, I used 160x120px
  4. drop to greyscale
  5. 8 colour palette using dithering
  6. save as gif
  7. run it through program below to make a black square for each pixel
  8. convert SVG to PostScript
  9. use Poster to blow it up to 4×4 A4 sheets to the size of your canvas
  10. Print to overhead transperancys, you will get registration points and numbering of the tiles
  11. cut out all the squares to make stencils
  12. apply black enamel paint to white canvas
  13. enjoy the analog digital fusion
  14. 160×120 pixels means you have to cut out 19200 little squares

Another idea would be to get 8 hole punches and change the code below to indicate what radius hole punch to use

that would cut down on the rsi by at least 80%

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env python
"""\
SVG.py - Construct/display SVG scenes.
 
The following code is a lightweight wrapper around SVG files. The metaphor
is to construct a scene, add objects to it, and then write it to a file
to display it.
 
This program uses ImageMagick to display the SVG files. ImageMagick also
does a remarkable job of converting SVG files into other formats.
"""
import math
import os
 
from PIL import Image
 
display_prog = 'display' # Command to execute to display images.
 
class Scene:
	def __init__(self,name="svg",height=400,width=400):
		self.name = name
		self.items = []
		self.height = height
		self.width = width
		return
 
	def add(self,item): self.items.append(item)
 
	def strarray(self):
		var = ["<?xml version=\"1.0\"?>\n",
			   "<svg height=\"%d\" width=\"%d\" >\n" % (self.height,self.width),
			   " <g style=\"fill-opacity:1.0; stroke:none;\n",
			   "  stroke-width:0;\">\n"]
		for item in self.items: var += item.strarray()
		var += [" </g>\n</svg>\n"]
		return var
 
	def write_svg(self,filename=None):
		if filename:
			self.svgname = filename
		else:
			self.svgname = self.name + ".svg"
		file = open(self.svgname,'w')
		file.writelines(self.strarray())
		file.close()
		return
 
	def display(self,prog=display_prog):
		os.system("%s %s" % (prog,self.svgname))
		return
 
 
class Line:
	def __init__(self,start,end):
		self.start = start #xy tuple
		self.end = end	 #xy tuple
		return
 
	def strarray(self):
		return ["  <line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" />\n" %\
				(self.start[0],self.start[1],self.end[0],self.end[1])]
 
 
class Circle:
	def __init__(self,center,radius,color):
		self.center = center #xy tuple
		self.radius = radius #xy tuple
		self.color = color   #rgb tuple in range(0,256)
		return
 
	def strarray(self):
		return ["  <circle cx=\"%d\" cy=\"%d\" r=\"%04f\"\n" %\
				(self.center[0],self.center[1],self.radius),
				"	style=\"fill:%s;\"  />\n" % colorstr(self.color)]
 
class Rectangle:
	def __init__(self,origin,height,width,color):
		self.origin = origin
		self.height = height
		self.width = width
		self.color = color
		return
 
	def strarray(self):
		return ["  <rect x=\"%04f\" y=\"%04f\" height=\"%04f\"\n" %\
				(float(self.origin[0]),float(self.origin[1]),float(self.height)),
				"	width=\"%d\" style=\"fill:%s;\" />\n" %\
				(self.width,colorstr(self.color))]
 
class Text:
	def __init__(self,origin,text,size=24):
		self.origin = origin
		self.text = text
		self.size = size
		return
 
	def strarray(self):
		return ["  <text x=\"%d\" y=\"%d\" font-size=\"%d\">\n" %\
				(self.origin[0],self.origin[1],self.size),
				"   %s\n" % self.text,
				"  </text>\n"]
 
 
def colorstr(rgb): return "#%x%x%x" % (rgb[0]/16,rgb[1]/16,rgb[2]/16)
 
def test():
	curImage = Image.open("/home/samh/input.gif")
	dimensions = curImage.size
 
	#print dimensions
	scale = 20.0
	scene = Scene('test',dimensions[1]*scale,dimensions[0]*scale)
	paletteSize = 8.0#len(curImage.palette.palette)/len(curImage.palette.getdata()[0])
	for row in range(dimensions[0]):
		for column in range(dimensions[1]):
			size = math.pow( (1 - float(curImage.getpixel((row,column)))/float(paletteSize))*2,0.5) * scale
			dimension = scale/float(paletteSize) * size
			black  = (0,0,0)
			bottomRight = (row*scale,column*scale)
			scene.add(Rectangle(bottomRight,dimension/5.0,dimension/5.0,black))
	scene.write_svg(filename="test.svg")
	scene.display(prog="inkscape")
	return
 
if __name__ == '__main__': test()

Leave a Reply