S3c2440 保存位图没数据,大侠们帮帮忙啊

534117403   2009-5-8 13:52 楼主
S3c2440 想把相机0v9655采进来的图像保存为BMP格式的,我的代码如下,但就是不成功啊,大侠们帮帮忙啊

typedef struct {
        WORD    bfType;
        DWORD   bfSize;
        WORD    bfReserved1;
        WORD    bfReserved2;
        DWORD   bfOffBits;
} BMPFILEHEADER_T;

struct BMPFILEHEADER_S{
        WORD    bfType;
        DWORD   bfSize;
        WORD    bfReserved1;
        WORD    bfReserved2;
        DWORD   bfOffBits;
};

typedef struct{
        DWORD      biSize;
        LONG       biWidth;
        LONG       biHeight;
        WORD       biPlanes;
        WORD       biBitCount;
        DWORD      biCompression;
        DWORD      biSizeImage;
        LONG       biXPelsPerMeter;
        LONG       biYPelsPerMeter;
        DWORD      biClrUsed;
        DWORD      biClrImportant;
} BMPINFOHEADER_T;
       struct RGB{
              BYTE b;
              BYTE g;
              BYTE r;
       }pRGB[180][240];  // 定义位图数据

typedef struct PINGPONG_PR
{
        unsigned int rgb_address;
        unsigned char flag;               
} PINGPONG_PR;
struct PINGPONG_PR bTemp;



void CMyCameraTestDlg::OnPic()
{
        // TODO: Add your control notification handler code here
        int iSize=240*180;
        int X_H,Y_V;
        int i,j;
        int  width,height;
         width=240;height=180;
         struct RGB temp;

       memset( pRGB, 0, sizeof(pRGB) );    // 设置背景为黑色
        if (!DeviceIoControl
                (m_hled,
         CAM_IOCTL_SAMSUNG_CAM_PR,           //根据具体的设备有相关的定义
         NULL,                                //没有向设备传递的数据,置为NULL
         0,                                   //没有向设备传递的数据,置为NULL
         &bTemp,                              //读取设备的数据返回地址
         sizeof(PINGPONG_PR *),               //读取数据的字节数
         NULL,
         NULL)
        )
        { AfxMessageBox(_T("拍照失败!"));
   
        }  
        //GetPixelFormat()和SetPixelFormat()  RGB16转RGB24
for(Y_V=0;Y_V<180;Y_V++)
{


         for(X_H=0;X_H<240;X_H++)
         {
         pRGB[Y_V][X_H].r = (((*(BYTE *)(bTemp.rgb_address+Y_V*240+X_H*2+1))>>3)&0Xf8) * 255 / 63;
         pRGB[Y_V][X_H].g  = ((*(BYTE *)(bTemp.rgb_address+Y_V*240+X_H*2+1)<<3)&0x38+((*(BYTE *)(bTemp.rgb_address+Y_V*240+X_H*2))>>5)&0x07)* 255 / 127;
     pRGB[Y_V][X_H].b  =((*(BYTE *)(bTemp.rgb_address+Y_V*240+X_H*2))& 0x1F)* 255 / 63;
         }

}

//倒序
        for(i=0;i<90;i++)
        {        for(j=0;j<240;j++)
                {
                        temp = pRGB[j];
                        pRGB[j] = pRGB[179-i][j];
                        pRGB[179-i][j] = temp;                       
                }
        }

      // 位图第一部分,文件信息
       BMPFILEHEADER_T bfh;
       bfh.bfType = 0X4d42;  //bm
       bfh.bfSize =3* width*height         // data size
              + sizeof( BMPFILEHEADER_T ) // first section size
              + sizeof( BMPINFOHEADER_T ) // second section size
              ;
       bfh.bfReserved1 = 0; // reserved
       bfh.bfReserved2 = 0; // reserved
       bfh.bfOffBits = bfh.bfSize -3* width*height;
       // 位图第二部分,数据信息
       BMPINFOHEADER_T bih;
       bih.biSize = sizeof(BMPINFOHEADER_T);
       bih.biWidth = width;
       bih.biHeight = height;
       bih.biPlanes = 1;
       bih.biBitCount = 24;
       bih.biCompression = 0;
       bih.biSizeImage = 3* width*height;
       bih.biXPelsPerMeter = 0;
       bih.biYPelsPerMeter = 0;
       bih.biClrUsed = 0;
       bih.biClrImportant = 0;  
      //保存文件          
       CFile file(_T("image.bmp"),CFile::modeCreate|CFile::modeReadWrite);
       file.Write(&bfh,sizeof(BMPFILEHEADER_T));
       file.Write(&bih,sizeof(BMPINFOHEADER_T));
       file.Write(( BYTE*)pRGB,240*180*3);
       file.Close();
       

}

回复评论 (10)

if (!DeviceIoControl
(m_hled,
        CAM_IOCTL_SAMSUNG_CAM_PR,          //根据具体的设备有相关的定义
        NULL,                                //没有向设备传递的数据,置为NULL
        0,                                  //没有向设备传递的数据,置为NULL
        &bTemp,                              //读取设备的数据返回地址
        sizeof(PINGPONG_PR ),              //读取数据的字节数
        NULL,
        NULL)
        )
也不行。
点赞  2009-5-8 13:55
看上去没有问题哦,你在应用和驱动打印 图像数据,看是否一致。

如果不一致再检查别的原因吧。
点赞  2009-5-8 14:44
不成功是什么意思?是无法获取摄像头数据,还是生成的BMP文件图像不对?
建议LZ分步调试,先确认下
1、驱动有没有传数据上来?
2、驱动传上来的数据是否正确?
3、生成的BMP文件是否正确?
点赞  2009-5-8 16:46
谢谢两位啊,现在弄出来了,保存的BMP文件有图像了。但还是有问题,保存的图片是以中间为界限,左右是一样的。像是镜像一样。rgb16转 RGB24的时候 算法改为
for(Y_V=0;Y_V<180;Y_V++)
{
   for(X_H=0;X_H<240;X_H++)
         {

         pRGB[Y_V][X_H].r =  (*(BYTE *)(bTemp.rgb_address+Y_V*240+X_H*2+1))&0Xf8;
pRGB[Y_V][X_H].g=(((*(BYTE *)(bTemp.rgb_address+Y_V*240+X_H*2+1))&0X07)<<5)+(((*(BYTE *)(bTemp.rgb_address+Y_V*240+X_H*2))&0Xe0)>>3);
     pRGB[Y_V][X_H].b  = ((*(BYTE *)(bTemp.rgb_address+Y_V*240+X_H*2))<<3)&0Xf8;
}
}
点赞  2009-5-8 22:26
现在换成这种方式,正常保存了:
   先定义image_buffer,
  BYTE *image_buffer = (BYTE*)malloc(iSize*2);        //RGB16
   memset(image_buffer,0,iSize*2);
while(1)
{
           if (!DeviceIoControl
                (m_hled,
         CAM_IOCTL_SAMSUNG_CAM_PR,           //根据具体的设备有相关的定义
         NULL,                                //没有向设备传递的数据,置为NULL
         0,                                   //没有向设备传递的数据,置为NULL
         &bTemp,                              //读取设备的数据返回地址
         sizeof(PINGPONG_PR),               //读取数据的字节数
         NULL,
         NULL)
        )
        { AfxMessageBox(_T("拍照失败!"));
        }  
           if(bTemp.flag==1)
           { //AfxMessageBox(_T("拍照!"));
                   break;
           }
}

for(Y_V=0;Y_V<180;Y_V++)
{
        memcpy((image_buffer+Y_V*240),(void *)bTemp.rgb_address,240*2);//czx

         for(X_H=0;X_H<240;X_H++)
         { pRGB[Y_V][X_H].r = (*(image_buffer+Y_V*240+X_H*2+1))&0Xf8 ;
      pRGB[Y_V][X_H].g  = (((*(image_buffer+Y_V*240+X_H*2+1))&0x07)<<5)+(((*(image_buffer+Y_V*240+X_H*2))&0xe0)>>3);
      pRGB[Y_V][X_H].b  =((*(image_buffer+Y_V*240+X_H*2))<<3)&0xf8;
         
         }
         bTemp.rgb_address+=240*2;
}


很奇怪其它的代码一样, 为什么用memcpy中间转一次,就成功了,而直接pRGB[Y_V][X_H].r =  (*(BYTE *)(bTemp.rgb_address+Y_V*240+X_H*2+1))&0Xf8等操作会出现问题呢?高人解惑下啊。指针数组的问题? 数据格式溢出问题?要是不通过image_buffer中转一次,就减少了一次内存操作,代码效率会更高啊。
点赞  2009-5-8 23:19
可能跟内存对齐有关系,
而且建议LZ用32位对齐的方式去转换,这样效率会更高!
点赞  2009-5-9 15:04
可能跟内存对齐有关系,
而且建议LZ用32位对齐的方式去转换,这样效率会更高!

能详细点吗?
对齐,32位对齐转换
点赞  2009-5-9 15:47
uping
点赞  2009-5-11 08:37
学习
点赞  2009-5-11 08:48
比如你要保存的位图是16位或32位色的,那么就用UINT32*来操作内存缓存和屏幕缓存,然后拷贝时用memcpy((UINT32*)src,((UINT32*)dest,size);
这样会大大提供运算和内存拷贝的效率,特别是屏幕分辨率很大的情况下,比如800*480
如果是24位,就另作处理!
点赞  2009-5-11 09:28
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复