android下根据公司需要修改后的能正常使用的坐标校准代码

来源:互联网 发布:柏林爱乐乐团知乎 编辑:程序博客网 时间:2024/05/10 12:47

     用于电子书的屏(具体我也不是很清楚),故需要在android系统源代码中修改坐标校准算法。

     上层代码应用在其它网页上也有,只是根据网上信息修改了校准算法(可上网查询,这里不再详述),同时将结果保存。代码如下:

package com.;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

public class Calibration extends Activity {
 static final int SAMPLE_COUNTS = 5;
 static final int POINT_DEGREE = 2;
 static final int FACTOR_COUNTS = 7;
 static final int TOP_LEFT = 0;
 static final int TOP_RIGHT = 1;
 static final int BOTTOM_RIGHT = 2;
 static final int BOTTOM_LEFT = 3;
 static final int CENTER = 4;
 static final int X_AXIS = 0;
 static final int Y_AXIS = 1;
 static final int EDGE_GAP = 200;

 static final String CALIBRATION_FILE = "/data/pointercal";
 //static final String CALIBRATION_FILE = "/mnt/sdcard/pointercal";
 static final String TAG = "Calibration";
 static final boolean DEBUG = true;

 private int X_RES;
 private int Y_RES;
 
 class calibration {
  int x[] = new int[5];//TouchScreen的x坐标
  int y[] = new int[5];//TouchScreen的y坐标
  int xfb[] = new int[5];//LCD的x坐标
  int yfb[] = new int[5];//LCD的y坐标
//  float a[] = new float[2];
  float a[] = new float[6];
 };

 private calibration cal;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  //Log.d(TAG, "onCreate");
  
  cal = new calibration();

  DisplayMetrics dpm = new DisplayMetrics();
  getWindowManager().getDefaultDisplay().getMetrics(dpm);
  X_RES = dpm.widthPixels;
  Y_RES = dpm.heightPixels;
  String str = String.format("X_RES = %d, Y_RES = %d", X_RES, Y_RES);
  Log.d(TAG, str);

  this.initScreenPoints();

