根據上一章節,這次加入 preview 處理,把 preview 存入 SDcard。

  • preview 處理要先 implements Camera.PreviewCallback
  • 然後再 Camera.setPreviewCallback(this)
  • 這樣每次 camera preview 時都會呼叫 onPreviewFrame()
  • Android 提供 YuvImage class 處理 preview 的 raw data
  • 可以直接使用 YuvImage.compressToJpeg() 存成 JPEG
  • 雖然預覽有轉 90 度,但是 preview raw data 卻沒有,網上找了一個 rotateYUV420Degree90() 幫助轉換角度。
  • preview 轉 90 度後要注意 width height 也要互換喔,長變寬,寬變長,為此我浪費了半天的時間找原因。
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import android.graphics.Rect; import android.graphics.YuvImage; import android.hardware.Camera; import android.hardware.Camera.Size; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.widget.FrameLayout; public class CameraTestActivity extends Activity implements SurfaceHolder.Callback, Camera.PreviewCallback { private SurfaceView mSurfaceview = null; private SurfaceHolder mSurfaceHolder = null; private Camera mCamera = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); FrameLayout fl = new FrameLayout(this); setContentView(fl); mSurfaceview = new SurfaceView(this); mSurfaceHolder = mSurfaceview.getHolder(); mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); mSurfaceHolder.addCallback(this); fl.addView(mSurfaceview); } @Override public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { } @Override public void surfaceCreated(SurfaceHolder arg0) { try { mCamera = Camera.open(); mCamera.setDisplayOrientation(90); mCamera.setPreviewDisplay(mSurfaceHolder); } catch (IOException e) { e.printStackTrace(); } // set auto focus mode Camera.Parameters parameters = mCamera.getParameters(); List<String> allFocus = parameters.getSupportedFocusModes(); if(allFocus.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)){ parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); } else if(allFocus.contains(Camera.Parameters.FLASH_MODE_AUTO)){ parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); } mCamera.setParameters(parameters); mCamera.setPreviewCallback(this); mCamera.startPreview(); } @Override public void surfaceDestroyed(SurfaceHolder arg0) { mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.release(); } @Override public void onPreviewFrame(byte[] data, Camera camera) { String sFileName = "IMG_" + new SimpleDateFormat("yyyyMMdd_HHmmss") .format(new Date()) .toString() + ".jpg"; File root = Environment.getExternalStorageDirectory(); String dir = "/Camera/"; File CameraDir = new File(root, dir); if (!CameraDir.exists()) CameraDir.mkdirs(); File jpgFile = new File(root, dir + sFileName); if (!jpgFile.exists()) { try { Camera.Parameters parameters = camera.getParameters(); Size size = parameters.getPreviewSize(); YuvImage image = new YuvImage( rotateYUV420Degree90(data, size.width, size.height), parameters.getPreviewFormat(), size.height, size.width, null); FileOutputStream filecon = new FileOutputStream(jpgFile); image.compressToJpeg( new Rect(0, 0, image.getWidth(), image.getHeight()), 90, filecon); } catch (IOException e) { e.printStackTrace(); } } } private byte[] rotateYUV420Degree90(byte[] data, int imageWidth, int imageHeight) { byte[] yuv = new byte[imageWidth * imageHeight * 3 / 2]; // Rotate the Y luma int i = 0; for (int x = 0; x < imageWidth; x++) { for (int y = imageHeight - 1; y >= 0; y--) { yuv[i] = data[y * imageWidth + x]; i++; } } // Rotate the U and V color components i = imageWidth * imageHeight * 3 / 2 - 1; for (int x = imageWidth - 1; x > 0; x = x - 2) { for (int y = 0; y < imageHeight / 2; y++) { yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + x]; i--; yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + (x - 1)]; i--; } } return yuv; } }

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()