Tslib Manual Calibrate On Android
来源:互联网 发布:手机淘宝淘部落 编辑:程序博客网 时间:2024/05/16 16:21
Tslib Manual Calibrate On Android 话接上回,我们发现了手工利用tslib校验触摸屏的缺点。那么这一回 我们就来一次稍微高级一点的校验吧。 我们其实只需要相对的x,y以及lcd的x,y就可以把校验系数算出来。这里要说的是lcd的x,y是绝对的准确的 比如我们要在(50,50)画一个十字 那么这个50,50就是我们认为的绝对坐标。我们要的只是从android通过getX()和getY()拿到我们需要的相对坐标。 其实一切我们打算做的事情可以都在InputDevice里面做完 下面我把完整之后整个的InputDevice贴出来: 与上一次的那个InputDevice相比 我将读取校准文件的代码单独的变成一个函数,之所以这么做 是因为我们打算不重启就可以直接让android校准完成。这 里其实也没什么东西 只是读取校验文件 如果读取成功了就用校验公式计算出校准后的坐标。 为了避免重启 所以用了一个系统属性ts.config.calibrate来决定重新读取一次文件。当然 当ts.config.calibrate值表明正在校验的话 就直接传上来点击的原始坐标而不经过换算。校验完成之后读取一次校验文件 然后将系统属性变成其他值不再读取文件。 下面我们就要写一个apk来实现校准了。 这里 我尝试了2种方法 一种是纯java的apk 一种是jni的apk。其实对于校准来说 上层已经能拿到x,y那么我们取5个点就已经可以算出来那7个校准值 然后利用java存文件了。整个apk的java代码 其实这个就是tslib里那个ts_calibrate.cpp的姐妹篇。重要的函数就一个perform_calibration() 。这里要注意的是 你必须首先利用get_sample读取5个点的值来初始化cal然后再调用calibrate_main来计算校验系数。而且那5个点的顺序为 左上 右上 右下 左下 中间。这4个点基本上应该在屏幕的边缘附近 否则计算出来的校验值可能不准。 利用上面的那个类 写一个apk出来跑跑看 流程应该就可以了。
--by ONCE
1.android 的坐标转换处理
This implementation is a linear transformation using 7 parameters
(a, b, c, d, e, f and s) to transform the device coordinates (Xd, Yd)
into screen coordinates (Xs, Ys) using the following equations:
s*Xs = a*Xd + b*Yd + c
s*Ys = d*Xd + e*Yd + f
Xs,Ys:LCD 坐标(也就是所谓的绝对坐标)
Xd,Yd:触摸屏坐标
在编译好了的 ANDROID 根文件系统的 system/etc/pointercal 这个文件
内,存放着 7 个数,
这 7 个数就是对应上面公式的 a,b,c,d,e,f,s
比如我原来的:
+----+-----+--------+------+--+--------+----+
a | b | c |d |e | f |s |
+----+-----+--------+------+--+--------+----+
|-411|37818|-3636780|-51325|39|47065584|6553|
+----+-----+--------+------+--+--------+----+
2.tslib 库的移植
首先下载到一份 tslib 的代码,我用的是 tslib011.tar.gz(该包由
luzhuwei 同学友情赞助)。
将 tslib 解压到 external/下
要将一份代码编译到 android 里面去 其实没什么其他工作 主要就是那
个 Android.mk 文件的编写。网上找找 自己改改也就出来了。我的
Android.mk 文件内容如下:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
TSLIB_PLUGINDIR := /system/lib/ts/plugins
LOCAL_SRC_FILES := /
src/ts_attach.c /
src/ts_close.c /
src/ts_config.c /
src/ts_error.c /
src/ts_fd.c /
src/ts_load_module.c /
src/ts_open.c /
src/ts_parse_vars.c /
src/ts_read.c /
src/ts_read_raw.c /
src/ts_read_raw_module.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/ /
/usr/include/
LOCAL_SHARED_LIBRARIES := libdl
LOCAL_MODULE := libts
include $(BUILD_SHARED_LIBRARY)
#
# plugin: input-raw
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := plugins/input-raw.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts/plugins/input-raw
include $(BUILD_SHARED_LIBRARY)
#
# plugin: pthres
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := plugins/pthres.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts/plugins/pthres
include $(BUILD_SHARED_LIBRARY)
#
# plugin: linear
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := plugins/linear.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts/plugins/linear
include $(BUILD_SHARED_LIBRARY)
#
# plugin: dejitter
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := plugins/dejitter.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts/plugins/dejitter
include $(BUILD_SHARED_LIBRARY)
#
# plugin: variance
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := plugins/variance.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts/plugins/variance
include $(BUILD_SHARED_LIBRARY)
#
# ts_calibrate
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := tests/testutils.c /
tests/fbutils.c /
tests/font_8x8.c /
tests/ts_calibrate.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/ /
tests/ts_calibrate.h /
/usr/include/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts_calibrate
include $(BUILD_EXECUTABLE)
#
# ts_test
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := tests/testutils.c /
tests/fbutils.c /
tests/font_8x8.c /
tests/ts_test.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/ /
/usr/include/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts_test
include $(BUILD_EXECUTABLE)
#
# ts_print
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := tests/testutils.c /
tests/fbutils.c /
tests/font_8x8.c /
tests/ts_print.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/ /
/usr/include/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts_print
include $(BUILD_EXECUTABLE)
#
# ts_print_raw
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := tests/testutils.c /
tests/fbutils.c /
tests/font_8x8.c /
tests/ts_print_raw.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/ /
/usr/include/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts_print_raw
include $(BUILD_EXECUTABLE)
#
# ts_harvest
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES := tests/testutils.c /
tests/fbutils.c /
tests/font_8x8.c /
tests/ts_harvest.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/ /
/usr/include/
LOCAL_SHARED_LIBRARIES := libdl /
libts
LOCAL_MODULE := ts_harvest
include $(BUILD_EXECUTABLE)
我真不愿意粘帖上面的这个文件...太大 不过方便后人拷贝。
这里要注意是我们需要修改一下 tslib 的几个相关文件,因为 android
里的部分设备文件位置比较特殊。还有就是 tslib 里的部分变量他是
定义在 Makefile 里的 我们要把它定义到我们的文件中去。
首先 fb0 的位置变了: tests/fbutils.c
static char *defaultfbdevice = "/dev/fb0";
static char *defaultfbdevice = "/dev/graphics/fb0";
其次 plugins 的目录变了 src/ts_load_module.c
#define PLUGIN_DIR "/system/lib/ts/plugins/"
最后 config 文件的位置变了 src/ts_config.c
#define TS_CONF "/system/etc/ts.conf"
最后的最后不得不提到我们的配置文件 ts.conf。其他都不要动 但是
必须将它的 module_raw input 注释出来。并且 因为我们的 input 模块
编译出来之后我们命名为 input-raw 了 所以这里得改成
module_raw input-raw
下面就是编译了。发现错误就手工拷贝一下编出来的库到需要它在的
目录。
3. ts_calibrate 生成 pointercal
这里要首先不启动 android,然后进命令行手工启动 ts_calibrate 程序。
然后在屏幕上校验,完成后会生成一个正确的 pointercal 文件。
4.Android 读取校验文件 pointercal
如果要让我们的 android 被校验 那莪没我们就要按上面的公式 将
android 读取坐标部分替换掉。
“system/etc/pointercal”这个文件是被 java 程序读取使用的,文件目录:
f rameworks/base/services/java/com/android/server/InputDevice.java
看了一下这个文件的代码 发现要被修改的坐标为
if (device.absX != null) {
//xxw added
if (device.tInfo != null){
scaledX = (device.tInfo.x1 * x + device.tInfo.y1 * y +
device.tInfo.z1)/ device.tInfo.s;
Log.i("XXW","x: "+x);
Log.i("XXW","trans x: "+scaledX);
}
else//end
scaledX = ((scaledX-device.absX.minValue)
/ device.absX.range) * w;
}
if (device.absY != null) {
//xxw added
if (device.tInfo != null){
scaledY = (device.tInfo.x2 * x + device.tInfo.y2 * y +
device.tInfo.z2) / device.tInfo.s;
Log.i("XXW","y: "+y);
Log.i("XXW","trans y: "+scaledY);
}
else //end
scaledY = ((scaledY-device.absY.minValue)
/ device.absY.range) * h;
}
对照上面的公式其实很容易理解 在注释 xxw 和 end 之间的代码就是
我修改的代码。其中的 device.tInfo 是我定义的一个结构,这个结构
是用来读取 pointercal 文件里的 7 个数字得到的对应的值,具体结构
如下:
static class TransformInfo {
float x1;
float y1;
float z1;
float x2;
float y2;
float z2;
float s;
};
读取文件的代码 我放在 InputDevice 的构造函数里:
//xxw added
TransformInfo t = null;
try {Log.i("XXW","InputDevice! try");
FileInputStream is = new FileInputStream(CALIBRATION_FILE);
byte[] mBuffer = new byte[64];
int len = is.read(mBuffer);
is.close();
if (len > 0) {Log.i("XXW","InputDevice! len>0");
int i;
for (i = 0 ; i < len ; i++) {
if (mBuffer[i] == '/n' || mBuffer[i] == 0) {
break;
}
}
len = i;
}Log.i("XXW","InputDevice! len"+len);
StringTokenizer st = new StringTokenizer( new String(mBuffer, 0, 0,
len));
t = new TransformInfo ();
t.x1 = Integer.parseInt( st.nextToken() ); Log.i("XXW", "t.x1"+t.x1);
t.y1 = Integer.parseInt( st.nextToken() );Log.i("XXW", "t.y1"+t.y1);
t.z1 = Integer.parseInt( st.nextToken() );Log.i("XXW", "t.z1"+t.z1);
t.x2 = Integer.parseInt( st.nextToken() );Log.i("XXW", "t.x2"+t.x2);
t.y2 = Integer.parseInt( st.nextToken() );Log.i("XXW", "t.y2"+t.y2);
t.z2 = Integer.parseInt( st.nextToken() );Log.i("XXW", "t.z2"+t.z2);
t.s = Integer.parseInt( st.nextToken() );Log.i("XXW", "t.s"+t.s);
} catch (java.io.FileNotFoundException e) {Log.i("XXW",
"FileNotFound!");
} catch (java.io.IOException e) {Log.i("XXW", "IOException");
}
tInfo = t;
Log.i("XXW","InputDevice end!");
}
其中 static final String CALIBRATION_FILE = "/etc/pointercal";
这个时候点击一下屏幕看看是不是准确就知道是不是成功了。这里要
注意的是因为是在 InputDevice 里读取的文件 所以当我们中途替换了
pointercal 文件的时候 android 并不会再去读取这个文件。所以当我们
用 ts_calibrate 程序生成 pointercal 文件之后需要重启一下。同样 当我
们修改或者删除了那个文件 我们也是需要重启的。所以这个文档 的
名字叫手工校验。
PS:
如何自动化?
如何用 android 应用程序校验而不是命令行?
如何不需要重启也能实现?
请听下回分解。
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.WindowManagerPolicy;
import java.io.FileInputStream;
import java.util.StringTokenizer;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.os.SystemProperties;
public class InputDevice {
/** Amount that trackball needs to move in order to generate a key event. */
static final int TRACKBALL_MOVEMENT_THRESHOLD = 6;
//once edit
static final String CALIBRATION_FILE = "/data/etc/pointercal";
//edit ends
final int id;
final int classes;
final String name;
final AbsoluteInfo absX;
final AbsoluteInfo absY;
final AbsoluteInfo absPressure;
final AbsoluteInfo absSize;
//once edit
static TransformInfo tInfo;
//edit ends
long mDownTime = 0;
int mMetaKeysState = 0;
static File desFile;
final MotionState mAbs = new MotionState(0, 0);
final MotionState mRel = new MotionState(TRACKBALL_MOVEMENT_THRESHOLD,
TRACKBALL_MOVEMENT_THRESHOLD);
static class MotionState {
int xPrecision;
int yPrecision;
float xMoveScale;
float yMoveScale;
MotionEvent currentMove = null;
boolean changed = false;
boolean down = false;
boolean lastDown = false;
long downTime = 0;
int x = 0;
int y = 0;
int pressure = 1;
int size = 0;
MotionState(int mx, int my) {
xPrecision = mx;
yPrecision = my;
xMoveScale = mx != 0 ? (1.0f/mx) : 1.0f;
yMoveScale = my != 0 ? (1.0f/my) : 1.0f;
}
MotionEvent generateMotion(InputDevice device, long curTime,
boolean isAbs, Display display, int orientation,
int metaState) {
if (!changed) {
return null;
}
//once edit
//String prop = System.getProperty("ts.config.calibrate", "noset");
String prop = SystemProperties.get("ts.config.calibrate", "noset");
if (prop.equalsIgnoreCase("start")){
Log.i("XXW prop", prop);
Log.i("XXW", "prop.equalsIgnoreCase start");
device.tInfo = null;
}else if (prop.equalsIgnoreCase("done")){
Log.i("XXW prop", prop);
Log.i("XXW", "prop.equalsIgnoreCase done");
readCalibrate();
SystemProperties.set("ts.config.calibrate", "end");
}else{
Log.i("XXW prop", prop);
Log.i("XXW", "prop.equalsIgnoreCase else");
}
//edit ends
float scaledX = x;
float scaledY = y;
float temp;
float scaledPressure = 1.0f;
float scaledSize = 0;
int edgeFlags = 0;
if (isAbs) {
int w = display.getWidth()-1;
int h = display.getHeight()-1;
if (orientation == Surface.ROTATION_90
|| orientation == Surface.ROTATION_270) {
int tmp = w;
w = h;
h = tmp;
}
if (device.absX != null) {
//once edit
if (device.tInfo != null){
scaledX = (device.tInfo.x1 * x + device.tInfo.y1 * y + device.tInfo.z1)/ device.tInfo.s;
Log.i("XXW","x: "+x);
Log.i("XXW","trans x: "+scaledX);
}
else
//edit ends
scaledX = ((scaledX-device.absX.minValue)
/ device.absX.range) * w;
}
if (device.absY != null) {
//once edit
if (device.tInfo != null){
scaledY = (device.tInfo.x2 * x + device.tInfo.y2 * y + device.tInfo.z2) / device.tInfo.s;
Log.i("XXW","y: "+y);
Log.i("XXW","trans y: "+scaledY);
}
else
//edit ends
scaledY = ((scaledY-device.absY.minValue)
/ device.absY.range) * h;
}
if (device.absPressure != null) {
scaledPressure =
((pressure-device.absPressure.minValue)
/ (float)device.absPressure.range);
}
if (device.absSize != null) {
scaledSize =
((size-device.absSize.minValue)
/ (float)device.absSize.range);
}
switch (orientation) {
case Surface.ROTATION_90:
temp = scaledX;
scaledX = scaledY;
scaledY = w-temp;
break;
case Surface.ROTATION_180:
scaledX = w-scaledX;
scaledY = h-scaledY;
break;
case Surface.ROTATION_270:
temp = scaledX;
scaledX = h-scaledY;
scaledY = temp;
break;
}
if (scaledX == 0) {
edgeFlags += MotionEvent.EDGE_LEFT;
} else if (scaledX == display.getWidth() - 1.0f) {
edgeFlags += MotionEvent.EDGE_RIGHT;
}
if (scaledY == 0) {
edgeFlags += MotionEvent.EDGE_TOP;
} else if (scaledY == display.getHeight() - 1.0f) {
edgeFlags += MotionEvent.EDGE_BOTTOM;
}
} else {
scaledX *= xMoveScale;
scaledY *= yMoveScale;
switch (orientation) {
case Surface.ROTATION_90:
temp = scaledX;
scaledX = scaledY;
scaledY = -temp;
break;
case Surface.ROTATION_180:
scaledX = -scaledX;
scaledY = -scaledY;
break;
case Surface.ROTATION_270:
temp = scaledX;
scaledX = -scaledY;
scaledY = temp;
break;
}
}
changed = false;
if (down != lastDown) {
int action;
lastDown = down;
if (down) {
action = MotionEvent.ACTION_DOWN;
downTime = curTime;
} else {
action = MotionEvent.ACTION_UP;
}
currentMove = null;
if (!isAbs) {
x = y = 0;
}
return MotionEvent.obtain(downTime, curTime, action,
scaledX, scaledY, scaledPressure, scaledSize, metaState,
xPrecision, yPrecision, device.id, edgeFlags);
} else {
if (currentMove != null) {
if (false) Log.i("InputDevice", "Adding batch x=" + scaledX
+ " y=" + scaledY + " to " + currentMove);
currentMove.addBatch(curTime, scaledX, scaledY,
scaledPressure, scaledSize, metaState);
if (WindowManagerPolicy.WATCH_POINTER) {
Log.i("KeyInputQueue", "Updating: " + currentMove);
}
return null;
}
MotionEvent me = MotionEvent.obtain(downTime, curTime,
MotionEvent.ACTION_MOVE, scaledX, scaledY,
scaledPressure, scaledSize, metaState,
xPrecision, yPrecision, device.id, edgeFlags);
currentMove = me;
return me;
}
}
}
static class AbsoluteInfo {
int minValue;
int maxValue;
int range;
int flat;
int fuzz;
};
//once edit
static class TransformInfo {
float x1;
float y1;
float z1;
float x2;
float y2;
float z2;
float s;
};
//edit ends
InputDevice(int _id, int _classes, String _name,
AbsoluteInfo _absX, AbsoluteInfo _absY,
AbsoluteInfo _absPressure, AbsoluteInfo _absSize) {
id = _id;
classes = _classes;
name = _name;
absX = _absX;
absY = _absY;
absPressure = _absPressure;
absSize = _absSize;
//once edit
desFile = new File(CALIBRATION_FILE);
readCalibrate();
//edit ends
}
static void readCalibrate(){
//xxw added
Log.i("XXW","readCalibrate!");
TransformInfo t = null;
try {
FileInputStream is = new FileInputStream(CALIBRATION_FILE);
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;
}
StringTokenizer st = new StringTokenizer( new String(mBuffer, 0, 0, len));
t = new TransformInfo ();
t.x1 = Integer.parseInt( st.nextToken() );
t.y1 = Integer.parseInt( st.nextToken() );
t.z1 = Integer.parseInt( st.nextToken() );
t.x2 = Integer.parseInt( st.nextToken() );
t.y2 = Integer.parseInt( st.nextToken() );
t.z2 = Integer.parseInt( st.nextToken() );
t.s = Integer.parseInt( st.nextToken() );
} catch (java.io.FileNotFoundException e) {
Log.i("XXW", "FileNotFound!");
} catch (java.io.IOException e) {
Log.i("XXW", "IOException");
}
tInfo = t;
Log.i("XXW","readCalibrate done!");
}
};
package com.android.calibrate;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.util.Log;
public class Calibrate {
private calibration cal;
public Calibrate() {
cal = new calibration();
}
class calibration {
int x[] = new int[5];
int xfb[] = new int[5];
int y[] = new int[5];
int yfb[] = new int[5];
int a[] = new int[7];
};
boolean perform_calibration() {
Log.i("XXW", "perform_calibration");
int j;
float n, x, y, x2, y2, xy, z, zx, zy;
float det, a, b, c, e, f, i;
float scaling = (float)65536.0;
// Get sums for matrix
n = x = y = x2 = y2 = xy = 0;
for (j = 0; j < 5; j++) {
n += 1.0;
x += (float)cal.x[j];
y += (float)cal.y[j];
x2 += (float)(cal.x[j] * cal.x[j]);
y2 += (float)(cal.y[j] * cal.y[j]);
xy += (float)(cal.x[j] * cal.y[j]);
}
// Get determinant of matrix -- check if determinant is too small
det = n * (x2 * y2 - xy * xy) + x * (xy * y - x * y2) + y * (x * xy - y * x2);
if (det < 0.1 && det > -0.1) {
Log.i("ts_calibrate: determinant is too small -- %f/n", "" + det);
return false;
}
// Get elements of inverse matrix
a = (x2 * y2 - xy * xy) / det;
b = (xy * y - x * y2) / det;
c = (x * xy - y * x2) / det;
e = (n * y2 - y * y) / det;
f = (x * y - n * xy) / det;
i = (n * x2 - x * x) / det;
// Get sums for x calibration
z = zx = zy = 0;
for (j = 0; j < 5; j++) {
z += (float)cal.xfb[j];
zx += (float)(cal.xfb[j] * cal.x[j]);
zy += (float)(cal.xfb[j] * cal.y[j]);
}
// Now multiply out to get the calibration for framebuffer x coord
cal.a[0] = (int)((a * z + b * zx + c * zy) * (scaling));
cal.a[1] = (int)((b * z + e * zx + f * zy) * (scaling));
cal.a[2] = (int)((c * z + f * zx + i * zy) * (scaling));
System.out.printf("%f %f %f/n", (a * z + b * zx + c * zy), (b * z + e * zx + f * zy), (c
* z + f * zx + i * zy));
// Get sums for y calibration
z = zx = zy = 0;
for (j = 0; j < 5; j++) {
z += (float)cal.yfb[j];
zx += (float)(cal.yfb[j] * cal.x[j]);
zy += (float)(cal.yfb[j] * cal.y[j]);
}
// Now multiply out to get the calibration for framebuffer y coord
cal.a[3] = (int)((a * z + b * zx + c * zy) * (scaling));
cal.a[4] = (int)((b * z + e * zx + f * zy) * (scaling));
cal.a[5] = (int)((c * z + f * zx + i * zy) * (scaling));
System.out.printf("%f %f %f/n", (a * z + b * zx + c * zy), (b * z + e * zx + f * zy), (c
* z + f * zx + i * zy));
// If we got here, we're OK, so assign scaling to a[6] and return
cal.a[6] = (int)scaling;
return true;
/*
* // This code was here originally to just insert default values
* for(j=0;j<7;j++) { c->a[j]=0; } c->a[1] = c->a[5] = c->a[6] = 1;
* return 1;
*/
}
void get_sample(int index, int x1, int y1, int x, int y) {
Log.i("XXW", "get_sample");
cal.x[index] = x1;
cal.y[index] = y1;
cal.xfb[index] = x;
cal.yfb[index] = y;
}
int calibrate_main() {
int result = 0;
Log.i("XXW", "calibrate_main");
if (perform_calibration()) {
String strPara = String.format("%d %d %d %d %d %d %d", cal.a[1], cal.a[2], cal.a[0],
cal.a[4], cal.a[5], cal.a[3], cal.a[6]);
boolean success = new File("/data/etc").mkdir();
if (!success) {
Log.i(this.toString(), "no success");
}
File desFile = new File("/data/etc/pointercal");
if (!desFile.exists())
try {
desFile.createNewFile();
} catch (IOException e1) {
e1.printStackTrace();
}
FileOutputStream fos;
try {
fos = new FileOutputStream(desFile);
byte[] buf = strPara.getBytes();
int bytesRead = buf.length;
try {
fos.write(buf, 0, bytesRead);
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
result = 0;
} else {
result = -1;
}
return result;
}
}
package com.android.calibrate;
import com.android.calibrate.R;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnTouchListener;
import android.widget.Toast;
import android.os.SystemProperties;
public class AndroidCalibrate extends Activity {
final String TAG = "ScreenCalibration";
final int UI_SCREEN_WIDTH = 800;
final int UI_SCREEN_HEIGHT = 480;
CrossView myview;
int direction;
private Calibrate cal;
int xList[] = {
50, UI_SCREEN_WIDTH - 50, UI_SCREEN_WIDTH - 50, 50, UI_SCREEN_WIDTH / 2
};
int yList[] = {
50, UI_SCREEN_HEIGHT - 50, UI_SCREEN_HEIGHT - 50, 50, UI_SCREEN_HEIGHT / 2
};
static void setNotTitle(Activity act) {
act.requestWindowFeature(Window.FEATURE_NO_TITLE);
}
static void setFullScreen(Activity act) {
setNotTitle(act);
act.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setFullScreen(this);
myview = new CrossView(this);
setContentView(myview);
SystemProperties.set("ts.config.calibrate", "start");
cal = new Calibrate();
direction = 0;
myview.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.i("OnTouch", event.getX() + "," + event.getY());
v.invalidate();
if (direction < 4) {
Log.i("XXW time onTouchListener", " " + direction);
cal.get_sample(direction, (int)event.getX(), (int)event.getY(),
xList[direction], yList[direction]);
}
if (direction == 4) {
cal.get_sample(direction, (int)event.getX(), (int)event.getY(),
xList[direction], yList[direction]);
Log.i("XXW", "calibrate_main");
cal.calibrate_main();
Toast.makeText(getBaseContext(), "Calibrate Done!", Toast.LENGTH_SHORT).show();
SystemProperties.set("ts.config.calibrate", "done");
AndroidCalibrate.this.finish();
}
direction++;
return false;
}
});
}
public class CrossView extends View {
public CrossView(Context context) {
super(context);
}
public void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(Color.GREEN);
if (direction == 0) {
canvas.drawLine(40, 50, 60, 50, paint);
canvas.drawLine(50, 40, 50, 60, paint);
paint.setColor(Color.WHITE);
} else if (direction == 1) {
canvas.drawLine(UI_SCREEN_WIDTH - 60, 50, UI_SCREEN_WIDTH - 40, 50, paint);
canvas.drawLine(UI_SCREEN_WIDTH - 50, 40, UI_SCREEN_WIDTH - 50, 60, paint);
paint.setColor(Color.WHITE);
} else if (direction == 2) {
canvas.drawLine(UI_SCREEN_WIDTH - 60, UI_SCREEN_HEIGHT - 50, UI_SCREEN_WIDTH - 40,
UI_SCREEN_HEIGHT - 50, paint);
canvas.drawLine(UI_SCREEN_WIDTH - 50, UI_SCREEN_HEIGHT - 60, UI_SCREEN_WIDTH - 50,
UI_SCREEN_HEIGHT - 40, paint);
paint.setColor(Color.WHITE);
} else if (direction == 3) {
canvas.drawLine(40, UI_SCREEN_HEIGHT - 50, 60, UI_SCREEN_HEIGHT - 50, paint);
canvas.drawLine(50, UI_SCREEN_HEIGHT - 60, 50, UI_SCREEN_HEIGHT - 40, paint);
paint.setColor(Color.WHITE);
} else if (direction == 4) {
canvas.drawLine(UI_SCREEN_WIDTH / 2 - 10, UI_SCREEN_HEIGHT / 2,
UI_SCREEN_WIDTH / 2 + 10, UI_SCREEN_HEIGHT / 2, paint);
canvas.drawLine(UI_SCREEN_WIDTH / 2, UI_SCREEN_HEIGHT / 2 - 10,
UI_SCREEN_WIDTH / 2, UI_SCREEN_HEIGHT / 2 + 10, paint);
paint.setColor(Color.WHITE);
} else {
}
// canvas.drawText(getResources().getString(R.string.
// screen_calibration_content),
// UI_SCREEN_WIDTH / 2 - 50, UI_SCREEN_HEIGHT / 2, paint);
super.onDraw(canvas);
}
}
}
http://xxw8393.blog.163.com/blog/static/3725683420098113187900/
- Tslib Manual Calibrate On Android
- Tslib Manual Calibrate On Android
- Tslib Manual Calibrate On Android
- [记忆] Tslib Manual Calibrate On Android
- tslib配置on Android
- calibrate kinnect v1 on ubuntu
- Android touch screen Calibrate with Intent
- tslib android 参考帖
- tslib android 参考帖
- tslib for android
- android下移植tslib
- Manual SysDateLookup on a FormStringControl
- calibrate sensors
- tslib
- tslib
- tslib
- tslib
- Tslib 移植 Android.mk文件
- Struts2中的I18N(国际化)处理
- kobject_example 初探
- 圣诞节
- Java中找到每月第一天、最后一天的方法
- SQL Server是如何判断Status状态位的?
- Tslib Manual Calibrate On Android
- Visual Studio 2010 Team System 动手实验室
- 在C#中使用server.UrlEncode() 方法
- myEclipse debug android 'hello world'
- zz迅雷7无法自动登录解决办法
- Gridview操作集锦
- SQL Server 2008 筛选器报错
- JSF Gossip: Backing Beans
- vc中调用其他应用程序的方法(函数) winexec,shellexecute ,createprocess