OSDN Git Service

[backup]NyARToolkit
[nyartoolkit-and/nyartoolkit-and.git] / trunk / src.utils / jmf / jp / nyatla / nyartoolkit / jmf / utils / JmfNyARRaster_RGB.java
index 9e9dd9e..06fd00b 100644 (file)
-/**\r
- * RGB形式のJMFバッファをラップするNyARRasterです。\r
- * JMFから得たラスタデータのピクセル並び順を考慮します。\r
- * (c)2008 A虎@nyatla.jp\r
+/* \r
+ * PROJECT: NyARToolkit JMF utilities.\r
+ * --------------------------------------------------------------------------------\r
+ * The MIT License\r
+ * Copyright (c) 2008 nyatla\r
  * airmail(at)ebony.plala.or.jp\r
- * http://nyatla.jp/\r
+ * http://nyatla.jp/nyartoolkit/\r
+ * \r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy\r
+ * of this software and associated documentation files (the "Software"), to deal\r
+ * in the Software without restriction, including without limitation the rights\r
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+ * copies of the Software, and to permit persons to whom the Software is\r
+ * furnished to do so, subject to the following conditions:\r
+ * The above copyright notice and this permission notice shall be included in\r
+ * all copies or substantial portions of the Software.\r
+ * \r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+ * THE SOFTWARE.\r
+ * \r
  */\r
 package jp.nyatla.nyartoolkit.jmf.utils;\r
 \r
-\r
-import javax.media.format.RGBFormat;\r
+import javax.media.format.*;\r
+import javax.media.*;\r
 import java.awt.Dimension;\r
+import com.sun.media.codec.video.colorspace.*;\r
+\r
 import jp.nyatla.nyartoolkit.NyARException;\r
-import jp.nyatla.nyartoolkit.core.raster.NyARRaster;\r
+import jp.nyatla.nyartoolkit.core.raster.rgb.*;\r
+import jp.nyatla.nyartoolkit.core.rasterreader.*;\r
+import jp.nyatla.nyartoolkit.core.raster.*;\r
+import jp.nyatla.nyartoolkit.core.types.*;\r
 \r
 \r
