淮安网站seo,品牌建设心得体会,滁州金鹏建设集团网站,wordpress汉化主体本文已授权微信公众号《鸿洋》原创首发#xff0c;转载请务必注明出处。概述 相机差点儿是每一个APP都要用到的功能#xff0c;万一老板让你定制相机方不方#xff1f;反正我是有点方。关于相机的两天奋斗总结免费送给你。Intent intent new Intent(); intent.setAction(M… 本文已授权微信公众号《鸿洋》原创首发转载请务必注明出处。 概述 相机差点儿是每一个APP都要用到的功能万一老板让你定制相机方不方反正我是有点方。关于相机的两天奋斗总结免费送给你。 Intent intent new Intent(); intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); startActivity(intent); 或者指定返回图片的名称mCurrentPhotoFile。 Intent intent new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(mCurrentPhotoFile));startActivityForResult(intent, CAMERA_WITH_DATA); 2.自己定义启动相机。 今天以另外一种为例。效果图例如以下 自己定义相机的一般步骤 创建显示相机画面的布局。Android已经为我们选定好SurfaceView通过SurfaceView#getHolder()获得链接Camera和SurfaceView的SurfaceHolderCamame.open()打开相机通过SurfaceHolder链接Camera和urfaceView一般步骤的代码演示 public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback, Camera.AutoFocusCallback {private static final String TAG CameraSurfaceView;private Context mContext;private SurfaceHolder holder;private Camera mCamera;private int mScreenWidth;private int mScreenHeight;public CameraSurfaceView(Context context) {this(context, null);}public CameraSurfaceView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public CameraSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mContext context;getScreenMetrix(context);initView();}private void getScreenMetrix(Context context) {WindowManager WM (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);DisplayMetrics outMetrics new DisplayMetrics();WM.getDefaultDisplay().getMetrics(outMetrics);mScreenWidth outMetrics.widthPixels;mScreenHeight outMetrics.heightPixels;}private void initView() {holder getHolder();//获得surfaceHolder引用holder.addCallback(this);holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置类型}Overridepublic void surfaceCreated(SurfaceHolder holder) {Log.i(TAG, surfaceCreated);if (mCamera null) {mCamera Camera.open();//开启相机try {mCamera.setPreviewDisplay(holder);//摄像头画面显示在Surface上} catch (IOException e) {e.printStackTrace();}}}Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {Log.i(TAG, surfaceChanged);mCamera.startPreview();}Overridepublic void surfaceDestroyed(SurfaceHolder holder) {Log.i(TAG, surfaceDestroyed);mCamera.stopPreview();//停止预览mCamera.release();//释放相机资源mCamera null;holder null;}Overridepublic void onAutoFocus(boolean success, Camera Camera) {if (success) {Log.i(TAG, onAutoFocus successsuccess);}}
} 加入相机和自己主动聚焦限权 uses-permission android:nameandroid.permission.CAMERA /
uses-feature android:nameandroid.hardware.camera.autofocus / 将CameraSurfaceView放在布局文件里这里建议最外层为FrameLayout后面会用到。如此。我们便有了一个没有照相功能的相机。初次之外细致观察相机显示画面图片是不是变形严重那是由于我们还没有为相机设置各种參数。在预览前要设置摄像头的分辨率、预览分辨率和图片分辨率的宽高比保持一致。这样图片才不会变形。这是个比較难以理解的部分想深刻理解还需读者自己动手去实践。 private void setCameraParams(Camera camera, int width, int height) {Log.i(TAG,setCameraParams widthwidth heightheight);Camera.Parameters parameters mCamera.getParameters();// 获取摄像头支持的PictureSize列表ListCamera.Size pictureSizeList parameters.getSupportedPictureSizes();for (Camera.Size size : pictureSizeList) {Log.i(TAG, pictureSizeList size.width size.width size.height size.height);}/**从列表中选取合适的分辨率*/Camera.Size picSize getProperSize(pictureSizeList, ((float) height / width));if (null picSize) {Log.i(TAG, null picSize);picSize parameters.getPictureSize();}Log.i(TAG, picSize.width picSize.width picSize.height picSize.height);// 依据选出的PictureSize又一次设置SurfaceView大小float w picSize.width;float h picSize.height;parameters.setPictureSize(picSize.width,picSize.height);this.setLayoutParams(new FrameLayout.LayoutParams((int) (height*(h/w)), height));// 获取摄像头支持的PreviewSize列表ListCamera.Size previewSizeList parameters.getSupportedPreviewSizes();for (Camera.Size size : previewSizeList) {Log.i(TAG, previewSizeList size.width size.width size.height size.height);}Camera.Size preSize getProperSize(previewSizeList, ((float) height) / width);if (null ! preSize) {Log.i(TAG, preSize.width preSize.width preSize.height preSize.height);parameters.setPreviewSize(preSize.width, preSize.height);}parameters.setJpegQuality(100); // 设置照片质量if (parameters.getSupportedFocusModes().contains(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {parameters.setFocusMode(android.hardware.Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 连续对焦模式}mCamera.cancelAutoFocus();//自己主动对焦。 // 设置PreviewDisplay的方向。效果就是将捕获的画面旋转多少度显示 // TODO 这里直接设置90°不严谨。详细见https://developer.android.com/reference/android/hardware/Camera.html#setPreviewDisplay%28android.view.SurfaceHolder%29 mCamera.setDisplayOrientation(90); mCamera.setParameters(parameters); } /** * 从列表中选取合适的分辨率 * 默认w:h 4:3 * ptip这里的w相应屏幕的height * h相应屏幕的widthp/ */ private Camera.Size getProperSize(ListCamera.Size pictureSizeList, float screenRatio) { Log.i(TAG, screenRatio screenRatio); Camera.Size result null; for (Camera.Size size : pictureSizeList) { float currentRatio ((float) size.width) / size.height; if (currentRatio - screenRatio 0) { result size; break; } } if (null result) { for (Camera.Size size : pictureSizeList) { float curRatio ((float) size.width) / size.height; if (curRatio 4f / 3) {// 默认w:h 4:3 result size; break; } } } return result; } 进去的是屏幕宽高。出来的是调整好了的參数。在surfaceChanged方法中运行mCamera.startPreview(); 前调用setCameraParams(mCamera, mScreenWidth, mScreenHeight); 就能够了。最后要在AndroidManifest.xml里设置activity的方向android:screenOrientationportrait代码里有非常多凝视当中也有我自己调试时候的Log大家能够自己调试下。看看不同參数的效果。昨天调參数搞到一点多都在折腾这个函数。唉一把辛酸泪。 身为一个相机竟然不能照相真是太丢脸了以下给我们的相机加入上照相的功能。照相核心代码就一句mCamera.takePicture(null, null, jpeg); 能够看到takePicture方法有三个參数各自是ShutterCallback、PictureCallback和PictureCallback。这里我们仅仅用了PictureCallback // 拍照瞬间调用private Camera.ShutterCallback shutter new Camera.ShutterCallback() {Overridepublic void onShutter() {Log.i(TAG,shutter);}};// 获得没有压缩过的图片数据private Camera.PictureCallback raw new Camera.PictureCallback() {Overridepublic void onPictureTaken(byte[] data, Camera Camera) {Log.i(TAG, raw);}};//创建jpeg图片回调数据对象private Camera.PictureCallback jpeg new Camera.PictureCallback() {Overridepublic void onPictureTaken(byte[] data, Camera Camera) {BufferedOutputStream bos null;Bitmap bm null;try {// 获得图片bm BitmapFactory.decodeByteArray(data, 0, data.length);if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {Log.i(TAG, Environment.getExternalStorageDirectory()Environment.getExternalStorageDirectory());String filePath /sdcard/dykSystem.currentTimeMillis().jpg;//照片保存路径File file new File(filePath);if (!file.exists()){file.createNewFile();}bos new BufferedOutputStream(new FileOutputStream(file));bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);//将图片压缩到流中}else{Toast.makeText(mContext,没有检測到内存卡, Toast.LENGTH_SHORT).show();}} catch (Exception e) {e.printStackTrace();} finally {try {bos.flush();//输出bos.close();//关闭bm.recycle();// 回收bitmap空间mCamera.stopPreview();// 关闭预览mCamera.startPreview();// 开启预览} catch (IOException e) {e.printStackTrace();}}}}; 在jpeg#onPictureTaken()里。我们将存储照片信息的byte[] data解析成bitmap然后转换成JPG格式的图片保存在SD卡中。注意finally中最后两句mCamera.stopPreview();// 关闭预览 mCamera.startPreview();// 开启预览 上文也提到当调用camera.takePiture()方法后。camera关闭了预览。这时须要调用startPreview()来又一次开启预览。假设不再次开启预览。则会一直停留在拍摄照片画面。为了方便外部调用拍照。这里我暴露了一个方法供外部拍照。 public void takePicture(){//设置參数,并拍照setCameraParams(mCamera, mScreenWidth, mScreenHeight);// 当调用camera.takePiture方法后camera关闭了预览这时须要调用startPreview()来又一次开启预览mCamera.takePicture(null, null, jpeg);} 在布局文件里加入一个Button点击Button运行takePicture()方法。不要忘了加入写SD卡限权 uses-permission android:nameandroid.permission.WRITE_EXTERNAL_STORAGE / 至此。一个具有照相并保存拍摄图片功能的相机就做出来了。But我们就此满足了吗要是为了这些简单的功能我也不会写这篇博客。这仅仅是个開始 真正的開始 别人APP在照相的时候。屏幕上竟然能够显示像效果图那样的框框啦、辅助点啦、图片bulabulabula~。在网上搜索一番实现方式再加上一些自己的理解构成了这篇博客。 上文布局文件一直没有贴。如今贴出来大家先扫一眼有些控件会在接下来展示 ?xml version1.0 encodingutf-8?
FrameLayout xmlns:androidhttp://schemas.android.com/apk/res/androidandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentcom.dyk.cameratest.view.CameraSurfaceViewandroid:idid/cameraSurfaceViewandroid:layout_widthmatch_parentandroid:layout_heightmatch_parent /com.dyk.cameratest.view.RectOnCameraandroid:layout_widthmatch_parentandroid:layout_heightmatch_parent /RelativeLayoutandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentButtonandroid:layout_alignParentBottomtrueandroid:layout_centerHorizontaltrueandroid:layout_marginBottom20dpandroid:idid/takePicandroid:layout_width80dpandroid:layout_height50dpandroid:background#88427ac7android:text拍照android:textColor#aaa //RelativeLayout
/FrameLayout 布局文件的最外层是个FrameLayout。我们知道FrameLayout是自带覆盖效果的。由来这个思路接下来就非常easy了。编程重要的是思想思想有了其余的就剩详细的实现细节。 自己定义边边框框 为了和CameraSurfaceView区分开再自己定义一个RectOnCamera专门用来画边边框框这些东西。这样做还一个优点是方便维护不至于将所有东西都放在一个View中。 RectOnCamera package com.dyk.cameratest.view;
...
/*** Created by 一口仨馍 on 2016/4/7.*/
public class RectOnCamera extends View {private static final String TAG CameraSurfaceView;private int mScreenWidth;private int mScreenHeight;private Paint mPaint;private RectF mRectF;// 圆private Point centerPoint;private int radio;public RectOnCamera(Context context) {this(context, null);}public RectOnCamera(Context context, AttributeSet attrs) {this(context, attrs, 0);}public RectOnCamera(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);getScreenMetrix(context);initView(context);}private void getScreenMetrix(Context context) {WindowManager WM (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);DisplayMetrics outMetrics new DisplayMetrics();WM.getDefaultDisplay().getMetrics(outMetrics);mScreenWidth outMetrics.widthPixels;mScreenHeight outMetrics.heightPixels;}private void initView(Context context) {mPaint new Paint();mPaint.setAntiAlias(true);// 抗锯齿mPaint.setDither(true);// 防抖动mPaint.setColor(Color.RED);mPaint.setStrokeWidth(5);mPaint.setStyle(Paint.Style.STROKE);// 空心int marginLeft (int) (mScreenWidth*0.15);int marginTop (int) (mScreenHeight * 0.25);mRectF new RectF(marginLeft, marginTop, mScreenWidth - marginLeft, mScreenHeight - marginTop);centerPoint new Point(mScreenWidth/2, mScreenHeight/2);radio (int) (mScreenWidth*0.1);}Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);mPaint.setColor(Color.RED);canvas.drawRect(mRectF, mPaint);mPaint.setColor(Color.WHITE);Log.i(TAG, onDraw);canvas.drawCircle(centerPoint.x,centerPoint.y, radio,mPaint);// 外圆canvas.drawCircle(centerPoint.x,centerPoint.y, radio - 20,mPaint); // 内圆}
} 这里简单的画了一个相似二维码扫描的框框。另一个相似聚焦的内外圆。那么问题来了聚焦的内外圆要随着手指滑而改变位置并且要有聚焦的效果。可又和具有聚焦功能的CameraSurfaceView不是同一个类。不仅如此聚焦内外圆还全然覆盖了CameraSurfaceView。要处理这样的问题须要接口回调。这就是思想以下的细节。如今尽管确定接口回调。但另一个问题CameraSurfaceView类和RectOnCamera类中都没有对方的对象或者引用。没错通过共同持有RectOnCamera和CameraSurfaceView的Activity能够实现此功能。以下是详细的实现方法 动起来 首先。想要随着手指的滑动而改变RectOnCamera的位置肯定是要复写onTouchEvent()方法 Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()){case MotionEvent.ACTION_DOWN:case MotionEvent.ACTION_MOVE:case MotionEvent.ACTION_UP:int x (int) event.getX();int y (int) event.getY();centerPoint new Point(x, y);invalidate();return true;}return true;} 其次定义回调接口 private IAutoFocus mIAutoFocus;/** 聚焦的回调接口 */public interface IAutoFocus{void autoFocus();}public void setIAutoFocus(IAutoFocus mIAutoFocus) {this.mIAutoFocus mIAutoFocus;} 在onTouchEvent()中return前加入 if (mIAutoFocus ! null){mIAutoFocus.autoFocus();} 至此我们的回调接口已经定义好了。此时还须要CameraSurfaceView暴露一个聚焦方法。以便Activity调用 public void setAutoFocus(){mCamera.autoFocus(this);} 准备工作已经所有完毕。以下请看Activity的详细实现 public class MainActivity extends Activity implements View.OnClickListener,RectOnCamera.IAutoFocus{private CameraSurfaceView mCameraSurfaceView;private RectOnCamera mRectOnCamera;private Button takePicBtn;private boolean isClicked;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);// 全屏显示 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);setContentView(R.layout.activity_main);mCameraSurfaceView (CameraSurfaceView) findViewById(R.id.cameraSurfaceView);mRectOnCamera (RectOnCamera) findViewById(R.id.rectOnCamera);takePicBtn (Button) findViewById(R.id.takePic);mRectOnCamera.setIAutoFocus(this);takePicBtn.setOnClickListener(this);}Overridepublic void onClick(View v) {switch (v.getId()){case R.id.takePic:mCameraSurfaceView.takePicture();break;default:break;}}Overridepublic void autoFocus() {mCameraSurfaceView.setAutoFocus();}
} 能够看到MainActivity实现了IAutoFocus接口并且在复写的IAutoFocus#autoFocus()方法中。调用了CameraSurfaceView暴露出来的方法setAutoFocus()。至此在RectOnCamera每次的滑动过程中都会改变聚焦内外圆的位置还会添加聚焦功能。一心二用甚至一心多用岂不是更好。 结束语 在经历两次断电没保存和一次CSDNserver错误内容丢失之后终究还是完毕了这篇博客实属不易。十分感谢能听我啰嗦到结尾~ PSDemo界面并没有做的非常精致仅仅是提供了一种思路。依照此思路能做出比較华丽的效果授人以鱼不如授人以渔。 2016.10.12 在经历了上述种种磨难之后。最终发表了这篇博文。然而发表没几天被我自己覆盖了。这下博文是真的丢了。心塞ing。今天没事百度下自己CSDN昵称“一口仨馍”发现其它站点爬过这篇博文。随后我复制了自己原创的博文再次发表。感谢那些爬我博文还不署名的站点。谢谢你全家。 源代码下载 http://download.csdn.net/detail/qq_17250009/9484160 转载于:https://www.cnblogs.com/yfceshi/p/7382534.html