fabmodules/src/scripts/eagle_png

186 wiersze
5.9 KiB
Python
Executable File

#!/usr/bin/env python
import os
import sys
import platform
import glob
import subprocess
import hashlib
def find_eagle():
if platform.uname()[0] == 'Darwin':
try:
eagle_dir = glob.glob('/Applications/EAGLE*')[-1]
except IndexError:
sys.stderr.write("Error: EAGLE not found.\n")
sys.exit(1)
return eagle_dir + '/EAGLE.app/Contents/MacOS/EAGLE'
else:
if subprocess.call(['which','eagle'],
stdout = open(os.devnull, 'w')):
sys.stderr.write("Error: EAGLE not found.\n")
sys.exit(1)
return 'eagle'
def create_images(name, resolution = 1500):
for img in ['top','bottom','cutout','holes','vias']:
file = '%s.%s.png' % (name, img)
if os.path.isfile(file):
os.remove(file)
script = '''
ratsnest; write;
set palette black; window;
display none top vias pads;
export image '{name}.top.png' monochrome {resolution};
display none bottom vias pads;
export image '{name}.bottom.png' monochrome {resolution};
display none milling;
export image '{name}.cutout.png' monochrome {resolution};
display none holes;
export image '{name}.holes.png' monochrome {resolution};
display none vias pads;
export image '{name}.vias.png' monochrome {resolution};
quit'''.format(name = name, resolution = resolution)
subprocess.call([find_eagle(), '-C', script, name + '.brd'])
def md5(filename):
with open(filename,'rb') as f:
m = hashlib.md5()
for chunk in iter(lambda: f.read(m.block_size*128), ''):
m.update(chunk)
return m.digest()
def clean_up(name):
preserve = ['top','bottom','cutout']
for img in ['top','bottom','cutout','holes','vias']:
file = '%s.%s.png' % (name, img)
file_ = '%s.%s_.png' % (name, img)
if os.path.isfile(file) and img not in preserve:
os.remove(file)
if os.path.isfile(file_):
os.remove(file_)
def print_help():
print """command line: eagle_png [options] target.brd
target.brd = EAGLE brd file to render
The board outline should be a solid polygon on the 'milling' layer
Internal cutouts should be solid shapes on the 'holes' layer
Valid options:
--resolution NUM : sets output image resolution
--doublesided : forces double-sided mode"""
sys.exit(1)
if __name__ == '__main__':
if len(sys.argv) == 1:
print_help()
sys.exit(1)
# Parse arguments
sys.argv = sys.argv[1:]
resolution = 1500
force_doublesided = False
while sys.argv:
if sys.argv[0] == '--resolution':
try:
resolution = sys.argv[1]
sys.argv = sys.argv[2:]
except IndexError:
sys.stderr.write("Error: No resolution provided.\n")
sys.exit(1)
try:
resolution = int(resolution)
except ValueError:
sys.stderr.write("Error: Invalid resolution.\n")
sys.exit(1)
elif sys.argv[0] == '--doublesided':
force_doublesided = True
sys.argv = sys.argv[1:]
elif len(sys.argv) == 1:
break
else:
sys.stderr.write("Error: No filename provided.\n")
sys.exit(1)
name = sys.argv[0].replace('.brd','')
if not os.path.isfile(name+'.brd'):
sys.stderr.write("Error: .brd file does not exist.\n")
sys.exit(1)
vias = name + '.vias.png'
cutout = name + '.cutout.png'
top = name + '.top.png'
bottom = name + '.bottom.png'
holes = name + '.holes.png'
print "Rendering images."
create_images(name, resolution)
# Check to make sure that imagemagick is installed.
if subprocess.call(['which','convert'], stdout = open(os.devnull, 'w')):
sys.stderr.write("""Error: 'convert' not found.
ImageMagick command-line tools must be installed to use eagle_png.""")
sys.exit(1)
print "Processing images."
# The following command is a set of ImageMagick instructions that
# combine all of the images.
# The following steps take place:
# - Perform a white flood fill on the vias image, starting in the upper
# left corner. This makes the via image a set of black holes on
# a uniform white background
# - Multiply the vias and cutout images, to cut the via holes from
# the cutout region.
# - Invert the cutout image.
# - Lighten the top and bottom traces with the inverted cutout. This
# ensures that we don't waste time milling traces in regions that
# will be cut out of the PCB.
# - Subtract the holes image from the original cutout image
# - Save this combined cutout image
command = [ 'convert',
vias, '-fill', 'white', '-draw', 'color 0,0 floodfill',
cutout, '-compose', 'Darken', '-composite',
'-compose','Lighten',
'(',
'+clone',
'-negate'
]
# If this is a two-sided board, then process the bottom layer
if md5(bottom) != md5(vias) or force_doublesided:
command += [
'(',
'+clone', bottom, '-composite',
'-flop', '-write', bottom, '+delete',
')'
]
else:
os.remove(bottom)
# Process the top layer
command += [
top, '-composite', '-write', top,
'+delete',
')',
holes, '-compose', 'Minus_Src', '-composite', cutout
]
# Execute this whole mess
subprocess.call(command)
os.remove(vias)
os.remove(holes)
if bottom in command:
print "Generated %s, %s, %s." % (top, bottom, cutout)
else:
print "Generated %s, %s." % (top, cutout)