Added img2scad.py script.

This commit is contained in:
Garth Minette 2022-05-17 22:36:30 -07:00
parent b6a1b83f51
commit 31e91f69a2
3 changed files with 89 additions and 0 deletions

79
scripts/img2scad.py Executable file
View file

@ -0,0 +1,79 @@
#!env python3
import re
import os
import sys
import os.path
import argparse
from PIL import Image
def img2scad(filename, varname, resize, outf):
indent = " " * 4
im = Image.open(filename).convert('L')
if resize:
print("Resizing to {}x{}".format(resize[0],resize[1]))
im = im.resize(resize)
pix = im.load()
width, height = im.size
print("// Image {} ({}x{})".format(filename, width, height), file=outf)
print("{} = [".format(varname), file=outf)
line = indent
for x in range(width):
line += "[ "
for y in range(height):
line += "{:d}, ".format(pix[x,y])
if len(line) > 60:
print(line, file=outf)
line = indent * 2
line += " ],"
if line != indent:
print(line, file=outf)
line = indent
print("];", file=outf)
print("", file=outf)
def main():
parser = argparse.ArgumentParser(prog='img2scad')
parser.add_argument('-o', '--outfile',
help='Output .scad file.')
parser.add_argument('-v', '--varname',
help='Variable to use in .scad file.')
parser.add_argument('-r', '--resize',
help='Resample image to WIDTHxHEIGHT.')
parser.add_argument('infile', help='Input image file.')
opts = parser.parse_args()
non_alnum = re.compile(r'[^a-zA-Z0-9_]')
if not opts.varname:
if opts.outfile:
opts.varname = os.path.splitext(os.path.basename(opts.outfile))[0]
opts.varname = non_alnum.sub("", opts.varname)
else:
opts.varname = "image_data"
size_pat = re.compile(r'^([0-9][0-9]*)x([0-9][0-9]*)$')
if opts.resize:
m = size_pat.match(opts.resize)
if not m:
print("Expected WIDTHxHEIGHT resize format.", file=sys.stderr)
sys.exit(-1)
opts.resize = (int(m.group(1)), int(m.group(2)))
if not opts.varname or non_alnum.search(opts.varname):
print("Bad variable name: {}".format(opts.varname), file=sys.stderr)
sys.exit(-1)
if opts.outfile:
with open(opts.outfile, "w") as outf:
img2scad(opts.infile, opts.varname, opts.resize, outf)
else:
img2scad(opts.infile, opts.varname, opts.resize, sys.stdout)
sys.exit(0)
if __name__ == "__main__":
main()

View file

@ -2775,6 +2775,8 @@ module interior_fillet(l=1.0, r, ang=90, overlap=0.01, d, anchor=CENTER, spin=0,
// Description:
// Given a regular rectangular 2D grid of scalar values, or a function literal, generates a 3D
// surface where the height at any given point is the scalar value for that position.
// One script to convert a grayscale image to a heightfield array in a .scad file can be found at:
// https://raw.githubusercontent.com/revarbat/BOSL2/master/scripts/img2scad.py
// Arguments:
// data = This is either the 2D rectangular array of heights, or a function literal that takes X and Y arguments.
// size = The [X,Y] size of the surface to create. If given as a scalar, use it for both X and Y sizes. Default: `[100,100]`
@ -2902,6 +2904,8 @@ function heightfield(data, size=[100,100], bottom=-20, maxz=100, xrange=[-1:0.04
// Given a regular rectangular 2D grid of scalar values, or a function literal of signature (x,y), generates
// a cylindrical 3D surface where the height at any given point above the radius `r=`, is the scalar value
// for that position.
// One script to convert a grayscale image to a heightfield array in a .scad file can be found at:
// https://raw.githubusercontent.com/revarbat/BOSL2/master/scripts/img2scad.py
// Arguments:
// data = This is either the 2D rectangular array of heights, or a function literal of signature `(x, y)`.
// l = The length of the cylinder to wrap around.

View file

@ -2125,6 +2125,8 @@ function _get_texture(tex,n,m) =
// Topics: Sweep, Extrusion, Textures, Knurling
// Description:
// Given a single polygon path, creates a linear extrusion of that polygon vertically, with a given texture tiled evenly over the side surfaces.
// One script to convert a grayscale image to a texture heightfield array in a .scad file can be found at:
// https://raw.githubusercontent.com/revarbat/BOSL2/master/scripts/img2scad.py
// Arguments:
// path = The path to sweep/extrude.
// texture = A texture name string, or a rectangular array of scalar height values (0.0 to 1.0) that define the texture to apply to vertical surfaces.
@ -2320,6 +2322,8 @@ module textured_linear_sweep(
// Description:
// Given a single 2D path, fully in the X+ half-plane, revolves that path around the Z axis (after rotating its Y+ to Z+).
// This creates a solid from that surface of revolution, capped top and bottom, with the sides covered in a given tiled texture.
// One script to convert a grayscale image to a texture heightfield array in a .scad file can be found at:
// https://raw.githubusercontent.com/revarbat/BOSL2/master/scripts/img2scad.py
// Arguments:
// path = The path to sweep/extrude.
// texture = A texture name string, or a rectangular array of scalar height values (0.0 to 1.0) that define the texture to apply to vertical surfaces. See {{textured_linear_sweep()}} for what textures are supported.
@ -2454,6 +2458,8 @@ module textured_revolution(
// Topics: Sweep, Extrusion, Textures, Knurling
// Description:
// Creates a cylinder or cone with optional chamfers or roundings, covered in a textured surface.
// One script to convert a grayscale image to a texture heightfield array in a .scad file can be found at:
// https://raw.githubusercontent.com/revarbat/BOSL2/master/scripts/img2scad.py
// Arguments:
// h | l = The height of the cylinder.
// r = The radius of the cylinder.