Mercurial > lasercutter
view src/laser/rasterize.clj @ 13:397ab24b4952
saving, to update with correct fix later
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sun, 29 Aug 2010 00:03:09 -0400 |
parents | f952052e37b7 |
children | db745c95aabd |
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-meta36 (apply f x)37 (meta (last x)))))39 (defmulti frame-hash-multi class)42 (defmethod frame-hash-multi ImagePlus43 [image+]44 (with-meta45 (let [buf (.. image+ getBufferedImage)46 color (.getColorModel buf)]47 (apply hash-map48 (interleave49 (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 String60 [image-name]61 (let [image+ (ImagePlus. image-name)]62 (frame-hash-multi image+)))65 (defn frame-hash66 "yields a convienent representation for the pixles in an image.67 Because of the size of the structvre generated, this must only be used68 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-euclidian83 [{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&w89 "turn everything strictly black or white"90 [window]91 (with-meta92 (zipmap93 (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 \newline103 ["M63 P0\nG61"104 (str \F feed)105 "M101"106 "M3 S1\n"]))108 (defn raster-epilogue []109 (str-join \newline110 ["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->bufferedImage129 [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-RGB137 (+ (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 display153 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 display162 ImagePlus [image]163 (display (.getBufferedImage image)))165 (defmethod display166 clojure.lang.PersistentHashMap [frame-hash]167 (display (frame-hash->bufferedImage frame-hash)))169 (defmethod display170 clojure.lang.PersistentArrayMap [frame-hash]171 (display (frame-hash->bufferedImage frame-hash)))177 ;this is a sequence of rows179 ;(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 x2 (+ x2 (* x-dpi 0.318))]190 ; (println x2)191 (str (format "G0 X%.3f Y%.3f\n"192 (float (* x1 (/ x-dpi)))193 (float (* y1 (/ y-dpi))))195 (format "G1 X%.3f Y%.3f\n"196 (float (* x2 (/ x-dpi)))197 (float (* y2 (/ y-dpi)))))))199 (defn gather-row [row]200 (let [base [[(first (first row)) (first (first row))]]]201 ; (println base)202 (reduce203 (fn colapse [collection new-n]205 (let [collection (apply vector collection)206 prevoius (last (last collection))207 range-start (first (last collection))]208 ; (println new-n)209 ; (println prevoius)210 ; (println range-start)211 (if (<= new-n (+ prevoius 1))212 (do ;(println "join")213 ;(println (butlast collection))214 (conj (apply vector (butlast collection))215 (vector range-start new-n)))216 (conj collection (vector new-n new-n)))))218 base219 (map first row))))224 (defn row->gmask [[x-dpi y-dpi] forward? row]225 ; (println forward?)226 (let [start (float (* (/ x-dpi) (first (first227 (if forward?228 (reverse row) row)))))]230 (let [preamble (if-not forward?231 (format "0 0 0 %.3f\n" start)232 (format "0 0 1 %.3f\n" start))233 body234 (for [[x y]235 (if forward?236 (reverse (gather-row row))237 (gather-row row))]238 (let [x (float (* x (/ x-dpi)))239 y (float (* y (/ x-dpi)))240 x (+ x 0.159)];; shift by a small margin.241 (if-not forward?242 (str (format "0 0 1 %.3f\n" x)243 (format "0 1 1 %.3f\n" y))245 (str (format "0 0 0 %.3f\n" y)246 (format "0 1 0 %.3f\n" x)))))]248 (str preamble (str-join "" body)))))252 (defn make-rows [pic]253 (map (partial sort #(< (first %1) (first %2)))254 (partition-by last255 (sort (fn [[x1 y1][x2 y2]] (> y2 y1))256 (map first (filter-vals (partial = black) pic))))))260 (defn generate-gmask [pic]262 (str "1 0 0 0\n"263 (str-join "" (map (fn [[index row]]264 (row->gmask dpi (even? index) row))265 (indexed (make-rows pic))))))268 ;; 1 0 0 0269 ;; 0 0 1 2.881270 ;; 0 0 0 2.881271 ;; 0 1 0 2.863272 ;; 0 0 0 2.769273 ;; 0 1 0 2.751274 ;; 0 0 0 2.729275 ;; 0 1 0 2.617276 ;; 0 0 0 2.593277 ;; 0 1 0 2.561278 ;; 0 0 0 2.463279 ;; 0 1 0 2.445280 ;; 0 0 0 2.385281 ;; 0 1 0 2.317282 ;; 0 0 0 2.253283 ;; 0 1 0 2.233284 ;; 0 0 0 2.177288 (defn generate-gcode [pic]289 (str (raster-preamble)292 (str-join "" (map (partial row->gcode dpi) (make-rows pic)))293 (raster-epilogue)))297 (defn rotate [degrees #^ImagePlus image]298 (.rotate (.getChannelProcessor image) degrees)299 image)301 (defn map-keys [f m]302 (into {} (map (fn [[key val]] [(f key) val]) m)))306 (defn invert-frame-hash [pic]307 (map-keys (fn [[x y]] [x (- (:height (meta pic)) y 1)]) pic ))310 (defn generate-files [pic]311 (let [image (invert-frame-hash (b&w (frame-hash (rotate 180 (ImagePlus. pic)))))]312 (spit "/home/r/kevin/out.ngc" (generate-gcode image))313 (spit "/home/r/kevin/out.gmask" (generate-gmask image))314 image))318 (defn update-state []319 (def sing "/home/r/lasercutter/graster/signer4laser2x1.png")321 (def pic (frame-hash (let [image (ImagePlus. sing)]322 (.rotate (.getChannelProcessor image) 180)323 image)))325 (def pic (b&w pic)))337 ;;;; testing339 (defn init []340 (let [stuff342 (bound-fn []344 (do345 (println "hi everyone")346 (def img "/home/r/kevin/sing.png")347 (def pic (frame-hash (let [image (ImagePlus. img)]348 (.rotate (.getChannelProcessor image) 180)349 image)))352 (def test-image353 (invert-frame-hash (b&w (frame-hash (rotate 180 (ImagePlus. img))))))355 (defn test-gmask []356 (println (str-join "" (take 170 (generate-gmask test-image)))))358 (println "ALL variables initialized!")360 ))]361 (.start362 (Thread. stuff))))366 (defn thread-test []368 (let [temp *out*]369 (.start370 (Thread.371 (fn []372 (with-bindings {#'*out* temp}373 (Thread/sleep 5000)374 (println "hi")))))))377 (comment378 (do379 (require 'rlm.quick)380 (ns laser.rasterize)381 (rlm.quick/dirty)382 (use :reload-all 'laser.rasterize)383 (undef map-keys)384 (use :reload-all 'laser.rasterize)))