#!/usr/bin/env python3 from PIL import Image import numpy as np # === CONFIG === INPUT_IMAGE = "t.png" OUTPUT_SCAD = "output.scad" PIXEL_SIZE = 1 # mm per pixel (X and Y) MAX_HEIGHT = 10.0 # max Z height in mm DOWNSCALE = 3 # Skip every N pixels for speed (set to 1 for full res) # Full res will result in very long openscad load times # === LOAD AND PROCESS IMAGE === img = Image.open(INPUT_IMAGE).convert("L") data = np.array(img) # Optionally downscale to speed up output data = data[::DOWNSCALE, ::DOWNSCALE] # Normalize grayscale to height zscale = MAX_HEIGHT / 255.0 heights = data * zscale rows, cols = heights.shape # === WRITE SCAD FILE === with open(OUTPUT_SCAD, "w") as f: f.write("// Generated by img2scad.py\n") f.write("union() {\n") for y in range(rows): for x in range(cols): h = heights[y, x] if h > 0: # OpenSCAD coordinate system: [x, y, z] f.write(f" translate([{x * PIXEL_SIZE}, {y * PIXEL_SIZE}, 0])\n") f.write(f" cube([{PIXEL_SIZE}, {PIXEL_SIZE}, {h:.2f}]);\n") f.write("}\n") print(f"Done. Output written to: {OUTPUT_SCAD}") ''' Notes: openSCAD will take forever to load a prebuilt complex openscad file IF you load that object from the start. (even if you have manifold selected in the rendering options of developer mode) (becuase init still uses CSG regardless) The work around is to load a blank output file, then generate the data using this script. then, provided you have manifold selected, reloading the data will be much faster. 2. This is true, to 200K objects. at over 200K objects, openscad will default to CSG modeling, which is the same as being broken. 3. background subtraction concept forgoing complex image processing: for h < some min_hight render no objects. this may help keep object count low, where you can continue to reap the benifits of manifold rendering. h < 3 but Im pretty tired finding other ppls bugs. Ima go sleep. '''