1#!/usr/local/bin/python3.8 2# crossstitch.py 3# Copyright (C) 2003 Nathan Hurst 4# Copyright (C) 2004 Paul Mateman 5# Copyright (C) 2005 Cameron Morland 6# Copyright (C) 2009 Robert Smies 7# 8# This program is free software; you can redistribute it and/or modify 9# it under the terms of the GNU General Public License as published by 10# the Free Software Foundation; either version 2 of the License, or 11# (at your option) any later version. 12# 13# This program is distributed in the hope that it will be useful, 14# but WITHOUT ANY WARRANTY; without even the implied warranty of 15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16# GNU General Public License for more details. 17# 18# You should have received a copy of the GNU General Public License 19# along with this program; if not, write to the Free Software 20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 22#from pyx import * 23import os.path 24try: 25 import Image 26except: 27 import PIL.Image as Image 28import sys 29 30## our symbols: 31sym = ""; 32sym += "/s0 { newpath moveto 0.3 neg 0.3 neg rmoveto 0.6 0 rlineto 0.6 neg 0.6 rlineto 0.6 0 rlineto 0.6 neg 0.6 neg rlineto stroke } bind def\n";## 0: blank 33sym += "/s1 { newpath 0.3 0 360 arc stroke } bind def\n";## 1: circle 34sym += "/s2 { newpath moveto 0.3 neg 0.3 neg rmoveto 0.6 0 rlineto 0 0.6 rlineto 0.6 neg 0 rlineto closepath stroke } bind def\n";## 2: square 35sym += "/s3 { newpath moveto 0.22 neg 0 rmoveto 0.45 0.26 rlineto 0 0.52 neg rlineto closepath stroke } bind def\n";## 3: ltriangle 36sym += "/s4 { newpath moveto 0.22 0 rmoveto 0.45 neg 0.26 rlineto 0 0.52 neg rlineto closepath stroke } bind def\n";## 4: rtriangle 37sym += "/s5 { newpath moveto 0.3 neg 0.2 rmoveto 0.6 0 rlineto 0 0.4 neg rmoveto 0.6 neg 0 rlineto stroke } bind def\n";## 5: = 38sym += "/s6 { newpath moveto 0.3 neg 0 rmoveto 0.6 0 rlineto 0.3 neg 0.3 neg rmoveto 0 0.6 rlineto stroke } bind def\n";## 6: + 39sym += "/s7 { newpath moveto 0.3 neg 0.3 neg rmoveto 0.6 0.6 rlineto stroke } bind def\n";## 7: slash 40sym += "/s8 { newpath moveto 0.3 0.3 neg rmoveto 0.6 neg 0.6 rlineto stroke } bind def\n";## 8: backslash 41sym += "/s9 { newpath moveto 0.3 neg 0.3 neg rmoveto 0.6 0.6 rlineto 0 0.6 neg rmoveto 0.6 neg 0.6 rlineto stroke } bind def\n";## 9: X 42sym += "/s10 { newpath moveto 0.2 neg 0.3 rmoveto 0 0.6 neg rlineto 0.4 0 rmoveto 0 0.6 rlineto stroke } bind def\n";## 10: || 43 44## 11-20: copies of 1-9, scaled by 0.5 45for i in range(11): 46 sym += "/s" + str(11+i)+ " { gsave translate 0.5 0.5 scale 0 0 s"+str(i)+" grestore } bind def\n"; 47 48ns = 22; 49 50if len(sys.argv) != 2: 51 print "Usage: prog file.png" 52 exit(0) 53in_file = sys.argv[1] 54in_file_root,in_file_ext = os.path.splitext(in_file) 55im = Image.open(in_file) 56width,height = im.size 57 58transparency = -1 59try: 60 transparency = im.info["transparency"] 61except KeyError: 62 pass 63pal_type,pal_data = im.palette.getdata() 64if pal_type != "RGB": 65 print "Unable to deal with non-rgb palettes. Please send me the picture." 66pal_data = map(ord,pal_data) 67 68################################################## 69# 70# compose legend for symbols <-> colour 71# 72################################################## 73 74psl = open(in_file_root+"-colour.eps", "w"); 75psl.write("%!PS-Adobe-2.0 EPSF-1.2\n"); 76psl.write("%%Creator: xs.py\n"); 77psl.write("%%Pages: 1\n"); 78psl.write("%%BoundingBox: 35.0 35.0 " + str(36*len(pal_data)/3 +37) + " 109\n"); 79psl.write("%%EndComments\n\n"); 80 81psl.write("%%EndProlog\n"); 82psl.write("%%Page: 1 1\n"); 83 84# provide our symbols as functions to the printer 85psl.write(sym); 86 87psl.write("1 setlinecap 1 setlinejoin\n"); # round ends to lines 88psl.write("36 36 translate\n"); 89psl.write("36 36 scale\n"); 90psl.write("1 18 div setlinewidth\n"); 91 92x = 0; 93for i in range(len(pal_data)/3): 94 r,g,b = map(lambda a:a/255.,tuple(pal_data[i*3:i*3+3])) 95 psl.write(str(i) + " 0 moveto 1 0 rlineto 0 1 rlineto 1 neg 0 rlineto closepath stroke\n"); 96 psl.write(str(i + 0.5) + " 0.5 s" + str(i) + "\n"); 97 psl.write(str(i) + " 1 moveto 1 0 rlineto 0 1 rlineto 1 neg 0 rlineto closepath\n"); 98 psl.write("gsave "+str(r)+" "+str(g)+" "+str(b)+" setrgbcolor fill grestore stroke\n"); 99 100psl.write("showpage\n"); 101psl.write("%%EOF\n"); 102psl.close(); 103 104if (ns < len(pal_data)/3): 105 print "Warning: only have " + str(ns) + " colours, need " + str(len(pal_data)/3); 106 107# determine how much to scale the large picture. Make it fit on a 108# letter sized sheet of paper. It doesn't matter much, since we can 109# scale the eps file at will. 110if (height/10 > width/7.5) : 111 scale = 72 * 10 / height; 112else : 113 scale = 72 * 7.5 / width; 114 115thinline = 0.04; 116thickline = 0.12; 117 118psf = open(in_file_root+".eps", "w") 119psf.write("%!PS-Adobe-2.0 EPSF-1.2\n"); 120psf.write("%%Creator: xs.py\n"); 121psf.write("%%Pages: 1\n"); 122psf.write("%%BoundingBox: 35.0 35.0 " + 123 str(scale*width+37) + " " + str(scale*height+37) + "\n"); 124psf.write("%%EndComments\n\n"); 125psf.write("%%EndProlog\n"); 126psf.write("%%Page: 1 1\n"); 127 128# provide our symbols as functions to the printer 129psf.write(sym); 130 131psf.write("\n"); 132 133psf.write("1 setlinecap 1 setlinejoin\n"); 134psf.write("36 36 translate\n"); 135psf.write(str(scale) + " " + str(scale) + " scale\n"); 136 137## display the vertical grid stripes 138psf.write("0 1 " + str(height) + "{ "); # loop from 0 to height 139psf.write("dup "); # copy y value 140psf.write("10 mod 0 eq { "); # if it's multipl of 10... 141psf.write(str(thickline) + " setlinewidth "); # be thick. 142psf.write("}{ "); # otherwise... 143psf.write(str(thinline) + " setlinewidth "); # be thin. 144psf.write("} ifelse "); 145psf.write("0 exch moveto " + str(width) + " 0 rlineto stroke "); 146psf.write("} for\n"); 147 148## display the horizontal grid stripes 149psf.write("0 1 " + str(width) + "{ "); # loop from 0 to width 150psf.write("dup "); # copy y value 151psf.write("10 mod 0 eq { "); # if it's multipl of 10... 152psf.write(str(thickline) + " setlinewidth "); # be thick. 153psf.write("}{ "); # otherwise... 154psf.write(str(thinline) + " setlinewidth "); # be thin. 155psf.write("} ifelse "); 156psf.write("0 moveto 0 " + str(height) + " rlineto stroke "); 157psf.write("} for\n"); 158 159psf.write("0.1 setlinewidth\n"); 160 161psf.write("gsave 0.5 0.5 translate\n"); # put marks at centre of squares 162 163## draws symbol for every pixel 164for y in range(height): 165 for x in range(width): 166 psf.write(str(x) + " " + str(y) + " s" 167 + (str(im.getpixel((x, height-y-1)) % ns)) + " "); 168 psf.write("\n"); 169 170psf.write("grestore\n"); 171psf.write("showpage\n"); 172psf.write("%%EOF\n"); 173psf.close(); 174