简体   繁体   English

如何从Android相机捕获原始图像

[英]How to capture raw image from android camera

The takePicture rawCallback returns a null pointer. takePicture rawCallback返回一个空指针。 The getPictureFormat only allows for .jpg. getPictureFormat仅允许.jpg。 While the jpeg can be improved with getParameters() setJpegQuality(100) setParameters, the image returned is still a jpeg. 尽管可以使用getParameters()setJpegQuality(100)setParameters改进jpeg,但返回的图像仍然是jpeg。 To get a bitmap image BitmapFactory.decodeByteArray needs to be called, which can take 1/2 second to process. 要获取位图图像,需要调用BitmapFactory.decodeByteArray,这可能需要1/2秒的处理时间。

The application I'm working on needs the most detailed image the camera can produce, which does not necessarily mean pretty. 我正在处理的应用程序需要相机可以产生的最详细的图像,这不一定意味着美观。 The raw camera chip capture format is bayer. 原始相机芯片捕获格式为Bayer。

The android (at least mine) has 2 camera parameters "rawsave-mode" and "rawfname" , with the default rawsave-mode=0 . android(至少是我的)具有2个摄像头参数"rawsave-mode""rawfname" ,默认的rawsave-mode=0 By setting rawsave-mode=1 , the camera will save the raw camera image file, along with performing the other camera functions as usual. 通过设置rawsave-mode=1 ,相机将保存原始相机图像文件,并照常执行其他相机功能。

Camera.Parameters parameters=preview.camera.getParameters();
parameters.set("rawsave-mode", "1");
parameters.set("rawfname", "/mnt/sdcard/test.raw");
preview.camera.setParameters(parameters);
preview.camera.takePicture(shutterCallback, null, jpegCallback);

The actual name of the file produced get modified to include the parameters of the raw file being produced. 产生的文件的实际名称被修改为包括产生的原始文件的参数。 For one of my androids, the name produced is "test__1604x1206_10_2.raw" which is a1 1604x1206 image, 10bit format 2. and "test__1284x966_10_3.raw" which is a 1284x966 image, 10 bit format 3. The 10 bytes are stored as 2 byte short int (little endian) . 对于我的一个"test__1604x1206_10_2.raw"机器人,产生的名称是"test__1604x1206_10_2.raw" ,它是10bit格式2的1604x1206图像,而"test__1284x966_10_3.raw"10 bit格式3,是1284x966图像10 bytes存储为2 byte short int (little endian)

parameters.set("rawsave-mode", "2");
// setting the rawsave-mode to 2 increased the resolution to 3204x2406
// and output the file test__3204x2406_10_2.raw

The image data is roughly 8 bit , but floats within the 10 bit , where a brighter image might use higher values and darker lower. 图像数据大约为8 bit ,但在10 bit内浮动,其中较亮的图像可能使用较高的值,而较暗的则使用较低的值。 This allows the image processing software to create a histogram and capture the useful range of the image. 这允许图像处理软件创建直方图并捕获图像的有用范围。 Because light is not a constant, it can also be necessary to adjust one channel differently than another to make the image look color correct. 因为光线不是恒定的,所以也有必要将一个通道调整为与另一个通道不同,以使图像看起来色彩正确。 There is a lot of info on the web regarding color theory which can explain this fully, but new users beware, the conversion of 10 bit to 8 gets deep quickly. 网上有很多有关色彩理论的信息可以充分解释这一点,但是新用户请注意,从10 bit8 10 bit的转换很快就会深入。 If you want a pretty picture, use the android picture capture and not the raw image! 如果您想要漂亮的图片,请使用android图片捕获而不是原始图片!

The format represents the bayer pattern of the bits. 该格式表示位的拜耳模式。 Bayer is a format where the odd/even value of the row and column indicate which color the pixel represents, where RGB has an 8 bit value for each color channel for each pixel, bayer has only one 10 bit value for pixel, where one pixel is red, then the next green, red, green, red, green. 拜耳(Bayer)是一种格式,其中行和列的奇/偶值指示像素代表的颜色,其中RGB对每个像素的每个颜色通道具有8 bit值,而拜耳对像素仅具有一个10 bit值,其中一个像素是红色,然后是下一个绿色,红色,绿色,红色,绿色。 Then the next row has blue, green, blue, green, blue green. 然后,下一行具有蓝色,绿色,蓝色,绿色,蓝绿色。 To determine the RGB value of a pixel requires interpreting the surrounding pixels. 要确定像素的RGB值,需要解释周围​​的像素。

Format 2 has pixel order
//            0 1 2 3 4 5
//          0 G R G R G R
//          1 B G B G B G
//          2 G R G R G R
//          3 B G B G B G

format 3 has the pixel order of 格式3的像素顺序为

//            0 1 2 3 4 5
//          0 R G R G R G
//          1 G B G B G B
//          2 R G R G R G
//          3 G B G B G B

I'm not sure if this technique will work on other androids or if it will work on future androids. 我不确定该技术是否可以在其他android上使用,或者是否可以在未来的android上使用。 If anyone tries this, please add a comment on success or failure. 如果有人尝试此操作,请添加关于成功或失败的评论。 My phones are direct chinese import unlocked iHTC Android phones which have been rooted. 我的手机是已经植根的直接中文进口解锁iHTC Android手机。

code for capture raw image: 捕获原始图像的代码:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;

import android.os.Bundle;
import android.os.Environment;
import android.os.Looper;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.Window;
import android.view.WindowManager;
import android.view.SurfaceHolder.Callback;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.view.KeyEvent;
import android.app.ProgressDialog;
import android.app.Dialog;
import android.os.Handler;
import android.os.Message;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.util.List;
import android.hardware.Camera.Size;
import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.util.Log;

public class Camera extends Activity implements SurfaceHolder.Callback {

    private int mMode;
    private boolean mIssdcardExist = false;
    private VideoPreview mVideoPreview; //缺VideoPreview这个类
    private int mPrvW = 640, mPrvH = 480;
    private int mDispW = 640, mDispH = 480;
    private int mPicW = 2560, mPicH = 1920;
    private Camera mCamera;
    private Camera.Parameters mCameraParam;
    private int mIsPreviewing = 0;
    private volatile int mIsFocused = 0;
    private volatile int mIsCapture = 0;
    private long mFocusStartTime;
    private long mFocusCallbackTime;
    private long mCaptureStartTime;
    private long mShutterCallbackTime;
    private long mRawPictureCallbackTime;
    private long mJpegPictureCallbackTime;
    private final AutoFocusCallback mAutoFocusCallback = new AutoFocusCallback();
    private final ShutterCallback mShutterCallback = new ShutterCallback();
    private final RawPictureCallback mRawPictureCallback = new RawPictureCallback();
    private static final String CAMERA_IMAGE_BUCKET_NAME = Environment.getExternalStorageDirectory().toString() + "/DCIM/CameraEM/";
    private int mAFEngMode = 0;

    public static final int CAPTURE_ID = Menu.FIRST;

    private String TAG = "EM-Camera";

    private final int DIALOG_PROGRESS = 1000;
    private ProgressDlgHandler mProgressDlgHandler = new ProgressDlgHandler();
    private final int EVENT_FULL_SCAN_START = 100;
    private final int EVENT_FULL_SCAN_COMPLETE = 101;
    private boolean mIsTest = false;
    private boolean mProgressDlgExists = false;

    private boolean mIsRawCapture = false;
    private String mRawCaptureFileName;

    private boolean mIsOnPause = false;
    private int mPos = 0;
    private static final int MSG_AF_MODE1_EVENT = 1001;
    private static final int MSG_AF_MODE3_EVENT = 1003;
    private static final int MSG_AF_MODE4_EVENT = 1004;
    private mAFMode1FirstThread threadFirst;
    private AFMode1Thread mode1Thread;
    private AFMode2Thread mode2Thread;
    private AFMode3Thread mode3Thread;
    private AFMode4Thread mode4Thread;
    private RawCaptureThread mRawCaptureThread;
    private boolean mCanBack = true;

    private Button mButtonPass;
    private Button mButtonFail;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.camera_test);

        Window win = getWindow();
        win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        if(Environment.getExternalStorageState().equals(Environment.MEDIA_REMOVED))
        {
            mIssdcardExist = false;
        }
        else
        {
            File file = new File(CAMERA_IMAGE_BUCKET_NAME);
            if(!file.isDirectory())
            {
                file.mkdirs();
            }
            mIssdcardExist = true;
        }

        mButtonPass = (Button) findViewById(R.id.camera_test_pass);
        mButtonPass.setOnClickListener(mButtonHandler);

        mButtonFail = (Button) findViewById(R.id.camera_test_fail);
        mButtonFail.setOnClickListener(mButtonHandler);
    }

        @Override
    public void onResume() {
        super.onResume();
        Log.i(TAG, "onResume ");
        mVideoPreview = (VideoPreview) findViewById(R.id.camera_preview);
        mVideoPreview.setAspectRatio(mPrvW, mPrvH);
        SurfaceHolder holder = mVideoPreview.getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        mIsTest = false;
        mIsOnPause = false;
    }

        @Override
    public void onPause() {
        mIsOnPause = true;
        if(null != mode1Thread && true == mode1Thread.isAlive()){
            try{
                mode1Thread.join();
            }catch(Exception e){
            }

        }

        if(null != threadFirst && true == threadFirst.isAlive()){
            try{
                threadFirst.join();
            }catch(Exception e){
            }

        }

        if(null != mode2Thread && true == mode2Thread.isAlive()){
            try{
                mode2Thread.join();
            }catch(Exception e){
            }

        }

        if(null != mode3Thread && true == mode3Thread.isAlive()){
            try{
                mode3Thread.join();
            }catch(Exception e){
            }

        }

        if(null != mode4Thread && true == mode4Thread.isAlive()){
            try{
                mode4Thread.join();
            }catch(Exception e){
            }

        }

        if(null != mRawCaptureThread && true == mRawCaptureThread.isAlive()){
            try{
                mRawCaptureThread.join();
            }catch(Exception e){
            }

        }

        super.onPause();
        Log.i(TAG, "super onPause.");
        this.finish();
    }

        @Override
        protected Dialog onCreateDialog(int id){
            if(id == DIALOG_PROGRESS){
                ProgressDialog dialog = new ProgressDialog(this);
                dialog.setMessage("It is in full scan, please wait......");
                dialog.setCancelable(false);
                return dialog;
            }
            return null;
        }

        private class ProgressDlgHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case EVENT_FULL_SCAN_START:
                    showDialog(DIALOG_PROGRESS);
                    mProgressDlgExists = true;
                    break;
                case EVENT_FULL_SCAN_COMPLETE:
                    dismissDialog(DIALOG_PROGRESS);
                    mProgressDlgExists = false;
                    break;
            }
        }
    }


    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        mDispW = w;
        mDispH = h;
        Log.i(TAG, "surfaceChanged width is : " + w);
        Log.i(TAG, "surfaceChanged height is : " + h);
        startPreview();
    }

    public void surfaceCreated(SurfaceHolder holder) {
        openCamera();
        try {
            mCamera.setPreviewDisplay(holder);
        } catch (IOException exception) {
            closeCamera();
            Log.i(TAG, "surfaceCreated closeCamera ");
        }       
    }

    public void surfaceDestroyed(SurfaceHolder arg0) {
            stopPreview();
        closeCamera();
        Log.i(TAG, "surfaceDestroyed closeCamera ");
    }

    private void openCamera() {
        if (mCamera == null) {
            mCamera = Camera.open();
            Log.i(TAG, "Enter openCamera to init the mCamera.");
            if(null == mCamera){
                Log.i(TAG, "init the mCamera is null.");
            }
        }
    }
    private void closeCamera() {
        if(null != mCamera){
            mCamera.release();
            mCamera = null;
        }
    }
    private void startPreview() {
        mCameraParam = mCamera.getParameters();
        //GW616 Camera preview problem
        // Set a preview size that is closest to the viewfinder height and has
        // the right aspect ratio.
        Size size = mCameraParam.getPictureSize();
        List<Size> sizes = mCameraParam.getSupportedPreviewSizes();
        Size optimalSize = getOptimalPreviewSize(
                sizes, (double) size.width / size.height);
        if (optimalSize != null) {
            mCameraParam.setPreviewSize(optimalSize.width, optimalSize.height);
        }
        //end
//      mCameraParam.setPreviewSize(mPrvW, mPrvH);
        mCameraParam.set("fps-mode", 0);    // Frame rate is normal
        mCameraParam.set("cam-mode", 0);    // Cam mode is preview
        mCamera.setParameters(mCameraParam);
        Log.i(TAG, "startPreview width is : " + mPrvW);
        Log.i(TAG, "startPreview height is : " + mPrvH);
        mCamera.startPreview();
        mIsPreviewing = 1;
    }
    private void stopPreview() {
        if(null != mCamera){
            mCamera.stopPreview();
        }
        mIsPreviewing = 0;
    }

    private Size getOptimalPreviewSize(List<Size> sizes, double targetRatio) {
        final double ASPECT_TOLERANCE = 0.05;
        if (sizes == null) return null;

        Size optimalSize = null;
        double minDiff = Double.MAX_VALUE;

        // Because of bugs of overlay and layout, we sometimes will try to
        // layout the viewfinder in the portrait orientation and thus get the
        // wrong size of mSurfaceView. When we change the preview size, the
        // new overlay will be created before the old one closed, which causes
        // an exception. For now, just get the screen size

        Display display = getWindowManager().getDefaultDisplay();
        int targetHeight = Math.min(display.getHeight(), display.getWidth());

        if (targetHeight <= 0) {
            // We don't know the size of SurefaceView, use screen height
            WindowManager windowManager = (WindowManager)
                    getSystemService(this.WINDOW_SERVICE);
            targetHeight = windowManager.getDefaultDisplay().getHeight();
        }

        // Try to find an size match aspect ratio and size
        for (Size size : sizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

        // Cannot find the one match the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            Log.v(TAG, "No preview size match the aspect ratio");
            minDiff = Double.MAX_VALUE;
            for (Size size : sizes) {
                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        Log.v(TAG, String.format(
                "Optimal preview size is %sx%s",
                optimalSize.width, optimalSize.height));
        return optimalSize;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_CAMERA:
                this.CapturePicture();
                return true;
            case KeyEvent.KEYCODE_DPAD_CENTER:
                return true;
            case KeyEvent.KEYCODE_SEARCH:
                return true;
            case KeyEvent.KEYCODE_FOCUS:
                return true;        
            }
            return super.onKeyDown(keyCode, event);
    }

    private void CapturePicture(){
        if(false == mIssdcardExist)
        {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("sdcard not available");
            builder.setMessage("Please insert sdcard.");
            builder.setPositiveButton("OK" , null);
            builder.create().show();
            return;
         }

         if(Environment.getExternalStorageState().equals(Environment.MEDIA_SHARED))
        {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
                    builder.setTitle("sdcard is busy");
                    builder.setMessage("Sorry, your SD card is busy.");
                    builder.setPositiveButton("OK" , null);
                    builder.create().show();
                    return;
        }

        if(true == mIsTest)
        {
            Toast.makeText(this,"It is in capturing, can not repeat capture.",Toast.LENGTH_LONG).show();
            if(true == mProgressDlgExists)
            {
                showDialog(DIALOG_PROGRESS);
            }
            return;
        }

        Intent intent = getIntent();
        int TestMode = intent.getIntExtra("TestMode", 0);
        Log.i(TAG, "The value of TestMode is :" + TestMode);
        if(1 == TestMode)//AF Mode
        {
            mMode = intent.getIntExtra("AFMode", 0);
            switch(mMode){
                case 1:
                    captureMode1();
                    break;
                case 2:
                    captureMode2();
                    break;
                case 3:
                    captureMode3();
                    break;
                case 4:
                    captureMode4();
                    break;
            }
         }
         else if(2 == TestMode)//RawCapture Mode
         {
             RawCapture();
         }
         else//not select mode yet
         {
             Toast.makeText(this,"Please select the test mode first!",Toast.LENGTH_LONG).show();
         }
    }

    private void captureMode1()
    {           
        Log.i(TAG, "Enter captureMode1 function.");
        threadFirst = new mAFMode1FirstThread();
        threadFirst.start();
    }

    class mAFMode1FirstThread extends Thread{
        public void run(){
            Log.i(TAG, "mAFMode1FirstThread");
            mIsTest = true;

            mAFEngMode = 0;
            mCameraParam.set("afeng-mode", mAFEngMode);
            mCameraParam.set("focus-mode", "auto");
            mCameraParam.set("focus-meter", "spot");
            mCamera.setParameters(mCameraParam);
            mFocusStartTime = System.currentTimeMillis();
            mIsFocused = 0;
            mCamera.autoFocus(mAutoFocusCallback);

            mCanBack = false;
            takePicture();
            mAFEngMode = 1;
            mCameraParam.set("afeng-mode", mAFEngMode);
            mCameraParam.set("focus-mode", "manual");
            mCamera.setParameters(mCameraParam);
            mPos = 0;
            mCameraParam.set("afeng-pos", mPos);
            mCamera.setParameters(mCameraParam);
            startPreview();
            mCanBack = true;
            Sleep(2000);

            mHandler.sendEmptyMessage(MSG_AF_MODE1_EVENT);          

            Log.i(TAG, "mAFMode1FirstThread finish.");
        }
    }

    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg){
            switch(msg.what){
                case MSG_AF_MODE1_EVENT:
                    mode1Thread = new AFMode1Thread();
                    mode1Thread.start();
                    break;
                case MSG_AF_MODE3_EVENT:
                    mode3Thread = new AFMode3Thread();
                    mode3Thread.start();
                    break;
                case MSG_AF_MODE4_EVENT:
                    mode4Thread = new AFMode4Thread();
                    mode4Thread.start();
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    public void onBackPressed() {
        if(false == mCanBack){
            return;
        }
        super.onBackPressed();
    }

    class AFMode1Thread extends Thread{
        public void run(){
            Log.i(TAG, "mAFMode1Thread");
            if(true == mIsOnPause){
                mHandler.removeMessages(MSG_AF_MODE1_EVENT);
                return;
            }
            mCanBack = false;
            takePicture();
            mPos ++;
            mCameraParam.set("afeng-pos", mPos);
            mCamera.setParameters(mCameraParam);            
            startPreview();
            mCanBack = true;
            Sleep(2000);            
            if(false == mIsOnPause && mPos <= 50){
                mHandler.sendEmptyMessage(MSG_AF_MODE1_EVENT);
            }
            if(mPos > 50){
                mIsTest = false;
            }
        }
    }

    private void captureMode2()
    {   
        Log.i(TAG, "Enter captureMode2 function.");
        mode2Thread = new AFMode2Thread();
        mode2Thread.start();
    }

    class AFMode2Thread extends Thread{
        public void run(){
            Log.i(TAG, "mAFMode2Thread");

            mIsTest = true; 
            mCanBack = true;
            mAFEngMode = 1;
            mCameraParam.set("afeng-mode", mAFEngMode);
            mCameraParam.set("focus-mode", "fullscan");
            mCamera.setParameters(mCameraParam);
            mIsFocused = 0;
            mCamera.autoFocus(mAutoFocusCallback);
            mProgressDlgHandler.sendEmptyMessage(EVENT_FULL_SCAN_START);

            mCanBack = false;
            takePicture();
            startPreview();
            mCanBack = true;
            mIsTest = false;
            Sleep(2000);

        }
    }

    private void captureMode3()
    {
        Log.i(TAG, "Enter captureMode3 function.");
        mPos = 0;
        mode3Thread = new AFMode3Thread();
        mode3Thread.start();
    }

    class AFMode3Thread extends Thread{
        public void run(){
            Log.i(TAG, "mAFMode3Thread");
            if(true == mIsOnPause){
                mHandler.removeMessages(MSG_AF_MODE3_EVENT);
                return;
            }

            mIsTest = true;

            mAFEngMode = 1;
            mCameraParam.set("afeng-mode", mAFEngMode);
            mCameraParam.set("focus-mode", "fullscan");
            mCamera.setParameters(mCameraParam);
            mIsFocused = 0;
            mCamera.autoFocus(mAutoFocusCallback);
            mProgressDlgHandler.sendEmptyMessage(EVENT_FULL_SCAN_START);

            mCanBack = false;
            takePicture();
            mPos ++;
            startPreview();
            mCanBack = true;
            Sleep(2000);

            if(false == mIsOnPause && mPos <= 50){
                mHandler.sendEmptyMessage(MSG_AF_MODE3_EVENT);
            }
            if(mPos > 50){
                mIsTest = false;
            }
        }
    }

    private void captureMode4()
    {       
        Log.i(TAG, "Enter captureMode4 function.");
        mPos = 0;
        mode4Thread = new AFMode4Thread();
        mode4Thread.start();
    }

    class AFMode4Thread extends Thread{
        public void run(){
            Log.i(TAG, "mAFMode4Thread");
            if(true == mIsOnPause){
                mHandler.removeMessages(MSG_AF_MODE4_EVENT);
                return;
            }

            mIsTest = true;

            mAFEngMode = 0;
            mCameraParam.set("afeng-mode", mAFEngMode);
            mCameraParam.set("focus-mode", "auto");
            mCameraParam.set("focus-meter", "spot");
            mCamera.setParameters(mCameraParam);
            mIsFocused = 0;
            mCamera.autoFocus(mAutoFocusCallback);
            mCanBack = false;
            takePicture();
            mPos ++;
            startPreview();
            mCanBack = true;
            Sleep(2000);

            if(false == mIsOnPause && mPos <= 50){
                mHandler.sendEmptyMessage(MSG_AF_MODE4_EVENT);
            }
            if(mPos > 50){
                mIsTest = false;
            }
        }
    }

    private void RawCapture()
    {
        Log.i(TAG, "Enter RawCapture function.");
        mRawCaptureThread = new RawCaptureThread();
        mRawCaptureThread.start();
    }

    class RawCaptureThread extends Thread{
        public void run(){
            Log.i(TAG, "mAFMode4Thread");
            mCanBack = true;

            mIsTest = true;
            mIsRawCapture = true;

            mCameraParam.set("rawsave-mode", "on");
            long dateTaken = System.currentTimeMillis();
            mRawCaptureFileName = CAMERA_IMAGE_BUCKET_NAME + createName(dateTaken);
            mCameraParam.set("rawfname", mRawCaptureFileName + ".raw");
            mCamera.setParameters(mCameraParam);
            mCamera.autoFocus(mAutoFocusCallback);
            mCanBack = false;
            takePicture();
            startPreview();
            mCanBack = true;
            mIsRawCapture = false;
            mIsTest = false;
            Sleep(2000);            

        }
    }

    private final class AutoFocusCallback implements android.hardware.Camera.AutoFocusCallback {
        public void onAutoFocus(boolean focused, android.hardware.Camera camera) {
            mFocusCallbackTime = System.currentTimeMillis();
            mIsFocused = 1;
            if(1 == mAFEngMode)
            {
                mProgressDlgHandler.sendEmptyMessage(EVENT_FULL_SCAN_COMPLETE);
            }
        }
    }
    private final class ShutterCallback implements android.hardware.Camera.ShutterCallback {
        public void onShutter() {           
            mShutterCallbackTime = System.currentTimeMillis();
        }
    }  
    private final class RawPictureCallback implements PictureCallback {
      public void onPictureTaken(byte [] rawData, android.hardware.Camera camera) {         
        mRawPictureCallbackTime = System.currentTimeMillis();
      }
    }
    private final class JpegPictureCallback implements PictureCallback {
      public void onPictureTaken(byte [] jpegData, android.hardware.Camera camera) {           
         mJpegPictureCallbackTime = System.currentTimeMillis();
         if (jpegData != null) {
            storeImage(jpegData);
         }
         mIsCapture = 0;
      }
    }

    private void takePicture() 
    {       
        while (mIsFocused == 0) {
            Sleep(100);
        }

        mIsCapture = 1;
        mCaptureStartTime = System.currentTimeMillis();
        mCamera.takePicture(mShutterCallback, mRawPictureCallback, new JpegPictureCallback());
        while (mIsCapture == 1) {
            Sleep(100);
        }
    }
    private void Sleep(long time) 
    {
        try{
            Thread.sleep(time);
        } catch (InterruptedException e){
            e.printStackTrace();
        }
    }

    private void storeImage(byte[] jpegData) {
        long time;
        long dateTaken = System.currentTimeMillis();
        String name = CAMERA_IMAGE_BUCKET_NAME + createName(dateTaken) + ".jpg";

        if(true == mIsRawCapture)
        {
            name = mRawCaptureFileName  + ".jpg";
        }

        File fHandle = new File(name);
        try {
            OutputStream bos = new FileOutputStream(fHandle);
            bos.write(jpegData);
            bos.close();
            time = System.currentTimeMillis();
        } catch (Exception ex) {
            fHandle.delete();
        }
    }
    private static String createName(long dateTaken) {
        return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString();
    }

    OnClickListener mButtonHandler = new OnClickListener() {
        public void onClick(View v) {
            SharedPreferences sharedPre = getSharedPreferences("test_results", Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = sharedPre.edit();

            if (v.getId() == R.id.camera_test_pass) {
                Log.i("CameraTest", "-----mButtonHandler----onClick()----camera_test_pass");
                editor.putBoolean("CameraTest", true);
            } else if (v.getId() == R.id.camera_test_fail) {
                Log.i("CameraTest", "-----mButtonHandler----onClick()----camera_test_fail");
                editor.putBoolean("CameraTest", false);
            }
            editor.commit();

            Intent intent = new Intent();
            intent.setClass(CameraTest.this, SpeakerTest.class);
            startActivity(intent);
            finish();
        }
    }; 

}

//Ugly code to convert bayer to rgb //将Bayer转换为RGB的丑陋代码

//test__1604x1206_10_2b.raw
//test__1284x966_10_3.raw
#include <stdio.h>
    unsigned short int bayerImage[2500][3500]; //times 3 allows for forming an RGB image for debugging
    unsigned char bmpImage[30000000]; //times 3 allows for forming an RGB image for debugging
#include <iomanip>
#include <iostream>
#include "bayer2rgb.h"
#include <memory.h>
#include <string.h>

/*****************************************************************************
**
*/

int DumpImage( char* pszFilename, BYTE* pImage, int bmpWidth, int bmpHeight,int bmpBits,int bmpFormat)
{
    FILE     *bayerFile;
    FILE     *rgbFile;
    int x,y;
    unsigned char lowOrder,highOrder;
    unsigned char bmpchar;
    unsigned short bayerVal;

    unsigned char bmpheader[62];
    char  FullFilename[MY_MAX_PATH];
    unsigned int  bmrgbFilesize;
    unsigned int minPixel=100000;
    unsigned int maxPixel=0;
    static unsigned int rgbValues[4][1024];

    /*expecting 10 bit bayer */
    if(bmpBits!=10)
    {
        printf("invalid bit specification\n");
        return(-1);
    }
    if(bmpHeight >= 0)
    {
        bmrgbFilesize = (((bmpWidth*24+31)/32)*4)*bmpHeight;
    }
    else
    {
        bmrgbFilesize = (((bmpWidth*24+31)/32)*4)*(-bmpHeight);
    }

    #ifdef LINUX

      strcpy( FullFilename, pszFilename );

      rgbFile = fopen( FullFilename, "w+b" );

      if( rgbFile )

    #else

      strcpy_s( FullFilename, sizeof(FullFilename), pszFilename );

      errno_t  errno;
      errno = fopen_s( &bayerFile, FullFilename, "r+b" );  
      if(errno == 0)
      {
          printf("size %d", strlen(FullFilename)-4);
        memcpy(&FullFilename[strlen(FullFilename)-4],".bmp",4);
        errno = fopen_s( &rgbFile, FullFilename, "w+b" );  
      }
      if ( errno == 0 )
    #endif
    {

/*    0 1 2 3 4 5     0 1 2 3 4 5     0 1 2 3 4 5 */
/*  0 R G R G R G   0 G R G R G R   0 B G B G B G */
/*  1 G B G B G B   1 B G B G B G   1 G R G R G R */
/*  2 R G R G R G   2 G R G R G R   2 B G B G B G */
/*  3 G B G B G B   3 B G B G B G   3 G R G R G R */



        memset(bmpImage,255,sizeof(bmpImage));
        switch(bmpFormat)
        {
        case 2:
//            0 1 2 3 4 5
//          0 G R G R G R
//          1 B G B G B G
//          2 G R G R G R
//          3 B G B G B G
            for(y=0;y<bmpHeight;y++)
            {
                for(x=0;x<bmpWidth;x++)
                {
                    lowOrder=fgetc(bayerFile);
                    highOrder=fgetc(bayerFile);
                    bayerVal=(highOrder * 0x100);
                    bayerVal+=lowOrder;
                    bayerImage[y][x]=bayerVal;
                    if(bayerVal<minPixel)
                    {
                        minPixel=bayerVal;
                    }
                    if(bayerVal>maxPixel)
                    {
                        maxPixel=bayerVal;
                    }
                    if(y%2==0)
                    {
                        if(x%2==0)
                        {
                            //green
                            bayerImage[y][x]=bayerVal/2;
                            //if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
                            //bayerImage[y][x]*=.65;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[0][bayerVal]++;
                        }
                        else
                        {
                            //red
                            bayerImage[y][x]=bayerVal/2;
                            //if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
                            //bayerImage[y][x]*=.85;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[1][bayerVal]++;
                        }
                    }
                    else
                    {
                        if(x%2==0)
                        {
                            //blue
                            bayerImage[y][x]=bayerVal/2;
                            //if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
                            //bayerImage[y][x]*=.85;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[2][bayerVal]++;
                        }
                        else
                        {
                            //green
                            bayerImage[y][x]=bayerVal/2;
                            //if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
                            //bayerImage[y][x]*=.65;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[3][bayerVal]++;
                        }
                    }
                 }
            }
            for(y=1;y<bmpHeight-1;y++)
            {
                for(x=1;x<bmpWidth-1;x++)
                {            
                    bmpchar=bayerImage[y][x]/4;
                    if(y%2==0)
                    {
                        if(x%2==0)
                        {
                            //green pixel bayerImage[y][x]
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y-1][x]+bayerImage[y+1][x])/2;//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y][x]/2)+((bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/8);//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y][x-1]+bayerImage[y][x+1])/2;//red
                        }
                        else
                        {
                            //red pixel
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/4;//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y-1][x]+bayerImage[y+1][x]+bayerImage[y][x-1]+bayerImage[y][x+1])/4;//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y][x]);//red
                        }
                    }
                    else
                    {
                        if(x%2==0)
                        {
                            //blue pixel
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=bayerImage[y][x];//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y-1][x]+bayerImage[y+1][x]+bayerImage[y][x-1]+bayerImage[y][x+1])/4;//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/4;//red
                        }
                        else
                        {
                            //green pixel 
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y][x-1]+bayerImage[y][x+1])/2;//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y][x]/2)+((bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/8);//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y-1][x]+bayerImage[y+1][x])/2;//red
                        }
                    }
                }
            }
            break;
        case 3:
            printf("format 3\n");
//            0 1 2 3 4 5
//          0 R G R G R G
//          1 G B G B G B
//          2 R G R G R G
//          3 G B G B G B
            for(y=0;y<bmpHeight;y++)
            {
                for(x=0;x<bmpWidth;x++)
                {
                    lowOrder=fgetc(bayerFile);
                    highOrder=fgetc(bayerFile);
                    bayerVal=(highOrder * 0x100);
                    bayerVal+=lowOrder;
                    bayerImage[y][x]=bayerVal;
                    if(bayerVal<minPixel)
                    {
                        minPixel=bayerVal;
                    }
                    if(bayerVal>maxPixel)
                    {
                        maxPixel=bayerVal;
                    }
                    if(y%2==0)
                    {
                        if(x%2==0)
                        {
                            //red
                            bayerImage[y][x]=bayerVal;
                            if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
                            //bayerImage[y][x]*=.85;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[1][bayerVal]++;
                        }
                        else
                        {
                            //green
                            bayerImage[y][x]=bayerVal;
                            if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
                            bayerImage[y][x]*=.65;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[0][bayerVal]++;
                        }
                    }
                    else
                    {
                        if(x%2==0)
                        {
                            //green
                            bayerImage[y][x]=bayerVal;
                            if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
                            bayerImage[y][x]*=.65;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[3][bayerVal]++;
                        }
                        else
                        {
                            //blue
                            bayerImage[y][x]=bayerVal;
                            if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
                            //bayerImage[y][x]*=.85;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[2][bayerVal]++;
                        }
                    }
                 }
            }
            for(y=1;y<bmpHeight-1;y++)
            {
                for(x=1;x<bmpWidth-1;x++)
                {            
                    bmpchar=bayerImage[y][x]/4;
                    if(y%2==0)
                    {
                        if(x%2==0)
                        {
                            //red pixel
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/4;//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y-1][x]+bayerImage[y+1][x]+bayerImage[y][x-1]+bayerImage[y][x+1])/4;//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=bayerImage[y][x];//red 
                        }
                        else
                        {
                            //green pixel bayerImage[y][x]
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y-1][x]+bayerImage[y+1][x])/2;//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y][x]/2)+((bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/8);//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y][x-1]+bayerImage[y][x+1])/2;//red 
                        }
                    }
                    else
                    {
                        if(x%2==0)
                        {
                            //green pixel 
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y][x-1]+bayerImage[y][x+1])/2;//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y][x]/2)+((bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/8);//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y-1][x]+bayerImage[y+1][x])/2;//red
                        }
                        else
                        {
                            //blue pixel
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=bayerImage[y][x];//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y-1][x]+bayerImage[y+1][x]+bayerImage[y][x-1]+bayerImage[y][x+1])/4;//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/4;//red
                        }
                    }
                }
            }
            break;
        case 4:
//            0 1 2 3 4 5
//          0 G R G R G R
//          1 B G B G B G
//          2 G R G R G R
//          3 B G B G B G
            for(y=0;y<bmpHeight;y++)
            {
                for(x=0;x<bmpWidth;x++)
                {
                    lowOrder=fgetc(bayerFile);
                    highOrder=fgetc(bayerFile);
                    bayerVal=(highOrder * 0x100);
                    bayerVal+=lowOrder;
                    bayerImage[y][x]=bayerVal;
                    if(bayerVal<minPixel)
                    {
                        minPixel=bayerVal;
                    }
                    if(bayerVal>maxPixel)
                    {
                        maxPixel=bayerVal;
                    }
                    if(y%2==0)
                    {
                        if(x%2==0)
                        {
                            //green
                            bayerImage[y][x]=bayerVal;
                            if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
                            bayerImage[y][x]*=.65;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[0][bayerVal]++;
                        }
                        else
                        {
                            //red
                            bayerImage[y][x]=bayerVal;
                            if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
                            //bayerImage[y][x]*=.85;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[1][bayerVal]++;
                        }
                    }
                    else
                    {
                        if(x%2==0)
                        {
                            //blue
                            bayerImage[y][x]=bayerVal;
                            if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
                            //bayerImage[y][x]*=.85;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[2][bayerVal]++;
                        }
                        else
                        {
                            //green
                            bayerImage[y][x]=bayerVal;
                            if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
                            bayerImage[y][x]*=.65;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[3][bayerVal]++;
                        }
                    }
                 }
            }
            for(y=1;y<bmpHeight-1;y++)
            {
                for(x=1;x<bmpWidth-1;x++)
                {            
                    bmpchar=bayerImage[y][x]/4;
                    if(y%2==0)
                    {
                        if(x%2==0)
                        {
                            //green pixel bayerImage[y][x]
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y][x]+bayerImage[y][x+1]+bayerImage[y+1][x])/3;//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=bmpImage[(((y*bmpWidth)+x)*3)+0];//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=bmpImage[(((y*bmpWidth)+x)*3)+0];//red
                        }
                        else
                        {
                            //red pixel
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y][x]+bayerImage[y][x+1]+bayerImage[y+1][x+1])/3;//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=bmpImage[(((y*bmpWidth)+x)*3)+0];//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=bmpImage[(((y*bmpWidth)+x)*3)+0];//red
                        }
                    }
                    else
                    {
                        if(x%2==0)
                        {
                            //blue pixel
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y][x]+bayerImage[y+1][x]+bayerImage[y+1][x+1])/3;//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=bmpImage[(((y*bmpWidth)+x)*3)+0];//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=bmpImage[(((y*bmpWidth)+x)*3)+0];//red
                        }
                        else
                        {
                            //green pixel 
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y][x]+bayerImage[y][x+1]+bayerImage[y+1][x])/3;//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=bmpImage[(((y*bmpWidth)+x)*3)+0];//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=bmpImage[(((y*bmpWidth)+x)*3)+0];//red
                        }
                    }
                }
            }
            break;
        case 5:
//            0 1 2 3 4 5
//          0 G R G R G R
//          1 B G B G B G
//          2 G R G R G R
//          3 B G B G B G
            for(y=0;y<bmpHeight;y++)
            {
                for(x=0;x<bmpWidth;x++)
                {
                    lowOrder=fgetc(bayerFile);
                    highOrder=fgetc(bayerFile);
                    bayerVal=(highOrder * 0x100);
                    bayerVal+=lowOrder;
                    bayerImage[y][x]=bayerVal;
                    if(bayerVal<minPixel)
                    {
                        minPixel=bayerVal;
                    }
                    if(bayerVal>maxPixel)
                    {
                        maxPixel=bayerVal;
                    }
                    if(y%2==0)
                    {
                        if(x%2==0)
                        {
                            //green
                            bayerImage[y][x]=bayerVal;
                            //if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
                            bayerImage[y][x]/=256;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[0][bayerVal]++;
                        }
                        else
                        {
                            //red
                            bayerImage[y][x]=bayerVal;
                            //if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
                            bayerImage[y][x]/=256;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[1][bayerVal]++;
                        }
                    }
                    else
                    {
                        if(x%2==0)
                        {
                            //blue
                            bayerImage[y][x]=bayerVal;
                            //if (bayerImage[y][x] >= 10) bayerImage[y][x]-=10; else bayerImage[y][x]=0;
                            bayerImage[y][x]/=256;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[2][bayerVal]++;
                        }
                        else
                        {
                            //green
                            bayerImage[y][x]=bayerVal;
                            //if (bayerImage[y][x] >= 20) bayerImage[y][x]-=20; else bayerImage[y][x]=0;
                            bayerImage[y][x]/=256;
                            if(bayerImage[y][x]>255) 
                                bayerImage[y][x]=255;
                            rgbValues[3][bayerVal]++;
                        }
                    }
                 }
            }
            for(y=1;y<bmpHeight-1;y++)
            {
                for(x=1;x<bmpWidth-1;x++)
                {            
                    bmpchar=bayerImage[y][x]/4;
                    if(y%2==0)
                    {
                        if(x%2==0)
                        {
                            //green pixel bayerImage[y][x]
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y-1][x]+bayerImage[y+1][x])/2;//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y][x]/2)+((bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/8);//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y][x-1]+bayerImage[y][x+1])/2;//red
                        }
                        else
                        {
                            //red pixel
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/4;//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y-1][x]+bayerImage[y+1][x]+bayerImage[y][x-1]+bayerImage[y][x+1])/4;//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y][x]);//red
                        }
                    }
                    else
                    {
                        if(x%2==0)
                        {
                            //blue pixel
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=bayerImage[y][x];//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y-1][x]+bayerImage[y+1][x]+bayerImage[y][x-1]+bayerImage[y][x+1])/4;//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/4;//red
                        }
                        else
                        {
                            //green pixel 
                            bmpImage[(((y*bmpWidth)+x)*3)+0]=(bayerImage[y][x-1]+bayerImage[y][x+1])/2;//blue
                            bmpImage[(((y*bmpWidth)+x)*3)+1]=(bayerImage[y][x]/2)+((bayerImage[y-1][x-1]+bayerImage[y-1][x+1]+bayerImage[y+1][x-1]+bayerImage[y+1][x+1])/8);//green
                            bmpImage[(((y*bmpWidth)+x)*3)+2]=(bayerImage[y-1][x]+bayerImage[y+1][x])/2;//red
                        }
                    }
                }
            }
            break;
        default:
            printf("undefined bit format\n");
            return(-3);
            break;
        }
        bmpheader[0]='\x42';
        bmpheader[1]='\x4d';
        bmpheader[2]='\x38';
        bmpheader[3]='\x00';
        bmpheader[4]='\x90';
        bmpheader[5]='\x00';
        bmpheader[6]='\x00';
        bmpheader[7]='\x00';

        bmpheader[8]='\x00';
        bmpheader[9]='\x00';
        bmpheader[10]='\x36';
        bmpheader[11]='\x00';
        bmpheader[12]='\x00';
        bmpheader[13]='\x00';
        bmpheader[14]='\x28';
        bmpheader[15]='\x00';

        bmpheader[16]='\x00';
        bmpheader[17]='\x00';
        bmpheader[18]='\x00';
        bmpheader[19]='\x08';
        bmpheader[20]='\x00';
        bmpheader[21]='\x00';
        bmpheader[22]='\x00';
        bmpheader[23]='\x06';

        bmpheader[24]='\x00';
        bmpheader[25]='\x00';
        bmpheader[26]='\x01';
        bmpheader[27]='\x00';
        bmpheader[28]='\x18';
        bmpheader[29]='\x00';
        bmpheader[30]='\x00';
        bmpheader[31]='\x00';

        bmpheader[32]='\x00';
        bmpheader[33]='\x00';
        bmpheader[34]='\x00';
        bmpheader[35]='\x00';
        bmpheader[36]='\x00';
        bmpheader[37]='\x00';
        bmpheader[38]='\x5a';
        bmpheader[39]='\x37';

        bmpheader[40]='\x00';
        bmpheader[41]='\x00';
        bmpheader[42]='\x5a';
        bmpheader[43]='\x37';
        bmpheader[44]='\x00';
        bmpheader[45]='\x00';
        bmpheader[46]='\x00';
        bmpheader[47]='\x00';

        bmpheader[48]='\x00';
        bmpheader[49]='\x00';
        bmpheader[50]='\x00';
        bmpheader[51]='\x00';
        bmpheader[52]='\x00';
        bmpheader[53]='\x00';

        memcpy(&bmpheader[2],&bmrgbFilesize,4);
        memcpy(&bmpheader[18],&bmpWidth,4);
        memcpy(&bmpheader[22],&bmpHeight,4);

        fwrite( bmpheader, 1, 54, rgbFile );

        fwrite( pImage, 1, bmrgbFilesize, rgbFile );
        fclose( rgbFile );
        fclose( bayerFile );
        return(1);
    }
    return(-2);

} // end DumpImage()


