Skip to content

Instantly share code, notes, and snippets.

@lygaret
Created July 8, 2010 04:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lygaret/467654 to your computer and use it in GitHub Desktop.
Save lygaret/467654 to your computer and use it in GitHub Desktop.
get webcam frames from quicktime, process and display in clojure
;; open a skeleton swing window, and provide an image to draw into
(import
'(video VideoCapture)
'(java.awt Color Graphics Dimension)
'(java.awt.image BufferedImage ConvolveOp Kernel)
'(javax.swing JPanel JFrame))
(def fps 30)
(def fps-ms (/ 1000 fps))
(declare frame panel)
(def video (ref (new VideoCapture 400 400)))
(def mod-image (ref nil))
(def raw-image (ref nil))
(def modification-agent (agent nil))
(defn modify [x]
"Does whatever image processing is required"
(let [kernel (float-array [0.0 -1.0 0.0 -1.0 4.0 -1.0 0.0 -1.0 -0.0])
edgeop (new ConvolveOp (new Kernel 3 3 kernel))]
(dosync
(ref-set mod-image (. edgeop (filter @raw-image nil))))))
(def capture-agent (agent nil))
(defn capture [x]
"Captures an image from the video source, and stores in it the image ref"
(dosync
(ref-set raw-image (. @video getNextImage))
(. Thread (sleep fps-ms))
(send-off modification-agent #'modify)
(send-off *agent* #'capture)))
(def drawing-agent (agent nil))
(defn draw [x]
"Forces the screen to refresh"
(dosync
(. panel repaint)
(. Thread (sleep fps-ms))
(send-off *agent* #'draw)))
;;;; UI
(defn render [gfx]
(. gfx (drawImage @mod-image 0 0 nil)))
(def panel (doto (proxy [JPanel] []
(paint [gfx] (render gfx)))
(.setPreferredSize (new Dimension 400 400))))
(def frame (doto (new JFrame "Image Capture") (.add panel) (.pack) (.show)))
(defn start []
(send-off capture-agent #'capture)
(send-off drawing-agent #'draw))
package video;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.WritableRaster;
import quicktime.QTRuntimeException;
import quicktime.QTRuntimeHandler;
import quicktime.QTSession;
import quicktime.qd.PixMap;
import quicktime.qd.QDConstants;
import quicktime.qd.QDGraphics;
import quicktime.qd.QDRect;
import quicktime.std.StdQTConstants;
import quicktime.std.sg.SequenceGrabber;
import quicktime.std.sg.SGVideoChannel;
import quicktime.util.RawEncodedImage;
public class VideoCapture {
private SequenceGrabber grabber;
private SGVideoChannel channel;
private RawEncodedImage rowEncodedImage;
private int width;
private int height;
private int videoWidth;
private int[] pixels;
private BufferedImage image;
private WritableRaster raster;
public VideoCapture(int width, int height) throws Exception {
this.width = width;
this.height = height;
try {
QTSession.open();
QDRect bounds = new QDRect(width, height);
QDGraphics graphics = new QDGraphics(bounds);
grabber = new SequenceGrabber();
grabber.setGWorld(graphics, null);
channel = new SGVideoChannel(grabber);
channel.setBounds(bounds);
channel.setUsage(StdQTConstants.seqGrabPreview);
grabber.prepare(true, false);
grabber.startPreview();
PixMap pixMap = graphics.getPixMap();
rowEncodedImage = pixMap.getPixelData();
videoWidth = width + (rowEncodedImage.getRowBytes() - width * 4) / 4;
pixels = new int[videoWidth * height];
image = new BufferedImage(
videoWidth, height, BufferedImage.TYPE_INT_RGB);
raster = WritableRaster.createPackedRaster(DataBuffer.TYPE_INT,
videoWidth, height,
new int[] { 0x00ff0000, 0x0000ff00, 0x000000ff }, null);
raster.setDataElements(0, 0, videoWidth, height, pixels);
image.setData(raster);
QTRuntimeException.registerHandler(new QTRuntimeHandler() {
public void exceptionOccurred(
QTRuntimeException e, Object eGenerator,
String methodNameIfKnown, boolean unrecoverableFlag) {
System.out.println("what should i do?");
}
});
} catch (Exception e) {
QTSession.close();
throw e;
}
}
public void dispose() {
try {
grabber.stop();
grabber.release();
grabber.disposeChannel(channel);
image.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
QTSession.close();
}
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public int getVideoWidth() {
return videoWidth;
}
public int getVideoHeight() {
return height;
}
public void getNextPixels(int[] pixels) throws Exception {
grabber.idle();
rowEncodedImage.copyToArray(0, pixels, 0, pixels.length);
}
public Image getNextImage() throws Exception {
grabber.idle();
rowEncodedImage.copyToArray(0, pixels, 0, pixels.length);
raster.setDataElements(0, 0, videoWidth, height, pixels);
image.setData(raster);
return image;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment