如何保存和比较Android中的签名

时间:2010-12-08 10:35:18

标签: android graphics

我有用于绘制用户签名的编码。现在我需要编码以保存数据库中的签名,我需要比较签名是否正确。 你可以在屏幕上看到我的抽奖签名编码

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.LinearLayout;

public class sign extends Activity {
  LinearLayout content;
  signature pnlpanel;
  Button btn,btn1;
@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);

   content = (LinearLayout) findViewById(R.id.linear);
   pnlpanel = new signature(this, null);
   pnlpanel.setBackgroundColor(Color.WHITE);
   content.addView(pnlpanel, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);

   btn = (Button) findViewById(R.id.bt);
   btn.setOnClickListener(new OnClickListener() {         
      public void onClick(View v) {
         pnlpanel.clear();
      }
   });

   btn1 = (Button) findViewById(R.id.button);
   btn1.setOnClickListener(new OnClickListener() {         
      public void onClick(View v) {

       switch(v.getId())
    {
    case R.id.linear:
  //db.open();
  //if(equals(linear));

      }}
   });




}


public class signature extends View {

private static final float STROKE_WIDTH = 5f;

/** Need to track this so the dirty region can accommodate the stroke. **/
private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;

private Paint paint = new Paint();
private Path path = new Path();

/**
* Optimizes painting by invalidating the smallest possible area.
*/
private float lastTouchX;
private float lastTouchY;
private final RectF dirtyRect = new RectF();

public signature(Context context, AttributeSet attrs) {
 super(context, attrs);

 paint.setAntiAlias(true);
 paint.setColor(Color.BLACK);
 paint.setStyle(Paint.Style.STROKE);
 paint.setStrokeJoin(Paint.Join.ROUND);
 paint.setStrokeWidth(STROKE_WIDTH);
 }

public void save() {

// TODO Auto-generated method stub

}

/**
* Erases the signature.
*/
public void clear() {
 path.reset();

 // Repaints the entire view.
 invalidate();
}

@Override
protected void onDraw(Canvas canvas) {
 canvas.drawPath(path, paint);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
 float eventX = event.getX();
 float eventY = event.getY();

 switch (event.getAction()) {
   case MotionEvent.ACTION_DOWN:
     path.moveTo(eventX, eventY);
     lastTouchX = eventX;
     lastTouchY = eventY;
     // There is no end point yet, so don't waste cycles invalidating.
     return true;

   case MotionEvent.ACTION_MOVE:
   case MotionEvent.ACTION_UP:
     // Start tracking the dirty region.
     resetDirtyRect(eventX, eventY);

     // When the hardware tracks events faster than they are delivered, the
     // event will contain a history of those skipped points.
     int historySize = event.getHistorySize();
     for (int i = 0; i < historySize; i++) {
       float historicalX = event.getHistoricalX(i);
       float historicalY = event.getHistoricalY(i);
       expandDirtyRect(historicalX, historicalY);
       path.lineTo(historicalX, historicalY);
     }

     // After replaying history, connect the line to the touch point.
     path.lineTo(eventX, eventY);
     break;

   default:
     debug("Ignored touch event: " + event.toString());
     return false;
 }

 // Include half the stroke width to avoid clipping.
 invalidate(
     (int) (dirtyRect.left - HALF_STROKE_WIDTH),
     (int) (dirtyRect.top - HALF_STROKE_WIDTH),
     (int) (dirtyRect.right + HALF_STROKE_WIDTH),
     (int) (dirtyRect.bottom + HALF_STROKE_WIDTH));

 lastTouchX = eventX;
 lastTouchY = eventY;

 return true;
}

private void debug(String string) {
// TODO Auto-generated method stub

}

/**
* Called when replaying history to ensure the dirty region includes all
* points.
*/
private void expandDirtyRect(float historicalX, float historicalY) {
 if (historicalX < dirtyRect.left) {
   dirtyRect.left = historicalX;
 } else if (historicalX > dirtyRect.right) {
   dirtyRect.right = historicalX;
 }
 if (historicalY < dirtyRect.top) {
   dirtyRect.top = historicalY;
 } else if (historicalY > dirtyRect.bottom) {
   dirtyRect.bottom = historicalY;
 }
}

    /**
    * Resets the dirty region when the motion event occurs.
    */
    private void resetDirtyRect(float eventX, float eventY) {

     // The lastTouchX and lastTouchY were set when the ACTION_DOWN
     // motion event occurred.
     dirtyRect.left = Math.min(lastTouchX, eventX);
     dirtyRect.right = Math.max(lastTouchX, eventX);
     dirtyRect.top = Math.min(lastTouchY, eventY);
     dirtyRect.bottom = Math.max(lastTouchY, eventY);
    }
    }
}

2 个答案:

答案 0 :(得分:2)

如果我是你,我不会太担心存储签名(无论是在图像文件还是数据库blob中)。

项目的难点在于尝试匹配两个图像并查看它们是否与另一个图像相同(因为在复制签名时,它不会100%相等:整个签名可能会更大一些,稍微小一些,旋转方式不同,有些字母的形状可能略有不同,......)。

您可以开始查看this questionthe neuroph library

答案 1 :(得分:2)

我在Android capture signature using Canvas and save in png format找到了一个答案。

public class GetSignature extends Activity { 
    LinearLayout mContent;
    signature mSignature;
    Button mClear, mGetSign;
    public static String tempDir;
    public int count = 1;
    public String current = null;
    private Bitmap mBitmap;
    View mView;

    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        tempDir = Environment.getExternalStorageDirectory() + "/" + getResources().getString(R.string.external_dir) + "/";
        prepareDirectory();
        current = count + ".png";

        mContent = (LinearLayout) findViewById(R.id.linearLayout);
        mSignature = new signature(this, null);
        mSignature.setBackgroundColor(Color.BLUE);
        mContent.addView(mSignature, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
        mClear = (Button)findViewById(R.id.clear);
        mGetSign = (Button)findViewById(R.id.getsign);
        mView = mContent;

        mClear.setOnClickListener(new OnClickListener() 
        {         
            public void onClick(View v) 
            {
                Log.v("log_tag", "Panel Cleared");
                mSignature.clear();
            }
        });

        mGetSign.setOnClickListener(new OnClickListener() 
        {         
            public void onClick(View v) 
            {
                Log.v("log_tag", "Panel Saved");
                mView.setDrawingCacheEnabled(true);
                mSignature.save(mView);
            }
        });

    }

    private boolean prepareDirectory() 
    {
        try 
        {
            if (makedirs()) 
            {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) 
        {
            e.printStackTrace();
            Toast.makeText(this, "Could not initiate File System.. Is Sdcard mounted properly?", 1000).show();
            return false;
        }
    }

    private boolean makedirs() 
    {
        File tempdir = new File(tempDir);
        if (!tempdir.exists())
            tempdir.mkdirs();

        if (tempdir.isDirectory()) 
        {
            File[] files = tempdir.listFiles();
            for (File file : files) 
            {
                if (!file.delete()) 
                {
                    System.out.println("Failed to delete " + file);
                }
            }
        }
        return (tempdir.isDirectory());
    }


    public class signature extends View 
    {
        private static final float STROKE_WIDTH = 5f;
        private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;
        private Paint paint = new Paint();
        private Path path = new Path();

        private float lastTouchX;
        private float lastTouchY;
        private final RectF dirtyRect = new RectF();

        public signature(Context context, AttributeSet attrs) 
        {
             super(context, attrs);
             paint.setAntiAlias(true);
             paint.setColor(Color.YELLOW);
             paint.setStyle(Paint.Style.STROKE);
             paint.setStrokeJoin(Paint.Join.ROUND);
             paint.setStrokeWidth(STROKE_WIDTH);
        }

        public void save(View v) 
        {
            Log.v("log_tag", "Width: " + v.getWidth());
            Log.v("log_tag", "Height: " + v.getHeight());
            if(mBitmap == null)
            {
                mBitmap =  Bitmap.createBitmap (320, 480, Bitmap.Config.RGB_565);;
            }
            Canvas canvas = new Canvas(mBitmap);
            String FtoSave = tempDir + current;
            File file = new File(FtoSave);
            try 
            {
                FileOutputStream mFileOutStream = new FileOutputStream(file);
                v.draw(canvas); 
                mBitmap.compress(Bitmap.CompressFormat.PNG, 90, mFileOutStream); 
                mFileOutStream.flush();
                mFileOutStream.close();
                String url = Images.Media.insertImage(getContentResolver(), mBitmap, "title", null);
                Log.v("log_tag","url" + url);
            }
            catch(Exception e) 
            { 
                Log.v("log_tag", e.toString()); 
            } 
        }

        public void clear() 
        {
             path.reset();
             invalidate();
        }

        @Override
        protected void onDraw(Canvas canvas) 
        {
             canvas.drawPath(path, paint);
        }

        @Override
        public boolean onTouchEvent(MotionEvent event) 
        {
             float eventX = event.getX();
             float eventY = event.getY();

             switch (event.getAction()) 
             {
               case MotionEvent.ACTION_DOWN:
                     path.moveTo(eventX, eventY);
                     lastTouchX = eventX;
                     lastTouchY = eventY;
                     return true;

               case MotionEvent.ACTION_MOVE:

               case MotionEvent.ACTION_UP:
                     resetDirtyRect(eventX, eventY);
                     int historySize = event.getHistorySize();
                     for (int i = 0; i < historySize; i++) 
                     {
                           float historicalX = event.getHistoricalX(i);
                           float historicalY = event.getHistoricalY(i);
                           expandDirtyRect(historicalX, historicalY);
                           path.lineTo(historicalX, historicalY);
                     }
                     path.lineTo(eventX, eventY);
                     break;

               default:
                     debug("Ignored touch event: " + event.toString());
                     return false;
             }

             invalidate((int) (dirtyRect.left - HALF_STROKE_WIDTH),
                 (int) (dirtyRect.top - HALF_STROKE_WIDTH),
                 (int) (dirtyRect.right + HALF_STROKE_WIDTH),
                 (int) (dirtyRect.bottom + HALF_STROKE_WIDTH));

             lastTouchX = eventX;
             lastTouchY = eventY;

             return true;
        }

        private void debug(String string) 
        {
        }

        private void expandDirtyRect(float historicalX, float historicalY) 
        {
             if (historicalX < dirtyRect.left) 
             {
               dirtyRect.left = historicalX;
             } 
             else if (historicalX > dirtyRect.right) 
             {
               dirtyRect.right = historicalX;
             }

             if (historicalY < dirtyRect.top) 
             {
               dirtyRect.top = historicalY;
             } 
             else if (historicalY > dirtyRect.bottom) 
             {
               dirtyRect.bottom = historicalY;
             }
        }

        private void resetDirtyRect(float eventX, float eventY) 
        {
             dirtyRect.left = Math.min(lastTouchX, eventX);
             dirtyRect.right = Math.max(lastTouchX, eventX);
             dirtyRect.top = Math.min(lastTouchY, eventY);
             dirtyRect.bottom = Math.max(lastTouchY, eventY);
        }
    }//signature
}