  setContentView(new MyView(this));
 }

 // TopLeft-->TopRight-->BottomRight-->BottomLeft-->Center
 // 为240 * 320分辨率,我们使用50像素作为边缘的差距
 private boolean initScreenPoints() {
  String str;
  
  cal.xfb[TOP_LEFT] = EDGE_GAP; // TopLeft
  cal.yfb[TOP_LEFT] = EDGE_GAP;
  str = String.format("cal.xfb[%d] = %d, cal.yfb[%d] = %d", TOP_LEFT, cal.xfb[TOP_LEFT], TOP_LEFT, cal.yfb[TOP_LEFT]);
  Log.d("zxb", str);

  cal.xfb[TOP_RIGHT] = X_RES - EDGE_GAP; // TopRight
  cal.yfb[TOP_RIGHT] = EDGE_GAP;
  str = String.format("cal.xfb[%d] = %d, cal.yfb[%d] = %d", TOP_RIGHT, cal.xfb[TOP_RIGHT], TOP_RIGHT, cal.yfb[TOP_RIGHT]);
  Log.d("zxb", str);
  
  cal.xfb[BOTTOM_RIGHT] = X_RES - EDGE_GAP; // BottomRight
  cal.yfb[BOTTOM_RIGHT] = Y_RES - EDGE_GAP;
  str = String.format("cal.xfb[%d] = %d, cal.yfb[%d] = %d", BOTTOM_RIGHT, cal.xfb[BOTTOM_RIGHT], BOTTOM_RIGHT, cal.yfb[BOTTOM_RIGHT]);
  Log.d("zxb", str);

  cal.xfb[BOTTOM_LEFT] = EDGE_GAP; // BottomLeft
  cal.yfb[BOTTOM_LEFT] = Y_RES - EDGE_GAP;
  str = String.format("cal.xfb[%d] = %d, cal.yfb[%d] = %d", BOTTOM_LEFT, cal.xfb[BOTTOM_LEFT], BOTTOM_LEFT, cal.yfb[BOTTOM_LEFT]);
  Log.d("zxb", str);

  cal.xfb[CENTER] = X_RES / 2; // Center
  cal.yfb[CENTER] = Y_RES / 2;
  str = String.format("cal.xfb[%d] = %d, cal.yfb[%d] = %d", CENTER, cal.xfb[CENTER], CENTER, cal.yfb[CENTER]);
  Log.d("zxb", str);
  
  return true;
 }

 private boolean perform_calibration() {
  String str;
/*  
  cal.a[0] = ((float)(cal.x[1] - cal.x[0]) / (float)(cal.xfb[1] - cal.xfb[0]) + (float)(cal.x[2] - cal.x[3]) / (float)(cal.xfb[2] - cal.xfb[3])) / 2.0f;
  cal.a[1] = ((float)(cal.y[3] - cal.y[0]) / (float)(cal.yfb[3] - cal.yfb[0]) + (float)(cal.y[2] - cal.y[1]) / (float)(cal.yfb[2] - cal.yfb[1])) / 2.0f;
  
  str = String.format("cal.a[0] = %f, cal.a[1] = %f\n", cal.a[0], cal.a[1]);
  Log.d(TAG, str);
  
  return true;
*/

  int j;
  float n, xt, yt, xt2, yt2, xtyt, xl, xlxt, xlyt, yl, ylxt, ylyt;
  float det, a, b, c, d, e, f;
  float scaling = 65536.0f;

     //Get sums for matrix
  n = xt = yt = xt2 = yt2 = xtyt = xl = xlxt = xlyt = yl = ylxt = ylyt = a = b = c = d = e = f = 0.0f;
  for(j=0; j<5; j++) {
   n += 1.0;
   xt += (float)cal.x[j];
   yt += (float)cal.y[j];
   xt2 += (float)(cal.x[j] * cal.x[j]);
   yt2 += (float)(cal.y[j] * cal.y[j]);
   xtyt += (float)(cal.x[j] * cal.y[j]);
   xl += (float)(cal.xfb[j]);
   xlxt += (float)(cal.xfb[j] * cal.x[j]);
   xlyt += (float)(cal.xfb[j] * cal.y[j]);
   yl += (float)cal.yfb[j];
   ylxt += (float)(cal.yfb[j] * cal.x[j]);
   ylyt += (float)(cal.yfb[j] * cal.y[j]);   
  }

        // Get determinant of matrix -- check if determinant is too small
  det = n * (xt2 * yt2 - xtyt * xtyt) + xt * (xtyt * yt - xt * yt2) + yt * (xt * xtyt - yt * xt2);
  if(det < 0.1 && det > -0.1) {
   str = String.format("ts_calibrate: determinant is too small -- %f\n", det);
   Log.d(TAG, str);
   
   return false;
  }

  a = n*(xlxt * yt2 - xtyt * xlyt) + xl * (xtyt * yt - xt * yt2) - yt * (xlxt * yt - xt * xlyt);  
  cal.a[0] = a / det;
  
  b = n * (xt2 * xlyt - xtyt * xlxt) + xt * (xlxt * yt - xt * xlyt) - xl * (xt2 * yt - xt * xtyt);
  cal.a[1] = b / det;
  
  c = xl * (xt2 * yt2 - xtyt * xtyt) + xt * (xtyt * xlyt - xlxt * yt2) - yt * (xt2 * xlyt - xlxt * xtyt);
  cal.a[2] = c / det;
 
  d = n * (ylxt * yt2 - xtyt * ylyt) + yl * (xtyt * yt - xt * yt2) - yt * (ylxt * yt - xt * ylyt);
  cal.a[3] = d / det;
  
  e = n * (xt2 * ylyt - ylxt * xtyt) + xt * (ylxt * yt - xt * ylyt) - yl * (xt2 * yt - xt * xtyt);
  cal.a[4] = e / det;
  
  f = yl * (xt2 * yt2 - xtyt * xtyt) + xt * (xtyt * ylyt - ylxt * yt2) - yt * (xt2 * ylyt - ylxt * xtyt);
  cal.a[5] = f / det;

  str = String.format("cal.a[0] = %f cal.a[1] = %f cal.a[2] = %f cal.a[3] = %f cal.a[4] = %f cal.a[5] = %f\n",
    cal.a[0], cal.a[1], cal.a[2], cal.a[3], cal.a[4], cal.a[5]);
  Log.d(TAG, str);

  return true;
 }

 private boolean saveCalibrationResult() {
  FileOutputStream os;
  String res = "";

  try {
   os = new FileOutputStream(CALIBRATION_FILE);
   res = String.format("%f %f %f %f %f %f", cal.a[0], cal.a[1], cal.a[2], cal.a[3], cal.a[4], cal.a[5]);

   Log.i(TAG, "calibration result=" + res);

   os.write(res.getBytes());
   os.close();
  } catch (FileNotFoundException e1) {
   // TODO Auto-generated catch block
   e1.printStackTrace();
   Log.w(TAG, "open calibration file write error: " + CALIBRATION_FILE);
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return true;
 }

 public class MyView extends View {
  private Canvas cv;
  private Paint paint;
  private Bitmap bmp;
  private int screen_pos;
  private Context mContext;

  public MyView(Context c) {
   super(c);
   // 镶满屏幕,没有标题
   //Log.d(TAG, "MyView");
   
   requestWindowFeature(Window.FEATURE_NO_TITLE);
   getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
     WindowManager.LayoutParams.FLAG_FULLSCREEN);
   mContext = c;
   paint = new Paint();
   paint.setDither(true);
   paint.setAntiAlias(true);
   paint.setStrokeWidth(2);
   paint.setColor(Color.WHITE);
   paint.setStyle(Paint.Style.STROKE);
   bmp = Bitmap.createBitmap(X_RES, Y_RES, Bitmap.Config.ARGB_8888);
   cv = new Canvas(bmp);
   screen_pos = 0;
   drawCalibrationCross(screen_pos);
  }

  protected void onDraw(Canvas canvas) {
   canvas.drawColor(Color.BLACK);
   canvas.drawBitmap(bmp, 0, 0, null);
  }

  private boolean drawCalibrationCross(int pos) {
   if (DEBUG) {
    Log.i("bigcren", "draw cross at pos " + pos);
   }

   cv.drawColor(Color.BLACK);

   // 画的X线
   cv.drawLine(cal.xfb[pos] - 30, cal.yfb[pos], cal.xfb[pos] - 3,
     cal.yfb[pos], paint);
   cv.drawLine(cal.xfb[pos] + 3, cal.yfb[pos], cal.xfb[pos] + 30,
     cal.yfb[pos], paint);

   // 画的Y线
   cv.drawLine(cal.xfb[pos], cal.yfb[pos] - 30, cal.xfb[pos],
     cal.yfb[pos] - 3, paint);
   cv.drawLine(cal.xfb[pos], cal.yfb[pos] + 3, cal.xfb[pos],
     cal.yfb[pos] + 30, paint);
   invalidate();
   return true;
  }

  public boolean onTouchEvent(MotionEvent event) {
   float tmpx, tmpy;
   boolean ret;
   if (screen_pos > SAMPLE_COUNTS - 1) {
    Log.i("bigcren", "get sample ok");
    return true;
   }

   if (event.getAction() == MotionEvent.ACTION_UP) {
    tmpx = event.getX();
    tmpy = event.getY();
    if (Math.abs(cal.xfb[screen_pos] - tmpx) > 15
      && Math.abs(cal.yfb[screen_pos] - tmpy) > 15) {
     Toast.makeText(mContext, R.string.calibration_error,
       Toast.LENGTH_SHORT).show();
     return false;
    }

    cal.x[screen_pos] = (int) event.getX();//(int) (event.getX() * 4096.0 / (float) X_RES + 0.5);
    cal.y[screen_pos] = (int) event.getY();//(int) (event.getY() * 4096.0 / (float) Y_RES + 0.5);
    String str = String.format("cal.x[%d] = %d, cal.y[%d] = %d", screen_pos, cal.x[screen_pos], screen_pos, cal.y[screen_pos]);
    Log.d(TAG, str);
    /*
    str = String.format("x[%d] = %d, y[%d] = %d", screen_pos, (int)event.getX(), screen_pos, (int)event.getY());
    Log.d(TAG, str);
    */

    if (screen_pos == 4) {
     ret = perform_calibration();
     if (ret) {
      saveCalibrationResult();
      finish();
      return true;
     } else {
      screen_pos = 0;
      Log.w(TAG, "Calibration failed");
     }
    } else {
     Led.ControlLed(Integer.toString(screen_pos));
     screen_pos++;
     drawCalibrationCross(screen_pos);
    }
   }
   return true;
  }
 }
}

 

