package com.kernal.passportreader.sdk.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.DashPathEffect; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PathEffect; import android.graphics.Rect; import android.os.Build; import android.util.AttributeSet; import android.view.View; import android.view.WindowManager; import com.kernal.passportreader.sdk.utils.CardScreenUtil; import kernal.idcard.android.Frame; /** * @author A@H * @describle 扫描识别界面的自定义的扫描识别框 */ public final class ViewfinderView extends View { private int checkLeftFrame = 0;// Test if the left of a document is existing or aligned. private int checkTopFrame = 0;// Test if the upper part of a document is existing or aligned. private int checkRightFrame = 0;// Test if the right of a document is existing or aligned. private int checkBottomFrame = 0;// Test if the lower part of a document is existing or aligned. private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64}; /** * the time to refresh interface */ private static final long ANIMATION_DELAY = 50L; /** * To judge directional value correspondig to rotation degree of the screen :0,1,2,3 */ private static int directtion = 0; /** * When idcardType=0, it will turn to MRZ for recognition. WhenidcardType=1, it will turn to the full page for recognition. */ private int idcardType = 2; private int nCropType = 0; public int barWidth, barHeight; private Paint paint; private int scannerAlpha; /** * The top of middle sliding line */ private int slideTop; private int slideTop1; /** * The bottom of middle sliding line */ private int slideBottom; /** * The movement length of middle line after refreshing each time */ private static final int SPEEN_DISTANCE = 10; /** * Width of line in scanning frame */ private static final int MIDDLE_LINE_WIDTH = 6; private boolean isFirst = false; /** * Width of frames all around */ private static final int FRAME_LINE_WIDTH = 4; public static int FRAMECOLOR = 0;//Color of frames all around private Rect frame; public static int width; public static int height; public static int portraitWidth; private Frame fourLines = new Frame(); //该参数是设置竖屏状态下,框线识别模式中,框的方向,true:width>height; false:height>width public static boolean isSameScreen=true; public void setFourLines(Frame fourLines, String str) { this.fourLines = fourLines; /** * When we get the result, we update the full screen content. */ postInvalidateDelayed(ANIMATION_DELAY, 0, 0, width, height); } /** * * @param context * @param nCropType 框的方式 * @param checkFrame */ public ViewfinderView(Context context, int nCropType,int checkFrame) { super(context); WindowManager manager = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); paint = new Paint(); FRAMECOLOR=0; scannerAlpha = 0; this.nCropType = nCropType; directtion = CardScreenUtil.getScreenOrientation(context); checkLeftFrame=checkFrame; checkBottomFrame=checkFrame; checkRightFrame=checkFrame; checkTopFrame=checkFrame; width=0; height=0; } public void setIdcardType(int idcardType) { this.idcardType = idcardType; } public ViewfinderView(Context context, AttributeSet attrs) { super(context, attrs); } public Rect getFrame() { return frame; } @Override public void onDraw(Canvas canvas) { if(width==0||height==0){ width = canvas.getWidth(); height= canvas.getHeight(); } // For a general device, when its width is less than height, the rotation degree is 0 or 2; But for Samsung, when its wideth is greater than height, the rotation degree is 0 or 2. if (directtion == 0 || directtion == 2) { if (width > height) { if (!Build.MODEL.equals("GT-P7500") && !Build.MODEL.equals("SM-T520")) { if ((float) width / height == (float) 4 / 3) { width = 3 * width / 4; } } //a special device drawLine(canvas, width, height, false); } else { drawLine(canvas, width, height, true); } // For a general device, when its width is more than height, the rotation degree is 1 or 3; when its wideth is less than height, the rotation degree is 1 or 3. } else if (directtion == 1 || directtion == 3) { if (width > height) { drawLine(canvas, width, height, false); } else { //a special device drawLine(canvas, width, height, true); } } } public void drawLine(Canvas canvas, int width, int height, boolean isPortrait) { if (idcardType == 3000) { if (!isPortrait) {// a special device frame = new Rect((int) (width * 0.2), height / 3, (int) (width * 0.85), 2 * height / 3); } else { // MRZ recognition /** * The rectangular is the frame shown in the middle. */ if(isSameScreen){ frame = new Rect((int) (width * 0.05), (int) (height * 0.4), (int) (width * 0.95), (int) (0.6 * height)); }else{ frame = new Rect((int) (width * 0.05), (int) (height * 0.4), (int) (width * 0.95), (int) (0.6 * height)); } } } else if (idcardType == 2 || idcardType == 4 || idcardType == 1013 || idcardType == 22 || idcardType == 1030 || idcardType == 1031 || idcardType == 1032 || idcardType == 1005 || idcardType == 1001 || idcardType == 2001 || idcardType == 2004 || idcardType == 2002 || idcardType == 2003 || idcardType == 14 || idcardType == 15 || idcardType == 25 || idcardType == 26) { if (!isPortrait) {// a special device frame = new Rect((int) (width * 0.2), (int) (height - 0.41004673 * width) / 2, (int) (width * 0.85), (int) (height + 0.41004673 * width) / 2); } else { if(isSameScreen){ frame = new Rect((int) (width * 0.025), (int) (height - 0.59375 * width) / 2, (int) (width * 0.975), (int) (height + 0.59375 * width) / 2); }else{ frame = new Rect((int) (width - 0.41004673 * height) / 2, (int) (height * 0.2), (int) (width + 0.41004673 * height) / 2, (int) (height * 0.85)); } } } else if (idcardType == 5 || idcardType == 6) { if (!isPortrait) { // a special device frame = new Rect((int) (width * 0.24), (int) (height - 0.41004673 * width) / 2, (int) (width * 0.81), (int) (height + 0.41004673 * width) / 2); } else { if(isSameScreen){ frame = new Rect((int) (width * 0.025), (int) (height - 0.64 * width) / 2, (int) (width * 0.975), (int) (height + 0.64 * width) / 2); }else{ frame = new Rect((int) (width - 0.41004673 * height) / 2, (int) (height * 0.24), (int) (width + 0.41004673 * height) / 2, (int) (height * 0.81)); } } } else { if (!isPortrait) {// a special device frame = new Rect((int) (width * 0.2), (int) (height - 0.45 * width) / 2, (int) (width * 0.85), (int) (height + 0.45 * width) / 2); } else { // for page if(isSameScreen){ frame = new Rect((int) (width * 0.025), (int) (height - 0.659 * width) / 2, (int) (width * 0.975), (int) (height + 0.659 * width) / 2); }else{ frame = new Rect( (int) (width - 0.45 * height) / 2, (int) (height * 0.2), (int) (width + 0.45 * height) / 2, (int) (height * 0.85)); } } } // } if (frame == null) { return; } // the highest and lowest point of initialization middle sliding line if (!isFirst) { isFirst = true; slideTop = height / 3; slideBottom = 2 * height / 3; slideTop1 = width / 2; } // Sketch the shady part out of scanning frame. There are four sections. The upper part of both scanning frame and scree and the lower part of both scanning frame and screen // The left part of both scanning frame and scree and right part of both scanning frame and screen if (nCropType == 0) { paint.setColor(Color.argb(48, 0, 0, 0)); canvas.drawRect(0, 0, width, frame.top, paint); canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint); canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint); canvas.drawRect(0, frame.bottom + 1, width, height, paint); } paint.setColor(Color.rgb(238, 65, 86)); // Draw two-pixel wide geen wireframes or red frames. if (FRAMECOLOR == 0) { paint.setColor(Color.rgb(77, 223, 68)); } else { paint.setColor(FRAMECOLOR); } if (idcardType == 3000) { canvas.drawRect(frame.left + FRAME_LINE_WIDTH - 2, frame.top, frame.right - FRAME_LINE_WIDTH + 2, frame.top + FRAME_LINE_WIDTH, paint);// top line canvas.drawRect(frame.left + FRAME_LINE_WIDTH - 2, frame.top, frame.left + FRAME_LINE_WIDTH + 2, frame.bottom + FRAME_LINE_WIDTH, paint);// left line canvas.drawRect(frame.right - FRAME_LINE_WIDTH - 2, frame.top, frame.right - FRAME_LINE_WIDTH + 2, frame.bottom + FRAME_LINE_WIDTH, paint);// right line canvas.drawRect(frame.left + FRAME_LINE_WIDTH - 2, frame.bottom, frame.right - FRAME_LINE_WIDTH + 2, frame.bottom + FRAME_LINE_WIDTH, paint);// bottom line // skeetch one red line which can scan consistenly // paint.setColor(laserColor); paint.setAlpha(SCANNER_ALPHA[scannerAlpha]); scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length; } else { if (nCropType == 0) { canvas.drawRect(frame.left + FRAME_LINE_WIDTH - 2, frame.top, frame.left + FRAME_LINE_WIDTH - 2 + 50, frame.top + FRAME_LINE_WIDTH, paint); canvas.drawRect(frame.left + FRAME_LINE_WIDTH - 2, frame.top, frame.left + FRAME_LINE_WIDTH + 2, frame.top + 50, paint);// Top left corner canvas.drawRect(frame.right - FRAME_LINE_WIDTH - 2, frame.top, frame.right - FRAME_LINE_WIDTH + 2, frame.top + 50, paint); canvas.drawRect(frame.right - FRAME_LINE_WIDTH - 2 - 50, frame.top, frame.right - FRAME_LINE_WIDTH + 2, frame.top + FRAME_LINE_WIDTH, paint);// Top right corner canvas.drawRect(frame.left + FRAME_LINE_WIDTH - 2, frame.bottom - 50, frame.left + FRAME_LINE_WIDTH + 2, frame.bottom, paint); canvas.drawRect(frame.left + FRAME_LINE_WIDTH - 2, frame.bottom - FRAME_LINE_WIDTH, frame.left + FRAME_LINE_WIDTH - 2 + 50, frame.bottom, paint); // Left bottom canvas.drawRect(frame.right - FRAME_LINE_WIDTH - 2, frame.bottom - 50, frame.right - FRAME_LINE_WIDTH + 2, frame.bottom, paint); canvas.drawRect(frame.right - FRAME_LINE_WIDTH - 2 - 50, frame.bottom - FRAME_LINE_WIDTH, frame.right - FRAME_LINE_WIDTH - 2, frame.bottom, paint); // Right bottom } else if (nCropType == 1) { // a special device lenovo if (!isPortrait) { if (!(fourLines.ltStartX == barWidth && fourLines.ltStartY == barHeight && fourLines.rtStartX == barWidth && fourLines.rtStartY == barHeight && fourLines.lbStartX == barWidth && fourLines.lbStartY == barHeight && fourLines.rbStartX == barWidth && fourLines.rbStartY == barHeight)) { paint.setStrokeWidth(6); paint.setAntiAlias(true); float length = 3; canvas.drawLine(fourLines.ltStartX, fourLines.ltStartY, fourLines.lbStartX, fourLines.lbStartY, paint);// left line canvas.drawLine(fourLines.ltStartX, fourLines.ltStartY, fourLines.rtStartX, fourLines.rtStartY, paint);// top line canvas.drawLine(fourLines.rtStartX, fourLines.rtStartY, fourLines.rbStartX, fourLines.rbStartY, paint);// right line canvas.drawLine(fourLines.lbStartX, fourLines.lbStartY, fourLines.rbStartX, fourLines.rbStartY, paint);// bottom line paint.setColor(Color.argb(80, 255, 255, 255)); Path topPath = new Path(); topPath.moveTo(fourLines.lbStartX, fourLines.lbStartY); topPath.lineTo(fourLines.ltStartX, fourLines.ltStartY); topPath.lineTo(width, 0); topPath.lineTo(0, 0); topPath.close();// Closure canvas.drawPath(topPath, paint); Path leftPath = new Path(); leftPath.moveTo(0, 0); leftPath.lineTo(fourLines.lbStartX, fourLines.lbStartY); leftPath.lineTo(fourLines.rbStartX, fourLines.rbStartY); leftPath.lineTo(0, height); leftPath.close();// Closure canvas.drawPath(leftPath, paint); Path rightPath = new Path(); rightPath.moveTo(fourLines.ltStartX, fourLines.ltStartY); rightPath.lineTo(width, 0); rightPath.lineTo(width, height); rightPath.lineTo(fourLines.rtStartX, fourLines.rtStartY); rightPath.close();// Closure canvas.drawPath(rightPath, paint); Path bottomPath = new Path(); bottomPath.moveTo(fourLines.rbStartX, fourLines.rbStartY); bottomPath.lineTo(fourLines.rtStartX, fourLines.rtStartY); bottomPath.lineTo(width, height); bottomPath.lineTo(0, height); bottomPath.close();// Closure canvas.drawPath(bottomPath, paint); } else if ((fourLines.ltStartX == barWidth && fourLines.ltStartY == barHeight && fourLines.rtStartX == barWidth && fourLines.rtStartY == barHeight && fourLines.lbStartX == barWidth && fourLines.lbStartY == barHeight && fourLines.rbStartX == barWidth && fourLines.rbStartY == barHeight)) { // a special device lenovo paint.setColor(Color.rgb(0, 255, 0)); paint.setStrokeWidth(5); paint.setAntiAlias(true); paint.setStyle(Paint.Style.STROKE); PathEffect effects = new DashPathEffect(new float[]{10, 10, 10, 10}, 1); paint.setPathEffect(effects); Path path1 = new Path(); path1.moveTo((int) (width * 0.2), (int) (height - 0.41004673 * width) / 2); path1.lineTo((int) (width * 0.85), (int) (height - 0.41004673 * width) / 2); path1.lineTo((int) (width * 0.85), (int) (height + 0.41004673 * width) / 2); path1.lineTo((int) (width * 0.2), (int) (height + 0.41004673 * width) / 2); path1.close(); canvas.drawPath(path1, paint); paint.reset(); } } else { if ((!(fourLines.ltStartX == barHeight && fourLines.ltStartY == barWidth && fourLines.rtStartX == barHeight && fourLines.rtStartY == barWidth && fourLines.lbStartX == barHeight && fourLines.lbStartY == barWidth && fourLines.rbStartX == barHeight && fourLines.rbStartY == barWidth))) { paint.setStrokeWidth(6); paint.setAntiAlias(true); float length = 3; // WriteUtil.writeLog("绘制线的四个坐标点"+(width-fourLines.ltStartY)+"::::"+fourLines.ltStartX+":::::"+(width-fourLines.lbStartY)+"::::"+fourLines.lbStartX); canvas.drawLine(portraitWidth - fourLines.ltStartY, fourLines.ltStartX, portraitWidth - fourLines.lbStartY, fourLines.lbStartX, paint);// left line canvas.drawLine(portraitWidth - fourLines.ltStartY, fourLines.ltStartX, portraitWidth - fourLines.rtStartY, fourLines.rtStartX, paint);// top line canvas.drawLine(portraitWidth - fourLines.rtStartY, fourLines.rtStartX, portraitWidth - fourLines.rbStartY, fourLines.rbStartX, paint);// right line canvas.drawLine(portraitWidth - fourLines.lbStartY, fourLines.lbStartX, portraitWidth - fourLines.rbStartY, fourLines.rbStartX, paint);// bottom line paint.setColor(Color.argb(80, 255, 255, 255)); Path topPath = new Path(); topPath.moveTo(portraitWidth - fourLines.lbStartY, fourLines.lbStartX); topPath.lineTo(portraitWidth - fourLines.ltStartY, fourLines.ltStartX); topPath.lineTo(width, 0); topPath.lineTo(0, 0); topPath.close();// Closure canvas.drawPath(topPath, paint); Path leftPath = new Path(); leftPath.moveTo(0, 0); leftPath.lineTo(portraitWidth - fourLines.lbStartY, fourLines.lbStartX); leftPath.lineTo(portraitWidth - fourLines.rbStartY, fourLines.rbStartX); leftPath.lineTo(0, height); leftPath.close();// Closure canvas.drawPath(leftPath, paint); Path rightPath = new Path(); rightPath.moveTo(portraitWidth - fourLines.ltStartY, fourLines.ltStartX); rightPath.lineTo(width, 0); rightPath.lineTo(width, height); rightPath.lineTo(portraitWidth - fourLines.rtStartY, fourLines.rtStartX); rightPath.close();// Closure canvas.drawPath(rightPath, paint); Path bottomPath = new Path(); bottomPath.moveTo(portraitWidth - fourLines.rbStartY, fourLines.rbStartX); bottomPath.lineTo(portraitWidth - fourLines.rtStartY, fourLines.rtStartX); bottomPath.lineTo(width, height); bottomPath.lineTo(0, height); bottomPath.close();// Closure canvas.drawPath(bottomPath, paint); } else if ((fourLines.ltStartX == barHeight && fourLines.ltStartY == barWidth && fourLines.rtStartX == barHeight && fourLines.rtStartY == barWidth && fourLines.lbStartX == barHeight && fourLines.lbStartY == barWidth && fourLines.rbStartX == barHeight && fourLines.rbStartY == barWidth)) { paint.setColor(Color.rgb(0, 255, 0)); paint.setStrokeWidth(5); paint.setAntiAlias(true); paint.setStyle(Paint.Style.STROKE); PathEffect effects = new DashPathEffect(new float[]{10, 10, 10, 10}, 1); paint.setPathEffect(effects); Path path1 = new Path(); path1.moveTo((int) (width * 0.1), (int) (height - 1.28 * width) / 2); path1.lineTo((int) (width * 0.9), (int) (height - 1.28 * width) / 2); path1.lineTo((int) (width * 0.9), (int) (height + 1.28 * width) / 2); path1.lineTo((int) (width * 0.1), (int) (height + 1.28 * width) / 2); path1.close();// Closure canvas.drawPath(path1, paint); paint.reset(); } } } if (nCropType == 0) { // If it tests the left part of a document, a reminder line of left will be drawn. if (checkLeftFrame == 1) canvas.drawRect(frame.left + FRAME_LINE_WIDTH - 2, frame.top, frame.left + FRAME_LINE_WIDTH + 2, frame.bottom, paint);// left // If it tests the abover part of a document, a reminder line of uppper part will be drawn. if (checkTopFrame == 1) canvas.drawRect(frame.left + FRAME_LINE_WIDTH - 2, frame.top, frame.right - FRAME_LINE_WIDTH + 2, frame.top + FRAME_LINE_WIDTH, paint);// top // If it tests the right part of a document, a reminder line of right will be drawn. if (checkRightFrame == 1) canvas.drawRect(frame.right - FRAME_LINE_WIDTH - 2, frame.top, frame.right - FRAME_LINE_WIDTH + 2, frame.bottom, paint);// right // If it tests the bottom part of a document, a reminder line of bottom part will be drawn. if (checkRightFrame == 1) canvas.drawRect(frame.left + FRAME_LINE_WIDTH - 2, frame.bottom - FRAME_LINE_WIDTH, frame.right - FRAME_LINE_WIDTH - 2, frame.bottom, paint); // bottom } } } }