int main(int argc, char* argv[]) 
{

    if(argc !=2)
    {
        printf("wrong number of arugments\n");
        printf("drag file to decode on top of program icon\n");
        return(-1);
    }
    else
    {
        printf("%s\n",argv[0]);
        printf("%s\n",argv[1]);
    }
/*
char *str = "sdfadabcGGGGGGGGG";
char *result = strstr(str, "abc");
int position = result - str;
int substringLength = strlen(str) - position;
*/
    char *widthStr = strstr(argv[1],"__")+2;
    int widthInt=atoi(widthStr);

    char *heightStr = strstr(widthStr,"x")+1;
    int heightInt=atoi(heightStr);

    char *bitsStr = strstr(heightStr,"_")+1;
    int bitsInt=atoi(bitsStr);

    char *formatStr = strstr(bitsStr,"_")+1;
    int formatInt=atoi(formatStr);

    //DumpImage( argv[1], bmpImage, widthInt, heightInt,bitsInt,formatInt);
    DumpImage( argv[1], bmpImage, widthInt, heightInt,bitsInt,2);
    printf("done\n");
    return 1;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从Android的Camera中捕获图像? - how to capture image from Camera in Android? Android:如何从相机获取原始图像数据 - Android: How to get raw image data from camera Android-如何从相机捕获图像或从库中添加图像 - Android - How Capture image from camera or add from Library 如何在Android编程中从Camera Application捕获图像? - How to Capture image from Camera Application in Android Programming? 在 Android 上 - 如何从广角相机捕获图像/视频? - On Android - how to capture image/video from the wide angle camera? 如何在Android中同时获取传感器测量值和从相机捕获图像? - How to get sensor measurement and capture image from camera simultaneously in android? 安卓。 如何从相机捕获图像并将其存储在服务器中? - Android. How to capture image from camera and store it in server? PhoneGap - Android - 如何在SD卡中保存摄像头的捕获图像 - PhoneGap - Android - how to save the capture image from camera in the sd card 如何从Android编程中的Camera Application捕获预览图像帧? - How to capture preview image frames from Camera Application in Android Programming? Android从相机捕获的图像作为缩略图,但不是应该的 - Android capture image from camera as thumbnail but not as it should be
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM