2013-02-08 100 views
9

takePicture rawCallback返回空指針。 getPictureFormat只允許使用.jpg。儘管可以通過getParameters()setJpegQuality(100)setParameters改進jpeg,但返回的圖像仍然是一個jpeg。要獲取位圖圖像,需要調用BitmapFactory.decodeByteArray,這可能需要1/2秒來處理。如何從android攝像頭捕獲原始圖像

我正在處理的應用程序需要相機可以生成的最詳細的圖像,這並不一定意味着漂亮。原始攝像頭芯片採集格式是拜耳。

回答

10

android(至少我的)有兩個攝像機參數"rawsave-mode""rawfname",默認rawsave-mode=0。通過設置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); 

生成的文件的實際名稱被修改爲包含正在生成的原始文件的參數。對於我的一個機器人,產生的名稱是"test__1604x1206_10_2.raw"這是一個1604x1206圖像,10bit格式2和"test__1284x966_10_3.raw"這是一個1284x966圖像,10 bit格式3. 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 

的圖像數據大致8 bit,但10 bit,其中較亮的圖像可能使用較高的值和較暗下部內浮動。這允許圖像處理軟件創建直方圖並捕獲圖像的有用範圍。由於光線不是一個常量,因此也可能需要以不同於另一個的方式調整一個通道,以使圖像看起來顏色正確。網上有很多關於顏色理論的信息可以完全解釋這一點,但新用戶注意,10 bit8的轉換變得很快。如果你想要一張漂亮的圖片,請使用android圖片截圖,而不是原始圖片!

格式表示位的拜耳模式。拜耳是一種格式,其中行和列的奇數/偶數值指示像素表示哪種顏色,其中RGB具有每個像素的每個顏色通道的8 bit值,拜爾僅具有一個像素爲10 bit的值,其中一個像素是紅色的,然後是下一個綠色,紅色,綠色,紅色,綠色。然後下一行有藍色,綠色,藍色,綠色,藍色綠色。要確定一個像素的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 

格式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 

像素的排列,我不知道,如果這種技術將在其他機器人工作,或者它是否會在未來的機器人工作。如果有人嘗試此操作,請添加評論成功或失敗。我的手機是直接中國進口解鎖iHTC Android手機已經紮根。

+0

請你怎麼能說這實際上是原始圖像,如果將它們保存爲.BMP ?請你能幫我理解嗎?無論如何感謝帖子! – 2013-06-01 21:54:36

+0

對不起,我的閱讀障礙再次踢,''。bmp'不正確,應該是'.raw',如1parameters.set(「rawfname」,「/mnt/sdcard/test.raw」);'。圖像文件輸出是一個「拜耳」圖像,而不是RGB圖像,因此每個像素只有一個10位的紅色或綠色或藍色的值。要製作RGB圖像,必須解釋周圍的像素。 – 2013-06-02 01:17:25

+0

有趣的是,拜耳形象不是真正的「THE」'原始形象'。在使用管道進行播放時,首先會創建另一個原始圖像,然後將其製作爲bayer,然後刪除第一個文件。我唯一能看到第一張圖像的方式是在試圖使用管道時相機掛起。由於攝像機的CMOS芯片是一個拜耳陣列,我的假設是格式的改變是爲了在字節邊界上獲得數據而不是半字節或位邊界的友好性。 – 2013-06-02 01:23:38

1

//醜陋的代碼轉換拜耳爲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; 
} 
1

代碼捕獲原始圖像:

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(); 
     } 
    }; 

}