展会信息港展会大全

照相机滤镜使用,优化解码和滤镜导致的预览卡屏现象
来源:互联网   发布日期:2015-09-29 10:09:26   浏览:2246次  

导读:这几天看到亚瑟boy的技术连载,也试着做了下带滤镜特效的照相机,效果也出来了,但是发现添加滤镜特效后的预览窗口卡屏现象很严重,于是自己索性 试着尝试修改,在亚瑟和其他网友的代码中基本上都是对于照相机d......

这几天看到亚瑟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 代码:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="horizontal" android:layout_width="fill_parent"

android:layout_height="fill_parent" android:background="#000000">

<SurfaceView android:id="@+id/camera_surface"

android:layout_height="fill_parent"

android:layout_width="fill_parent"

android:layout_weight="2.0" />

<LinearLayout android:orientation="vertical"

android:layout_width="50dip"

android:layout_height="fill_parent"

android:gravity="center_vertical">

<ImageButton android:layout_width="48dip"

android:layout_height="48dip"

android:src="@android:drawable/ic_menu_camera"

android:id="@+id/take_picture" />

<View android:layout_width="40dip"

android:layout_height="fill_parent"

android:layout_weight="2.0"/>

</LinearLayout>

</LinearLayout>

赞助本站

人工智能实验室

相关热词: 照相机 滤镜

AiLab云推荐
推荐内容
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港