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();
}
if (!DeviceIoControl
(m_hled,
CAM_IOCTL_SAMSUNG_CAM_PR, //根据具体的设备有相关的定义
NULL, //没有向设备传递的数据,置为NULL
0, //没有向设备传递的数据,置为NULL
&bTemp, //读取设备的数据返回地址
sizeof(PINGPONG_PR ), //读取数据的字节数
NULL,
NULL)
)
也不行。
看上去没有问题哦,你在应用和驱动打印 图像数据,看是否一致。
如果不一致再检查别的原因吧。
不成功是什么意思?是无法获取摄像头数据,还是生成的BMP文件图像不对?
建议LZ分步调试,先确认下
1、驱动有没有传数据上来?
2、驱动传上来的数据是否正确?
3、生成的BMP文件是否正确?
谢谢两位啊,现在弄出来了,保存的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;
}
}
现在换成这种方式,正常保存了:
先定义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中转一次,就减少了一次内存操作,代码效率会更高啊。
可能跟内存对齐有关系,
而且建议LZ用32位对齐的方式去转换,这样效率会更高!
可能跟内存对齐有关系,
而且建议LZ用32位对齐的方式去转换,这样效率会更高!
能详细点吗?
对齐,32位对齐转换
比如你要保存的位图是16位或32位色的,那么就用UINT32*来操作内存缓存和屏幕缓存,然后拷贝时用memcpy((UINT32*)src,((UINT32*)dest,size);
这样会大大提供运算和内存拷贝的效率,特别是屏幕分辨率很大的情况下,比如800*480
如果是24位,就另作处理!