annotate src/laser/rasterize.clj @ 14:db745c95aabd

trying to revert back to a usable form
author Robert McIntyre <rlm@mit.edu>
date Sun, 29 Aug 2010 00:09:28 -0400
parents 397ab24b4952
children 8ad629298649
rev   line source
rlm@0 1 (ns laser.rasterize)
rlm@0 2
rlm@0 3 (import '(java.io File))
rlm@0 4 (import '(org.apache.commons.io FileUtils))
rlm@0 5 (import '(javax.imageio ImageIO) )
rlm@0 6 (import '(javax.swing JFrame))
rlm@0 7 (import '(java.awt Color BorderLayout))
rlm@0 8 (import '(ij ImagePlus IJ))
rlm@0 9 (import '(java.lang Math))
rlm@2 10 (import '(java.awt Graphics2D Panel))
rlm@0 11 (import '(ij Macro))
rlm@0 12
rlm@0 13 (import '(java.io BufferedReader InputStreamReader))
rlm@0 14 (import '(java.awt.image BufferedImage))
rlm@0 15
rlm@11 16 ;(use 'clojure.contrib.str-utils)
rlm@11 17 ;(use 'clojure.contrib.seq-utils)
rlm@11 18 ;(use 'clojure.contrib.combinatorics)
rlm@11 19 ;(use 'clojure.contrib.duck-streams)
rlm@0 20
rlm@11 21 ;(use 'clojure.contrib.repl-utils)
rlm@0 22
rlm@11 23 ;(set! *print-length* 20)
rlm@0 24
rlm@0 25
rlm@0 26
rlm@1 27
rlm@1 28 (def feed 120)
rlm@1 29 (def dpi [500, 500])
rlm@8 30
rlm@8 31
rlm@1 32
rlm@1 33
rlm@5 34 (defn preserve-meta [f]
rlm@5 35 (fn [& x] (with-meta
rlm@5 36 (apply f x)
rlm@5 37 (meta (last x)))))
rlm@2 38
rlm@8 39 (defmulti frame-hash-multi class)
rlm@1 40
rlm@1 41
rlm@8 42 (defmethod frame-hash-multi ImagePlus
rlm@8 43 [image+]
rlm@0 44 (with-meta
rlm@0 45 (let [buf (.. image+ getBufferedImage)
rlm@0 46 color (.getColorModel buf)]
rlm@0 47 (apply hash-map
rlm@0 48 (interleave
rlm@0 49 (doall (for [x (range (.getWidth image+)) y (range (.getHeight image+))]
rlm@0 50 (vector x y)))
rlm@0 51 (doall (for [x (range (.getWidth image+)) y (range (.getHeight image+))]
rlm@0 52 (let [data (.getRGB buf x y)]
rlm@0 53 (hash-map :r (bit-shift-right (bit-and 0xff0000 data) 16)
rlm@0 54 :g (bit-shift-right (bit-and 0x00ff00 data) 8)
rlm@0 55 :b (bit-and 0x0000ff data))))))))
rlm@8 56 {:width (.getWidth image+) :height (.getHeight image+)}))
rlm@0 57
rlm@0 58
rlm@8 59 (defmethod frame-hash-multi String
rlm@8 60 [image-name]
rlm@8 61 (let [image+ (ImagePlus. image-name)]
rlm@8 62 (frame-hash-multi image+)))
rlm@5 63
rlm@5 64
rlm@8 65 (defn frame-hash
rlm@8 66 "yields a convienent representation for the pixles in an image.
rlm@8 67 Because of the size of the structvre generated, this must only be used
rlm@8 68 in a transient way so that java can do it's garbage collection."
rlm@8 69 [something]
rlm@8 70 (frame-hash-multi something))
rlm@8 71
rlm@8 72 ;(def frame-hash (preserve-meta frame-hash))
rlm@8 73
rlm@5 74
rlm@5 75
rlm@5 76
rlm@1 77 (def white {:r 255, :g 255, :b 255})
rlm@1 78 (def black {:r 0, :g 0, :b 0})
rlm@1 79
rlm@11 80
rlm@1 81
rlm@1 82 (defn rgb-euclidian
rlm@1 83 [{r1 :r g1 :g b1 :b} {r2 :r g2 :g b2 :b} ]
rlm@1 84 (expt (+ (expt (- r1 r2) 2)
rlm@1 85 (expt (- g1 g2) 2)
rlm@1 86 (expt (- b1 b2) 2)) 0.5))
rlm@1 87
rlm@1 88 (defn b&w
rlm@1 89 "turn everything strictly black or white"
rlm@1 90 [window]
rlm@1 91 (with-meta
rlm@1 92 (zipmap
rlm@1 93 (keys window)
rlm@1 94 (map (fn [rgb]
rlm@1 95 (if (> (rgb-euclidian rgb white) (rgb-euclidian rgb black))
rlm@1 96 black white))
rlm@1 97 (vals window))) (meta window)))
rlm@1 98
rlm@1 99
rlm@1 100
rlm@3 101 (defn raster-preamble []
rlm@3 102 (str-join \newline
rlm@3 103 ["M63 P0\nG61"
rlm@3 104 (str \F feed)
rlm@3 105 "M101"
rlm@8 106 "M3 S1\n"]))
rlm@3 107
rlm@4 108 (defn raster-epilogue []
rlm@4 109 (str-join \newline
rlm@8 110 ["M63 P0"
rlm@4 111 "M5"
rlm@8 112 "M2\n"]))
rlm@3 113
rlm@1 114
rlm@4 115 (defn raster-comment [string]
rlm@4 116 (str "(" (re-gsub #"[()]" "" string) ")"))
rlm@1 117
rlm@4 118 (defn filter-keys [fun m]
rlm@4 119 (select-keys m (filter fun (keys m))))
rlm@6 120
rlm@5 121 (def filter-keys (preserve-meta filter-keys))
rlm@2 122
rlm@4 123 (defn filter-vals [fun m]
rlm@5 124 (into {} (filter (comp fun val) m)))
rlm@6 125
rlm@5 126 (def filter-vals (preserve-meta filter-vals))
rlm@1 127
rlm@0 128 (defn frame-hash->bufferedImage
rlm@0 129 [frame-hash]
rlm@0 130 (let [data (meta frame-hash)
rlm@0 131 image (BufferedImage. (:width data) (:height data) BufferedImage/TYPE_INT_BGR)]
rlm@0 132
rlm@0 133 (doall (for [element frame-hash]
rlm@0 134 (let [coord (key element)
rlm@0 135 rgb (val element)
rlm@0 136 packed-RGB
rlm@0 137 (+ (bit-shift-left (:r rgb) 16)
rlm@0 138 (bit-shift-left (:g rgb) 8)
rlm@0 139 (:b rgb))]
rlm@0 140 (.setRGB image (first coord) (last coord) packed-RGB))))
rlm@0 141 image))
rlm@5 142
rlm@5 143 (defmulti display "Creates a JFrame and displays a buffered image" class)
rlm@0 144
rlm@5 145 (defn- makePanel [image] (proxy [Panel] [] (paint [g] (.drawImage g image 0 0 nil))))
rlm@0 146
rlm@6 147 (defn select-row [x window]
rlm@6 148 (filter-keys (comp (partial = x) first) window))
rlm@6 149
rlm@6 150
rlm@0 151
rlm@5 152 (defmethod display
rlm@5 153 BufferedImage [image]
rlm@5 154 (let [panel (makePanel image)
rlm@5 155 frame (JFrame. "Oh Yeah!")]
rlm@5 156 (.add frame panel)
rlm@5 157 (.pack frame)
rlm@5 158 (.setVisible frame true )
rlm@5 159 (.setSize frame(.getWidth image) (.getHeight image))))
rlm@5 160
rlm@5 161 (defmethod display
rlm@5 162 ImagePlus [image]
rlm@5 163 (display (.getBufferedImage image)))
rlm@5 164
rlm@5 165 (defmethod display
rlm@5 166 clojure.lang.PersistentHashMap [frame-hash]
rlm@5 167 (display (frame-hash->bufferedImage frame-hash)))
rlm@5 168
rlm@5 169 (defmethod display
rlm@5 170 clojure.lang.PersistentArrayMap [frame-hash]
rlm@5 171 (display (frame-hash->bufferedImage frame-hash)))
rlm@5 172
rlm@5 173
rlm@5 174
rlm@5 175
rlm@5 176
rlm@7 177 ;this is a sequence of rows
rlm@7 178
rlm@7 179 ;(defn span [row]
rlm@7 180 ; (let [sorted-row (sort #(< (first %1) (first %2)) row)]
rlm@7 181 ; (vector (first sorted-row) (last sorted-row))))
rlm@7 182
rlm@7 183
rlm@14 184
rlm@14 185 (defn row->gcode [[x-dpi y-dpi] forward? row]
rlm@14 186
rlm@14 187 (let [[x1 y1] (if forward? (last row) (first row))
rlm@14 188 [x2 y2] (if forward? (first row) (last row))]
rlm@14 189
rlm@14 190
rlm@14 191 ; (let [[x1 y1] (first row)
rlm@14 192 ; [x2 y2] (last row)
rlm@14 193 ; x2 (+ x2 (* x-dpi 0.318))]
rlm@13 194
rlm@13 195
rlm@13 196 ; (println x2)
rlm@8 197 (str (format "G0 X%.3f Y%.3f\n"
rlm@7 198 (float (* x1 (/ x-dpi)))
rlm@7 199 (float (* y1 (/ y-dpi))))
rlm@7 200
rlm@7 201 (format "G1 X%.3f Y%.3f\n"
rlm@7 202 (float (* x2 (/ x-dpi)))
rlm@7 203 (float (* y2 (/ y-dpi)))))))
rlm@7 204
rlm@7 205 (defn gather-row [row]
rlm@7 206 (let [base [[(first (first row)) (first (first row))]]]
rlm@7 207 ; (println base)
rlm@7 208 (reduce
rlm@7 209 (fn colapse [collection new-n]
rlm@7 210
rlm@7 211 (let [collection (apply vector collection)
rlm@7 212 prevoius (last (last collection))
rlm@7 213 range-start (first (last collection))]
rlm@7 214 ; (println new-n)
rlm@7 215 ; (println prevoius)
rlm@7 216 ; (println range-start)
rlm@7 217 (if (<= new-n (+ prevoius 1))
rlm@11 218 (do ;(println "join")
rlm@7 219 ;(println (butlast collection))
rlm@11 220 (conj (apply vector (butlast collection))
rlm@11 221 (vector range-start new-n)))
rlm@11 222 (conj collection (vector new-n new-n)))))
rlm@7 223
rlm@7 224 base
rlm@11 225 (map first row))))
rlm@11 226
rlm@7 227
rlm@7 228
rlm@7 229
rlm@7 230 (defn row->gmask [[x-dpi y-dpi] forward? row]
rlm@11 231 ; (println forward?)
rlm@11 232 (let [start (float (* (/ x-dpi) (first (first
rlm@11 233 (if forward?
rlm@11 234 (reverse row) row)))))]
rlm@7 235
rlm@11 236 (let [preamble (if-not forward?
rlm@7 237 (format "0 0 0 %.3f\n" start)
rlm@11 238 (format "0 0 1 %.3f\n" start))
rlm@7 239 body
rlm@11 240 (for [[x y]
rlm@11 241 (if forward?
rlm@11 242 (reverse (gather-row row))
rlm@11 243 (gather-row row))]
rlm@7 244 (let [x (float (* x (/ x-dpi)))
rlm@13 245 y (float (* y (/ x-dpi)))
rlm@14 246 ;; x (+ x 0.159)];; shift by a small margin.
rlm@11 247 (if-not forward?
rlm@7 248 (str (format "0 0 1 %.3f\n" x)
rlm@7 249 (format "0 1 1 %.3f\n" y))
rlm@7 250
rlm@11 251 (str (format "0 0 0 %.3f\n" y)
rlm@11 252 (format "0 1 0 %.3f\n" x)))))]
rlm@7 253
rlm@7 254 (str preamble (str-join "" body)))))
rlm@7 255
rlm@7 256
rlm@7 257
rlm@7 258 (defn make-rows [pic]
rlm@7 259 (map (partial sort #(< (first %1) (first %2)))
rlm@7 260 (partition-by last
rlm@7 261 (sort (fn [[x1 y1][x2 y2]] (> y2 y1))
rlm@7 262 (map first (filter-vals (partial = black) pic))))))
rlm@7 263
rlm@7 264
rlm@7 265
rlm@7 266 (defn generate-gmask [pic]
rlm@7 267
rlm@7 268 (str "1 0 0 0\n"
rlm@8 269 (str-join "" (map (fn [[index row]]
rlm@11 270 (row->gmask dpi (even? index) row))
rlm@8 271 (indexed (make-rows pic))))))
rlm@8 272
rlm@11 273
rlm@8 274 ;; 1 0 0 0
rlm@8 275 ;; 0 0 1 2.881
rlm@8 276 ;; 0 0 0 2.881
rlm@8 277 ;; 0 1 0 2.863
rlm@8 278 ;; 0 0 0 2.769
rlm@8 279 ;; 0 1 0 2.751
rlm@8 280 ;; 0 0 0 2.729
rlm@8 281 ;; 0 1 0 2.617
rlm@8 282 ;; 0 0 0 2.593
rlm@8 283 ;; 0 1 0 2.561
rlm@8 284 ;; 0 0 0 2.463
rlm@8 285 ;; 0 1 0 2.445
rlm@8 286 ;; 0 0 0 2.385
rlm@8 287 ;; 0 1 0 2.317
rlm@8 288 ;; 0 0 0 2.253
rlm@8 289 ;; 0 1 0 2.233
rlm@8 290 ;; 0 0 0 2.177
rlm@8 291
rlm@7 292
rlm@7 293
rlm@7 294 (defn generate-gcode [pic]
rlm@8 295 (str (raster-preamble)
rlm@14 296
rlm@14 297 (str-join ""
rlm@14 298 (map
rlm@14 299 (fn [index row]
rlm@14 300 (partial row->gcode dpi (even? index)) (indexed (make-rows pic))))
rlm@14 301 (raster-epilogue))))
rlm@14 302
rlm@14 303
rlm@8 304
rlm@14 305 ; (str-join "" (map (partial row->gcode dpi) (make-rows pic)))
rlm@14 306 ; (raster-epilogue)))
rlm@8 307
rlm@7 308
rlm@7 309
rlm@8 310 (defn rotate [degrees #^ImagePlus image]
rlm@8 311 (.rotate (.getChannelProcessor image) degrees)
rlm@8 312 image)
rlm@7 313
rlm@8 314 (defn map-keys [f m]
rlm@8 315 (into {} (map (fn [[key val]] [(f key) val]) m)))
rlm@8 316
rlm@8 317
rlm@8 318
rlm@8 319 (defn invert-frame-hash [pic]
rlm@8 320 (map-keys (fn [[x y]] [x (- (:height (meta pic)) y 1)]) pic ))
rlm@8 321
rlm@8 322
rlm@8 323 (defn generate-files [pic]
rlm@8 324 (let [image (invert-frame-hash (b&w (frame-hash (rotate 180 (ImagePlus. pic)))))]
rlm@8 325 (spit "/home/r/kevin/out.ngc" (generate-gcode image))
rlm@8 326 (spit "/home/r/kevin/out.gmask" (generate-gmask image))
rlm@8 327 image))
rlm@8 328
rlm@11 329
rlm@11 330
rlm@11 331 (defn update-state []
rlm@11 332 (def sing "/home/r/lasercutter/graster/signer4laser2x1.png")
rlm@11 333
rlm@11 334 (def pic (frame-hash (let [image (ImagePlus. sing)]
rlm@11 335 (.rotate (.getChannelProcessor image) 180)
rlm@11 336 image)))
rlm@11 337
rlm@11 338 (def pic (b&w pic)))
rlm@11 339
rlm@11 340
rlm@11 341
rlm@11 342
rlm@11 343
rlm@11 344
rlm@11 345
rlm@11 346
rlm@11 347
rlm@11 348
rlm@8 349
rlm@8 350 ;;;; testing
rlm@8 351
rlm@8 352 (defn init []
rlm@8 353 (let [stuff
rlm@8 354
rlm@8 355 (bound-fn []
rlm@8 356
rlm@8 357 (do
rlm@8 358 (println "hi everyone")
rlm@8 359 (def img "/home/r/kevin/sing.png")
rlm@8 360 (def pic (frame-hash (let [image (ImagePlus. img)]
rlm@8 361 (.rotate (.getChannelProcessor image) 180)
rlm@8 362 image)))
rlm@8 363
rlm@8 364
rlm@8 365 (def test-image
rlm@8 366 (invert-frame-hash (b&w (frame-hash (rotate 180 (ImagePlus. img))))))
rlm@8 367
rlm@8 368 (defn test-gmask []
rlm@8 369 (println (str-join "" (take 170 (generate-gmask test-image)))))
rlm@8 370
rlm@8 371 (println "ALL variables initialized!")
rlm@8 372
rlm@8 373 ))]
rlm@8 374 (.start
rlm@8 375 (Thread. stuff))))
rlm@8 376
rlm@8 377
rlm@8 378
rlm@8 379 (defn thread-test []
rlm@8 380
rlm@8 381 (let [temp *out*]
rlm@8 382 (.start
rlm@8 383 (Thread.
rlm@8 384 (fn []
rlm@11 385 (with-bindings {#'*out* temp}
rlm@8 386 (Thread/sleep 5000)
rlm@8 387 (println "hi")))))))
rlm@13 388
rlm@13 389
rlm@13 390 (comment
rlm@13 391 (do
rlm@13 392 (require 'rlm.quick)
rlm@13 393 (ns laser.rasterize)
rlm@13 394 (rlm.quick/dirty)
rlm@13 395 (use :reload-all 'laser.rasterize)
rlm@13 396 (undef map-keys)
rlm@13 397 (use :reload-all 'laser.rasterize)))