view src/laser/rasterize.clj @ 16:52f544d05414

I think I've made it worse....
author Robert McIntyre <rlm@mit.edu>
date Sun, 29 Aug 2010 23:40:39 -0400
parents 8ad629298649
children 962e223bab0d
line wrap: on
line source
1 (ns laser.rasterize
2 (:use [rlm
3 image-utils
4 map-utils]
5 [clojure.contrib
6 [str-utils :only [str-join re-gsub]]
7 [seq :only [indexed]]
8 [math]
9 [def]
10 ])
11 (:import [ij ImagePlus IJ]))
13 ;(import '(java.io File))
14 ;(import '(org.apache.commons.io FileUtils))
15 ;(import '(javax.imageio ImageIO) )
18 (set! *print-length* 20)
19 (def feed 120)
20 (def dpi [500, 500])
22 (def paramaters {:x-dpi 500 :y-dpi 500 :margin 0 :x-offset 0 :y-offset 0})
24 ;;; this process is divided into two tasks,
25 ;;; creating the raster g-code, which sweeps back and forth
26 ;;; and creating the gmask, which turns the laser on and off.
29 ;;; we'll be using frame-hashes, which represent picutres as
30 ;;; a 3D vector field over 2D space, with the vectors representing
31 ;;; the rgb values at that particular point.
33 (defn select-row
34 "returns a frame hash that is just a single line at the chosen y"
35 [y window]
36 (reduce
37 (fn [old-map number]
38 (let [pixel (get window [number y] nil)]
39 (if-not (nil? pixel)
40 (into old-map {[number y] pixel})
41 old-map)))
42 {}
43 (range (width window))))
45 (defn make-rows [pic]
46 (map (partial sort #(< (first %1) (first %2)))
47 (partition-by last
48 (sort (fn [[x1 y1][x2 y2]] (> y2 y1))
49 (map first (filter-vals (partial = black) pic))))))
51 ;;; generate rastering g-code
53 (defn raster-preamble []
54 (str-join \newline ["M63 P0\nG61" (str "F" feed) "M101" "M3 S1\n"]))
56 (defn raster-epilogue []
57 (str-join \newline ["M63 P0" "M5" "M2\n"]))
59 (defn raster-comment
60 "wrap a statement in PARENTHENSIS to make it a comment in gcode.
61 parenthesis themselves aren't allowed in comments.
62 Oh the humanity!!"
63 [string]
64 (str "(" (re-gsub #"[()]" "" string) ")"))
66 (defn rows
67 "creates a sequence of one dimensional vector fields which
68 represent the rows of a picture"
69 [pic]
70 (let [non-empty-rows (apply sorted-set (map (comp last first) pic))]
71 (pmap (fn [n] (select-row n pic)) non-empty-rows)))
77 (defn row->gcode [{:keys [x-dpi y-dpi margin x-offset y-offset]} row]
78 (let [pixels (keys row)
79 x2 0
80 [_ y2] (first pixels)
81 [_ y1] (first pixels)
82 x1 533]
84 ;(let [ordered-row
85 ; (sort-map-by (fn [[x1 _] [x2 _]] (> x2 x1)) row)]
87 (let [;[x1 y1] (last (keys ordered-row))
88 ;[x2 y2] (first (keys ordered-row))
89 [x1 y1 x2 y2] (if (odd? y1) [x2 y2 x1 y1] [x1 y1 x2 y2])]
91 (str (format "G0 X%.3f Y%.3f\n"
92 (float (* x1 (/ x-dpi)))
93 (float (* y1 (/ y-dpi))))
95 (format "G1 X%.3f Y%.3f\n"
96 (float (* x2 (/ x-dpi)))
97 (float (* y2 (/ y-dpi))))))))
100 (defn pic->gcode [paramaters pic]
101 (reduce (fn [gcode current-height]
102 (let [current-row (select-row current-height pic)]
103 (if-not (empty? current-row)
104 (let [new-code (row->gcode paramaters current-row)]
105 (println new-code)
106 (str gcode new-code))
107 gcode)))
108 ""
109 (range (height pic))))
112 ;(defn pic->gcode [paramaters pic]
115 (defn generate-gcode [pic]
116 (str (raster-preamble)
117 (row->gcode paramaters pic)
118 (raster-epilogue)))
138 (defn gather-row [row]
139 (let [base [[(first (first row)) (first (first row))]]]
140 ; (println base)
141 (reduce
142 (fn colapse [collection new-n]
144 (let [collection (apply vector collection)
145 prevoius (last (last collection))
146 range-start (first (last collection))]
147 ; (println new-n)
148 ; (println prevoius)
149 ; (println range-start)
150 (if (<= new-n (+ prevoius 1))
151 (do ;(println "join")
152 ;(println (butlast collection))
153 (conj (apply vector (butlast collection))
154 (vector range-start new-n)))
155 (conj collection (vector new-n new-n)))))
157 base
158 (map first row))))
163 (defn row->gmask [[x-dpi y-dpi] forward? row]
164 (let [start (float (* (/ x-dpi) (first (first
165 (if forward?
166 (reverse row) row)))))]
167 (let [preamble (if-not forward?
168 (format "0 0 0 %.3f\n" start)
169 (format "0 0 1 %.3f\n" start))
170 body
171 (for [[x y]
172 (if forward?
173 (reverse (gather-row row))
174 (gather-row row))]
175 (let [x (float (* x (/ x-dpi)))
176 y (float (* y (/ x-dpi)))]
177 ;; x (+ x 0.159)];; shift by a small margin.
178 (if-not forward?
179 (str (format "0 0 1 %.3f\n" x)
180 (format "0 1 1 %.3f\n" y))
182 (str (format "0 0 0 %.3f\n" y)
183 (format "0 1 0 %.3f\n" x)))))]
185 (str preamble (str-join "" body)))))
188 (defn generate-gmask [pic]
189 (str "1 0 0 0\n"
190 (str-join "" (map (fn [[index row]]
191 (row->gmask dpi (even? index) row))
192 (indexed (make-rows pic))))))
197 ;;;; testing
199 (defn generate-files [pic]
200 (println "made-image")
201 (spit "/home/r/kevin/out.ngc" (generate-gcode pic))
202 (println "/home/r/kevin/out.ngc")
203 (spit "/home/r/kevin/out.gmask" (generate-gmask pic))
204 (println "/home/r/kevin/out.gmask")
205 pic)
207 (defn update-state []
208 (def sing "/home/r/kevin/sing.png")
209 (def pic (frame-hash (ImagePlus. sing)))
210 (def pic (b&w pic))
211 (def pic (filter-vals (partial = black) pic)))
213 (defn compare-gen-fn
214 ([n f cmp]
215 (let [theirs (re-split #"\n" (slurp cmp))
216 ours (re-split #"\n" (f pic))]
217 (println (format "%1$-25s%2$s" "OURS" "THEIRS"))
218 (println "_______________________________________")
219 (dorun (map (fn [[us them]] (println
220 (format "%1$-25s%2$s" us them)))
221 (take n (partition 2 (interleave ours theirs))))))))
223 (defn compare-gcode
224 ([] (compare-gcode 25))
225 ([n] (compare-gen-fn n generate-gcode "/home/r/kevin/reference.ngc")))
227 (defn compare-gmask
228 ([] compare-gmask 25)
229 ([n] (compare-gen-fn n generate-gmask "/home/r/kevin/reference.gmask")))