capture.java

来自「This is processing for java examples.」· Java 代码 · 共 548 行 · 第 1/2 页

JAVA
548
字号
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- *//*  Part of the Processing project - http://processing.org  Copyright (c) 2004-08 Ben Fry and Casey Reas  The previous version of this code was developed by Hernando Barragan  This library is free software; you can redistribute it and/or  modify it under the terms of the GNU Lesser General Public  License as published by the Free Software Foundation; either  version 2.1 of the License, or (at your option) any later version.  This library is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  Lesser General Public License for more details.  You should have received a copy of the GNU Lesser General  Public License along with this library; if not, write to the  Free Software Foundation, Inc., 59 Temple Place, Suite 330,  Boston, MA  02111-1307  USA*/package processing.video;import processing.core.*;import java.lang.reflect.*;import quicktime.*;import quicktime.qd.*;import quicktime.std.*;import quicktime.std.sg.*;import quicktime.util.RawEncodedImage;/** * Watchin' shit on the telly. */public class Capture extends PImage implements Runnable {  // there are more, but these are all we'll provide for now  // The useful ref page for <a href="http://developer.apple.com/documentation/Java/Reference/1.4.1/Java141API_QTJ/constant-values.html">quicktime constants</a>  static public final int COMPOSITE = StdQTConstants.compositeIn;  // 0  static public final int SVIDEO = StdQTConstants.sVideoIn;  // 1  static public final int COMPONENT = StdQTConstants.rgbComponentIn;  // 2  static public final int TUNER = StdQTConstants.tvTunerIn;  // 6  static public final int NTSC = StdQTConstants.ntscIn;  static public final int PAL = StdQTConstants.palIn;  static public final int SECAM = StdQTConstants.secamIn;  // no longer needed because parent field added to PImage  //PApplet parent;  Method captureEventMethod;  String name; // keep track for error messages (unused)  Thread runner;  boolean available = false;  /** Temporary storage for the raw image      data read directly from the capture device */  public int data[];  public int dataWidth;  public int dataHeight;  public int dataRowBytes;  /** True if this image is currently being cropped */  public boolean crop;  public int cropX;  public int cropY;  public int cropW;  public int cropH;  public int frameRate;  public RawEncodedImage raw;  public SequenceGrabber capture;  /** the guy who's doing all the work */  public SGVideoChannel channel;  /** boundary of image at the requested size */  protected QDRect qdrect;    /*  static {    try {      QTSession.open();    } catch (QTException e) {      e.printStackTrace();    }      // this doesn't appear to do jack    QTRuntimeException.registerHandler(new QTRuntimeHandler() {        public void exceptionOccurred(QTRuntimeException e,                                      Object obj, String s, boolean flag) {          System.err.println("Problem inside Capture");          e.printStackTrace();        }      });  }    */  public Capture(PApplet parent, int requestWidth, int requestHeight) {    this(parent, requestWidth, requestHeight, null, 30);  }  public Capture(PApplet parent, int reqWidth, int reqHeight, int frameRate) {    this(parent, reqWidth, reqHeight, null, frameRate);  }  public Capture(PApplet parent, int reqWidth, int reqHeight, String name) {    this(parent, reqWidth, reqHeight, name, 30);  }  /**   * If 'name' is null or the empty string, it won't set a specific   * device, which means that QuickTime will use that last device   * used by a QuickTime application.   * <P/>   * Unfortunately, Apple's QuickTime API uses the name to select devices,   * and in some cases there might be cameras with the same name on a machine.   * If you ask for a camera of the same name in sequence, you might see if it   * just does the right thing and grabs each separate camera in succession.   * If that doesn't work, you might try calling settings() which will   * bring up the prompt where you can select a capture device.   * <P/>   * If the following function:   * <PRE>public void captureEvent(Capture c)</PRE>   * is defined in the host PApplet, then it will be called every   * time a new frame is available from the capture device.   */  public Capture(final PApplet parent,                 final int requestWidth, final int requestHeight,                 final String name, final int frameRate) {      // Running on EDT because of weird hang on OS X      // http://dev.processing.org/bugs/show_bug.cgi?id=882      // QTSession.open() is hanging, not sure why, but it seems to prefer      // being run from the EDT. Not sure if that's a mistaken expectation in      // QTJava (we hadn't had trouble in the past because we did everything      // on the EDT) or if something broken in more recent QTJ. Or (maybe most      // likely) we're simply hitting some other threading strangeness, and      // using invokeLater() isolates us from that. Which is a nice way of      // saying that it's a hack.    //SwingUtilities.invokeLater(new Runnable() {    //  public void run() {    init(parent, requestWidth, requestHeight, name, frameRate);    //}    //});  }  public void init(PApplet parent, int requestWidth, int requestHeight,                   String name, int frameRate) {    this.parent = parent;    this.name = name;    this.frameRate = frameRate;    try {      QTSession.open();    } catch (QTException e) {      e.printStackTrace(System.out);      return;    }    try {      qdrect = new QDRect(requestWidth, requestHeight);      // workaround for bug with the intel macs      QDGraphics qdgraphics = null; //new QDGraphics(qdrect);      if (quicktime.util.EndianOrder.isNativeLittleEndian()) {        qdgraphics = new QDGraphics(QDConstants.k32BGRAPixelFormat, qdrect);      } else {        qdgraphics = new QDGraphics(QDGraphics.kDefaultPixelFormat, qdrect);      }      capture = new SequenceGrabber();      capture.setGWorld(qdgraphics, null);      channel = new SGVideoChannel(capture);      channel.setBounds(qdrect);      channel.setUsage(2);  // what is this usage number?      capture.startPreview();  // maybe this comes later?      PixMap pixmap = qdgraphics.getPixMap();      raw = pixmap.getPixelData();      /*      if (name == null) {        channel.settingsDialog();      } else if (name.length() > 0) {        channel.setDevice(name);      }      */      if ((name != null) && (name.length() > 0)) {        channel.setDevice(name);      }      dataRowBytes = raw.getRowBytes();      dataWidth = dataRowBytes / 4;      dataHeight = raw.getSize() / dataRowBytes;      if (dataWidth != requestWidth) {        crop = true;        cropX = 0;        cropY = 0;        cropW = requestWidth;        cropH = requestHeight;      }      // initialize my PImage self      super.init(requestWidth, requestHeight, RGB);      parent.registerDispose(this);      try {        captureEventMethod =          parent.getClass().getMethod("captureEvent",                                      new Class[] { Capture.class });      } catch (Exception e) {        // no such method, or an error.. which is fine, just ignore      }      runner = new Thread(this);      runner.start();    } catch (QTException qte) {      //} catch (StdQTException qte) {      //qte.printStackTrace();      int errorCode = qte.errorCode();      if (errorCode == Errors.couldntGetRequiredComponent) {        // this can happen when the capture device isn't available        // or wasn't shut down properly        parent.die("No capture could be found, " +                   "or the VDIG is not installed correctly.", qte);      } else {        parent.die("Error while setting up Capture", qte);      }    } catch (Exception e) {      parent.die("Error while setting up Capture", e);    }  }  /**   * True if a frame is ready to be read.   * <PRE>   * // put this somewhere inside draw   * if (capture.available()) capture.read();   * </PRE>   * Alternatively, you can use captureEvent(Capture c) to notify you   * whenever available() is set to true. In which case, things might   * look like this:   * <PRE>   * public void captureEvent(Capture c) {   *   c.read();   *   // do something exciting now that c has been updated   * }   * </PRE>   */  public boolean available() {    return available;  }  /**   * Set the video to crop from its original.   * <P>   * It seems common that captures add lines to the top or bottom

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?