当前位置: 首页 > news >正文

叶县建设局网站安卓网页制作软件

叶县建设局网站,安卓网页制作软件,重庆网站推广产品,网站服务器失去响应1. 前言 这段时间#xff0c;在使用 natario1/CameraView 来实现带滤镜的预览、拍照、录像功能。 由于CameraView封装的比较到位#xff0c;在项目前期#xff0c;的确为我们节省了不少时间。 但随着项目持续深入#xff0c;对于CameraView的使用进入深水区#xff0c;逐…1. 前言 这段时间在使用 natario1/CameraView 来实现带滤镜的预览、拍照、录像功能。 由于CameraView封装的比较到位在项目前期的确为我们节省了不少时间。 但随着项目持续深入对于CameraView的使用进入深水区逐渐出现满足不了我们需求的情况。 Github中的issues中有些BUG作者一直没有修复。 那要怎么办呢 ? 项目迫切地需要实现相关功能只能自己硬着头皮去看它的源码去解决这些问题。 而这篇文章是其中关于CameraView怎么进行拍照的源码解析。 以下源码解析基于CameraView 2.7.2 implementation(com.otaliastudios:cameraview:2.7.2)为了在博客上更好的展示本文贴出的代码进行了部分精简 拍照的入口是cameraView.takePicture()我们从这个方法开始解析。 2. CameraEngine.takePicture cameraView.takePicture()会调用到mCameraEngine.takePicture() 这个PictureResult.Stub是一个参数封装类这里重新创建了一个PictureResult.Stub并传入takePicture()方法中。 mCameraEngine是CameraEngine抽象类实现类有Camera1Engine和Camera2Engine。 public void takePicture() {PictureResult.Stub stub new PictureResult.Stub();mCameraEngine.takePicture(stub); }我们这里以Camera2为例可以看到这里对stub参数封装类赋值了一些参数(摄像头ID、图片格式等)并调用了onTakePicture public void takePicture(final PictureResult.Stub stub) {final boolean metering mPictureMetering;getOrchestrator().scheduleStateful(take picture, CameraState.BIND,new Runnable() {Overridepublic void run() {if (isTakingPicture()) return;if (mMode Mode.VIDEO) {throw new IllegalStateException(Cant take hq pictures while in VIDEO mode);}stub.isSnapshot false;stub.location mLocation;stub.facing mFacing;stub.format mPictureFormat;onTakePicture(stub, metering);}}); }3. onTakePicture 接着来看onTakePicture() 设置Rotation stub.rotation getAngles().offset(Reference.SENSOR, Reference.OUTPUT, Axis.RELATIVE_TO_SENSOR);设置设定好拍照图片尺寸 stub.size getPictureSize(Reference.OUTPUT);接着调用mPictureRecorder.take()mPictureRecorder是PictureRecorder接口具体实现是Full2PictureRecorder专门用来调用Camera2 API捕获图片。 mPictureRecorder new Full2PictureRecorder(stub, this, builder,mPictureReader); mPictureRecorder.take();来看一下完整的重点代码 EngineThread Override protected void onTakePicture(NonNull final PictureResult.Stub stub, boolean doMetering) {//...省略不重要代码...//设置Rotationstub.rotation getAngles().offset(Reference.SENSOR, Reference.OUTPUT, Axis.RELATIVE_TO_SENSOR);//设置设定好拍照图片尺寸stub.size getPictureSize(Reference.OUTPUT);//...省略不重要代码...CaptureRequest.Builder builder mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);applyAllParameters(builder, mRepeatingRequestBuilder);mPictureRecorder new Full2PictureRecorder(stub, this, builder,mPictureReader);mPictureRecorder.take(); }4. Full2PictureRecorder.take 再来看Full2PictureRecorder.take() Override public void take() {mAction.start(mHolder); }这里调用了mAction.start(mHolder)来看一下mAction初始化 4.1 初始化BaseAction mAction new BaseAction() {Overrideprotected void onStart(ActionHolder holder) { //省略了代码这里只看结构 }Overridepublic void onCaptureStarted(ActionHolder holder,CaptureRequest request) { //省略了代码这里只看结构 }Overridepublic void onCaptureCompleted(ActionHolder holder,CaptureRequest request,TotalCaptureResult result) { //省略了代码这里只看结构 } };mAction是BaseAction抽象类有onStart、onCaptureStarted、onCaptureProgressed、onCaptureCompleted等方法。mHolder是构造方法传入过来的Camera2Engine实现了ActionHolder接口。 4.2 BaseAction.onStart 调用了mAction.start(mHolder)后mAction和mHolder会建立关联也就是BaseAction和Camera2Engine会建立关联具体代码为Camera2Engine.addAction(BaseAction)将其添加到Actions列表中并在合适的时机回调BaseAction的onCaptureStarted、onCaptureProgressed、onCaptureCompleted方法。 mAction和mHolder建立关联后会调用onStart方法这里是对mPictureBuilder这个建造者设置了一些值 Override protected void onStart(NonNull ActionHolder holder) {super.onStart(holder);//mPictureBuilder是一个建造者这里给建造者设置一些值mPictureBuilder.addTarget(mPictureReader.getSurface());if (mResult.format PictureFormat.JPEG) {mPictureBuilder.set(CaptureRequest.JPEG_ORIENTATION, mResult.rotation);}mPictureBuilder.setTag(CameraDevice.TEMPLATE_STILL_CAPTURE);//应用这个建造者holder.applyBuilder(this, mPictureBuilder); }再来看onCaptureStarted调用了dispatchOnShutter来回调 Override public void onCaptureStarted(NonNull ActionHolder holder,NonNull CaptureRequest request) {super.onCaptureStarted(holder, request);if (request.getTag() (Integer) CameraDevice.TEMPLATE_STILL_CAPTURE) {dispatchOnShutter(false);setState(STATE_COMPLETED);} }4.3 BaseAction.onCaptureCompleted 再来看onCaptureCompleted主要是在DNG格式的时候做了一些特殊处理。 Override public void onCaptureCompleted(ActionHolder holder, CaptureRequest request, TotalCaptureResult result) {if (mResult.format PictureFormat.DNG) {mDngCreator new DngCreator(holder.getCharacteristics(this), result);mDngCreator.setOrientation(ExifHelper.getExifOrientation(mResult.rotation));if (mResult.location ! null) {mDngCreator.setLocation(mResult.location);}} }结果发现这里不是重点那么重点在哪里呢 ? 5. 设置OnImageAvailableListener监听 在Full2PictureRecorder初始化构造方法中还有这么一句 mPictureReader.setOnImageAvailableListener(this, WorkerHandler.get().getHandler());在Android的Camera2 API中setOnImageAvailableListener方法用于注册一个回调监听器以在每次图像数据可用时接收通知。 5.1 onImageAvailable回调 来看onImageAvailable回调方法这里会调用android.media.ImageReader.acquireNextImage()来获取图像数据。 然后如果是JPEG格式则会调用readJpegImage()方法读取图像数据 最后都会调用dispatchResult来分发数据。 Override public void onImageAvailable(ImageReader reader) {Image image null;try {image reader.acquireNextImage();switch (mResult.format) {case JPEG: readJpegImage(image); break;case DNG: readRawImage(image); break;default: throw new IllegalStateException(Unknown format: mResult.format);}} catch (Exception e) {mResult null;mError e;dispatchResult();return;} finally {if (image ! null) {image.close();}}dispatchResult(); }5.2 读取JPEG数据 我们先来看下readJpegImage()方法 private void readJpegImage(NonNull Image image) {//从Iamge中读取数据ByteBuffer buffer image.getPlanes()[0].getBuffer();byte[] bytes new byte[buffer.remaining()];buffer.get(bytes);mResult.data bytes;//根据Exif设置rotationmResult.rotation 0;ExifInterface exif new ExifInterface(new ByteArrayInputStream(mResult.data));int exifOrientation exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL);mResult.rotation ExifHelper.getOrientation(exifOrientation); }5.3 分发回调 再来看dispatchResult最终会调用到CameraView中的dispatchOnPictureTaken这个方法中会遍历mListeners回调列表调用onPictureTaken() Override public void dispatchOnPictureTaken(final PictureResult.Stub stub) {mUiHandler.post(new Runnable() {Overridepublic void run() {PictureResult result new PictureResult(stub);for (CameraListener listener : mListeners) {listener.onPictureTaken(result);}}}); }而mListeners什么时候被添加呢 ? CameraView中有一个addCameraListener方法专门直接添加回调。 public void addCameraListener(CameraListener cameraListener) {mListeners.add(cameraListener); }5.4 设置回调 所以我们只要添加了这个回调并实现onPictureTaken方法就可以在onPictureTaken()中获取到拍照后的图像信息了。 binding.cameraView.addCameraListener(object : CameraListener() {override fun onPictureTaken(result: PictureResult) {super.onPictureTaken(result)//拍照回调val bitmap BitmapFactory.decodeByteArray(result.data, 0, result.data.size)bitmap?.also {Toast.makeText(thisTest2Activity, 拍照成功, Toast.LENGTH_SHORT).show()//将Bitmap设置到ImageView上binding.img.setImageBitmap(it)val file getNewImageFile()//保存图片到指定目录ImageUtils.save(it, file, Bitmap.CompressFormat.JPEG)}} })6. 其他 6.1 CameraView源码解析系列 Android 相机库CameraView源码解析 (一) : 预览-CSDN博客 Android 相机库CameraView源码解析 (二) : 拍照-CSDN博客
http://www.huolong8.cn/news/1588/

相关文章: