/**
         * i_imageから、idマーカを読みだします。
         * o_dataにはマーカデータ、o_paramにはまーかのパラメータを返却します。
         * @param image
         * @param i_square
         * @param o_data
         * @param o_param
         * @return
         * @throws NyARException
         */
        public bool pickFromRaster(INyARRgbRaster image, NyARIntPoint2d[] i_vertex, NyIdMarkerPattern o_data, NyIdMarkerParam o_param)
        {
            //遠近法のパラメータを計算
            if (!this._perspective_reader.setSourceSquare(i_vertex))
            {
                return(false);
            }
            ;

            INyARRgbPixelReader reader      = image.getRgbPixelReader();
            NyARIntSize         raster_size = image.getSize();


            PerspectivePixelReader.TThreshold th = this.__pickFromRaster_th;
            MarkerPattEncoder encoder            = this.__pickFromRaster_encoder;

            //マーカパラメータを取得
            this._perspective_reader.detectThresholdValue(reader, raster_size, th);

            if (!this._perspective_reader.readDataBits(reader, raster_size, th, encoder))
            {
                return(false);
            }
            int d = encoder.encode(o_data);

            if (d < 0)
            {
                return(false);
            }
            o_param.direction = d;
            o_param.threshold = th.th;

            return(true);
        }
        /**
         * i_imageから、idマーカを読みだします。
         * o_dataにはマーカデータ、o_paramにはマーカのパラメータを返却します。
         * @param image
         * @param i_vertex
         * @param o_data
         * @param o_param
         * @return
         * @
         */
        private bool _pickFromRaster(INyARGsPixelDriver i_pix_drv, NyIdMarkerPattern o_data, NyIdMarkerParam o_param)
        {
            PerspectivePixelReader.TThreshold th = this.__pickFromRaster_th;
            MarkerPattEncoder encoder            = this.__pickFromRaster_encoder;

            //マーカパラメータを取得
            this._perspective_reader.detectThresholdValue(i_pix_drv, th);

            if (!this._perspective_reader.readDataBits(i_pix_drv, i_pix_drv.getSize(), th, encoder))
            {
                return(false);
            }
            int d = encoder.encode(o_data);

            if (d < 0)
            {
                return(false);
            }
            o_param.direction = d;
            o_param.threshold = th.th;

            return(true);
        }
        public bool readDataBits(INyARRgbPixelReader i_reader, NyARIntSize i_raster_size, PerspectivePixelReader.TThreshold i_th, MarkerPattEncoder o_bitbuffer)
        {
            double[] index_x = this.__readDataBits_index_bit_x;
            double[] index_y = this.__readDataBits_index_bit_y;
            //読み出し位置を取得
            int size       = detectDataBitsIndex(i_reader, i_raster_size, i_th, index_x, index_y);
            int resolution = size + size - 1;

            if (size < 0)
            {
                return(false);
            }
            if (!o_bitbuffer.initEncoder(size - 1))
            {
                return(false);
            }

            double[] cpara       = this._cparam;
            int[]    ref_x       = this._ref_x;
            int[]    ref_y       = this._ref_y;
            int[]    pixcel_temp = this._pixcel_temp;

            double cpara_0 = cpara[0];
            double cpara_1 = cpara[1];
            double cpara_3 = cpara[3];
            double cpara_6 = cpara[6];


            int th = i_th.th;
            int p  = 0;

            for (int i = 0; i < resolution; i++)
            {
                //1列分のピクセルのインデックス値を計算する。
                double cy0     = 1 + index_y[i * 2 + 0];
                double cy1     = 1 + index_y[i * 2 + 1];
                double cpy0_12 = cpara_1 * cy0 + cpara[2];
                double cpy0_45 = cpara[4] * cy0 + cpara[5];
                double cpy0_7  = cpara[7] * cy0 + 1.0;
                double cpy1_12 = cpara_1 * cy1 + cpara[2];
                double cpy1_45 = cpara[4] * cy1 + cpara[5];
                double cpy1_7  = cpara[7] * cy1 + 1.0;

                int pt = 0;
                for (int i2 = 0; i2 < resolution; i2++)
                {
                    double d;
                    double cx0 = 1 + index_x[i2 * 2 + 0];
                    double cx1 = 1 + index_x[i2 * 2 + 1];

                    double cp6_0  = cpara_6 * cx0;
                    double cpx0_0 = cpara_0 * cx0;
                    double cpx3_0 = cpara_3 * cx0;

                    double cp6_1  = cpara_6 * cx1;
                    double cpx0_1 = cpara_0 * cx1;
                    double cpx3_1 = cpara_3 * cx1;

                    d         = cp6_0 + cpy0_7;
                    ref_x[pt] = (int)((cpx0_0 + cpy0_12) / d);
                    ref_y[pt] = (int)((cpx3_0 + cpy0_45) / d);
                    pt++;

                    d         = cp6_0 + cpy1_7;
                    ref_x[pt] = (int)((cpx0_0 + cpy1_12) / d);
                    ref_y[pt] = (int)((cpx3_0 + cpy1_45) / d);
                    pt++;

                    d         = cp6_1 + cpy0_7;
                    ref_x[pt] = (int)((cpx0_1 + cpy0_12) / d);
                    ref_y[pt] = (int)((cpx3_1 + cpy0_45) / d);
                    pt++;

                    d         = cp6_1 + cpy1_7;
                    ref_x[pt] = (int)((cpx0_1 + cpy1_12) / d);
                    ref_y[pt] = (int)((cpx3_1 + cpy1_45) / d);
                    pt++;
                }
                //1行分のピクセルを取得(場合によっては専用アクセサを書いた方がいい)
                i_reader.getPixelSet(ref_x, ref_y, resolution * 4, pixcel_temp);
                //グレースケールにしながら、line→mapへの転写
                for (int i2 = 0; i2 < resolution; i2++)
                {
                    int index = i2 * 3 * 4;
                    int pixel = (pixcel_temp[index + 0] + pixcel_temp[index + 1] + pixcel_temp[index + 2] +
                                 pixcel_temp[index + 3] + pixcel_temp[index + 4] + pixcel_temp[index + 5] +
                                 pixcel_temp[index + 6] + pixcel_temp[index + 7] + pixcel_temp[index + 8] +
                                 pixcel_temp[index + 9] + pixcel_temp[index + 10] + pixcel_temp[index + 11]) / (4 * 3);
                    //暗点を1、明点を0で表現します。
                    o_bitbuffer.setBitByBitIndex(p, pixel > th ? 0 : 1);
                    p++;
                }
            }

            /*
             *      for(int i=0;i<225*4;i++){
             *          this.vertex_x[i]=0;
             *          this.vertex_y[i]=0;
             *      }
             *      for(int i=0;i<(resolution)*2;i++){
             *          for(int i2=0;i2<(resolution)*2;i2++){
             *              this.vertex_x[i*(resolution)*2+i2]=(int)index_x[i2];
             *              this.vertex_y[i*(resolution)*2+i2]=(int)index_y[i];
             *
             *          }
             *      }
             */
            return(true);
        }
        private int detectDataBitsIndex(INyARRgbPixelReader i_reader, NyARIntSize i_raster_size, PerspectivePixelReader.TThreshold i_th, double[] o_index_row, double[] o_index_col)
        {
            //周波数を測定
            int[] freq_index1 = this.__detectDataBitsIndex_freq_index1;
            int[] freq_index2 = this.__detectDataBitsIndex_freq_index2;


            int frq_t = getRowFrequency(i_reader, i_raster_size, i_th.lt_y, i_th.th_h, i_th.th_l, freq_index1);
            int frq_b = getRowFrequency(i_reader, i_raster_size, i_th.rb_y, i_th.th_h, i_th.th_l, freq_index2);

            //周波数はまとも?
            if ((frq_t < 0 && frq_b < 0) || frq_t == frq_b)
            {
                return(-1);
            }
            //タイミングパターンからインデクスを作成
            int freq_h, freq_v;

            int[] index;
            if (frq_t > frq_b)
            {
                freq_h = frq_t;
                index  = freq_index1;
            }
            else
            {
                freq_h = frq_b;
                index  = freq_index2;
            }
            for (int i = 0; i < freq_h + freq_h - 1; i++)
            {
                o_index_row[i * 2]     = ((index[i + 1] - index[i]) * 2 / 5 + index[i]) + FRQ_EDGE;
                o_index_row[i * 2 + 1] = ((index[i + 1] - index[i]) * 3 / 5 + index[i]) + FRQ_EDGE;
            }


            int frq_l = getColFrequency(i_reader, i_raster_size, i_th.lt_x, i_th.th_h, i_th.th_l, freq_index1);
            int frq_r = getColFrequency(i_reader, i_raster_size, i_th.rb_x, i_th.th_h, i_th.th_l, freq_index2);

            //周波数はまとも?
            if ((frq_l < 0 && frq_r < 0) || frq_l == frq_r)
            {
                return(-1);
            }
            //タイミングパターンからインデクスを作成
            if (frq_l > frq_r)
            {
                freq_v = frq_l;
                index  = freq_index1;
            }
            else
            {
                freq_v = frq_r;
                index  = freq_index2;
            }
            //同じ周期?
            if (freq_v != freq_h)
            {
                return(-1);
            }

            for (int i = 0; i < freq_v + freq_v - 1; i++)
            {
                int w  = index[i];
                int w2 = index[i + 1] - w;
                o_index_col[i * 2]     = ((w2) * 2 / 5 + w) + FRQ_EDGE;
                o_index_col[i * 2 + 1] = ((w2) * 3 / 5 + w) + FRQ_EDGE;
            }
            //Lv4以上は無理
            if (freq_v > MAX_FREQ)
            {
                return(-1);
            }
            return(freq_v);
        }
        /**
         * この関数は、マーカパターンからデータを読み取ります。
         * @param i_reader
         * ラスタリーダ
         * @param i_raster_size
         * ラスタのサイズ
         * @param i_th
         * 敷居値情報
         * @param o_bitbuffer
         * データビットの出力先
         * @return
         * 成功するとtrue
         * @
         */
        public bool readDataBits(INyARGrayscaleRaster i_raster, PerspectivePixelReader.TThreshold i_th, MarkerPattEncoder o_bitbuffer)
        {
            int raster_width  = i_raster.getWidth();
            int raster_height = i_raster.getHeight();

            double[] index_x = this.__readDataBits_index_bit_x;
            double[] index_y = this.__readDataBits_index_bit_y;


            //読み出し位置を取得
            int size       = detectDataBitsIndex(i_raster, i_th, index_x, index_y);
            int resolution = size + size - 1;

            if (size < 0)
            {
                return(false);
            }
            if (!o_bitbuffer.initEncoder(size - 1))
            {
                return(false);
            }

            double[] cpara       = this._cparam;
            int[]    ref_x       = this._ref_x;
            int[]    ref_y       = this._ref_y;
            int[]    pixcel_temp = this._pixcel_temp;

            double cpara_0 = cpara[0];
            double cpara_1 = cpara[1];
            double cpara_3 = cpara[3];
            double cpara_6 = cpara[6];


            int th = i_th.th;
            int p  = 0;

            for (int i = 0; i < resolution; i++)
            {
                //1列分のピクセルのインデックス値を計算する。
                double cy0     = 1 + index_y[i * 2 + 0];
                double cy1     = 1 + index_y[i * 2 + 1];
                double cpy0_12 = cpara_1 * cy0 + cpara[2];
                double cpy0_45 = cpara[4] * cy0 + cpara[5];
                double cpy0_7  = cpara[7] * cy0 + 1.0;
                double cpy1_12 = cpara_1 * cy1 + cpara[2];
                double cpy1_45 = cpara[4] * cy1 + cpara[5];
                double cpy1_7  = cpara[7] * cy1 + 1.0;

                int pt = 0;
                for (int i2 = 0; i2 < resolution; i2++)
                {
                    int    xx, yy;
                    double d;
                    double cx0 = 1 + index_x[i2 * 2 + 0];
                    double cx1 = 1 + index_x[i2 * 2 + 1];

                    double cp6_0  = cpara_6 * cx0;
                    double cpx0_0 = cpara_0 * cx0;
                    double cpx3_0 = cpara_3 * cx0;

                    double cp6_1  = cpara_6 * cx1;
                    double cpx0_1 = cpara_0 * cx1;
                    double cpx3_1 = cpara_3 * cx1;

                    d         = cp6_0 + cpy0_7;
                    ref_x[pt] = xx = (int)((cpx0_0 + cpy0_12) / d);
                    ref_y[pt] = yy = (int)((cpx3_0 + cpy0_45) / d);
                    if (xx < 0 || xx >= raster_width || yy < 0 || yy >= raster_height)
                    {
                        ref_x[pt] = xx < 0 ? 0 : (xx >= raster_width ? raster_width - 1 : xx);
                        ref_y[pt] = yy < 0 ? 0 : (yy >= raster_height ? raster_height - 1 : yy);
                    }
                    pt++;

                    d         = cp6_0 + cpy1_7;
                    ref_x[pt] = xx = (int)((cpx0_0 + cpy1_12) / d);
                    ref_y[pt] = yy = (int)((cpx3_0 + cpy1_45) / d);
                    if (xx < 0 || xx >= raster_width || yy < 0 || yy >= raster_height)
                    {
                        ref_x[pt] = xx < 0 ? 0 : (xx >= raster_width ? raster_width - 1 : xx);
                        ref_y[pt] = yy < 0 ? 0 : (yy >= raster_height ? raster_height - 1 : yy);
                    }
                    pt++;

                    d         = cp6_1 + cpy0_7;
                    ref_x[pt] = xx = (int)((cpx0_1 + cpy0_12) / d);
                    ref_y[pt] = yy = (int)((cpx3_1 + cpy0_45) / d);
                    if (xx < 0 || xx >= raster_width || yy < 0 || yy >= raster_height)
                    {
                        ref_x[pt] = xx < 0 ? 0 : (xx >= raster_width ? raster_width - 1 : xx);
                        ref_y[pt] = yy < 0 ? 0 : (yy >= raster_height ? raster_height - 1 : yy);
                    }
                    pt++;

                    d         = cp6_1 + cpy1_7;
                    ref_x[pt] = xx = (int)((cpx0_1 + cpy1_12) / d);
                    ref_y[pt] = yy = (int)((cpx3_1 + cpy1_45) / d);
                    if (xx < 0 || xx >= raster_width || yy < 0 || yy >= raster_height)
                    {
                        ref_x[pt] = xx < 0 ? 0 : (xx >= raster_width ? raster_width - 1 : xx);
                        ref_y[pt] = yy < 0 ? 0 : (yy >= raster_height ? raster_height - 1 : yy);
                    }
                    pt++;
                }
                //1行分のピクセルを取得(場合によっては専用アクセサを書いた方がいい)
                i_raster.getPixelSet(ref_x, ref_y, resolution * 4, pixcel_temp, 0);
                //グレースケールにしながら、line→mapへの転写
                for (int i2 = 0; i2 < resolution; i2++)
                {
                    int index = i2 * 4;
                    int pixel = (pixcel_temp[index + 0] + pixcel_temp[index + 1] + pixcel_temp[index + 2] + pixcel_temp[index + 3]) / 4;
                    //				+pixcel_temp[index+4]+pixcel_temp[index+5]+
                    //							pixcel_temp[index+6]+pixcel_temp[index+7]+pixcel_temp[index+8]+
                    //							pixcel_temp[index+9]+pixcel_temp[index+10]+pixcel_temp[index+11])/(4*3);
                    //暗点を1、明点を0で表現します。
                    o_bitbuffer.setBitByBitIndex(p, pixel > th ? 0 : 1);
                    p++;
                }
            }
            return(true);
        }