日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > android環境下攝像頭數據采集及顯示

android環境下攝像頭數據采集及顯示

來源:程序員人生   發布時間:2015-07-01 08:05:30 閱讀次數:5512次

       之前項目觸及些攝像頭預覽及數據處理操作,當時的需求是除做攝像頭預覽外,還要顯示文字、個性圖象等,當初在查找資料實現相干模塊時,發現很多資料講的比較繁瑣,不夠簡潔,這里將自己的實現方式分享出來,希望能夠為正在做相干工作的同學提供些思路。不過這里先順便提1下,如果單純的做攝像頭預覽,不在預覽數據時做添加文字、圖象等額外操作,可以用surfaceview方式,性能上會更好些。

       這里將攝像頭收集及視頻圖象繪制放在1個模塊中,比較便于管理及保護,同時在使用時,由于該類繼承自view類,所以可以向操作很多view類1樣,將其添加到任何布局中,在與收集的數據寬高比例保持1致的條件下,在頁面顯示上可以非常靈活的控制視圖尺寸大小。不過使用這類方式實現攝像頭預覽,最大的瓶頸是在旋轉yuv數據及將其轉為rgb數據時,計算比較耗時,1般情況下收集640*480數據還好,但對960*720數據來講,手機性能1般的話,就會顯得比較卡了。解決方式在做數據旋轉時,可以嘗試采取ndk c的方式,以提高運行效力,在做yuv轉rgb時,也能夠嘗試用ndk c的方式,但是最好的方式是采取gpu shader方式,直接渲染yuv數據,行將收集的yuv數據以紋理的方式上傳至gpu,然后由gpu完成yuv轉rgb并顯示。下面是相干代碼:

public class CameraView extends View implements PreviewCallback { // 源視頻幀寬/高 private int srcFrameWidth = 640; private int srcFrameHeight = 480; private int frameSize = srcFrameWidth * srcFrameHeight; private int qtrFrameSize = srcFrameWidth * srcFrameHeight >> 2; // 幀預覽貼圖 private Bitmap previewBmp = null; private Rect previewRect = null; private Camera camera = null; // 圖層 private BaseLayer[] layers = null; // 數據收集 private int[] rgb_data = null; private byte[] yuvdata = null; // 攝像頭前置/后置 public static final int CAMERA_BACK = 0; public static final int CAMERA_FRONT = 1; private int curCameraIndex = CAMERA_BACK; public CameraView(Context _context) { super(_context); } public CameraView(Context _context, AttributeSet _attrs) { super(_context, _attrs); } public CameraView(Context context, int previewWidth, int previewHeight, int cameraIndex) { super(context); curCameraIndex = cameraIndex; rgb_data = new int[frameSize]; yuvdata = new byte[frameSize * 3 / 2]; previewBmp = Bitmap.createBitmap(srcFrameHeight, srcFrameWidth, Config.ARGB_8888); previewRect = new Rect(0, 0, previewWidth, previewHeight); // 定義圖層 layers = new BaseLayer[2]; layers[0] = new TextLayer(context, 0, false); layers[1] = new ImageLayer(context, 1, false); // 文字 ((TextLayer)layers[0]).setFontParams(32, Color.CYAN); ((TextLayer)layers[0]).setTextPos(100, 300); ((TextLayer)layers[0]).setContent("天氣還不錯...."); layers[0].setVisible(true); // 圖象 ((ImageLayer)layers[1]).setImagePos(100, 150); layers[1].setVisible(true); // 初始化并打開攝像頭 startCamera(cameraIndex); this.setBackgroundColor(Color.parseColor("#82858b")); } // 根據索引初始化攝像頭 public void startCamera(int cameraIndex) { // 先停止攝像頭 stopCamera(); // 再初始化并打開攝像頭 if (camera == null) { camera = Camera.open(cameraIndex); Camera.Parameters params = camera.getParameters(); params.setPreviewSize(srcFrameWidth, srcFrameHeight); params.setPreviewFormat(ImageFormat.NV21); camera.setParameters(params); camera.setPreviewCallback(this); camera.startPreview(); } } // 停止并釋放攝像頭 public void stopCamera() { if (camera != null) { camera.setPreviewCallback(null); camera.stopPreview(); camera.release(); camera = null; } } // 繪制 @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 填充數據(由于數據已旋轉過,此時寬與高需要互換) previewBmp.setPixels(rgb_data, 0, srcFrameHeight, 0, 0, srcFrameHeight, srcFrameWidth); // 繪制圖層 for (BaseLayer layer : layers) { if (layer.isVisible()) { layer.drawLayer(previewBmp); } } // 貼圖 canvas.drawBitmap(previewBmp, null, previewRect, null); } // 獲得攝像頭視頻數據 @Override public void onPreviewFrame(byte[] data, Camera camera) { int i = 0, j = 0, k = 0; int uvHeight = srcFrameHeight >> 1; // 旋轉yuv數據 if (curCameraIndex == CAMERA_BACK) { // 旋轉y for (i = 0; i < srcFrameWidth; i++) { for (j = srcFrameHeight - 1; j >= 0; j--) { yuvdata[k] = data[srcFrameWidth * j + i]; k++; } } // 旋轉uv for (i = 0; i < srcFrameWidth; i += 2) { for (j = uvHeight - 1; j >= 0; j--) { yuvdata[k] = data[frameSize + srcFrameWidth * j + i + 1];// cb/u yuvdata[k + qtrFrameSize] = data[frameSize + srcFrameWidth * j + i];// cr/v k++; } } } else { // 旋轉y for (i = srcFrameWidth - 1; i >= 0; i--) { for (j = srcFrameHeight - 1; j >= 0; j--) { yuvdata[k] = data[srcFrameWidth * j + i]; k++; } } // 旋轉uv for (i = srcFrameWidth - 2; i >= 0; i -= 2) { for (j = uvHeight - 1; j >= 0; j--) { yuvdata[k] = data[frameSize + srcFrameWidth * j + i + 1];// cb/u yuvdata[k + qtrFrameSize] = data[frameSize + srcFrameWidth * j + i];// cr/v k++; } } } // yuv轉rgb(由于數據已旋轉過,此時寬與高需要互換) int yp = 0; for (i = 0, yp = 0; i < srcFrameWidth; i++) { int uvp = frameSize + (i >> 1) * uvHeight, u = 0, v = 0; for (j = 0; j < srcFrameHeight; j++, yp++) { int y = (0xff & yuvdata[yp]) - 16; if ((j & 1) == 0) { u = (0xff & yuvdata[uvp + (j>>1)]) - 128; v = (0xff & yuvdata[uvp + qtrFrameSize + (j>>1)]) - 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_data[i*srcFrameHeight + j] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); }// for }// for invalidate(); } }
工程下載鏈接:http://download.csdn.net/detail/u013085897/8652979




生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: a级成人毛片 | 成人观看视频 | 国产精品国产成人国产三级 | 日韩免费精品视频 | 女人夜夜春 | 精品视频免费 | www黄色| 欧美福利专区 | 天堂蜜桃一区二区三区 | 色姑娘桃花网 | 99国产精品视频免费观看一公开 | 在线一本| 国产一区二 | 欧区一欧区二欧区三免费 | 青青av| 99免费观看视频 | 国产精品久久久久久久久久嫩草 | 久久久久一区二区 | 欧美一区二区三区视频在线观看 | 亚洲视频精品 | 亚洲看片网站 | 中文字幕一区二区三区日韩精品 | 国产综合精品一区二区三区 | 日韩不卡一区二区 | 欧美一区二区三区在线观看 | 久久精品亚洲精品国产欧美 | 欧美中文| 久久精品国产一区二区 | 欧美一区二区三区影视 | 波多野结衣在线视频播放 | 插综合网 | 国产成人精品一区二区三区视频 | 99re视频在线播放 | 精品欧美乱码久久久久久1区2区 | 男女网站在线观看 | 高清不卡一区二区 | 国产精品国产三级国产 | 91一区二区在线观看 | 久久综合一区二区 | 嫩草影院在线观看视频 | 国产精品久久久久9999 |