从YV12格式的Android CameraPreview中获取阵列获取Luminance

时间:2014-06-22 11:15:16

标签: android arrays camera android-camera

我正在开发一款能够拍摄照片的应用程序"然后保存YV12图像的亮度(Y分量)。我不想要JPG压缩文件或PNG,因为我只需要每像素8位灰度(亮度)图像。

我在SurfaceView上显示图像预览,然后我得到了YV12阵列。之后,我将亮度/灰度数据保存在PGM文件中,但它没有正确显示信息。

正如您在the image中看到的那样,Y数据位于数组的第一个W * H值中,但是使用它,我得到this

我的代码是:

public class AndroidCamera extends Activity implements SurfaceHolder.Callback,
    Camera.PreviewCallback {
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;
Camera.Size size;
Camera.Parameters parameters;
byte[] myData;
Button takePhoto;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    // Set this APK no title
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.main);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    getWindow().setFormat(PixelFormat.UNKNOWN);
    surfaceView = (SurfaceView) findViewById(R.id.camerapreview);
    surfaceHolder = surfaceView.getHolder();
    surfaceHolder.addCallback(this);
    surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    takePhoto = (Button) findViewById(R.id.BtnTakePhoto);
    takePhoto.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            try {
                createPGMFile("/sdcard/ltw/cam.pgm", myData, size.width, size.height);
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }           
        }
    });
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    // TODO Auto-generated method stub
    if (previewing) {
        camera.stopPreview();
        previewing = false;
    }
    if (camera != null) {
        try {
            camera.setPreviewDisplay(surfaceHolder);
            camera.startPreview();
            previewing = true;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    camera = Camera.open();
    Camera.Parameters params = camera.getParameters();
    List<Size> sizes = params.getSupportedPictureSizes();
    // See which sizes the camera supports and choose one of those
    Camera.Size size = sizes.get(0);
    params.setPictureSize(size.width, size.height);
    params.setColorEffect(Parameters.EFFECT_MONO);
    params.setPictureFormat(ImageFormat.NV21);
    camera.setParameters(params);
    camera.setDisplayOrientation(90);
    camera.setPreviewCallback(this);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    camera.stopPreview();
    camera.release();
    camera = null;
    previewing = false;
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
    // TODO Auto-generated method stub
    parameters = camera.getParameters();
    // parameters = Utils.getOptimalParameters(camera, display);
    size = parameters.getPreviewSize();
    myData = data;
}
public void createPGMFile(String filename, byte[] image, int width,
        int height) throws FileNotFoundException {
    PrintWriter pw = new PrintWriter(filename);
    // magic number, width, height, and maxval
    pw.println("P2");
    pw.println(width + " " + height);
    pw.println(255);
    // print out the data, limiting the line lengths to 70 characters
    int lineLength = 0;
    /*
     * for (int i = 0; i < height; ++i) { for (int j = 0; j < width; ++j) {
     */
    int i = 0;
    while (i < width * height) {
        int myByte = (int) image[i];
        int value = myByte + 128;
        // if we are going over 70 characters on a line,
        // start a new line
        String stringValue = "" + value;
        int currentLength = stringValue.length() + 1;
        if (currentLength + lineLength > 70) {
            pw.println();
            lineLength = 0;
        }
        lineLength += currentLength;
        pw.print(value + " ");
        i++;
        // }
    }
    pw.close();
}}

我不知道发生了什么。提前谢谢。

1 个答案:

答案 0 :(得分:0)

我终于找到了解决方案。方法 onPreviewFrame 必须像这样实现:

@Override
public void onPreviewFrame(byte[] data, Camera camera) {
    parameters = camera.getParameters();
    size = parameters.getPreviewSize();
    y = new int[size.height*size.width];
    int index = 0;
    while(index < (size.height*size.width)) {
        int y[index] = (0xff & ((int) data[index]));
        index++;
    }
    if(savePic){
        savePic = false;
        try {
            createPGMFile(y, size.width, size.height);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

savePic 是一个布尔变量,我用一个按钮更改。