view src/laser/rasterize.clj @ 20:6bed8ceb51a9

obtained a linear relation between output and target.
author Robert McIntyre <rlm@mit.edu>
date Mon, 30 Aug 2010 01:01:35 -0400
parents 3b255dcd6c50
children e72220627685
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 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 :x-offset 1 :y-offset 1})
21 ;;; this process is divided into two tasks,
22 ;;; creating the raster g-code, which sweeps back and forth
23 ;;; and creating the gmask, which turns the laser on and off.
26 ;;; we'll be using frame-hashes, which represent picutres as
27 ;;; a 3D vector field over 2D space, with the vectors representing
28 ;;; the rgb values at that particulat point.
30 (defn select-row
31 "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 last
38 (sort (fn [[x1 y1][x2 y2]] (> y2 y1))
39 (map first (filter-vals (partial = black) pic))))))
42 ;;; generate rastering g-code
44 (defn raster-preamble []
45 (str-join \newline
46 ["M63 P0\nG61"
47 (str "F" feed)
48 "M101"
49 "M3 S1\n"]))
51 (defn raster-epilogue []
52 (str-join \newline
53 ["M63 P0"
54 "M5"
55 "M2\n"]))
57 (defn raster-comment [string]
58 (str "(" (re-gsub #"[()]" "" string) ")"))
61 ;this is a sequence of rows
63 ;(defn span [row]
64 ; (let [sorted-row (sort #(< (first %1) (first %2)) row)]
65 ; (vector (first sorted-row) (last sorted-row))))
68 (comment
70 (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 mirror [#^ImagePlus img]
87 (let [title (.getTitle img)
88 target (.getBufferedImage img)
89 s2b (Stream2BufferedImage.)
90 shiv (doto (IMOperation.)
91 ;(.blur 2.0)
92 (.flip)
93 (.addImage)
94 (.addImage (into-array String ["png:-"])))
95 conv-shiv (doto (ConvertCmd.)
96 (.setOutputConsumer s2b))]
98 (.run conv-shiv shiv (into-array Object [target]))
99 (ImagePlus. title (.getImage s2b))))
103 (defn row->gcode [{:keys [x-dpi y-dpi margin x-offset y-offset]} forward? row]
105 (let [[x1 y1] (if forward? (last row) (first row))
106 [x2 y2] (if forward? (first row) (last row))]
108 (let [x1 (* x1 (/ x-dpi))
109 x2 (* x2 (/ x-dpi))
110 y1 (* y1 (/ y-dpi))
111 y2 (* y2 (/ y-dpi))]
113 (let [x1 (+ x1 x-offset)
114 x2 (+ x2 x-offset)
115 y1 (+ y1 y-offset)
116 y2 (+ y2 y-offset)]
120 (str (format "G0 X%.3f Y%.3f\n"
121 (float x1 )
122 (float y1))
124 (format "G1 X%.3f Y%.3f\n"
125 (float x2)
126 (float y2)))))))
128 (defn generate-gcode [pic]
129 (str (raster-preamble)
130 (str-join ""
131 (map
132 (fn [[index row]]
133 (row->gcode paramaters (even? index) row))
134 (indexed (make-rows pic))))
135 (raster-epilogue)))
155 (defn gather-row [row]
156 (let [base [[(first (first row)) (first (first row))]]]
157 ; (println base)
158 (reduce
159 (fn colapse [collection new-n]
161 (let [collection (apply vector collection)
162 prevoius (last (last collection))
163 range-start (first (last collection))]
164 ; (println new-n)
165 ; (println prevoius)
166 ; (println range-start)
167 (if (<= new-n (+ prevoius 1))
168 (do ;(println "join")
169 ;(println (butlast collection))
170 (conj (apply vector (butlast collection))
171 (vector range-start new-n)))
172 (conj collection (vector new-n new-n)))))
174 base
175 (map first row))))
180 (defn row->gmask [[x-dpi y-dpi] forward? row]
181 (let [start (float (* (/ x-dpi) (first (first
182 (if forward?
183 (reverse row) row)))))]
184 (let [preamble (if-not forward?
185 (format "0 0 0 %.3f\n" start)
186 (format "0 0 1 %.3f\n" start))
187 body
188 (for [[x y]
189 (if forward?
190 (reverse (gather-row row))
191 (gather-row row))]
192 (let [x (float (* x (/ x-dpi)))
193 y (float (* y (/ x-dpi)))]
194 ;; x (+ x 0.159)];; shift by a small margin.
195 (if-not forward?
196 (str (format "0 0 1 %.3f\n" x)
197 (format "0 1 1 %.3f\n" y))
199 (str (format "0 0 0 %.3f\n" y)
200 (format "0 1 0 %.3f\n" x)))))]
202 (str preamble (str-join "" body)))))
205 (defn generate-gmask [pic]
206 (str "1 0 0 0\n"
207 (str-join "" (map (fn [[index row]]
208 (row->gmask dpi (even? index) row))
209 (indexed (make-rows pic))))))
214 ;;;; testing
216 (defn generate-files [pic]
217 (println "made-image")
218 (spit "/home/r/kevin/out.ngc" (generate-gcode pic))
219 (println "/home/r/kevin/out.ngc")
220 (spit "/home/r/kevin/out.gmask" (generate-gmask pic))
221 (println "/home/r/kevin/out.gmask")
222 pic)
224 (defn update-state []
225 (def sing "/home/r/kevin/sing.png")
226 (def pic (frame-hash (mirror (ImagePlus. sing))))
227 (def pic (b&w pic)))
229 (defn compare-gen-fn [n f cmp]
230 (let [theirs (re-split #"\n" (slurp cmp))
231 ours (re-split #"\n" (f pic))]
232 (println (format "%1$-25s%2$s" "OURS" "THEIRS"))
233 (println "_______________________________________")
234 (dorun (map (fn [[us them]] (println
235 (format "%1$-25s%2$s" us them)))
236 (take n (partition 2 (interleave ours theirs)))))))
238 (defn compare-gcode [n]
239 (compare-gen-fn n generate-gcode "/home/r/kevin/reference.ngc"))
240 (defn compare-gmask [n]
241 (compare-gen-fn n generate-gmask "/home/r/kevin/reference.gmask"))