将校准数据保存到文本文件后,就需要修改android系统源码中的InputDevice.java代码中。下面的代码有些加到MotionEvent generateAbsMotion(InputDevice device, long curTime, long curTimeNano, Display display, int orientation, int metaState)代码中for循环语句的最后面,其它加到该java文件的最后。因为手上暂时没有android的源代码,故无法解释generateAbsMotion函数中每条语句的意思。

//Begin-Modify by zxb for Calibration
                x_tmp = reportData[j + MotionEvent.SAMPLE_X];
                y_tmp = reportData[j + MotionEvent.SAMPLE_Y];
                str = String.format("j = %d MotionEvent.SAMPLE_X = %d MotionEvent.SAMPLE_Y= %d", j,  MotionEvent.SAMPLE_X, MotionEvent.SAMPLE_Y);
        Log.i("zxb", str);
                str = String.format(" 1 reportData[%d] = %f reportData[%d] = %f",  j + MotionEvent.SAMPLE_X, reportData[j + MotionEvent.SAMPLE_X], j + MotionEvent.SAMPLE_Y, reportData[j + MotionEvent.SAMPLE_Y]);
        Log.i("zxb", str);

                if (device.tInfo != null) {
            str = String.format("device.tInfo.x1 = %f device.tInfo.y1 = %f device.tInfo.z1 = %f", device.tInfo.x1, device.tInfo.y1, device.tInfo.z1);
                    Log.i("zxb", str);
                    reportData[j + MotionEvent.SAMPLE_X] =  (device.tInfo.x1 * x_tmp + device.tInfo.y1 * y_tmp + device.tInfo.z1);// / device.tInfo.s;
                    str = String.format("device.tInfo.x2 = %f device.tInfo.y2 = %f device.tInfo.z2 = %f", device.tInfo.x2, device.tInfo.y2, device.tInfo.z2);
                    Log.i("zxb", str);
            reportData[j + MotionEvent.SAMPLE_Y] =  (device.tInfo.x2 * x_tmp + device.tInfo.y2 * y_tmp + device.tInfo.z2);// / device.tInfo.s;
                }
                str = String.format("2 reportData[%d] = %f reportData[%d] = %f",  j + MotionEvent.SAMPLE_X, reportData[j + MotionEvent.SAMPLE_X], j + MotionEvent.SAMPLE_Y, reportData[j + MotionEvent.SAMPLE_Y]);
        Log.i("zxb", str);
                //End-Modify by zxb for Calibration



    //Begin-Add by zxb for Calibration
    static class TransformInfo {
        static float x1;
     static float y1;
     static float z1;
     static float x2;
     static float y2;
     static float z2;
     TransformInfo() {
            x1 = 1.0f;
            y1 = 1.0f;
            z1 = 0.0f;
            x2 = 1.0f;
            y2 = 1.0f;
            z2 = 0.0f;
    }
        
    };
    //End-Add by zxb for Calibration




        //Begin-Add by zxb for Calibration
        readCalibrationResult();
        //End-Add by zxb for Calibration



    //Begin-Add by zxb for Calibration
    private void readCalibrationResult() {
        try {
             FileInputStream is = new FileInputStream(CALIBRATION_FILE);
             Log.d("zxb", String.format("1 tInfo.x1 = %f tInfo.y1 = %f tInfo.z1 = %f tInfo.x2 = %f tInfo.y2 = %f tInfo.z2 = %f", tInfo.x1, tInfo.y1, tInfo.z1, tInfo.x2, tInfo.y2, tInfo.z2));
         byte[] mBuffer = new byte[64];
         int len = is.read(mBuffer);
         is.close();
            if (len > 0) {
             int i;
             for (i = 0; i < len; i++)
             if (mBuffer[i] == '\n' || mBuffer[i] == 0)
                 break;
             len = i;
            }

            if (len > 0) {
         tInfo = new TransformInfo();
         
               StringTokenizer st = new StringTokenizer(new String(mBuffer, 0, len));
               tInfo.x1 = Float.parseFloat(st.nextToken());
               tInfo.y1 = Float.parseFloat(st.nextToken());
               tInfo.z1 = Float.parseFloat(st.nextToken());
               tInfo.x2 = Float.parseFloat(st.nextToken());
               tInfo.y2 = Float.parseFloat(st.nextToken());
               tInfo.z2 = Float.parseFloat(st.nextToken());
               Log.d("zxb", String.format("2 tInfo.x1 = %f tInfo.y1 = %f tInfo.z1 = %f tInfo.x2 = %f tInfo.y2 = %f tInfo.z2 = %f", tInfo.x1, tInfo.y1, tInfo.z1, tInfo.x2, tInfo.y2, tInfo.z2));
        }   
        } catch (java.io.FileNotFoundException e) {
             Log.i("InputDevice", "calibration file not found exception");
        } catch (java.io.IOException e) {
             Log.i("InputDevice", "io exception");
        } catch (java.lang.NumberFormatException e) {
             Log.i("InputDevice", "number format exception");
        }

    }
     //End-Add by zxb for Calibration
};
根据输出坐标值与实际坐标值比较,此校准算法的优缺点是:在坐标不准确时能提高精度,但坐标比较准时会略降低精度;但提高的精度远大于降低的精度。

至于是使用android系统源码自带的校准算法还是采用本文的校准算法,就是仁者见仁智者见智了。因为我没有详细比较两者的优缺点。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 支付宝ofo退押金后余额怎么办 e招贷分期多还了怎么办 别人用我的手机号贷款不还怎么办 电脑文件夹怎么设密码忘记了怎么办 苹果手机id有分机和主机怎么办 绝地求生号被盗了邮箱被改了怎么办 微信邮箱怎么接收不到验证码怎么办 要申请一个特定的qq邮箱号怎么办 中银e贷额度为0怎么办 中银e贷被冻结了怎么办 中国银行e贷款填错了被拒怎么办 中银e贷逾期2天怎么办 大学生助学贷款网站密码忘了怎么办 乳晕毛囊挤压捏起来有小硬节怎么办 手机版模拟人生孕妇任务卡死怎么办 百度网盘的表格没保存怎么办 爱奇艺买的会员不小心删了怎么办 多次举报和拉黑克隆不了好友怎么办 货车把货拉到货主不付钱怎么办 中国银行网银公司用户名忘了怎么办 伟星管网站查不到电水管图纸怎么办 我的耕地己确权被他人侵权怎么办 掌上川电登录密码忘记了怎么办 华为商城不小心点了确认收货怎么办 买的认证服务号没有微信支付怎么办 手机微信里的外网链接打不开怎么办 微信违规无法加入群聊怎么办 苹果手机微信储存空间不足怎么办 拼多多砍价砍不到0元怎么办 妻子婚内出轨我的熟人怎么办 父亲怀疑母亲有外遇作为儿子怎么办 老婆出轨我总心理过不去坎该怎么办 失业人员离培训机构远了怎么办 遇到申请假冒商品的仅退款怎么办 微信被骗什么消息都不知道怎么办 微信用手机登录显示未注册怎么办 唯品会海淘订单取消不了怎么办 大排量摩托芯片钥匙断了怎么办 夏天太热在宿舍没空调怎么办? 汽车钥匙掉了怎么办半路到不了家 当顾客说产品太贵的时候 怎么办