Mercurial > lasercutter
view src/laser/rasterize.clj @ 21:e72220627685 tip
0.002 inch discrepancy with target. going to test anyway
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Mon, 30 Aug 2010 01:19:21 -0400 |
parents | 6bed8ceb51a9 |
children |
line wrap: on
line source
1 (ns laser.rasterize2 (:use [rlm3 image-utils4 map-utils]5 [clojure.contrib6 [str-utils :only [str-join re-gsub re-split]]7 [seq :only [indexed]]8 [math]])9 (:import [ij ImagePlus IJ]))11 ;(import '(java.io File))12 ;(import '(org.apache.commons.io FileUtils))13 ;(import '(javax.imageio ImageIO) )16 (set! *print-length* 20)17 (def feed 120)18 (def dpi [500, 500])19 (def paramaters {:x-dpi 500 :y-dpi 500 :margin 0.501 :x-offset 1.001 :y-offset 1})21 ;;; this process is divided into two tasks,22 ;;; creating the raster g-code, which sweeps back and forth23 ;;; and creating the gmask, which turns the laser on and off.26 ;;; we'll be using frame-hashes, which represent picutres as27 ;;; a 3D vector field over 2D space, with the vectors representing28 ;;; the rgb values at that particulat point.30 (defn select-row31 "returns a frame hash that is just a single line at the chosen y"32 [y window]33 (filter-keys (comp (partial = y) last) window))35 (defn make-rows [pic]36 (map (partial sort #(< (first %1) (first %2)))37 (partition-by last38 (sort (fn [[x1 y1][x2 y2]] (> y2 y1))39 (map first (filter-vals (partial = black) pic))))))42 ;;; generate rastering g-code44 (defn raster-preamble []45 (str-join \newline46 ["M63 P0\nG61"47 (str "F" feed)48 "M101"49 "M3 S1\n"]))51 (defn raster-epilogue []52 (str-join \newline53 ["M63 P0"54 "M5"55 "M2\n"]))57 (defn raster-comment [string]58 (str "(" (re-gsub #"[()]" "" string) ")"))61 ;this is a sequence of rows63 ;(defn span [row]64 ; (let [sorted-row (sort #(< (first %1) (first %2)) row)]65 ; (vector (first sorted-row) (last sorted-row))))68 (comment70 (import 'org.im4java.core.ConvertCmd)71 (import 'org.im4java.core.IMOperation)72 (import 'org.im4java.core.Stream2BufferedImage)74 (def target (.getBufferedImage (ImagePlus. sing)))75 (def shiv (IMOperation.))76 (.addImage shiv)77 (.addImage shiv (into-array String ["png:-"]))78 (def conv-shiv (ConvertCmd.))79 (def s2b (Stream2BufferedImage.))80 (.setOutputConsumer conv-shiv s2b)81 (.run conv-shiv shiv (into-array Object [target]))82 (def result (.getImage s2b ))84 )86 (defn mirror87 "ImagePlus to ImagePlus via imageMagick through im4java!"88 [#^ImagePlus img]89 (let [title (.getTitle img)90 target (.getBufferedImage img)91 s2b (Stream2BufferedImage.)92 shiv (doto (IMOperation.)93 ;(.blur 2.0)94 (.flip)95 (.addImage)96 (.addImage (into-array String ["png:-"])))97 conv-shiv (doto (ConvertCmd.)98 (.setOutputConsumer s2b))]100 (.run conv-shiv shiv (into-array Object [target]))101 (ImagePlus. title (.getImage s2b))))105 (defn row->gcode [{:keys [x-dpi y-dpi margin x-offset y-offset]} forward? row]107 (let [[x1 y1] (if forward? (last row) (first row))108 [x2 y2] (if forward? (first row) (last row))]110 (let [x1 (* x1 (/ x-dpi))111 x2 (* x2 (/ x-dpi))112 y1 (* y1 (/ y-dpi))113 y2 (* y2 (/ y-dpi))]115 (let [x1 (+ x1 x-offset)116 x2 (+ x2 x-offset)117 y1 (+ y1 y-offset)118 y2 (+ y2 y-offset)]120 (let [margin (if forward? margin (- margin))]122 (let [x1 (+ x1 margin)123 x2 (- x2 margin)]127 (str (format "G0 X%.3f Y%.3f\n"128 (float x1 )129 (float y1))131 (format "G1 X%.3f Y%.3f\n"132 (float x2)133 (float y2)))))))))135 (defn generate-gcode [pic]136 (str (raster-preamble)137 (str-join ""138 (map139 (fn [[index row]]140 (row->gcode paramaters (even? index) row))141 (indexed (make-rows pic))))142 (raster-epilogue)))162 (defn gather-row [row]163 (let [base [[(first (first row)) (first (first row))]]]164 ; (println base)165 (reduce166 (fn colapse [collection new-n]168 (let [collection (apply vector collection)169 prevoius (last (last collection))170 range-start (first (last collection))]171 ; (println new-n)172 ; (println prevoius)173 ; (println range-start)174 (if (<= new-n (+ prevoius 1))175 (do ;(println "join")176 ;(println (butlast collection))177 (conj (apply vector (butlast collection))178 (vector range-start new-n)))179 (conj collection (vector new-n new-n)))))181 base182 (map first row))))187 (defn row->gmask [{:keys [x-dpi y-dpi margin x-offset y-offset]} forward? row]188 (let [start (float (* (/ x-dpi) (first (first189 (if forward?190 (reverse row) row)))))191 start (+ start x-offset)192 ]193 (let [preamble (if-not forward?194 (format "0 0 0 %.3f\n" start)195 (format "0 0 1 %.3f\n" start))196 body197 (for [[x y]198 (if forward?199 (reverse (gather-row row))200 (gather-row row))]201 (let [x (float (* x (/ x-dpi)))202 y (float (* y (/ x-dpi)))203 x (+ x x-offset)204 y (+ y y-offset)209 ]212 (if-not forward?213 (str (format "0 0 1 %.3f\n" x)214 (format "0 1 1 %.3f\n" y))216 (str (format "0 0 0 %.3f\n" y)217 (format "0 1 0 %.3f\n" x)))))]219 (str preamble (str-join "" body)))))222 (defn generate-gmask [pic]223 (str "1 0 0 0\n"224 (str-join "" (map (fn [[index row]]225 (row->gmask paramaters (even? index) row))226 (indexed (make-rows pic))))))231 ;;;; testing233 (defn generate-files [pic]234 (println "made-image")235 (spit "/home/r/kevin/out.ngc" (generate-gcode pic))236 (println "/home/r/kevin/out.ngc")237 (spit "/home/r/kevin/out.gmask" (generate-gmask pic))238 (println "/home/r/kevin/out.gmask")239 pic)241 (defn update-state []242 (def sing "/home/r/kevin/sing.png")243 (def pic (frame-hash (mirror (ImagePlus. sing))))244 (def pic (b&w pic)))246 (defn compare-gen-fn [n f cmp]247 (let [theirs (re-split #"\n" (slurp cmp))248 ours (re-split #"\n" (f pic))]249 (println (format "%1$-25s%2$s" "OURS" "THEIRS"))250 (println "_______________________________________")251 (dorun (map (fn [[us them]] (println252 (format "%1$-25s%2$s" us them)))253 (take n (partition 2 (interleave ours theirs)))))))255 (defn compare-gcode [n]256 (compare-gen-fn n generate-gcode "/home/r/kevin/reference.ngc"))257 (defn compare-gmask [n]258 (compare-gen-fn n generate-gmask "/home/r/kevin/reference.gmask"))