annotate src/laser/rasterize.clj @ 7:5e167f275a93

moving to rt, hopefully I can do stuff now
author Robert McIntyre <rlm@mit.edu>
date Fri, 20 Aug 2010 06:53:41 -0400
parents 4ae2497acf7d
children 0f48db8d2a05
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@0 16 (use 'clojure.contrib.str-utils)
rlm@0 17
rlm@0 18 (use 'clojure.contrib.combinatorics)
rlm@0 19
rlm@0 20
rlm@0 21 (use 'clojure.contrib.repl-utils)
rlm@0 22
rlm@0 23 (set! *print-length* 20)
rlm@0 24
rlm@0 25
rlm@0 26 (def img "/home/r/graster/test.png")
rlm@0 27
rlm@1 28
rlm@1 29 (def feed 120)
rlm@1 30 (def dpi [500, 500])
rlm@1 31 (def on_range [0.0, 0.5])
rlm@1 32 (def overshoot 0.5)
rlm@1 33 (def offset [1.0, 1.0])
rlm@1 34 (def tiles [1, 1])
rlm@1 35 (def tile_size [false, false])
rlm@1 36 (def tile_spacing [0.125, 0.125])
rlm@1 37 (def feed 120)
rlm@1 38 (def cut_feed 20)
rlm@1 39 (def corner_radius 0)
rlm@1 40
rlm@1 41
rlm@5 42 (defn preserve-meta [f]
rlm@5 43 (fn [& x] (with-meta
rlm@5 44 (apply f x)
rlm@5 45 (meta (last x)))))
rlm@2 46
rlm@1 47
rlm@1 48
rlm@0 49 (defn frame-hash
rlm@0 50 "yields a convienent representation for the pixles in an image.
rlm@0 51 Because of the size of the structvre generated, this must only be used
rlm@0 52 in a transient way so that java can do it's garbage collection."
rlm@0 53 [#^java.lang.String image-name]
rlm@0 54 (let [image+ (ImagePlus. image-name)]
rlm@0 55 (with-meta
rlm@0 56 (let [buf (.. image+ getBufferedImage)
rlm@0 57 color (.getColorModel buf)]
rlm@0 58 (apply hash-map
rlm@0 59 (interleave
rlm@0 60 (doall (for [x (range (.getWidth image+)) y (range (.getHeight image+))]
rlm@0 61 (vector x y)))
rlm@0 62 (doall (for [x (range (.getWidth image+)) y (range (.getHeight image+))]
rlm@0 63 (let [data (.getRGB buf x y)]
rlm@0 64 (hash-map :r (bit-shift-right (bit-and 0xff0000 data) 16)
rlm@0 65 :g (bit-shift-right (bit-and 0x00ff00 data) 8)
rlm@0 66 :b (bit-and 0x0000ff data))))))))
rlm@0 67 {:width (.getWidth image+) :height (.getHeight image+)})))
rlm@0 68
rlm@0 69
rlm@5 70
rlm@5 71
rlm@5 72
rlm@5 73
rlm@5 74
rlm@1 75 (def white {:r 255, :g 255, :b 255})
rlm@1 76 (def black {:r 0, :g 0, :b 0})
rlm@1 77
rlm@1 78 (def expt #(Math/pow %1 %2))
rlm@1 79
rlm@1 80 (defn rgb-euclidian
rlm@1 81 [{r1 :r g1 :g b1 :b} {r2 :r g2 :g b2 :b} ]
rlm@1 82 (expt (+ (expt (- r1 r2) 2)
rlm@1 83 (expt (- g1 g2) 2)
rlm@1 84 (expt (- b1 b2) 2)) 0.5))
rlm@1 85
rlm@1 86 (defn b&w
rlm@1 87 "turn everything strictly black or white"
rlm@1 88 [window]
rlm@1 89 (with-meta
rlm@1 90 (zipmap
rlm@1 91 (keys window)
rlm@1 92 (map (fn [rgb]
rlm@1 93 (if (> (rgb-euclidian rgb white) (rgb-euclidian rgb black))
rlm@1 94 black white))
rlm@1 95 (vals window))) (meta window)))
rlm@1 96
rlm@1 97
rlm@1 98
rlm@3 99 (defn raster-preamble []
rlm@3 100 (str-join \newline
rlm@3 101 ["M63 P0\nG61"
rlm@3 102 (str \F feed)
rlm@3 103 "M101"
rlm@3 104 "M3 S1"]))
rlm@3 105
rlm@4 106 (defn raster-epilogue []
rlm@4 107 (str-join \newline
rlm@4 108 ["M63 PO"
rlm@4 109 "M5"
rlm@4 110 "M2"]))
rlm@3 111
rlm@1 112
rlm@4 113 (defn raster-comment [string]
rlm@4 114 (str "(" (re-gsub #"[()]" "" string) ")"))
rlm@1 115
rlm@4 116 (defn filter-keys [fun m]
rlm@4 117 (select-keys m (filter fun (keys m))))
rlm@6 118
rlm@5 119 (def filter-keys (preserve-meta filter-keys))
rlm@2 120
rlm@4 121 (defn filter-vals [fun m]
rlm@5 122 (into {} (filter (comp fun val) m)))
rlm@6 123
rlm@5 124 (def filter-vals (preserve-meta filter-vals))
rlm@1 125
rlm@0 126 (defn frame-hash->bufferedImage
rlm@0 127 [frame-hash]
rlm@0 128 (let [data (meta frame-hash)
rlm@0 129 image (BufferedImage. (:width data) (:height data) BufferedImage/TYPE_INT_BGR)]
rlm@0 130
rlm@0 131 (doall (for [element frame-hash]
rlm@0 132 (let [coord (key element)
rlm@0 133 rgb (val element)
rlm@0 134 packed-RGB
rlm@0 135 (+ (bit-shift-left (:r rgb) 16)
rlm@0 136 (bit-shift-left (:g rgb) 8)
rlm@0 137 (:b rgb))]
rlm@0 138 (.setRGB image (first coord) (last coord) packed-RGB))))
rlm@0 139 image))
rlm@5 140
rlm@5 141 (defmulti display "Creates a JFrame and displays a buffered image" class)
rlm@0 142
rlm@5 143 (defn- makePanel [image] (proxy [Panel] [] (paint [g] (.drawImage g image 0 0 nil))))
rlm@0 144
rlm@6 145 (defn select-row [x window]
rlm@6 146 (filter-keys (comp (partial = x) first) window))
rlm@6 147
rlm@6 148
rlm@0 149
rlm@5 150 (defmethod display
rlm@5 151 BufferedImage [image]
rlm@5 152 (let [panel (makePanel image)
rlm@5 153 frame (JFrame. "Oh Yeah!")]
rlm@5 154 (.add frame panel)
rlm@5 155 (.pack frame)
rlm@5 156 (.setVisible frame true )
rlm@5 157 (.setSize frame(.getWidth image) (.getHeight image))))
rlm@5 158
rlm@5 159 (defmethod display
rlm@5 160 ImagePlus [image]
rlm@5 161 (display (.getBufferedImage image)))
rlm@5 162
rlm@5 163 (defmethod display
rlm@5 164 clojure.lang.PersistentHashMap [frame-hash]
rlm@5 165 (display (frame-hash->bufferedImage frame-hash)))
rlm@5 166
rlm@5 167 (defmethod display
rlm@5 168 clojure.lang.PersistentArrayMap [frame-hash]
rlm@5 169 (display (frame-hash->bufferedImage frame-hash)))
rlm@5 170
rlm@5 171
rlm@5 172
rlm@5 173
rlm@5 174
rlm@7 175 ;this is a sequence of rows
rlm@7 176
rlm@7 177 ;(defn span [row]
rlm@7 178 ; (let [sorted-row (sort #(< (first %1) (first %2)) row)]
rlm@7 179 ; (vector (first sorted-row) (last sorted-row))))
rlm@7 180
rlm@7 181
rlm@7 182 (defn row->gcode [[x-dpi y-dpi] row]
rlm@7 183 (let [[x1 y1] (first row)
rlm@7 184 [x2 y2] (last row)]
rlm@7 185 (str (format "GO X%.3f Y%.3f\n"
rlm@7 186 (float (* x1 (/ x-dpi)))
rlm@7 187 (float (* y1 (/ y-dpi))))
rlm@7 188
rlm@7 189 (format "G1 X%.3f Y%.3f\n"
rlm@7 190 (float (* x2 (/ x-dpi)))
rlm@7 191 (float (* y2 (/ y-dpi)))))))
rlm@7 192
rlm@7 193 (defn gather-row [row]
rlm@7 194 (let [base [[(first (first row)) (first (first row))]]]
rlm@7 195 ; (println base)
rlm@7 196 (reduce
rlm@7 197 (fn colapse [collection new-n]
rlm@7 198
rlm@7 199 (let [collection (apply vector collection)
rlm@7 200 prevoius (last (last collection))
rlm@7 201 range-start (first (last collection))]
rlm@7 202 ; (println new-n)
rlm@7 203 ; (println prevoius)
rlm@7 204 ; (println range-start)
rlm@7 205 (if (<= new-n (+ prevoius 1))
rlm@7 206 (do ;(println "join")
rlm@7 207 ;(println (butlast collection))
rlm@7 208 (conj (apply vector (butlast collection)) (vector range-start new-n)))
rlm@7 209 (conj collection (vector new-n new-n)))))
rlm@7 210
rlm@7 211 base
rlm@7 212 (map first row))))
rlm@7 213
rlm@7 214
rlm@7 215
rlm@7 216 (defn row->gmask [[x-dpi y-dpi] forward? row]
rlm@7 217
rlm@7 218 (let [start (float (* (/ x-dpi) (first (first row))))]
rlm@7 219
rlm@7 220 (let [preamble (if forward?
rlm@7 221 (str
rlm@7 222 (format "0 0 0 %.3f\n" start)
rlm@7 223 (format "0 0 1 %.3f\n" start)))
rlm@7 224 body
rlm@7 225 (for [[x y] (gather-row row)]
rlm@7 226 (let [x (float (* x (/ x-dpi)))
rlm@7 227 y (float (* y (/ x-dpi)))]
rlm@7 228 (if forward?
rlm@7 229 (str (format "0 0 1 %.3f\n" x)
rlm@7 230 (format "0 1 1 %.3f\n" y))
rlm@7 231
rlm@7 232 (str (format "0 0 0 %.3f\n" x)
rlm@7 233 (format "0 1 0 %.3f\n" y)))))]
rlm@7 234
rlm@7 235 (str preamble (str-join "" body)))))
rlm@7 236
rlm@7 237
rlm@7 238
rlm@7 239 (defn make-rows [pic]
rlm@7 240
rlm@7 241 (map (partial sort #(< (first %1) (first %2)))
rlm@7 242 (partition-by last
rlm@7 243 (sort (fn [[x1 y1][x2 y2]] (> y2 y1))
rlm@7 244 (map first (filter-vals (partial = black) pic))))))
rlm@7 245
rlm@7 246
rlm@7 247
rlm@7 248
rlm@7 249 ;sequence of numbers indicating width
rlm@7 250 (def mega
rlm@7 251
rlm@7 252 ;sequence of rows
rlm@7 253
rlm@7 254 (map (partial sort #(< (first %1) (first %2)))
rlm@7 255 (partition-by last
rlm@7 256 (sort (fn [[x1 y1][x2 y2]] (> y2 y1))
rlm@7 257 (map first (filter-vals (partial = black) pic))))))
rlm@7 258
rlm@7 259
rlm@7 260
rlm@7 261
rlm@7 262 (defn generate-gmask [pic]
rlm@7 263
rlm@7 264 (str "1 0 0 0\n"
rlm@7 265 (str-join "" (map (fn [[index row]] (row->gmask dpi (even? index) row)) (indexed (make-rows pic))))))
rlm@7 266
rlm@7 267
rlm@7 268 (defn generate-gcode [pic]
rlm@7 269 (str-join "" (map (partial row->gcode dpi) (make-rows pic))))
rlm@7 270
rlm@7 271
rlm@7 272