rlm@1: (ns clojureDemo.Xuggle) rlm@1: rlm@1: (import '(ij ImagePlus IJ)) rlm@1: (import '(java.awt Rectangle Robot Toolkit) ) rlm@1: (import '(java.awt.image BufferedImage) ) rlm@1: (import '(java.awt Graphics2D Panel)) rlm@1: (import '(java.io File) ) rlm@1: (import '(javax.imageio ImageIO) ) rlm@1: (import '(com.xuggle.mediatool ToolFactory)) rlm@1: (import '(com.xuggle.mediatool IMediaDebugListener IMediaDebugListener$Event)) rlm@1: (import '(com.xuggle.mediatool MediaToolAdapter MediaListenerAdapter)) rlm@1: (import '(com.xuggle.xuggler IContainer IContainer$Type IPacket)) rlm@1: (import '(javax.swing JFrame)) rlm@1: (import '(com.xuggle.mediatool IMediaWriter)) rlm@1: (import '(org.apache.commons.io FileUtils)) rlm@1: (import '(javax.imageio.stream FileImageOutputStream)) rlm@1: (import '(javax.imageio ImageWriteParam IIOImage)) rlm@1: (import '(com.xuggle.xuggler IRational)) rlm@1: (import '(java.util.concurrent TimeUnit)) rlm@1: (import '(com.xuggle.xuggler ICodec)) rlm@1: rlm@1: (use 'clojureDemo.Defines) rlm@1: ;(use '[clojureDemo.OpenCv :only (video-data)]) rlm@1: rlm@1: rlm@1: rlm@1: (import '(java.io File)) rlm@1: (import '(org.apache.commons.io FileUtils)) rlm@1: (import '(javax.imageio ImageIO) ) rlm@1: rlm@1: (import '(ij.plugin PlugIn)) rlm@1: (import '(ij ImagePlus IJ)) rlm@1: rlm@1: rlm@1: (use 'clojure.contrib.repl-utils) rlm@1: (use ['clojureDemo.Defines rlm@1: :only '( rlm@1: lian look getto human0 blow base app0 app1 app2 app3 app4 app5 rlm@1: bounce0 bounce1 bounce2 bounce3 bounce4 bounce5 bounce6 rlm@1: collide0 collide1 collide2 collide3 collide4 rlm@1: give0 give1 give2 give3 give4 target default)]) rlm@1: rlm@1: rlm@1: ;(def hamster (ImagePlus. "lklk" (first (video-seq look)))) rlm@1: rlm@1: rlm@1: rlm@1: rlm@1: rlm@1: (defn- makePanel [image] (proxy [Panel] [] (paint [g] (.drawImage g image 0 0 nil)))) rlm@1: rlm@1: rlm@1: (defmulti display "Creates a JFrame and displays a buffered image" class) rlm@1: rlm@1: (defmethod display rlm@1: BufferedImage [image] rlm@1: (let [panel (makePanel image) rlm@1: frame (JFrame. "Oh Yeah!")] rlm@1: (.add frame panel) rlm@1: (.pack frame) rlm@1: (.setVisible frame true ) rlm@1: (.setSize frame(.getWidth image) (.getHeight image)))) rlm@1: rlm@1: (defmethod display rlm@1: ImagePlus [image] rlm@1: (display (.getBufferedImage image))) rlm@1: rlm@1: rlm@1: rlm@1: rlm@1: (defn flash rlm@1: [image] rlm@1: rlm@1: (.start (Thread. (fn [] rlm@1: (do rlm@1: (.show image) rlm@1: (.updateAndRepaintWindow image) rlm@1: (Thread/sleep 4000) rlm@1: (.hide image)))))) rlm@1: rlm@1: rlm@1: (defn readerRecurse rlm@1: "calls .readPacket until there's nothing left to do" rlm@1: [reader] rlm@1: (if (not (nil? (.readPacket reader))) ; here .readPacket actually does the processing as a side-effect. rlm@1: nil ; it returns null when it has MORE to process, and signals an error when done... rlm@1: (recur reader))) rlm@1: rlm@1: rlm@1: (def *cache-directory* (File. "/home/r/Desktop/vision-cache")) rlm@1: (def *ext* "jpg") rlm@1: rlm@1: rlm@1: rlm@1: rlm@1: (defn writeJpg rlm@1: "WTF is this shit?!" rlm@1: [image target quality] rlm@1: (let [jpgWriter (.next (ImageIO/getImageWritersByFormatName *ext*))] rlm@1: (doto (.getDefaultWriteParam jpgWriter) rlm@1: (.setCompressionMode ImageWriteParam/MODE_EXPLICIT) rlm@1: (.setCompressionQuality quality)) rlm@1: (doto jpgWriter rlm@1: (.setOutput (FileImageOutputStream. target)) rlm@1: (.write (IIOImage. image nil nil)) rlm@1: (.dispose)))) rlm@1: rlm@1: rlm@1: rlm@1: (defn cache-path rlm@1: [video] rlm@1: (File. *cache-directory* (.getName video))) rlm@1: rlm@1: (defn video-frame-path rlm@1: [video n] rlm@1: (File. (cache-path video) (str n "." *ext*))) rlm@1: rlm@1: rlm@1: (defn already-cached rlm@1: "this is the simplest and most retarded way to do it" rlm@1: [video] rlm@1: (.exists (cache-path video))) rlm@1: rlm@1: rlm@1: rlm@1: rlm@1: rlm@1: rlm@1: (defn make-incrementer [start increment] (let [a (ref (- start increment))] (fn [] (dosync (ref-set a (+ @a increment)))))) rlm@1: rlm@1: (defn make-frame-writer rlm@1: [video] rlm@1: (let [incrementer (make-incrementer 0 1)] rlm@1: (proxy [MediaListenerAdapter] [] rlm@1: rlm@1: (onVideoPicture rlm@1: [event] rlm@1: ;(println (.getImage event)) rlm@1: ;(println (File. (cache-path video) (str (incrementer) "." *ext* ) )) rlm@1: rlm@1: (let [target (File. (cache-path video) (str (incrementer) "." *ext* ))] rlm@1: (if (= *ext* "jpg") rlm@1: (writeJpg (.getImage event) target 1) rlm@1: (ImageIO/write (.getImage event) *ext* target ))))))) rlm@1: rlm@1: rlm@1: rlm@1: (defn cache rlm@1: "caching of frames without opencv" rlm@1: [video] rlm@1: rlm@1: (if (already-cached video) rlm@1: nil rlm@1: (time rlm@1: (let [reader (ToolFactory/makeReader (str video))] rlm@1: (println "slow cache!") rlm@1: (FileUtils/forceMkdir (cache-path video)) rlm@1: (doto reader rlm@1: (.setBufferedImageTypeToGenerate BufferedImage/TYPE_3BYTE_BGR) rlm@1: (.addListener (make-frame-writer video)) rlm@1: (.addListener (ToolFactory/makeDebugListener (into-array [IMediaDebugListener$Event/META_DATA])))) rlm@1: (readerRecurse reader))))) rlm@1: rlm@1: rlm@1: (defn video-data rlm@1: "get video data without opencv" rlm@1: [video] (cache video) rlm@1: rlm@1: rlm@1: {:length (- (count (file-seq (cache-path video))) 1) rlm@1: :width (.getWidth (ImagePlus. (str (video-frame-path video 0)))) rlm@1: :height (.getHeight (ImagePlus. (str (video-frame-path video 0)))) rlm@1: :fps 30}) ; yeah --- I'll figure this out later. rlm@1: (def video-data (memoize video-data)) rlm@1: rlm@1: rlm@1: rlm@1: (defn convert rlm@1: "takes video and converts it to a new type of video" rlm@1: [videoInput videoOutput] rlm@1: (let [reader (ToolFactory/makeReader (str videoInput))] rlm@1: (doto reader rlm@1: (.addListener (ToolFactory/makeWriter (str videoOutput) reader)) rlm@1: (.addListener (ToolFactory/makeDebugListener (into-array [IMediaDebugListener$Event/META_DATA])))) rlm@1: (readerRecurse reader))) rlm@1: rlm@1: rlm@1: (import '(com.xuggle.xuggler.video ConverterFactory)) rlm@1: rlm@1: rlm@1: (defn trans-save rlm@1: "this is a transitive way to save a stream to an avi file. rlm@1: It uses meta data to determine what fps to use to encode." rlm@1: [destination video-seq] rlm@1: (let [data (meta video-seq) rlm@1: writer (ToolFactory/makeWriter (str destination)) rlm@1: incrementer (make-incrementer 0 (/ 1 30))] rlm@1: (.addVideoStream writer 0 0 (ICodec/findEncodingCodecByName "mpeg4") rlm@1: (IRational/make (double (:fps data))) rlm@1: (int (:width data)) (int (:height data))) rlm@1: (dorun (map #(.encodeVideo writer 0 rlm@1: (ConverterFactory/convertToType (.getBufferedImage %) BufferedImage/TYPE_3BYTE_BGR) rlm@1: (long (* 1000000000 (incrementer))) TimeUnit/NANOSECONDS) video-seq)) rlm@1: (.close writer)) rlm@1: video-seq) rlm@1: rlm@1: rlm@1: (defn video-seq rlm@1: "let's use ImagePlus stuff!" rlm@1: ([video] (cache video) rlm@1: (with-meta (map #(ImagePlus. (str (video-frame-path video %))) (range (:length (video-data video))) ) (video-data video)))) rlm@1: rlm@1: rlm@1: rlm@1: rlm@1: rlm@1: rlm@1: (comment rlm@1: (do (use :reload-all 'clojureDemo.Xuggle) (in-ns 'clojureDemo.Xuggle)) rlm@1: ) rlm@1: