#!/usr/local/bin/python3.11
#    crossstitch.py
#    Copyright (C) 2003  Nathan Hurst
#    Copyright (C) 2004  Paul Mateman
#    Copyright (C) 2005  Cameron Morland
#    Copyright (C) 2009  Robert Smies
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#from pyx import *
import os.path
try:
   import Image
except:
   import PIL.Image as Image
import sys

## our symbols:
sym = "";
sym += "/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
sym += "/s1 { newpath 0.3 0 360 arc stroke } bind def\n";## 1: circle
sym += "/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
sym += "/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
sym += "/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
sym += "/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: =
sym += "/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: +
sym += "/s7 { newpath moveto 0.3 neg 0.3 neg rmoveto 0.6 0.6 rlineto stroke } bind def\n";## 7: slash
sym += "/s8 { newpath moveto 0.3 0.3 neg rmoveto 0.6 neg 0.6 rlineto stroke } bind def\n";## 8: backslash
sym += "/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
sym += "/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: ||

## 11-20: copies of 1-9, scaled by 0.5
for i in range(11):
   sym += "/s" + str(11+i)+ " { gsave translate 0.5 0.5 scale 0 0 s"+str(i)+" grestore } bind def\n";

ns = 22;

if len(sys.argv) != 2:
    print "Usage: prog file.png"
    exit(0)
in_file = sys.argv[1]
in_file_root,in_file_ext = os.path.splitext(in_file)
im = Image.open(in_file)
width,height = im.size

transparency = -1
try:
    transparency = im.info["transparency"]
except KeyError:
    pass
pal_type,pal_data = im.palette.getdata()
if pal_type != "RGB":
    print "Unable to deal with non-rgb palettes.  Please send me the picture."
pal_data = map(ord,pal_data)

##################################################
#
# compose legend for symbols <-> colour
#
##################################################

psl = open(in_file_root+"-colour.eps", "w");
psl.write("%!PS-Adobe-2.0 EPSF-1.2\n");
psl.write("%%Creator: xs.py\n");
psl.write("%%Pages: 1\n");
psl.write("%%BoundingBox: 35.0 35.0 " + str(36*len(pal_data)/3 +37) + " 109\n");
psl.write("%%EndComments\n\n");

psl.write("%%EndProlog\n");
psl.write("%%Page: 1 1\n");

# provide our symbols as functions to the printer
psl.write(sym);

psl.write("1 setlinecap 1 setlinejoin\n"); # round ends to lines
psl.write("36 36 translate\n");             
psl.write("36 36 scale\n");
psl.write("1 18 div setlinewidth\n");

x = 0;
for i in range(len(pal_data)/3):
    r,g,b = map(lambda a:a/255.,tuple(pal_data[i*3:i*3+3]))
    psl.write(str(i) + " 0 moveto 1 0 rlineto 0 1 rlineto 1 neg 0 rlineto closepath stroke\n");
    psl.write(str(i + 0.5) + " 0.5 s" + str(i) + "\n");
    psl.write(str(i) + " 1 moveto 1 0 rlineto 0 1 rlineto 1 neg 0 rlineto closepath\n");
    psl.write("gsave "+str(r)+" "+str(g)+" "+str(b)+" setrgbcolor fill grestore  stroke\n");

psl.write("showpage\n");
psl.write("%%EOF\n");
psl.close();

if (ns < len(pal_data)/3):
   print "Warning: only have " + str(ns) + " colours, need " + str(len(pal_data)/3);

# determine how much to scale the large picture. Make it fit on a
# letter sized sheet of paper. It doesn't matter much, since we can
# scale the eps file at will.
if (height/10 > width/7.5) :
   scale = 72 * 10 / height;
else :
   scale = 72 * 7.5 / width;

thinline = 0.04;
thickline = 0.12;

psf = open(in_file_root+".eps", "w")
psf.write("%!PS-Adobe-2.0 EPSF-1.2\n");
psf.write("%%Creator: xs.py\n");
psf.write("%%Pages: 1\n");
psf.write("%%BoundingBox: 35.0 35.0 " +
          str(scale*width+37) + " " + str(scale*height+37) + "\n");
psf.write("%%EndComments\n\n");
psf.write("%%EndProlog\n");
psf.write("%%Page: 1 1\n");

# provide our symbols as functions to the printer
psf.write(sym);

psf.write("\n");

psf.write("1 setlinecap 1 setlinejoin\n");
psf.write("36 36 translate\n");
psf.write(str(scale) + " " + str(scale) + " scale\n");

## display the vertical grid stripes
psf.write("0 1 " + str(height) + "{ ");  # loop from 0 to height
psf.write("dup ");                       # copy y value
psf.write("10 mod 0 eq { ");             # if it's multipl of 10...
psf.write(str(thickline) + " setlinewidth ");   # be thick.
psf.write("}{ ");                        # otherwise...
psf.write(str(thinline) + " setlinewidth ");    # be thin.
psf.write("} ifelse ");
psf.write("0 exch moveto " + str(width) + " 0 rlineto stroke ");
psf.write("} for\n");

## display the horizontal grid stripes
psf.write("0 1 " + str(width) + "{ ");   # loop from 0 to width
psf.write("dup ");                       # copy y value
psf.write("10 mod 0 eq { ");             # if it's multipl of 10...
psf.write(str(thickline) + " setlinewidth ");   # be thick.
psf.write("}{ ");                        # otherwise...
psf.write(str(thinline) + " setlinewidth "); # be thin.
psf.write("} ifelse ");
psf.write("0 moveto 0 " + str(height) + " rlineto stroke ");
psf.write("} for\n");

psf.write("0.1 setlinewidth\n");

psf.write("gsave 0.5 0.5 translate\n");  # put marks at centre of squares

## draws symbol for every pixel
for y in range(height):
   for x in range(width):
      psf.write(str(x) + " " + str(y) + " s"
                + (str(im.getpixel((x, height-y-1)) % ns)) + " ");
   psf.write("\n");

psf.write("grestore\n");
psf.write("showpage\n");
psf.write("%%EOF\n");
psf.close();