-public class JmfNyARRaster_RGB implements NyARRaster\r
+\r
+\r
+\r
+/**\r
+ * \r
+ * RGB形式のJMFバッファをラップするNyARRasterです。\r
+ * JMFから得たラスタデータのピクセル並び順を考慮します。\r
+ *\r
+ */\r
+public class JmfNyARRaster_RGB implements INyARRgbRaster\r
 {\r
-    public final static int PIXEL_ORDER_RGB=1;\r
-    public final static int PIXEL_ORDER_BGR=2;\r
-    protected int pix_type;\r
-    private int red_idx;\r
-    private int green_idx;\r
-    private int blue_idx;\r
-    protected byte[] ref_buf;\r
-    protected int width=0;\r
-    protected int height=0;\r
-\r
-    /**\r
-     * RGB形式のJMFバッファをラップするオブジェクトをつくります。\r
-     * 生成直後のオブジェクトはデータを持ちません。\r
-     * メンバ関数はsetBufferを実行後に使用可能になります。\r
-     */\r
-    public JmfNyARRaster_RGB(int i_width,int i_height)\r
-    {\r
-       ref_buf=null;\r
-       width=i_width;\r
-       height=i_height;\r
-    }\r
-    /**\r
-     * フォーマットを解析して、インスタンスのフォーマットプロパティを初期化します。\r
-     * \r
-     * @param i_buffer\r
-     * @throws NyARException\r
-     */\r
-    protected void initFormatProperty(RGBFormat i_fmt) throws NyARException\r
-    {\r
-       //データサイズの確認\r
-        Dimension s=i_fmt.getSize();\r
-        if(width!=s.width || height !=s.height){\r
-           throw new NyARException();\r
-        }\r
-       //データ配列の確認\r
-       red_idx  =i_fmt.getRedMask()-1;\r
-       green_idx=i_fmt.getGreenMask()-1;\r
-       blue_idx =i_fmt.getBlueMask()-1;\r
-       \r
-       //色配列の特定\r
-       if(red_idx==0 && blue_idx==2){\r
-           pix_type=PIXEL_ORDER_RGB;\r
-       }else if(red_idx==2 && blue_idx==0){\r
-           pix_type=PIXEL_ORDER_BGR;\r
-       }else{\r
-           throw new NyARException("Unknown pixel order.");\r
-       }       \r
-    }\r
-    /**\r
-     * javax.media.Bufferを分析して、その分析結果をNyARRasterに適合する形で保持します。\r
-     * 関数実行後に外部でi_bufferの内容変更した場合には、再度setBuffer関数を呼び出してください。\r
-     * @param i_buffer\r
-     * RGB形式のデータを格納したjavax.media.Bufferオブジェクトを指定してください。\r
-     * @return\r
-     * i_bufferをラップしたオブジェクトを返します。\r
-     * @throws NyARException\r
-     */\r
-    public void setBuffer(javax.media.Buffer i_buffer) throws NyARException\r
-    {\r
-       initFormatProperty((RGBFormat)i_buffer.getFormat());\r
-        ref_buf=(byte[])i_buffer.getData();\r
-    }\r
-    public int getPixelTotal(int i_x,int i_y)\r
-    {\r
-        int bp=(i_x+i_y*width)*3;\r
-        byte[] ref=this.ref_buf;\r
-        return (ref[bp] & 0xff)+(ref[bp+1] & 0xff)+(ref[bp+2] & 0xff);\r
-    }\r
-    public void getPixelTotalRowLine(int i_row,int[] o_line)\r
-    {\r
-        final byte[] ref=this.ref_buf;\r
-        int bp=(i_row+1)*this.width*3-3;\r
-        for(int i=this.width-1;i>=0;i--){\r
-           o_line[i]=(ref[bp] & 0xff)+(ref[bp+1] & 0xff)+(ref[bp+2] & 0xff);\r
-           bp-=3;\r
-       }\r
-    }    \r
-    public int getWidth()\r
-    {\r
-        return width;\r
-    }\r
-    public int getHeight()\r
-    {\r
-        return height;\r
-    }\r
-    public void getPixel(int i_x,int i_y,int[] i_rgb)\r
-    {\r
-        int bp=(i_x+i_y*this.width)*3;\r
-        byte[] ref=this.ref_buf;\r
-        i_rgb[0]=(ref[bp+this.red_idx] & 0xff);//R\r
-        i_rgb[1]=(ref[bp+this.green_idx] & 0xff);//G\r
-        i_rgb[2]=(ref[bp+this.blue_idx] & 0xff);//B\r
-    }\r
-    /**\r
-     * ピクセルの順序タイプを返します。\r
-     * @return\r
-     * その値\r
-     */\r
-    public int getPixelOrder()\r
-    {\r
-       return pix_type;\r
-    }\r
-    /**\r
-     * データを持っているかを返します。\r
-     * @return\r
-     */\r
-    public boolean hasData()\r
-    {\r
-       return ref_buf!=null;\r
-    }\r
-    public void getPixelSet(int[] i_x,int i_y[],int i_num,int[] o_rgb)\r
-    {\r
-       int ri=this.red_idx;\r
-       int bi=this.green_idx;\r
-       int gi=this.blue_idx;\r
-       int width=this.width;\r
-       byte[] ref=this.ref_buf;\r
-       int bp;\r
-       for(int i=i_num-1;i>=0;i--){\r
-           bp=(i_x[i]+i_y[i]*width)*3;\r
-           o_rgb[i*3+0]=(ref[bp+ri] & 0xff);//R\r
-           o_rgb[i*3+1]=(ref[bp+gi] & 0xff);//G\r
-           o_rgb[i*3+2]=(ref[bp+bi] & 0xff);//B\r
+       private JmfRGB24RasterHolder _holder;\r
+       protected NyARIntSize _size;\r
+\r
+       /**\r
+        * i_fmtに一致する画素フォーマットのRasterを作成します。\r
+        * このコンストラクタで作成したクラスは、hasBuffer()がfalseを返すことがあります。\r
+        * @param i_width\r
+        * @param i_height\r
+        * @param i_fmt\r
+        * @throws NyARException\r
+        */\r
+       public JmfNyARRaster_RGB(int i_width,int i_height,VideoFormat i_fmt) throws NyARException\r
+       {\r
+               initMember(i_width,i_height,i_fmt);\r
+       }\r
+       /**\r
+        * i_fmtに一致する画素フォーマットのRasterを作成します。\r
+        * このコンストラクタで作成したクラスは、hasBuffer()がfalseを返すことがあります。\r
+        * @param i_size\r
+        * @param i_fmt\r
+        * @throws NyARException\r
+        */\r
+       public JmfNyARRaster_RGB(NyARIntSize i_size,VideoFormat i_fmt) throws NyARException\r
+       {\r
+               initMember(i_size.w,i_size.h,i_fmt);\r
+       }\r
+       private void initMember(int i_width,int i_height,VideoFormat i_fmt) throws NyARException\r
+       {\r
+               this._size= new NyARIntSize(i_width,i_height);\r
+               // データサイズの確認\r
+               final Dimension s = i_fmt.getSize();\r
+               if (!this._size.isEqualSize(s.width,s.height)) {\r
+                       throw new NyARException();\r
+               }\r
+               // データ配列の確認\r
+               if(i_fmt instanceof YUVFormat){\r
+                       //YUVフォーマット\r
+                       this._holder=new NyARGLPixelReader_YUV(this._size,(YUVFormat)i_fmt);                    \r
+               }else if(i_fmt instanceof RGBFormat){\r
+                       //RGBフォーマット\r
+                       this._holder=new NyARGLPixelReader_RGB24(this._size,(RGBFormat)i_fmt);\r
+               }else{\r
+                       throw new NyARException();\r
+               }               \r
+       }\r
+       public void setBuffer(javax.media.Buffer i_buffer) throws NyARException\r
+       {\r
+               this._holder.setMediaBuffer(i_buffer);\r
+               return;\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._holder.buffer_type;\r
+       }\r
+       final public INyARRgbPixelReader getRgbPixelReader()\r
+       {\r
+               return this._holder;\r
+       }\r
+       /**\r
+        * インスタンスがバッファを所有するかを返します。\r
+        * @return\r
+        */     \r
+       final public boolean hasBuffer()\r
+       {\r
+               return this._holder.buffer!=null;\r
+       }\r
+       final public Object getBuffer()\r
+       {\r
+               assert(this._holder.buffer!=null);\r
+               return this._holder.buffer;\r
+       }\r
+       final public boolean isEqualBufferType(int i_type_value)\r
+       {\r
+               return this._holder.buffer_type==i_type_value;\r
+       }\r
+       final public void wrapBuffer(Object i_ref_buf) throws NyARException\r
+       {\r
+               NyARException.notImplement();\r
+       }\r
+       /**\r
+        *      @deprecated hasBuffer()関数を使ってください。\r
+        * \r
+        */\r
+       final public boolean hasData()\r
+       {\r
+               return this.hasBuffer();\r
+       }\r
+\r
+}\r
+\r
+\r
+/**\r
+ * JMFと汎用バッファを中継する拡張INyARRgbPixelReader\r
+ * @author nyatla\r
+ *\r
+ */\r
+abstract class JmfRGB24RasterHolder implements INyARRgbPixelReader\r
+{\r
+       public int buffer_type;\r
+       public byte[] buffer;\r
+       public abstract void setMediaBuffer(javax.media.Buffer i_buffer);\r
+}\r
+\r
+/**\r
+ * RGB24フォーマットのデータを扱うピクセルリーダ\r
+ */\r
+class NyARGLPixelReader_RGB24 extends JmfRGB24RasterHolder\r
+{\r
+       protected boolean _is_flipped;\r
+       private NyARIntSize _ref_size;\r
+       public NyARGLPixelReader_RGB24(NyARIntSize i_ref_size,RGBFormat i_input_format) throws NyARException\r
+       {\r
+               this._ref_size=i_ref_size;\r
+               //ピクセルフォーマットを設定(現状は24bitRGBを受けつける。)\r
+               RGBFormat fm=(RGBFormat)i_input_format;\r
+               if(fm.getBitsPerPixel()!=24){\r
+                       throw new NyARException();\r
+               }\r
+               int r=fm.getRedMask();\r
+               int b=fm.getBlueMask();\r
+               if(r==1 && b==3){\r
+                       this.buffer_type=INyARRaster.BUFFERFORMAT_BYTE1D_R8G8B8_24;\r
+               }else if(r==3 && b==1){\r
+                       this.buffer_type=INyARRaster.BUFFERFORMAT_BYTE1D_B8G8R8_24;                     \r
+               }else{\r
+                       throw new NyARException();\r
+               }\r
+               //vertical反転の有無を確認\r
+               this._is_flipped=i_input_format.getFlipped()!=0?true:false;\r
+               this.buffer=new byte[i_ref_size.w*i_ref_size.h*3];\r
+               //RGBフォーマット\r
+               \r
+               return;\r
+       }\r
+       public void setMediaBuffer(javax.media.Buffer i_buffer)\r
+       {\r
+               //vertical反転が必要ならば、反転した画像を作成する。\r
+               byte[] src=(byte[])i_buffer.getData();\r
+               if(this._is_flipped){\r
+                       final int length = this._ref_size.w * 3;\r
+                       int src_idx = 0;\r
+                       int dest_idx = (this._ref_size.h - 1) * length;                 \r
+                       for (int i = 0; i < this._ref_size.h; i++) {\r
+                               System.arraycopy(src,src_idx, this.buffer, dest_idx, length);\r
+                               src_idx += length;\r
+                               dest_idx -= length;\r
+                       }\r
+               }else{\r
+                       System.arraycopy(src,0,this.buffer,0,this.buffer.length);\r
+                       this.buffer=(byte[])i_buffer.getData();\r
+               }\r
+               return;\r
+       }\r
+       public void getPixel(int i_x, int i_y, int[] o_rgb) throws NyARException\r
+       {\r
+               int bp = (i_x + i_y * this._ref_size.w) * 3;\r
+               byte[] ref = this.buffer;\r
+               switch(this.buffer_type){\r
+               case INyARRaster.BUFFERFORMAT_BYTE1D_R8G8B8_24:\r
+                       o_rgb[0] = (ref[bp + 0] & 0xff);// R\r
+                       o_rgb[1] = (ref[bp + 1] & 0xff);// G\r
+                       o_rgb[2] = (ref[bp + 2] & 0xff);// B\r
+                       break;\r
+               case INyARRaster.BUFFERFORMAT_BYTE1D_B8G8R8_24:\r
+                       o_rgb[0] = (ref[bp + 2] & 0xff);// B\r
+                       o_rgb[1] = (ref[bp + 1] & 0xff);// G\r
+                       o_rgb[2] = (ref[bp + 0] & 0xff);// R\r
+                       break;\r
+               default:\r
+                       throw new NyARException();\r
+               }\r
+               return;\r
+       }\r
+       public void getPixelSet(int[] i_x, int i_y[], int i_num, int[] o_rgb) throws NyARException\r
+       {\r
+               int width = this._ref_size.w;\r
+               byte[] ref = this.buffer;\r
+               int bp;\r
+               switch(this.buffer_type){\r
+               case INyARRaster.BUFFERFORMAT_BYTE1D_R8G8B8_24:\r
+                       for (int i = i_num - 1; i >= 0; i--) {\r
+                               bp = (i_x[i] + i_y[i] * width) * 3;\r
+                               o_rgb[i * 3 + 0] = (ref[bp + 0] & 0xff);// R\r
+                               o_rgb[i * 3 + 1] = (ref[bp + 1] & 0xff);// G\r
+                               o_rgb[i * 3 + 2] = (ref[bp + 2] & 0xff);// B\r
+                       }\r
+                       break;\r
+               case INyARRaster.BUFFERFORMAT_BYTE1D_B8G8R8_24:\r
+                       for (int i = i_num - 1; i >= 0; i--) {\r
+                               bp = (i_x[i] + i_y[i] * width) * 3;\r
+                               o_rgb[i * 3 + 0] = (ref[bp + 2] & 0xff);// B\r
+                               o_rgb[i * 3 + 1] = (ref[bp + 1] & 0xff);// G\r
+                               o_rgb[i * 3 + 2] = (ref[bp + 0] & 0xff);// R\r
+                       }\r
+                       break;\r
+               default:\r
+                       throw new NyARException();\r
+               }\r
+               return;\r
+       }\r
+       public void setPixel(int i_x, int i_y, int[] i_rgb) throws NyARException\r
+       {\r
+               NyARException.notImplement();           \r
+       }\r
+       public void setPixels(int[] i_x, int[] i_y, int i_num, int[] i_intrgb) throws NyARException\r
+       {\r
+               NyARException.notImplement();           \r
+       }\r
+       public void switchBuffer(Object i_ref_object) throws NyARException\r
+       {\r
+               NyARException.notImplement();           \r
+       }\r
+\r
+}\r
+\r
+\r
+\r
+\r
+/**\r
+ * ソースがYUVフォーマットのデータをBGR24として扱うピクセルリーダ\r
+ * ソースデータをセットした時に変換します。\r
+ * (将来YUVをそのまま素通りさせるように書き換えるかも)\r
+ */\r
+class NyARGLPixelReader_YUV extends JmfRGB24RasterHolder\r
+{\r
+       private NyARIntSize _ref_size;  \r
+       private YUVToRGB _yuv2rgb;\r
+\r
+       private javax.media.Buffer _rgb_buf;\r
+       /**\r
+        * フォーマットアレイから、BGR24フォーマットを探す\r
+        * @param i_formats\r
+        * @return\r
+        */\r
+       private Format pickRGB24Format(Format[] i_formats)\r
+       {\r
+               for(int i=0;i<i_formats.length;i++){\r
+                       RGBFormat f=(RGBFormat)i_formats[i];\r
+                       if(f.getBitsPerPixel()!=24){\r
+                               continue;\r
+                       }\r
+                       if(f.getRedMask()!=3 ||f.getGreenMask()!=2 ||f.getBlueMask()!=1 || f.getFlipped()!=0)\r
+                       {\r
+                               continue;\r
+                       }\r
+                       return f;\r
+               }\r
+               return null;\r
+       }\r
+       public NyARGLPixelReader_YUV(NyARIntSize i_ref_size,YUVFormat i_input_format) throws NyARException\r
+       {\r
+               this._ref_size=i_ref_size;\r
+               this.buffer_type=INyARRaster.BUFFERFORMAT_BYTE1D_B8G8R8_24;\r
+               this.buffer=null;\r
+               this._yuv2rgb=new YUVToRGB();\r
+               this._rgb_buf=new javax.media.Buffer();\r
+               //24bit-BGRフォーマットのものを探す\r
+               Format output_format=pickRGB24Format(this._yuv2rgb.getSupportedOutputFormats(i_input_format));\r
+               if(output_format==null){\r
+                       throw new NyARException();\r
+               }\r
+               this._yuv2rgb.setInputFormat(i_input_format);\r
+               this._yuv2rgb.setOutputFormat(output_format);\r
+               try{\r
+                       this._yuv2rgb.open();\r
+               }catch(Exception e){\r
+                       throw new NyARException();\r
+               }\r
+               return;\r
+       }\r
+       public void setMediaBuffer(javax.media.Buffer i_buffer)\r
+       {\r
+               //エラー出した時のトラップ\r
+               if(this._yuv2rgb.process(i_buffer, this._rgb_buf)!=YUVToRGB.BUFFER_PROCESSED_OK){\r
+                       System.err.println("YUVToRGB.process error:");\r
+               }\r
+               this.buffer=(byte[])this._rgb_buf.getData();\r
+               return;\r
+       }\r
+       public void getPixel(int i_x, int i_y, int[] o_rgb) throws NyARException\r
+       {\r
+               //IN :BGRBGR\r
+               //   :012012\r
+               final int bp = (i_x + i_y * this._ref_size.w) * 3;\r
+               final byte[] ref = this.buffer;\r
+               o_rgb[0] = (ref[bp + 2] & 0xff);// R\r
+               o_rgb[1] = (ref[bp + 1] & 0xff);// G\r
+               o_rgb[2] = (ref[bp + 0] & 0xff);// B\r
+               return;\r
+       }\r
+       public void getPixelSet(int[] i_x, int i_y[], int i_num, int[] o_rgb) throws NyARException\r
+       {\r
+               int bp;\r
+               final int width = this._ref_size.w;\r
+               final byte[] ref = this.buffer;\r
+               for (int i = i_num - 1; i >= 0; i--) {\r
+                       bp = (i_x[i] + i_y[i] * width) * 3;\r
+                       o_rgb[i * 3 + 0] = (ref[bp + 2] & 0xff);// R\r
+                       o_rgb[i * 3 + 1] = (ref[bp + 1] & 0xff);// G\r
+                       o_rgb[i * 3 + 2] = (ref[bp + 0] & 0xff);// B\r
+               }\r
+               return;\r
+       }\r
+       public void setPixel(int i_x, int i_y, int[] i_rgb) throws NyARException\r
+       {\r
+               NyARException.notImplement();           \r
+       }\r
+       public void setPixels(int[] i_x, int[] i_y, int i_num, int[] i_intrgb) throws NyARException\r
+       {\r
+               NyARException.notImplement();           \r
+       }\r
+       public void switchBuffer(Object i_ref_object) throws NyARException\r
+       {\r
+               NyARException.notImplement();           \r
        }       \r
-       return;\r
-    }\r
 }\r
+\r