OSDN Git Service

[更新]NyARToolkit for Java
[nyartoolkit-and/nyartoolkit-and.git] / trunk / src / jp / nyatla / nyartoolkit / core / pickup / NyARColorPatt_Perspective.java
1 /* \r
2  * PROJECT: NyARToolkit(Extension)\r
3  * --------------------------------------------------------------------------------\r
4  * The NyARToolkit is Java edition ARToolKit class library.\r
5  * Copyright (C)2008-2009 Ryo Iizuka\r
6  *\r
7  * This program is free software: you can redistribute it and/or modify\r
8  * it under the terms of the GNU General Public License as published by\r
9  * the Free Software Foundation, either version 3 of the License, or\r
10  * (at your option) any later version.\r
11  * \r
12  * This program is distributed in the hope that it will be useful,\r
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15  * GNU General Public License for more details.\r
16  *\r
17  * You should have received a copy of the GNU General Public License\r
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
19  * \r
20  * For further information please contact.\r
21  *      http://nyatla.jp/nyatoolkit/\r
22  *      <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>\r
23  * \r
24  */\r
25 package jp.nyatla.nyartoolkit.core.pickup;\r
26 \r
27 import jp.nyatla.nyartoolkit.NyARException;\r
28 import jp.nyatla.nyartoolkit.core.raster.rgb.*;\r
29 import jp.nyatla.nyartoolkit.core.rasterreader.*;\r
30 import jp.nyatla.nyartoolkit.core.types.*;\r
31 import jp.nyatla.nyartoolkit.core.utils.NyARPerspectiveParamGenerator_O1;\r
32 \r
33 \r
34 /**\r
35  * 遠近法を使ったパースペクティブ補正をかけて、ラスタ上の四角形から\r
36  * 任意解像度の矩形パターンを作成します。\r
37  *\r
38  */\r
39 public class NyARColorPatt_Perspective implements INyARColorPatt\r
40 {\r
41         protected int[] _patdata;\r
42         protected NyARIntPoint2d _pickup_lt=new NyARIntPoint2d();       \r
43         protected int _resolution;\r
44         protected NyARBufferReader _buf_reader;\r
45         protected NyARIntSize _size;\r
46         protected NyARPerspectiveParamGenerator_O1 _perspective_gen;\r
47         private NyARRgbPixelReader_INT1D_X8R8G8B8_32 _pixelreader;\r
48         private static final int LOCAL_LT=1;\r
49         \r
50         private void initializeInstance(int i_width, int i_height,int i_point_per_pix)\r
51         {\r
52                 assert i_width>2 && i_height>2;\r
53                 this._resolution=i_point_per_pix;       \r
54                 this._size=new NyARIntSize(i_width,i_height);\r
55                 this._patdata = new int[i_height*i_width];\r
56                 this._buf_reader=new NyARBufferReader(this._patdata,NyARBufferReader.BUFFERFORMAT_INT1D_X8R8G8B8_32);\r
57                 this._pixelreader=new NyARRgbPixelReader_INT1D_X8R8G8B8_32(this._patdata,this._size);\r
58                 return;         \r
59         }\r
60         /**\r
61          * 例えば、64\r
62          * @param i_width\r
63          * 取得画像の解像度幅\r
64          * @param i_height\r
65          * 取得画像の解像度高さ\r
66          * @param i_point_per_pix\r
67          * 1ピクセルあたりの縦横サンプリング数。2なら2x2=4ポイントをサンプリングする。\r
68          */\r
69         public NyARColorPatt_Perspective(int i_width, int i_height,int i_point_per_pix)\r
70         {\r
71                 initializeInstance(i_width,i_height,i_point_per_pix);\r
72                 setEdgeSize(0,0,i_point_per_pix);\r
73                 return;\r
74         }\r
75         /**\r
76          * 例えば、64\r
77          * @param i_width\r
78          * 取得画像の解像度幅\r
79          * @param i_height\r
80          * 取得画像の解像度高さ\r
81          * @param i_edge_percentage\r
82          * エッジ幅の割合(ARToolKit標準と同じなら、25)\r
83          */\r
84         public NyARColorPatt_Perspective(int i_width, int i_height,int i_resolution,int i_edge_percentage)\r
85         {\r
86                 //入力制限\r
87                 initializeInstance(i_width,i_height,i_resolution);\r
88                 setEdgeSizeByPercent(i_edge_percentage,i_edge_percentage,i_resolution);\r
89                 return;\r
90         }       \r
91         /**\r
92          * 矩形領域のエッジサイズを指定します。\r
93          * エッジの計算方法は以下の通りです。\r
94          * 1.マーカ全体を(i_x_edge*2+width)x(i_y_edge*2+height)の解像度でパラメタを計算します。\r
95          * 2.ピクセルの取得開始位置を(i_x_edge/2,i_y_edge/2)へ移動します。\r
96          * 3.開始位置から、width x height個のピクセルを取得します。\r
97          * \r
98          * ARToolKit標準マーカの場合は、width/2,height/2を指定してください。\r
99          * @param i_x_edge\r
100          * @param i_y_edge\r
101          */\r
102         public void setEdgeSize(int i_x_edge,int i_y_edge,int i_resolution)\r
103         {\r
104                 assert(i_x_edge>=0);\r
105                 assert(i_y_edge>=0);\r
106                 //Perspectiveパラメタ計算器を作成\r
107                 this._perspective_gen=new NyARPerspectiveParamGenerator_O1(\r
108                         LOCAL_LT,LOCAL_LT,\r
109                         (i_x_edge*2+this._size.w)*i_resolution,\r
110                         (i_y_edge*2+this._size.h)*i_resolution);\r
111                 //ピックアップ開始位置を計算\r
112                 this._pickup_lt.x=i_x_edge*i_resolution+LOCAL_LT;\r
113                 this._pickup_lt.y=i_y_edge*i_resolution+LOCAL_LT;\r
114                 return;\r
115         }\r
116         public void setEdgeSizeByPercent(int i_x_percent,int i_y_percent,int i_resolution)\r
117         {\r
118                 assert(i_x_percent>=0);\r
119                 assert(i_y_percent>=0);\r
120                 setEdgeSize(this._size.w*i_x_percent/50,this._size.h*i_y_percent/50,i_resolution);\r
121                 return;\r
122         }\r
123 \r
124         \r
125         public final int getWidth()\r
126         {\r
127                 return this._size.w;\r
128         }\r
129         public final int getHeight()\r
130         {\r
131                 return this._size.h;\r
132         }\r
133         public final NyARIntSize getSize()\r
134         {\r
135                 return  this._size;\r
136         }\r
137         public final INyARBufferReader getBufferReader()\r
138         {\r
139                 return this._buf_reader;\r
140         }\r
141         public final INyARRgbPixelReader getRgbPixelReader()\r
142         {\r
143                 return this._pixelreader;\r
144         }\r
145         private final int[] __pickFromRaster_rgb_tmp = new int[3];\r
146         protected final double[] __pickFromRaster_cpara=new double[8];\r
147         \r
148         /**\r
149          * @see INyARColorPatt#pickFromRaster\r
150          */\r
151         public boolean pickFromRaster(INyARRgbRaster image,NyARIntPoint2d[] i_vertexs)throws NyARException\r
152         {\r
153                 //遠近法のパラメータを計算\r
154                 final double[] cpara = this.__pickFromRaster_cpara;\r
155                 if (!this._perspective_gen.getParam(i_vertexs, cpara)) {\r
156                         return false;\r
157                 }\r
158                 \r
159                 final int resolution=this._resolution;\r
160                 final int img_x = image.getWidth();\r
161                 final int img_y = image.getHeight();\r
162                 final int res_pix=resolution*resolution;\r
163 \r
164                 final int[] rgb_tmp = this.__pickFromRaster_rgb_tmp;\r
165 \r
166                 //ピクセルリーダーを取得\r
167                 INyARRgbPixelReader reader=image.getRgbPixelReader();\r
168                 int p=0;\r
169                 for(int iy=0;iy<this._size.h*resolution;iy+=resolution){\r
170                         //解像度分の点を取る。\r
171                         for(int ix=0;ix<this._size.w*resolution;ix+=resolution){\r
172                                 int r,g,b;\r
173                                 r=g=b=0;\r
174                                 for(int i2y=iy;i2y<iy+resolution;i2y++){\r
175                                         int cy=this._pickup_lt.y+i2y;\r
176                                         for(int i2x=ix;i2x<ix+resolution;i2x++){\r
177                                                 //1ピクセルを作成\r
178                                                 int cx=this._pickup_lt.x+i2x;\r
179                                                 final double d=cpara[6]*cx+cpara[7]*cy+1.0;\r
180                                                 int x=(int)((cpara[0]*cx+cpara[1]*cy+cpara[2])/d);\r
181                                                 int y=(int)((cpara[3]*cx+cpara[4]*cy+cpara[5])/d);\r
182                                                 if(x<0){x=0;}\r
183                                                 if(x>=img_x){x=img_x-1;}\r
184                                                 if(y<0){y=0;}\r
185                                                 if(y>=img_y){y=img_y-1;}\r
186                                                 \r
187                                                 reader.getPixel(x, y, rgb_tmp);\r
188                                                 r+=rgb_tmp[0];\r
189                                                 g+=rgb_tmp[1];\r
190                                                 b+=rgb_tmp[2];\r
191                                         }\r
192                                 }\r
193                                 r/=res_pix;\r
194                                 g/=res_pix;\r
195                                 b/=res_pix;\r
196                                 this._patdata[p]=((r&0xff)<<16)|((g&0xff)<<8)|((b&0xff));\r
197                                 p++;\r
198                         }\r
199                 }\r
200                         //ピクセル問い合わせ\r
201                         //ピクセルセット\r
202                 return true;\r
203         }\r
204 \r
205 }