view src/laser/rasterize.clj @ 12:aadb93318584

testing committ
author Robert McIntyre <rlm@mit.edu>
date Tue, 24 Aug 2010 19:10:22 -0400
parents f952052e37b7
children 397ab24b4952
line wrap: on
line source
1 (ns laser.rasterize)
3 (import '(java.io File))
4 (import '(org.apache.commons.io FileUtils))
5 (import '(javax.imageio ImageIO) )
6 (import '(javax.swing JFrame))
7 (import '(java.awt Color BorderLayout))
8 (import '(ij ImagePlus IJ))
9 (import '(java.lang Math))
10 (import '(java.awt Graphics2D Panel))
11 (import '(ij Macro))
13 (import '(java.io BufferedReader InputStreamReader))
14 (import '(java.awt.image BufferedImage))
16 ;(use 'clojure.contrib.str-utils)
17 ;(use 'clojure.contrib.seq-utils)
18 ;(use 'clojure.contrib.combinatorics)
19 ;(use 'clojure.contrib.duck-streams)
21 ;(use 'clojure.contrib.repl-utils)
23 ;(set! *print-length* 20)
28 (def feed 120)
29 (def dpi [500, 500])
34 (defn preserve-meta [f]
35 (fn [& x] (with-meta
36 (apply f x)
37 (meta (last x)))))
39 (defmulti frame-hash-multi class)
42 (defmethod frame-hash-multi ImagePlus
43 [image+]
44 (with-meta
45 (let [buf (.. image+ getBufferedImage)
46 color (.getColorModel buf)]
47 (apply hash-map
48 (interleave
49 (doall (for [x (range (.getWidth image+)) y (range (.getHeight image+))]
50 (vector x y)))
51 (doall (for [x (range (.getWidth image+)) y (range (.getHeight image+))]
52 (let [data (.getRGB buf x y)]
53 (hash-map :r (bit-shift-right (bit-and 0xff0000 data) 16)
54 :g (bit-shift-right (bit-and 0x00ff00 data) 8)
55 :b (bit-and 0x0000ff data))))))))
56 {:width (.getWidth image+) :height (.getHeight image+)}))
59 (defmethod frame-hash-multi String
60 [image-name]
61 (let [image+ (ImagePlus. image-name)]
62 (frame-hash-multi image+)))
65 (defn frame-hash
66 "yields a convienent representation for the pixles in an image.
67 Because of the size of the structvre generated, this must only be used
68 in a transient way so that java can do it's garbage collection."
69 [something]
70 (frame-hash-multi something))
72 ;(def frame-hash (preserve-meta frame-hash))
77 (def white {:r 255, :g 255, :b 255})
78 (def black {:r 0, :g 0, :b 0})
82 (defn rgb-euclidian
83 [{r1 :r g1 :g b1 :b} {r2 :r g2 :g b2 :b} ]
84 (expt (+ (expt (- r1 r2) 2)
85 (expt (- g1 g2) 2)
86 (expt (- b1 b2) 2)) 0.5))
88 (defn b&w
89 "turn everything strictly black or white"
90 [window]
91 (with-meta
92 (zipmap
93 (keys window)
94 (map (fn [rgb]
95 (if (> (rgb-euclidian rgb white) (rgb-euclidian rgb black))
96 black white))
97 (vals window))) (meta window)))
101 (defn raster-preamble []
102 (str-join \newline
103 ["M63 P0\nG61"
104 (str \F feed)
105 "M101"
106 "M3 S1\n"]))
108 (defn raster-epilogue []
109 (str-join \newline
110 ["M63 P0"
111 "M5"
112 "M2\n"]))
115 (defn raster-comment [string]
116 (str "(" (re-gsub #"[()]" "" string) ")"))
118 (defn filter-keys [fun m]
119 (select-keys m (filter fun (keys m))))
121 (def filter-keys (preserve-meta filter-keys))
123 (defn filter-vals [fun m]
124 (into {} (filter (comp fun val) m)))
126 (def filter-vals (preserve-meta filter-vals))
128 (defn frame-hash->bufferedImage
129 [frame-hash]
130 (let [data (meta frame-hash)
131 image (BufferedImage. (:width data) (:height data) BufferedImage/TYPE_INT_BGR)]
133 (doall (for [element frame-hash]
134 (let [coord (key element)
135 rgb (val element)
136 packed-RGB
137 (+ (bit-shift-left (:r rgb) 16)
138 (bit-shift-left (:g rgb) 8)
139 (:b rgb))]
140 (.setRGB image (first coord) (last coord) packed-RGB))))
141 image))
143 (defmulti display "Creates a JFrame and displays a buffered image" class)
145 (defn- makePanel [image] (proxy [Panel] [] (paint [g] (.drawImage g image 0 0 nil))))
147 (defn select-row [x window]
148 (filter-keys (comp (partial = x) first) window))
152 (defmethod display
153 BufferedImage [image]
154 (let [panel (makePanel image)
155 frame (JFrame. "Oh Yeah!")]
156 (.add frame panel)
157 (.pack frame)
158 (.setVisible frame true )
159 (.setSize frame(.getWidth image) (.getHeight image))))
161 (defmethod display
162 ImagePlus [image]
163 (display (.getBufferedImage image)))
165 (defmethod display
166 clojure.lang.PersistentHashMap [frame-hash]
167 (display (frame-hash->bufferedImage frame-hash)))
169 (defmethod display
170 clojure.lang.PersistentArrayMap [frame-hash]
171 (display (frame-hash->bufferedImage frame-hash)))
177 ;this is a sequence of rows
179 ;(defn span [row]
180 ; (let [sorted-row (sort #(< (first %1) (first %2)) row)]
181 ; (vector (first sorted-row) (last sorted-row))))
184 (defn row->gcode [[x-dpi y-dpi] row]
185 (let [[x1 y1] (first row)
186 [x2 y2] (last row)]
187 (str (format "G0 X%.3f Y%.3f\n"
188 (float (* x1 (/ x-dpi)))
189 (float (* y1 (/ y-dpi))))
191 (format "G1 X%.3f Y%.3f\n"
192 (float (* x2 (/ x-dpi)))
193 (float (* y2 (/ y-dpi)))))))
195 (defn gather-row [row]
196 (let [base [[(first (first row)) (first (first row))]]]
197 ; (println base)
198 (reduce
199 (fn colapse [collection new-n]
201 (let [collection (apply vector collection)
202 prevoius (last (last collection))
203 range-start (first (last collection))]
204 ; (println new-n)
205 ; (println prevoius)
206 ; (println range-start)
207 (if (<= new-n (+ prevoius 1))
208 (do ;(println "join")
209 ;(println (butlast collection))
210 (conj (apply vector (butlast collection))
211 (vector range-start new-n)))
212 (conj collection (vector new-n new-n)))))
214 base
215 (map first row))))
220 (defn row->gmask [[x-dpi y-dpi] forward? row]
221 ; (println forward?)
222 (let [start (float (* (/ x-dpi) (first (first
223 (if forward?
224 (reverse row) row)))))]
226 (let [preamble (if-not forward?
227 (format "0 0 0 %.3f\n" start)
228 (format "0 0 1 %.3f\n" start))
229 body
230 (for [[x y]
231 (if forward?
232 (reverse (gather-row row))
233 (gather-row row))]
234 (let [x (float (* x (/ x-dpi)))
235 y (float (* y (/ x-dpi)))]
236 (if-not forward?
237 (str (format "0 0 1 %.3f\n" x)
238 (format "0 1 1 %.3f\n" y))
240 (str (format "0 0 0 %.3f\n" y)
241 (format "0 1 0 %.3f\n" x)))))]
243 (str preamble (str-join "" body)))))
247 (defn make-rows [pic]
249 (map (partial sort #(< (first %1) (first %2)))
250 (partition-by last
251 (sort (fn [[x1 y1][x2 y2]] (> y2 y1))
252 (map first (filter-vals (partial = black) pic))))))
256 (defn generate-gmask [pic]
258 (str "1 0 0 0\n"
259 (str-join "" (map (fn [[index row]]
260 (row->gmask dpi (even? index) row))
261 (indexed (make-rows pic))))))
264 ;; 1 0 0 0
265 ;; 0 0 1 2.881
266 ;; 0 0 0 2.881
267 ;; 0 1 0 2.863
268 ;; 0 0 0 2.769
269 ;; 0 1 0 2.751
270 ;; 0 0 0 2.729
271 ;; 0 1 0 2.617
272 ;; 0 0 0 2.593
273 ;; 0 1 0 2.561
274 ;; 0 0 0 2.463
275 ;; 0 1 0 2.445
276 ;; 0 0 0 2.385
277 ;; 0 1 0 2.317
278 ;; 0 0 0 2.253
279 ;; 0 1 0 2.233
280 ;; 0 0 0 2.177
284 (defn generate-gcode [pic]
285 (str (raster-preamble)
288 (str-join "" (map (partial row->gcode dpi) (make-rows pic)))
289 (raster-epilogue)))
293 (defn rotate [degrees #^ImagePlus image]
294 (.rotate (.getChannelProcessor image) degrees)
295 image)
297 (defn map-keys [f m]
298 (into {} (map (fn [[key val]] [(f key) val]) m)))
302 (defn invert-frame-hash [pic]
303 (map-keys (fn [[x y]] [x (- (:height (meta pic)) y 1)]) pic ))
306 (defn generate-files [pic]
307 (let [image (invert-frame-hash (b&w (frame-hash (rotate 180 (ImagePlus. pic)))))]
308 (spit "/home/r/kevin/out.ngc" (generate-gcode image))
309 (spit "/home/r/kevin/out.gmask" (generate-gmask image))
310 image))
314 (defn update-state []
315 (def sing "/home/r/lasercutter/graster/signer4laser2x1.png")
317 (def pic (frame-hash (let [image (ImagePlus. sing)]
318 (.rotate (.getChannelProcessor image) 180)
319 image)))
321 (def pic (b&w pic)))
333 ;;;; testing
335 (defn init []
336 (let [stuff
338 (bound-fn []
340 (do
341 (println "hi everyone")
342 (def img "/home/r/kevin/sing.png")
343 (def pic (frame-hash (let [image (ImagePlus. img)]
344 (.rotate (.getChannelProcessor image) 180)
345 image)))
348 (def test-image
349 (invert-frame-hash (b&w (frame-hash (rotate 180 (ImagePlus. img))))))
351 (defn test-gmask []
352 (println (str-join "" (take 170 (generate-gmask test-image)))))
354 (println "ALL variables initialized!")
356 ))]
357 (.start
358 (Thread. stuff))))
362 (defn thread-test []
364 (let [temp *out*]
365 (.start
366 (Thread.
367 (fn []
368 (with-bindings {#'*out* temp}
369 (Thread/sleep 5000)
370 (println "hi")))))))