--- /dev/null
+/* \r
+ * PROJECT: NyARToolkit Quicktime utilities.\r
+ * --------------------------------------------------------------------------------\r
+ * Copyright (C)2008 arc@dmz\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this framework; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+ * \r
+ * For further information please contact.\r
+ * \r
+ * <arc(at)digitalmuseum.jp>\r
+ * \r
+ */\r
+\r
+package jp.nyatla.nyartoolkit.qt.utils;\r
+\r
+import java.awt.Dimension;\r
+import java.awt.event.ActionEvent;\r
+import java.awt.event.ActionListener;\r
+import java.io.File;\r
+\r
+import javax.swing.Timer;\r
+\r
+import quicktime.QTException;\r
+import quicktime.QTSession;\r
+import quicktime.io.QTFile;\r
+import quicktime.qd.PixMap;\r
+import quicktime.qd.QDConstants;\r
+import quicktime.qd.QDGraphics;\r
+import quicktime.qd.QDRect;\r
+import quicktime.std.StdQTConstants;\r
+import quicktime.std.movies.Movie;\r
+import quicktime.std.movies.media.DataRef;\r
+import quicktime.std.sg.SGVideoChannel;\r
+import quicktime.std.sg.SequenceGrabber;\r
+import quicktime.util.RawEncodedImage;\r
+\r
+import jp.nyatla.nyartoolkit.NyARException;\r
+\r
+/**\r
+ * QuickTimeキャプチャクラス\r
+ *\r
+ */\r
+public class QtCameraCapture implements ActionListener\r
+{\r
+\r
+ private Dimension image_size;\r
+\r
+ private QtCaptureListener capture_listener;\r
+\r
+ protected float fps = 30; // キャプチャ画像を取得するfps\r
+\r
+ protected byte[] pixels; // キャプチャ画像の実データを保持するバイト型配列\r
+\r
+ // キャプチャに使うタイマー\r
+ private Timer timer;\r
+\r
+ // QTJava用のあれこれ\r
+ private QDGraphics graphics;\r
+\r
+ private QDRect bounds;\r
+\r
+ private SequenceGrabber grabber;\r
+\r
+ private SGVideoChannel channel;\r
+\r
+ private RawEncodedImage rawEncodedImage;\r
+\r
+ private Movie movie;\r
+\r
+ // ピクセルフォーマット変換用の一時変数\r
+ private int[] pixels_int;\r
+\r
+ public static final int PIXEL_FORMAT_RGB = quicktime.util.EndianOrder.isNativeLittleEndian() ? QDConstants.k32BGRAPixelFormat : QDGraphics.kDefaultPixelFormat;\r
+\r
+ public QtCameraCapture(int i_width, int i_height, float i_rate)\r
+ {\r
+ image_size = new Dimension(i_width, i_height);\r
+ fps = i_rate;\r
+ }\r
+\r
+ public Dimension getSize()\r
+ {\r
+ return image_size;\r
+ }\r
+\r
+ public byte[] readBuffer() throws NyARException\r
+ {\r
+ if (grabber == null) {\r
+ throw new NyARException();\r
+ }\r
+ return pixels;\r
+ }\r
+\r
+ public void setCaptureListener(QtCaptureListener i_listener) throws NyARException\r
+ {\r
+ if (grabber != null) {\r
+ throw new NyARException();\r
+ }\r
+ capture_listener = i_listener;\r
+\r
+ }\r
+\r
+ /**\r
+ * @param input\r
+ * @throws QTException\r
+ */\r
+ public void prepSetInput(Object input) throws QTException\r
+ {\r
+ QTSession.open();\r
+ bounds = new QDRect(image_size.width, image_size.height);\r
+ graphics = new QDGraphics(quicktime.util.EndianOrder.isNativeLittleEndian() ? QDConstants.k32BGRAPixelFormat : QDGraphics.kDefaultPixelFormat, bounds);\r
+ if (input != null && input.getClass().equals(File.class)) {\r
+ movie = quicktime.std.movies.Movie.fromDataRef(new DataRef(new QTFile((File) input)), StdQTConstants.newMovieActive);\r
+ } else {\r
+ grabber = new SequenceGrabber();\r
+ grabber.setGWorld(graphics, null);\r
+ //Please check WinVDIG if you got couldntGetRequiredComponent exception on Windows.\r
+ channel = new SGVideoChannel(grabber);\r
+ channel.setBounds(bounds);\r
+\r
+ // seqGrabPreview == 2, Processingでmagic numberとしてハードコートされていた…\r
+ channel.setUsage(StdQTConstants.seqGrabPreview);\r
+\r
+ if (input != null) {\r
+ try {\r
+ channel.setDevice(input.toString());\r
+ } catch (QTException e) {\r
+ e.printStackTrace();\r
+ throw e;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Webcamの設定ダイアログを表示する。\r
+ * 既定のWebcamでは駄目な場合(複数のWebcamが接続されているPCなど)ではこれを実行するとよい。\r
+ */\r
+ public void prepShowDialog() throws QTException\r
+ {\r
+ channel.settingsDialog();\r
+ }\r
+\r
+ public void start() throws NyARException\r
+ {\r
+ try {\r
+\r
+ if (grabber == null)\r
+ prepSetInput(null);\r
+\r
+ if (movie == null) {\r
+ grabber.prepare(true, false); // あってもなくてもよさそう\r
+ grabber.startPreview();\r
+ } else {\r
+ movie.preroll(0, 1.0f);\r
+ while (movie.maxLoadedTimeInMovie() == 0)\r
+ movie.task(100);\r
+ movie.setRate(1);\r
+ movie.getPict(movie.getTime()).draw(graphics, bounds);\r
+ }\r
+ PixMap pixmap = graphics.getPixMap();\r
+ rawEncodedImage = pixmap.getPixelData();\r
+\r
+ image_size.width = rawEncodedImage.getRowBytes() / 4;\r
+ pixels = new byte[image_size.width * image_size.height * 3];\r
+ pixels_int = new int[image_size.width * image_size.height];\r
+ } catch (QTException e) {\r
+ QTSession.close();\r
+ throw new NyARException(e);\r
+ }\r
+\r
+ // キャプチャイメージを定期的に更新するタイマー\r
+ timer = new Timer((int) (1000 / fps), this);\r
+ timer.start();\r
+ }\r
+\r
+ public void stop()\r
+ {\r
+ finalize();\r
+ }\r
+\r
+ /** タイマー処理。キャプチャイメージの更新結果をリスナに伝える。 */\r
+ public void actionPerformed(ActionEvent event)\r
+ {\r
+\r
+ // 画像をQTJavaのRawEncodedImageとして取得\r
+ try {\r
+ if (movie == null) {\r
+ grabber.idle();\r
+ } else {\r
+ if (movie.isDone())\r
+ movie.goToBeginning();\r
+ movie.getPict(movie.getTime()).draw(graphics, bounds);\r
+ }\r
+ } catch (QTException e) {\r
+ QTSession.close();\r
+ e.printStackTrace();\r
+ }\r
+\r
+ // RawEncodedImageをint列に落とし込む\r
+ rawEncodedImage.copyToArray(0, pixels_int, 0, pixels_int.length);\r
+\r
+ // バイト列を生成する\r
+ int idx_byte = 0;\r
+ for (int idx = 0; idx < image_size.width * image_size.height; idx++) {\r
+ pixels[idx_byte++] = (byte) (pixels_int[idx] >> 16);\r
+ pixels[idx_byte++] = (byte) (pixels_int[idx] >> 8 & 0xff);\r
+ pixels[idx_byte++] = (byte) (pixels_int[idx] & 0xff);\r
+ }\r
+\r
+ // 各リスナに更新されたバイト列を渡す\r
+ capture_listener.onUpdateBuffer(pixels);\r
+ }\r
+\r
+ protected void finalize()\r
+ {\r
+ try {\r
+ if (movie == null) {\r
+ grabber.stop();\r
+ grabber.release();\r
+ grabber.disposeChannel(channel);\r
+ }\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ } finally {\r
+ QTSession.close();\r
+ }\r
+ timer.stop();\r
+ }\r
+\r
+}\r
--- /dev/null
+/* \r
+ * PROJECT: NyARToolkit Quicktime utilities.\r
+ * --------------------------------------------------------------------------------\r
+ * Copyright (C)2008 arc@dmz\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this framework; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+ * \r
+ * For further information please contact.\r
+ * \r
+ * <arc(at)digitalmuseum.jp>\r
+ * \r
+ */\r
+package jp.nyatla.nyartoolkit.qt.utils;\r
+\r
+/**\r
+ * QuickTime リスナクラス\r
+ *\r
+ */\r
+public interface QtCaptureListener\r
+{\r
+ public void onUpdateBuffer(byte[] i_buffer);\r
+ \r
+}
\ No newline at end of file
--- /dev/null
+/* \r
+ * PROJECT: NyARToolkit Quicktime utilities.\r
+ * --------------------------------------------------------------------------------\r
+ * Copyright (C)2008 arc@dmz\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ * \r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this framework; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+ * \r
+ * For further information please contact.\r
+ * \r
+ * <arc(at)digitalmuseum.jp>\r
+ * \r
+ */\r
+package jp.nyatla.nyartoolkit.qt.utils;\r
+\r
+\r
+import jp.nyatla.nyartoolkit.NyARException;\r
+import jp.nyatla.nyartoolkit.core.raster.rgb.*;\r
+import jp.nyatla.nyartoolkit.core.rasterreader.*;\r
+import jp.nyatla.nyartoolkit.core.types.*;\r
+\r
+/**\r
+ * RGB形式のbyte配列をラップするNyARRasterです。\r
+ * 保持したデータからBufferedImageを出力する機能も持ちます。\r
+ */\r
+public class QtNyARRaster_RGB implements INyARRgbRaster\r
+{\r
+ private NyARIntSize _size;\r
+ private byte[] _buffer;\r
+ private NyARRgbPixelReader_BYTE1D_R8G8B8_24 _reader;\r
+ private int _buffer_type;\r
+\r
+ /**\r
+ * QuickTimeオブジェクトからイメージを取得するラスタオブジェクトを作ります。\r
+ * この\r
+ * @param i_width\r
+ * @param i_height\r
+ */\r
+ public QtNyARRaster_RGB(int i_width, int i_height)\r
+ {\r
+ this._size=new NyARIntSize(i_width,i_height);\r
+ this._buffer= null;\r
+ this._buffer_type=NyARBufferType.BYTE1D_R8G8B8_24;\r
+ this._reader = new NyARRgbPixelReader_BYTE1D_R8G8B8_24(null,this._size);\r
+ }\r
+ \r
+ final public int getWidth()\r
+ {\r
+ return this._size.w;\r
+ }\r
+\r
+ final public int getHeight()\r
+ {\r
+ return this._size.h;\r
+ }\r
+\r
+ final public NyARIntSize getSize()\r
+ {\r
+ return this._size;\r
+ }\r
+ final public int getBufferType()\r
+ {\r
+ return this._buffer_type;\r
+ }\r
+ final public INyARRgbPixelReader getRgbPixelReader()\r
+ {\r
+ return this._reader;\r
+ }\r
+ final public boolean hasBuffer()\r
+ {\r
+ return this._buffer!=null;\r
+ }\r
+ final public Object getBuffer()\r
+ {\r
+ assert(this._buffer!=null);\r
+ return this._buffer;\r
+ }\r
+ final public boolean isEqualBufferType(int i_type_value)\r
+ {\r
+ return this._buffer_type==i_type_value;\r
+ }\r
+ final public void wrapBuffer(Object i_ref_buf) throws NyARException\r
+ {\r
+ this._buffer=(byte[])i_ref_buf;\r
+ this._reader.switchBuffer(i_ref_buf);\r
+ }\r
+}\r