博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
照相机滤镜使用,优化解码和滤镜导致的预览卡屏现象
阅读量:6844 次
发布时间:2019-06-26

本文共 14510 字,大约阅读时间需要 48 分钟。

这几天看到亚瑟boy的技术连载,也试着做了下带滤镜特效的照相机,效果也出来了,但是发现添加滤镜特效后的预览窗口卡屏现象很严重,于是自己索性 试着尝试修改,在亚瑟和其他网友的代码中基本上都是对于照相机data视频流先进行解码,然后对解码出的帧Bitmap进行滤镜算法处理,这个是必走的流 程,而每一帧在处理解码和滤镜时都需要用掉大量时间,我测了下,解码需要300毫秒左右,滤镜处理需要600毫秒左右(冰冻滤镜),如此一来,处理完这两 个流程需要的时间要在900毫秒甚至更长,我们知道如果看上去比较流畅的话我们需要每秒更新三帧的图片,而这么处理只能更新一张,明显的卡屏。

于是试着去缩小处理的Bitmap大小,在照相机预览返回照片大小中设置:

Camera.Parameters parameters = camera.getParameters();parameters.setPreviewSize(display.getWidth()/2, display.getHeight()/2);// 设置预览照片的大小

原来默认是返回屏幕大小的预览图片,此时我改成了屏幕大小一半的图片,发现处理过程明显加快了(当然也有稍微的卡屏),最后在预览回调接口 PreviewCallBack中再将图片放大到屏幕大小,有雨我预览图片返回时只是缩小了一半,此时放大回屏幕大小时仍然是非常清晰的,如果你想速度更 快的话可以继续缩小预览图片的返回大小。

代码如下:

