最近公司项目有需要开发一个相机?要识别车牌号和VIN(车架号)要求如下:
1.要求扫描车牌号要竖屏显示。
2.要求扫描车架号要横屏显示。
并且在扫描的时候要遮挡区域只显示中间的矩形扫描框,拍照完成后只显示矩形框的图片,然后将图片上传上去进行识别返回车牌信息和VIN信息。这里项目做完了做了一个Dome希望可以帮到大家。先上两张图:
第一步:
package com.leict.custom.maskcamera.camera; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.ImageFormat; import android.graphics.Matrix; import android.hardware.Camera; import android.hardware.Camera.Parameters; import android.hardware.Camera.PictureCallback; import android.hardware.Camera.Size; import android.media.AudioManager; import android.media.ToneGenerator; import android.os.Environment; import android.util.Log; import android.view.SurfaceHolder; import com.leict.custom.maskcamera.utils.Utils; import com.leict.custom.maskcamera.views.PlateSurfaceView; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; public class CameraPlateHelper { private final String TAG = CameraPlateHelper.class.getSimpleName(); private boolean isPreview; private static CameraPlateHelper helper; private Camera camera; private ToneGenerator tone; private PlateSurfaceView surfaceView; /** * 分辨率 */ private Size resolution; /** * 照片质量 */ private int picQuality = 100; /** * 照片尺寸 */ private Size pictureSize; /** * 上下文 */ private Context mContext; /** * 闪光灯模式(default:自动) */ private String flashStatus = Parameters.FLASH_MODE_AUTO; public enum Flashlight { AUTO, ON, OFF } private CameraPlateHelper(Context context) { this.mContext = context; } public static CameraPlateHelper getInstance(Context context) { if (helper == null) { synchronized (CameraPlateHelper.class) { if (helper == null) { helper = new CameraPlateHelper(context.getApplicationContext()); } } } return helper; } /** * 设置闪光灯模式 * * @param status * @return */ public CameraPlateHelper setFlashState(Flashlight status) { switch (status) { case AUTO: this.flashStatus = Parameters.FLASH_MODE_AUTO; break; case ON: this.flashStatus = Parameters.FLASH_MODE_ON; break; case OFF: this.flashStatus = Parameters.FLASH_MODE_OFF; break; default: this.flashStatus = Parameters.FLASH_MODE_AUTO; } return helper; } public CameraPlateHelper setMaskSurfaceView(PlateSurfaceView surfaceView) { this.surfaceView = surfaceView; return helper; } /** * 获取Camera对象 * * @return */ private Camera getCamera() { Camera camera; try { camera = Camera.open(); } catch (Exception e) { camera = null; e.printStackTrace(); } return camera; } /** * 打开相机并开启预览 * * @param holder SurfaceHolder * @param format 图片格式 * @param width SurfaceView宽度 * @param height SurfaceView高度 * @param screenWidth 屏幕宽度 * @param screenHeight 屏幕高度 */ public void openCamera(SurfaceHolder holder, int format, int width, int height, int screenWidth, int screenHeight) { if (this.camera != null) { this.camera.release(); } this.camera = getCamera(); this.setParameter(holder, format, width, height, screenWidth, screenHeight); this.startPreview(); } /** * 照相 */ public void tackPicture(final TakePhotoCallback callback) { this.camera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean flag, Camera camera) { camera.takePicture(new Camera.ShutterCallback() { @Override public void onShutter() { if (tone == null) { //发出提示用户的声音 tone = new ToneGenerator(AudioManager.STREAM_MUSIC, ToneGenerator.MAX_VOLUME); } tone.startTone(ToneGenerator.TONE_PROP_BEEP2); } }, null, new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { String filepath = savePicture(data); boolean success = false; if (filepath != null) { success = true; } stopPreview(); callback.onCapture(success, filepath); } }); } }); } /** * 裁剪并保存照片 * * @param data * @return */ private String savePicture(byte[] data) { String filePath = Environment.getExternalStorageDirectory() + "/cbx/vehicle.jpg"; Bitmap bitmap = cutPicture(data); try { int length = filePath.length(); String strPath = filePath.substring(0, filePath.indexOf("v")); String strName = filePath.substring(filePath.indexOf("v"), length); if (Utils.isExist(strPath, strName)) { File imgFile = new File(filePath); FileOutputStream fos = new FileOutputStream(imgFile); BufferedOutputStream bos = new BufferedOutputStream(fos); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos); fos.close(); bos.flush(); bos.close(); } } catch (IOException e) { e.printStackTrace(); } return filePath; } /** * 初始化相机参数 * * @param holder SurfaceHolder * @param format 图片格式 * @param width SurfaceView宽度 * @param height SurfaceView高度 * @param screenWidth 屏幕宽度 * @param screenHeight 屏幕高度 */ private void setParameter(SurfaceHolder holder, int format, int width, int height, int screenWidth, int screenHeight) { try { Parameters p = this.camera.getParameters(); this.camera.setPreviewDisplay(holder); if (width > height) { //横屏 this.camera.setDisplayOrientation(0); } else { //竖屏 this.camera.setDisplayOrientation(90); } //照片质量 p.set("jpeg-quality", picQuality); //设置照片格式 p.setPictureFormat(ImageFormat.JPEG); //设置闪光灯 p.setFlashMode(flashStatus); //设置最佳预览尺寸 ListpreviewSizes = p.getSupportedPreviewSizes(); //设置预览分辨率 if (this.resolution == null) { this.resolution = this.getOptimalPreviewSize(previewSizes, width, height); } try { p.setPreviewSize(this.resolution.width, this.resolution.height); } catch (Exception e) { Log.e(TAG, "不支持的预览分辨率: " + this.resolution.width + " × " + this.resolution.height); } //设置照片尺寸 if (this.pictureSize == null) { List pictureSizes = p.getSupportedPictureSizes(); this.setPicutreSize(pictureSizes, screenWidth, screenHeight); } try { p.setPictureSize(this.pictureSize.width, this.pictureSize.height); } catch (Exception e) { Log.e(TAG, "不支持的照片尺寸: " + this.pictureSize.width + " × " + this.pictureSize.height); } this.camera.setParameters(p); } catch (Exception e) { e.printStackTrace(); Log.e(TAG, "相机参数设置错误"); } } /** * 释放Camera */ public void releaseCamera() { if (this.camera != null) { if (this.isPreview) { this.stopPreview(); } this.camera.setPreviewCallback(null); this.isPreview = false; this.camera.release(); this.camera = null; } } /** * 停止预览 */ private void stopPreview() { if (this.camera != null && this.isPreview) { this.camera.stopPreview(); this.isPreview = false; } } /** * 开始预览 */ public void startPreview() { if (this.camera != null) { this.camera.startPreview(); this.camera.autoFocus(null); this.isPreview = true; } } /** * 裁剪照片 * * @param data * @return */ private Bitmap cutPicture(byte[] data) { Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); if (this.surfaceView.getWidth() < this.surfaceView.getHeight()) { //竖屏旋转照片 Matrix matrix = new Matrix(); matrix.reset(); matrix.setRotate(90); bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); } if (this.surfaceView == null) { return bitmap; } else { int[] sizes = this.surfaceView.getMaskSize(); if (sizes[0] == 0 || sizes[1] == 0) { return bitmap; } int w = bitmap.getWidth(); int h = bitmap.getHeight(); int x = (w - sizes[0]) / 2; int y = (h - sizes[1]) / 2; Log.i("bitmap_w--------->>>", String.valueOf(w)); Log.i("bitmap_h--------->>>", String.valueOf(h)); Log.i("x--------->>>", String.valueOf(x)); Log.i("y--------->>>", String.valueOf(y)); Log.i("w--------->>>", String.valueOf(sizes[0])); Log.i("h--------->>>", String.valueOf(sizes[1])); //return Bitmap.createBitmap(bitmap, x, y, sizes[0], sizes[1]); return Bitmap.createBitmap(bitmap, 0, y - 30, w, sizes[0]); } } /** * 获取最佳预览尺寸 */ private Size getOptimalPreviewSize(List sizes, int width, int height) { final double ASPECT_TOLERANCE = 0.05; double targetRatio = (double) width / height; if (sizes == null) return null; Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetHeight = height; // Try to find an size match aspect ratio and size for (Size size : sizes) { double r = size.width * 1.0 / size.height * 1.0; if (r != 4 / 3 || r != 3 / 4 || r != 16 / 9 || r != 9 / 16) { continue; } double ratio = (double) size.width / size.height; if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } // Cannot find the one match the aspect ratio, ignore the requirement if (optimalSize == null) { minDiff = Double.MAX_VALUE; for (Size size : sizes) { if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } } return optimalSize; } /** * 设置照片尺寸为最接近屏幕尺寸 * * @param list * @return */ private void setPicutreSize(List list, int screenWidth, int screenHeight) { int approach = Integer.MAX_VALUE; for (Size size : list) { int temp = Math.abs(size.width - screenWidth + size.height - screenHeight); if (approach > temp) { approach = temp; this.pictureSize = size; } } } }
第二步:
package com.leict.custom.maskcamera.camera; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.ImageFormat; import android.graphics.Matrix; import android.hardware.Camera; import android.media.AudioManager; import android.media.ToneGenerator; import android.os.Environment; import android.util.Log; import android.view.SurfaceHolder; import com.leict.custom.maskcamera.utils.Utils; import com.leict.custom.maskcamera.views.VinSurfaceView; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; public class CameraVinHelper { private final String TAG = CameraVinHelper.class.getSimpleName(); private boolean isPreview; private static CameraVinHelper helper; private Camera camera; private ToneGenerator tone; private VinSurfaceView surfaceView; /** * 分辨率 */ private Camera.Size resolution; /** * 照片质量 */ private int picQuality = 100; /** * 照片尺寸 */ private Camera.Size pictureSize; /** * 上下文 */ private Context mContext; /** * 闪光灯模式(default:自动) */ private String flashStatus = Camera.Parameters.FLASH_MODE_AUTO; public enum Flashlight { AUTO, ON, OFF } private CameraVinHelper(Context context) { this.mContext = context; } public static CameraVinHelper getInstance(Context context) { if (helper == null) { synchronized (CameraVinHelper.class) { if (helper == null) { helper = new CameraVinHelper(context.getApplicationContext()); } } } return helper; } /** * 设置闪光灯模式 * * @param status * @return */ public CameraVinHelper setFlashState(CameraPlateHelper.Flashlight status) { switch (status) { case AUTO: this.flashStatus = Camera.Parameters.FLASH_MODE_AUTO; break; case ON: this.flashStatus = Camera.Parameters.FLASH_MODE_ON; break; case OFF: this.flashStatus = Camera.Parameters.FLASH_MODE_OFF; break; default: this.flashStatus = Camera.Parameters.FLASH_MODE_AUTO; } return helper; } public CameraVinHelper setMaskSurfaceView(VinSurfaceView surfaceView) { this.surfaceView = surfaceView; return helper; } /** * 获取Camera对象 * * @return */ private Camera getCamera() { Camera camera; try { camera = Camera.open(); } catch (Exception e) { camera = null; e.printStackTrace(); } return camera; } /** * 打开相机并开启预览 * * @param holder SurfaceHolder * @param format 图片格式 * @param width SurfaceView宽度 * @param height SurfaceView高度 * @param screenWidth 屏幕宽度 * @param screenHeight 屏幕高度 */ public void openCamera(SurfaceHolder holder, int format, int width, int height, int screenWidth, int screenHeight) { if (this.camera != null) { this.camera.release(); } this.camera = getCamera(); this.setParameter(holder, format, width, height, screenWidth, screenHeight); this.startPreview(); } /** * 照相 */ public void tackPicture(final TakePhotoCallback callback) { this.camera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean flag, Camera camera) { camera.takePicture(new Camera.ShutterCallback() { @Override public void onShutter() { if (tone == null) { //发出提示用户的声音 tone = new ToneGenerator(AudioManager.STREAM_MUSIC, ToneGenerator.MAX_VOLUME); } tone.startTone(ToneGenerator.TONE_PROP_BEEP2); } }, null, new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { String filepath = savePicture(data); boolean success = false; if (filepath != null) { success = true; } stopPreview(); callback.onCapture(success, filepath); } }); } }); } /** * 裁剪并保存照片 * * @param data * @return */ private String savePicture(byte[] data) { String filePath = Environment.getExternalStorageDirectory() + "/cbx/vin.jpg"; Bitmap bitmap = cutPicture(data); try { int length = filePath.length(); String strPath = filePath.substring(0, filePath.indexOf("v")); String strName = filePath.substring(filePath.indexOf("v"), length); if (Utils.isExist(strPath, strName)) { File imgFile = new File(filePath); FileOutputStream fos = new FileOutputStream(imgFile); BufferedOutputStream bos = new BufferedOutputStream(fos); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos); fos.close(); bos.flush(); bos.close(); } } catch (IOException e) { e.printStackTrace(); } return filePath; } /** * 初始化相机参数 * * @param holder SurfaceHolder * @param format 图片格式 * @param width SurfaceView宽度 * @param height SurfaceView高度 * @param screenWidth 屏幕宽度 * @param screenHeight 屏幕高度 */ private void setParameter(SurfaceHolder holder, int format, int width, int height, int screenWidth, int screenHeight) { try { Camera.Parameters p = this.camera.getParameters(); this.camera.setPreviewDisplay(holder); if (width > height) { //横屏 this.camera.setDisplayOrientation(0); } else { //竖屏 this.camera.setDisplayOrientation(90); } //照片质量 p.set("jpeg-quality", picQuality); //设置照片格式 p.setPictureFormat(ImageFormat.JPEG); //设置闪光灯 p.setFlashMode(flashStatus); //设置最佳预览尺寸 ListpreviewSizes = p.getSupportedPreviewSizes(); //设置预览分辨率 if (this.resolution == null) { this.resolution = this.getOptimalPreviewSize(previewSizes, width, height); } try { p.setPreviewSize(this.resolution.width, this.resolution.height); } catch (Exception e) { Log.e(TAG, "不支持的预览分辨率: " + this.resolution.width + " × " + this.resolution.height); } //设置照片尺寸 if (this.pictureSize == null) { List pictureSizes = p.getSupportedPictureSizes(); this.setPicutreSize(pictureSizes, screenWidth, screenHeight); } try { p.setPictureSize(this.pictureSize.width, this.pictureSize.height); } catch (Exception e) { Log.e(TAG, "不支持的照片尺寸: " + this.pictureSize.width + " × " + this.pictureSize.height); } this.camera.setParameters(p); } catch (Exception e) { e.printStackTrace(); Log.e(TAG, "相机参数设置错误"); } } /** * 释放Camera */ public void releaseCamera() { if (this.camera != null) { if (this.isPreview) { this.stopPreview(); } this.camera.setPreviewCallback(null); this.isPreview = false; this.camera.release(); this.camera = null; } } /** * 停止预览 */ private void stopPreview() { if (this.camera != null && this.isPreview) { this.camera.stopPreview(); this.isPreview = false; } } /** * 开始预览 */ public void startPreview() { if (this.camera != null) { this.camera.startPreview(); this.camera.autoFocus(null); this.isPreview = true; } } /** * 裁剪照片 * * @param data * @return */ private Bitmap cutPicture(byte[] data) { Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); if (this.surfaceView.getWidth() < this.surfaceView.getHeight()) { //竖屏旋转照片 Matrix matrix = new Matrix(); matrix.reset(); matrix.setRotate(90); bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); } if (this.surfaceView == null) { return bitmap; } else { int[] sizes = this.surfaceView.getMaskSize(); if (sizes[0] == 0 || sizes[1] == 0) { return bitmap; } int w = bitmap.getWidth(); int h = bitmap.getHeight(); int x = (w - sizes[0]) / 2; int y = (h - sizes[1]) / 2; Log.i("bitmap_w--------->>>", String.valueOf(w)); Log.i("bitmap_h--------->>>", String.valueOf(h)); Log.i("x--------->>>", String.valueOf(x)); Log.i("y--------->>>", String.valueOf(y)); Log.i("w--------->>>", String.valueOf(sizes[0])); Log.i("h--------->>>", String.valueOf(sizes[1])); return Bitmap.createBitmap(bitmap, x, y, sizes[0], sizes[1]); } } /** * 获取最佳预览尺寸 */ private Camera.Size getOptimalPreviewSize(List sizes, int width, int height) { final double ASPECT_TOLERANCE = 0.05; double targetRatio = (double) width / height; if (sizes == null) return null; Camera.Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetHeight = height; // Try to find an size match aspect ratio and size for (Camera.Size size : sizes) { double r = size.width * 1.0 / size.height * 1.0; if (r != 4 / 3 || r != 3 / 4 || r != 16 / 9 || r != 9 / 16) { continue; } double ratio = (double) size.width / size.height; if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } // Cannot find the one match the aspect ratio, ignore the requirement if (optimalSize == null) { minDiff = Double.MAX_VALUE; for (Camera.Size size : sizes) { if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } } return optimalSize; } /** * 设置照片尺寸为最接近屏幕尺寸 * * @param list * @return */ private void setPicutreSize(List list, int screenWidth, int screenHeight) { int approach = Integer.MAX_VALUE; for (Camera.Size size : list) { int temp = Math.abs(size.width - screenWidth + size.height - screenHeight); if (approach > temp) { approach = temp; this.pictureSize = size; } } } }
第三步:
package com.leict.custom.maskcamera.views; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.PixelFormat; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.FrameLayout; import com.leict.custom.maskcamera.camera.CameraPlateHelper; import com.leict.custom.maskcamera.utils.Utils; /** * 车牌识别 */ public class PlateSurfaceView extends FrameLayout { private MSurfaceView surfaceView; private MaskView imageView; private Context mContext; private int width; private int height; private int maskWidth; private int maskHeight; private int screenWidth; private int screenHeight; public PlateSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); this.mContext = context; surfaceView = new MSurfaceView(context); imageView = new MaskView(context); this.addView(surfaceView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); this.addView(imageView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); this.screenHeight = Utils.getHeight(mContext); this.screenWidth = Utils.getWidth(mContext); CameraPlateHelper.getInstance(mContext).setMaskSurfaceView(this); } public void setMaskSize(Integer width, Integer height) { maskHeight = height; maskWidth = width; } public int[] getMaskSize() { return new MaskSize().size; } private class MSurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder holder; @SuppressWarnings("deprecation") public MSurfaceView(Context context) { super(context); this.holder = this.getHolder(); //translucent半透明 transparent透明 this.holder.setFormat(PixelFormat.TRANSPARENT); this.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); this.holder.addCallback(this); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { width = w; height = h; CameraPlateHelper.getInstance(mContext).openCamera(holder, format, width, height, screenWidth, screenHeight); } @Override public void surfaceCreated(SurfaceHolder holder) { //CameraHelper.getInstance(mContext).openCamera(holder, 100, width, height, screenWidth, screenHeight); } @Override public void surfaceDestroyed(SurfaceHolder holder) { CameraPlateHelper.getInstance(mContext).releaseCamera(); } } private class MaskSize { private int[] size; private MaskSize() { this.size = new int[]{maskWidth, maskHeight, width, height}; } } private class MaskView extends View { private Paint linePaint; private Paint rectPaint; private RectF rectFLine; public MaskView(Context context) { super(context); //绘制中间透明区域矩形边界的Paint linePaint = new Paint(Paint.ANTI_ALIAS_FLAG); linePaint.setColor(Color.WHITE); linePaint.setStyle(Style.STROKE); linePaint.setAntiAlias(true); linePaint.setStrokeWidth(5f); //绘制四周矩形阴影区域 rectPaint = new Paint(Paint.ANTI_ALIAS_FLAG); rectPaint.setColor(Color.BLACK); rectPaint.setStyle(Style.FILL); rectPaint.setAlpha(180); } @Override protected void onDraw(Canvas canvas) { if (maskHeight == 0 && maskWidth == 0) { return; } if (maskHeight == height || maskWidth == width) { return; } if ((height > width && maskHeight < maskWidth) || (height < width && maskHeight > maskWidth)) { int temp = maskHeight; maskHeight = maskWidth; maskWidth = temp; } int h = Math.abs((height - maskHeight) / 2); int w = Math.abs((width - maskWidth) / 2); //上 canvas.drawRect(0, 0, width, h, rectPaint); Log.i("上-M---------------L>>", String.valueOf(0)); Log.i("上-M---------------T>>", String.valueOf(0)); Log.i("上-M---------------R>>", String.valueOf(width)); Log.i("上-M---------------B>>", String.valueOf(h)); //右 //canvas.drawRect(width - w, h, width, height - h, rect); canvas.drawRect(width - 50, h, width, width - w, rectPaint); Log.i("右-M---------------L>>", String.valueOf(width - w)); Log.i("右-M---------------T>>", String.valueOf(h)); Log.i("右-M---------------R>>", String.valueOf(width)); Log.i("右-M---------------B>>", String.valueOf(height - h)); //下 //canvas.drawRect(0, height - h, width, height, this.rectPaint); canvas.drawRect(0, width - w, width, height, this.rectPaint); Log.i("下-M---------------L>>", String.valueOf(0)); Log.i("下-M---------------T>>", String.valueOf(height - h)); Log.i("下-M---------------R>>", String.valueOf(width)); Log.i("下-M---------------B>>", String.valueOf(height)); //左 //canvas.drawRect(0, h, w, h + maskHeight, rect); canvas.drawRect(0, h, 50, width - w, this.rectPaint); Log.i("左-M---------------L>>", String.valueOf(0)); Log.i("左-M---------------T>>", String.valueOf(h)); Log.i("左-M---------------R>>", String.valueOf(w)); Log.i("左-M---------------B>>", String.valueOf(h + maskHeight)); //矩形边框的颜色 //canvas.drawRect(w, h, w + maskWidth, h + maskHeight, linePaint); rectFLine = new RectF(50, h, width - 50, width - w); canvas.drawRoundRect(rectFLine, 10, 10, linePaint); Log.i("框-M---------------L>>", String.valueOf(w)); Log.i("框-M---------------T>>", String.valueOf(h)); Log.i("框-M---------------R>>", String.valueOf(w + maskWidth)); Log.i("框-M---------------B>>", String.valueOf(h + maskHeight)); super.onDraw(canvas); } } }
第四步:
package com.leict.custom.maskcamera.views; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.FrameLayout; import com.leict.custom.maskcamera.camera.CameraVinHelper; import com.leict.custom.maskcamera.utils.Utils; /** * 车架号识别 */ public class VinSurfaceView extends FrameLayout { private MSurfaceView surfaceView; private MaskView imageView; private Context mContext; private int width; private int height; private int maskWidth; private int maskHeight; private int screenWidth; private int screenHeight; public VinSurfaceView(Context context, AttributeSet attrs) { super(context, attrs); this.mContext = context; surfaceView = new MSurfaceView(context); imageView = new MaskView(context); this.addView(surfaceView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); this.addView(imageView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); this.screenHeight = Utils.getHeight(mContext); this.screenWidth = Utils.getWidth(mContext); CameraVinHelper.getInstance(mContext).setMaskSurfaceView(this); } public void setMaskSize(Integer width, Integer height) { maskHeight = height; maskWidth = width; } public int[] getMaskSize() { return new MaskSize().size; } private class MSurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder holder; @SuppressWarnings("deprecation") public MSurfaceView(Context context) { super(context); this.holder = this.getHolder(); //translucent半透明 transparent透明 this.holder.setFormat(PixelFormat.TRANSPARENT); this.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); this.holder.addCallback(this); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { width = w; height = h; CameraVinHelper.getInstance(mContext).openCamera(holder, format, width, height, screenWidth, screenHeight); } @Override public void surfaceCreated(SurfaceHolder holder) { //CameraHelper.getInstance(mContext).openCamera(holder, 100, width, height, screenWidth, screenHeight); } @Override public void surfaceDestroyed(SurfaceHolder holder) { CameraVinHelper.getInstance(mContext).releaseCamera(); } } private class MaskSize { private int[] size; private MaskSize() { this.size = new int[]{maskWidth, maskHeight, width, height}; } } private class MaskView extends View { private Paint linePaint; private Paint rectPaint; private RectF rectFLine; public MaskView(Context context) { super(context); //绘制中间透明区域矩形边界的Paint linePaint = new Paint(Paint.ANTI_ALIAS_FLAG); linePaint.setColor(Color.WHITE); linePaint.setStyle(Paint.Style.STROKE); linePaint.setAntiAlias(true); linePaint.setStrokeWidth(5f); //绘制四周矩形阴影区域 rectPaint = new Paint(Paint.ANTI_ALIAS_FLAG); rectPaint.setColor(Color.BLACK); rectPaint.setStyle(Paint.Style.FILL); rectPaint.setAlpha(180); } @Override protected void onDraw(Canvas canvas) { if (maskHeight == 0 && maskWidth == 0) { return; } if (maskHeight == height || maskWidth == width) { return; } if ((height > width && maskHeight < maskWidth) || (height < width && maskHeight > maskWidth)) { int temp = maskHeight; maskHeight = maskWidth; maskWidth = temp; } int h = Math.abs((height - maskHeight) / 2); int w = Math.abs((width - maskWidth) / 2); //上 canvas.drawRect(0, 0, width, h, rectPaint); Log.i("上-M---------------L>>", String.valueOf(0)); Log.i("上-M---------------T>>", String.valueOf(0)); Log.i("上-M---------------R>>", String.valueOf(width)); Log.i("上-M---------------B>>", String.valueOf(h)); //右 canvas.drawRect(width - w, h, width, height - h, rectPaint); Log.i("右-M---------------L>>", String.valueOf(width - w)); Log.i("右-M---------------T>>", String.valueOf(h)); Log.i("右-M---------------R>>", String.valueOf(width)); Log.i("右-M---------------B>>", String.valueOf(height - h)); //下 canvas.drawRect(0, height - h, width, height, this.rectPaint); Log.i("下-M---------------L>>", String.valueOf(0)); Log.i("下-M---------------T>>", String.valueOf(height - h)); Log.i("下-M---------------R>>", String.valueOf(width)); Log.i("下-M---------------B>>", String.valueOf(height)); //左 canvas.drawRect(0, h, w, h + maskHeight, rectPaint); Log.i("左-M---------------L>>", String.valueOf(0)); Log.i("左-M---------------T>>", String.valueOf(h)); Log.i("左-M---------------R>>", String.valueOf(w)); Log.i("左-M---------------B>>", String.valueOf(h + maskHeight)); //矩形边框的颜色 rectFLine = new RectF(w, h, w + maskWidth, h + maskHeight); canvas.drawRoundRect(rectFLine, 10, 10, linePaint); Log.i("框-M---------------L>>", String.valueOf(w)); Log.i("框-M---------------T>>", String.valueOf(h)); Log.i("框-M---------------R>>", String.valueOf(w + maskWidth)); Log.i("框-M---------------B>>", String.valueOf(h + maskHeight)); super.onDraw(canvas); } } }
总结:到这里大部分代码就已经写完了,剩下布局文件自己可以去布局!!!!!