好的,有幾種方法可以做到這一點。但是,性能存在重大問題。如果您想顯示它,則來自相機的字節[]位於YUV format,必須將其轉換爲某種RGB格式。這種轉換是相當昂貴的操作,並顯着降低輸出fps。
這取決於你實際上想用相機預覽做什麼。因爲最好的解決方案是在沒有回調的情況下繪製相機預覽,並對相機預覽產生一些效果。這是做出有爭議的重要性的常用方式。
但是,如果您確實需要手動顯示輸出,有幾種方法可以做到這一點。你的例子不起作用的原因有幾個。首先,你根本不顯示圖像。如果你這樣稱呼:
mCamera.setPreviewCallback(new CameraGreenFilter());
mCamera.setPreviewDisplay(null);
比你的相機根本不顯示預覽,你必須手動顯示它。並且你不能在onPreviewFrame方法中進行任何昂貴的操作,因爲數據的生命週期是有限的,它會覆蓋下一幀。一個提示,使用setPreviewCallbackWithBuffer,速度更快,因爲它重用了一個緩衝區,並且不必在每個幀上分配新的內存。
所以,你必須做這樣的事情:
private byte[] cameraFrame;
private byte[] buffer;
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
cameraFrame = data;
addCallbackBuffer(data); //actually, addCallbackBuffer(buffer) has to be called once sowhere before you call mCamera.startPreview();
}
private ByteOutputStream baos;
private YuvImage yuvimage;
private byte[] jdata;
private Bitmap bmp;
private Paint paint;
@Override //from SurfaceView
public void onDraw(Canvas canvas) {
baos = new ByteOutputStream();
yuvimage=new YuvImage(cameraFrame, ImageFormat.NV21, prevX, prevY, null);
yuvimage.compressToJpeg(new Rect(0, 0, width, height), 80, baos); //width and height of the screen
jdata = baos.toByteArray();
bmp = BitmapFactory.decodeByteArray(jdata, 0, jdata.length);
canvas.drawBitmap(bmp , 0, 0, paint);
invalidate(); //to call ondraw again
}
爲了使這項工作,你需要調用setWillNotDraw(false)在類的構造函數或其他地方。
在onDraw中,例如,如果要修改顏色,則可以應用paint.setColorFilter(filter)。如果你願意,我可以發佈一些例子。
因此,這將工作,但性能會低(小於8fps),因爲BitmapFactory.decodeByteArray是緩慢的。您可以嘗試使用本地代碼和android NDK將YUV數據轉換爲RGB,但這非常複雜。
另一種選擇是使用openGL ES。您需要GLSurfaceView,將相機框架作爲紋理進行綁定(在GLSurfaceView中實現Camera.previewCallback,因此您在常規曲面中使用onPreviewFrame)。但也有同樣的問題,您需要轉換YUV數據。有一個機會 - 因爲YUV中的字節數組的前半部分只是沒有顏色的亮度數據,所以只能從預覽(灰度圖像)快速顯示亮度數據。因此,對onPreviewFrame您使用arraycopy到陣列的前半部分拷貝,比你綁定像這樣的質地:
gl.glGenTextures(1, cameraTexture, 0);
int tex = cameraTexture[0];
gl.glBindTexture(GL10.GL_TEXTURE_2D, tex);
gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_LUMINANCE,
this.prevX, this.prevY, 0, GL10.GL_LUMINANCE,
GL10.GL_UNSIGNED_BYTE, ByteBuffer.wrap(this.cameraFrame)); //cameraFrame is the first half od byte[] from onPreviewFrame
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
你不能得到16-18 fps的這種方式,你可以使用OpenGL做一些過濾器。如果你願意,我可以寄給你更多的代碼,但是這裏太長了......
欲瞭解更多信息,你可以看到我的simillar question,但是沒有一個好的解決方案...
你說YUV數據需要轉換爲RGB數據才能顯示,這會給出8fps左右。什麼是Android框架如何獲得如此高的顯示速度(不應用過濾器)?你認爲他們正在包裝所有的東西來打開GL ES以獲得接近20幀/秒的速度嗎? :) – poitroae
更可能的是,他們沒有使用Android API :)它可能是用本地代碼或類似的東西編寫的(這只是猜測)......但Android是開源的,因此您可以嘗試查找代碼的實際內容作品:) –
Jaa-c,我想知道是否可以使用上面編寫的代碼發佈示例(不是openGL)。我無法弄清楚如何將它們全部加在一起才能正確工作,並且我知道這是一個較老的問題,但我在Google上找不到這件事。或者你可以製作一個迷你教程,說明爲實現這個目的需要製作哪些類? –