public class CameraActivity extends NoSearchActivity {         private static final String TAG = "CameraActivity";         private SurfaceView surfaceView;         private Camera camera;         private boolean preview;         private ImageButton take_picture;         private int width,height;         @Override         public void onCreate(Bundle savedInstanceState) {                 super.onCreate(savedInstanceState);                 Window window = getWindow();                 requestWindowFeature(Window.FEATURE_NO_TITLE);// 没有标题                 window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,                                 WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏                 window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);// 高亮                 setContentView(R.layout.camera_view);                 ButtonClickingListener buttonlistener = new ButtonClickingListener();                 surfaceView = (SurfaceView) this.findViewById(R.id.camera_surface);                 WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);                 Display display = wm.getDefaultDisplay();                 width = display.getWidth();                 height = display.getHeight();                 take_picture = (ImageButton) findViewById(R.id.take_picture);//拍照                 take_picture.setOnClickListener(buttonlistener);                 surfaceView.getHolder().setFixedSize(width, height); // 设置分辨率                 /* 下面设置Surface不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到用户面前 */                 surfaceView.getHolder().addCallback(new SurfaceCallback());         }         //按钮监听         private final class ButtonClickingListener implements View.OnClickListener {                 @Override                 public void onClick(View v) {                         if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {                                 Toast.makeText(CameraActivity.this, R.string.sdcarderror, 1).show();                                 return;                         }                         try {                                 switch (v.getId()) {                                 case R.id.take_picture:                                         camera.takePicture(null, null, new TakePictureCallback());                                         break;                                 }                         } catch (Exception e) {                                 Toast.makeText(CameraActivity.this, R.string.error, 1).show();                                 Log.e(TAG, e.toString());                         }                 }         }         @Override         protected void onDestroy() {                 // TODO Auto-generated method stub                 if(camera!=null){                         camera.setPreviewCallback(null) ;             camera.stopPreview();             camera.release();             camera = null;                 }                 super.onDestroy();         }         private final class SurfaceCallback implements SurfaceHolder.Callback {                 @Override                 public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {}                 @Override                 public void surfaceCreated(SurfaceHolder holder) {                         if(camera==null){                                 camera = Camera.open();//打开相机                         }else{                                 Toast.makeText(CameraActivity.this, "相机正在使用中", 1).show();                         }                         WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);                         Display display = wm.getDefaultDisplay();                         Camera.Parameters parameters = camera.getParameters();                         parameters.setPreviewSize(display.getWidth()/2, display.getHeight()/2);// 设置预览照片的大小                         parameters.setPreviewFrameRate(3);// 每秒3帧                         parameters.setPictureFormat(PixelFormat.JPEG);// 设置照片的输出格式                         parameters.set("jpeg-quality", 100);// 照片质量                         parameters.setPictureSize(display.getWidth(), display.getHeight());// 设置照片的大小                                                 camera.setParameters(parameters);                         camera.setPreviewCallback(new PreviewCallBack());// 通过SurfaceView显示取景画面                         camera.startPreview();//开始预览                         preview = true;                 }                 @Override                 public void surfaceDestroyed(SurfaceHolder holder) {                         if (camera != null) {                                 if (preview)                                         camera.stopPreview();                                 camera.release();                         }                 }         }         @Override         public boolean onKeyDown(int keyCode, KeyEvent event) {                 if (camera != null && event.getRepeatCount() == 0) {                         switch (keyCode) {                                 case KeyEvent.KEYCODE_MENU:                                         camera.autoFocus(null);// 自动对焦                                         break;                                 case KeyEvent.KEYCODE_CAMERA:                                 case KeyEvent.KEYCODE_DPAD_CENTER:                                         camera.takePicture(null, null, new TakePictureCallback());                                         break;                                 case KeyEvent.KEYCODE_BACK:                                         new AlertDialog.Builder(CameraActivity.this).setTitle("提示")                                         .setMessage("确定退出照相机?").setPositiveButton("确定",                                                         new DialogInterface.OnClickListener() {                                                 public void onClick(DialogInterface dialog,int whichButton) {                                                         Intent exit = new Intent(Intent.ACTION_MAIN);                                                         exit.addCategory(Intent.CATEGORY_HOME);                                                         exit.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);                                                         startActivity(exit);                                                         System.exit(0);                                                 }                                         }).setNegativeButton("取消",new DialogInterface.OnClickListener() {                                                 public void onClick(DialogInterface dialog,int whichButton) {                                                         // 取消按钮事件                                                         dialog.cancel();                                                 }                                         }).show();                                         break;                         }                 }                 return super.onKeyDown(keyCode, event); // 不会回到 home 页面         }         //预览回调接口         private final class PreviewCallBack implements Camera.PreviewCallback {                 public void onPreviewFrame(byte[] data, Camera camera) {                         if (data != null) {                                 int imageWidth = camera.getParameters().getPreviewSize().width;                                 int imageHeight = camera.getParameters().getPreviewSize().height;                                 int RGBData[] = new int[imageWidth * imageHeight];                                 decodeYUV420SP(RGBData, data, imageWidth, imageHeight); //解码                                 Bitmap bm = Bitmap.createBitmap(RGBData, imageWidth, imageHeight, Config.ARGB_8888); //                                bm = toGrayscale(bm);//实时滤镜效果,现在是变成黑白效果                                 bm = ice(bm);//冰冻效果                                 Canvas canvas = surfaceView.getHolder().lockCanvas();                     // 判断非null,才能drawBitmap.                     if (bm != null) {                             bm = Bitmap.createScaledBitmap(bm, width, height,false);                         canvas.drawBitmap(bm, 0, 0, null);                     }                     surfaceView.getHolder().unlockCanvasAndPost(canvas);                         }         }         }

灰度效果(黑白照片)

public static Bitmap toGrayscale(Bitmap bmp) {                 int height = bmp.getHeight();                 int width = bmp.getWidth();                 Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);                 Canvas c = new Canvas(bmpGrayscale);                 Paint paint = new Paint();                 ColorMatrix cm = new ColorMatrix();                 cm.setSaturation(0);                 ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);                 paint.setColorFilter(f);                 c.drawBitmap(bmp, 0, 0, paint);                 return bmpGrayscale;         }

冰冻特效

public static Bitmap ice(Bitmap bmp) {                 int width = bmp.getWidth();                 int height = bmp.getHeight();                 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);                 int dst[] = new int[width * height];                 bmp.getPixels(dst, 0, width, 0, 0, width, height);                 int R, G, B, pixel;                 int pos, pixColor;                 for (int y = 0; y < height; y++) {                         for (int x = 0; x < width; x++) {                                 pos = y * width + x;                                 pixColor = dst[pos]; // 获取图片当前点的像素值                                 R = Color.red(pixColor); // 获取RGB三原色                                 G = Color.green(pixColor);                                 B = Color.blue(pixColor);                                 pixel = R - G - B;                                 pixel = pixel * 3 / 2;                                 if (pixel < 0)                                         pixel = -pixel;                                 if (pixel > 255)                                         pixel = 255;                                 R = pixel; // 计算后重置R值,以下类同                                 pixel = G - B - R;                                 pixel = pixel * 3 / 2;                                 if (pixel < 0)                                         pixel = -pixel;                                 if (pixel > 255)                                         pixel = 255;                                 G = pixel;                                 pixel = B - R - G;                                 pixel = pixel * 3 / 2;                                 if (pixel < 0)                                         pixel = -pixel;                                 if (pixel > 255)                                         pixel = 255;                                 B = pixel;                                 dst[pos] = Color.rgb(R, G, B); // 重置当前点的像素值                                 } // x                         } // y                 bitmap.setPixels(dst, 0, width, 0, 0, width, height);                 return bitmap;         }

获取照片回调

private final class TakePictureCallback implements PictureCallback {                 @Override                 public void onPictureTaken(byte[] data, Camera camera) {                         try {                                 Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,data.length);                                 bitmap = ice(bitmap);                                 File file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis() + ".jpg");//保存在SD卡根目录下,以当前时间毫秒命名                                 FileOutputStream outStream = new FileOutputStream(file);                                 bitmap.compress(CompressFormat.JPEG, 100, outStream);                                 outStream.close();                                 camera.stopPreview();                                 camera.startPreview();//重新开始照相预览                         } catch (Exception e) {                                 Log.e(TAG, e.toString());                         }                 }         }

 解码

static public void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) {                 final int frameSize = width * height;                 for (int j = 0, yp = 0; j < height; j++) {                         int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;                         for (int i = 0; i < width; i++, yp++) {                                 int y = (0xff & ((int) yuv420sp[yp])) - 16;                                 if (y < 0)y = 0;                                 if ((i & 1) == 0) {                                         v = (0xff & yuv420sp[uvp++]) - 128;                                         u = (0xff & yuv420sp[uvp++]) - 128;                                 }                                 int y1192 = 1192 * y;                                 int r = (y1192 + 1634 * v);                                 int g = (y1192 - 833 * v - 400 * u);                                 int b = (y1192 + 2066 * u);                                 if (r < 0)r = 0;                                 else if (r > 262143)r = 262143;                                 if (g < 0)g = 0;                                 else if (g > 262143)g = 262143;                                 if (b < 0)b = 0;                                 else if (b > 262143)                                         b = 262143;                                 rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);                         }                 }         } }

camera_view 代码:

 

转载于:https://www.cnblogs.com/xiaochao1234/p/3759499.html

你可能感兴趣的文章
【强化学习】python 实现 saras lambda 例一
查看>>
基于GPU屏幕空间的精确光学折射效果
查看>>
数据交换=>Windows_Mobile+WCF+Exchange2007 - part1
查看>>
下载ORACLE中BLOB内容到客户端
查看>>
matlab练习程序(图像放大/缩小,双立方插值)
查看>>
mysql命令
查看>>
第一章面向对象涉及原则
查看>>
SQL Server索引调优系列
查看>>
SQL 2000中的触发器使用
查看>>
CKEditor与CKFinder的配置(ASP.NET环境)
查看>>
linux运行级别
查看>>
High Availability PostgreSQL HOWTO
查看>>
C#继承机制
查看>>
Silverlight开发工具汇总
查看>>
简单设计实现基于Forms认证的注册登录等用户基础服务
查看>>
MySQL Query Cache 小结
查看>>
MusicXML 3.0 (6) - 符杠分组
查看>>
分享一个比lightbox配置更方便的jQuery web2.0图片显示插件:Topup
查看>>
Linux IPTables: Incoming and Outgoing Rule Examples (SSH and HTTP)
查看>>
C以二进制读、写、文本
查看>>