日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

照相机滤镜使用,优化解码和滤镜导致的预览卡屏现象

發(fā)布時(shí)間:2023/12/10 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 照相机滤镜使用,优化解码和滤镜导致的预览卡屏现象 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

這幾天看到亞瑟boy的技術(shù)連載,也試著做了下帶濾鏡特效的照相機(jī),效果也出來(lái)了,但是發(fā)現(xiàn)添加濾鏡特效后的預(yù)覽窗口卡屏現(xiàn)象很嚴(yán)重,于是自己索性試著嘗試修改,在亞瑟和其他網(wǎng)友的代碼中基本上都是對(duì)于照相機(jī)data視頻流先進(jìn)行解碼,然后對(duì)解碼出的幀Bitmap進(jìn)行濾鏡算法處理,這個(gè)是必走的流程,而每一幀在處理解碼和濾鏡時(shí)都需要用掉大量時(shí)間,我測(cè)了下,解碼需要300毫秒左右,濾鏡處理需要600毫秒左右(冰凍濾鏡),如此一來(lái),處理完這兩個(gè)流程需要的時(shí)間要在900毫秒甚至更長(zhǎng),我們知道如果看上去比較流暢的話我們需要每秒更新三幀的圖片,而這么處理只能更新一張,明顯的卡屏。
于是試著去縮小處理的Bitmap大小,在照相機(jī)預(yù)覽返回照片大小中設(shè)置:

Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewSize(display.getWidth()/2, display.getHeight()/2);// 設(shè)置預(yù)覽照片的大小


原來(lái)默認(rèn)是返回屏幕大小的預(yù)覽圖片,此時(shí)我改成了屏幕大小一半的圖片,發(fā)現(xiàn)處理過(guò)程明顯加快了(當(dāng)然也有稍微的卡屏),最后在預(yù)覽回調(diào)接口PreviewCallBack中再將圖片放大到屏幕大小,有雨我預(yù)覽圖片返回時(shí)只是縮小了一半,此時(shí)放大回屏幕大小時(shí)仍然是非常清晰的,如果你想速度更快的話可以繼續(xù)縮小預(yù)覽圖片的返回大小。

代碼如下:

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;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Window window = getWindow();requestWindowFeature(Window.FEATURE_NO_TITLE);// 沒(méi)有標(biāo)題 window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);// 設(shè)置全屏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); // 設(shè)置分辨率/* 下面設(shè)置Surface不維護(hù)自己的緩沖區(qū),而是等待屏幕的渲染引擎將內(nèi)容推送到用戶面前 */surfaceView.getHolder().addCallback(new SurfaceCallback());}//按鈕監(jiān)聽(tīng)private final class ButtonClickingListener implements View.OnClickListener {@Overridepublic 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());}}}@Overrideprotected void onDestroy() {// TODO Auto-generated method stubif(camera!=null){camera.setPreviewCallback(null) ;camera.stopPreview();camera.release();camera = null;}super.onDestroy();}private final class SurfaceCallback implements SurfaceHolder.Callback {@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {}@Overridepublic void surfaceCreated(SurfaceHolder holder) {if(camera==null){camera = Camera.open();//打開(kāi)相機(jī)}else{Toast.makeText(CameraActivity.this, "相機(jī)正在使用中", 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);// 設(shè)置預(yù)覽照片的大小parameters.setPreviewFrameRate(3);// 每秒3幀parameters.setPictureFormat(PixelFormat.JPEG);// 設(shè)置照片的輸出格式parameters.set("jpeg-quality", 100);// 照片質(zhì)量parameters.setPictureSize(display.getWidth(), display.getHeight());// 設(shè)置照片的大小 camera.setParameters(parameters);camera.setPreviewCallback(new PreviewCallBack());// 通過(guò)SurfaceView顯示取景畫(huà)面camera.startPreview();//開(kāi)始預(yù)覽preview = true;}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {if (camera != null) {if (preview)camera.stopPreview();camera.release();}} }@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if (camera != null && event.getRepeatCount() == 0) {switch (keyCode) {case KeyEvent.KEYCODE_MENU:camera.autoFocus(null);// 自動(dòng)對(duì)焦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("確定退出照相機(jī)?").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); // 不會(huì)回到 home 頁(yè)面 }//預(yù)覽回調(diào)接口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);//實(shí)時(shí)濾鏡效果,現(xiàn)在是變成黑白效果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]; // 獲取圖片當(dāng)前點(diǎn)的像素值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; // 計(jì)算后重置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); // 重置當(dāng)前點(diǎn)的像素值} // x} // ybitmap.setPixels(dst, 0, width, 0, 0, width, height);return bitmap;}

獲取照片回調(diào)

private final class TakePictureCallback implements PictureCallback {@Overridepublic 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卡根目錄下,以當(dāng)前時(shí)間毫秒命名FileOutputStream outStream = new FileOutputStream(file);bitmap.compress(CompressFormat.JPEG, 100, outStream);outStream.close();camera.stopPreview();camera.startPreview();//重新開(kāi)始照相預(yù)覽} 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>

效果如下圖:照相機(jī)冰凍效果

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/vus520/archive/2012/04/12/2561976.html

總結(jié)

以上是生活随笔為你收集整理的照相机滤镜使用,优化解码和滤镜导致的预览卡屏现象的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。