19,472
社区成员




struct RGB565
{
USHORT R:5;
USHORT G:6;
USHORT B:5;
};
FILE *fp=fopen(m_FileName,"r");
BITMAPFILEHEADER fileheader;
BITMAPINFO info;
fread(&fileheader,sizeof(fileheader),1,fp);
if(fileheader.bfType!=0x4D42)
{
fclose(fp);
return ;
}
fread(&info.bmiHeader, sizeof(BITMAPINFOHEADER), 1, fp);
long width=info.bmiHeader.biWidth;
long height=info.bmiHeader.biHeight;
UCHAR *buffer=new UCHAR[info.bmiHeader.biSizeImage];
fseek(fp,fileheader.bfOffBits,0);
fread(buffer,info.bmiHeader.biSizeImage,1,fp);
RGB565 *buffer1 = new RGB565[width*height*2];
for(int i=0;i<info.bmiHeader.biSizeImage;i=i+3)
{
buffer1[i/3].R = buffer[i]>>3;
buffer1[i/3].G = buffer[i+1]>>2;
buffer1[i/3].B = buffer[i+2]>>3;
}
CString bmpfile = "D:\\"+m_Name;
CFile File(bmpfile,CFile::modeCreate|CFile::modeWrite);
BITMAPFILEHEADER bmfh;
bmfh.bfType=0x4d42;
bmfh.bfSize=54+width*height*2;
bmfh.bfReserved1=bmfh.bfReserved2=0;
bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
BITMAPINFOHEADER bmih;
bmih.biWidth=width;
bmih.biHeight=height;
bmih.biPlanes=1;
bmih.biBitCount=16;
bmih.biCompression=BI_BITFIELDS;// BI_RGB ;
bmih.biSizeImage=width*height*2;
bmih.biXPelsPerMeter=0;
bmih.biYPelsPerMeter=0;
bmih.biClrUsed=0;
bmih.biClrImportant=0;
bmih.biSize=sizeof(BITMAPINFOHEADER);
File.Write(&bmfh,sizeof(BITMAPFILEHEADER));
File.Write(&bmih,sizeof(BITMAPINFOHEADER));
File.Write(buffer1,bmih.biSizeImage);
delete buffer;
delete buffer1;
File.Close();
DWORD nRGBMask[3];
nRGBMask[0] = 0xf800;
nRGBMask[1] = 0x07e0;
nRGBMask[2] = 0x001f;
WriteFile(hFile, nRGBMask, sizeof(nRGBMask), &dwByteWritten, NULL);
#ifndef WIDTHBYTES
#define WIDTHBYTES(bits) ((DWORD)(((bits)+31) & (~31)) / 8)
#endif
// BITMAPINFOHEADER m_bmih;
// BYTE *m_pR;
// BYTE *m_pG;
// BYTE *m_pB;
BOOL CImageProcessor::LoadFileFromBitmap(LPCTSTR lpFileName)
{
if(lpFileName == NULL)
{
return FALSE;
}
HANDLE hFile = ::CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
BOOL bRet = FALSE;
do
{
LARGE_INTEGER liSize;
liSize.QuadPart = 0;
::GetFileSizeEx(hFile, &liSize);
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
DWORD dwByteRead = 0;
::ReadFile(hFile, &bmfh, sizeof(bmfh), &dwByteRead, NULL);
if(dwByteRead < sizeof(bmfh))
{
break;
}
if(bmfh.bfType != 'MB' || bmfh.bfSize > liSize.QuadPart || bmfh.bfOffBits > liSize.QuadPart)
{
break;
}
dwByteRead = 0;
::ReadFile(hFile, &bmih, sizeof(bmih), &dwByteRead, NULL);
if(dwByteRead < sizeof(bmih))
{
break;
}
int nBitmapSize = abs(bmih.biHeight) * WIDTHBYTES(bmih.biWidth * bmih.biBitCount);
if(bmih.biPlanes != 1)
{
break;
}
if(bmih.biBitCount != 1 && bmih.biBitCount != 4 && bmih.biBitCount != 8 && bmih.biBitCount != 16 && bmih.biBitCount != 24 && bmih.biBitCount != 32)
{
break;
}
if(bmih.biCompression != BI_RGB && bmih.biCompression != BI_BITFIELDS)
{
break;
}
if(bmih.biWidth <= 0 || bmih.biHeight == 0)
{
break;
}
if(bmfh.bfOffBits + nBitmapSize > liSize.QuadPart)
{
break;
}
m_pR = new BYTE[bmih.biWidth * abs(bmih.biHeight)];
m_pG = new BYTE[bmih.biWidth * abs(bmih.biHeight)];
m_pB = new BYTE[bmih.biWidth * abs(bmih.biHeight)];
if(bmih.biBitCount < 16)
{
//...
}
else if(bmih.biBitCount == 16)
{
//...
}
else if(bmih.biBitCount == 24)
{
::SetFilePointer(hFile, bmfh.bfOffBits, NULL, SEEK_SET);
BYTE *pData = new BYTE[nBitmapSize];
dwByteRead = 0;
::ReadFile(hFile, pData, nBitmapSize, &dwByteRead, NULL);
BYTE *pR = m_pR;
BYTE *pG = m_pG;
BYTE *pB = m_pB;
for(int j = 0; j < abs(bmih.biHeight); j++)
{
BYTE *pTemp = pData + WIDTHBYTES(bmih.biWidth * bmih.biBitCount) * j;
for(int i = 0; i < bmih.biWidth; i++)
{
*pB++ = *pTemp++;
*pG++ = *pTemp++;
*pR++ = *pTemp++;
}
}
delete[] pData;
}
else if(bmih.biBitCount == 32)
{
//...
}
memcpy(&m_bmih, &bmih, sizeof(m_bmih));
bRet = TRUE;
}
while(0);
CloseHandle(hFile);
return bRet;
}
BOOL CImageProcessor::SaveFile565(HANDLE hFile)
{
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
memset(&bmfh, 0, sizeof(bmfh));
memset(&bmih, 0, sizeof(bmih));
int nBitmapSize = abs(m_bmih.biHeight) * WIDTHBYTES(m_bmih.biWidth * 16);
bmfh.bfType = 'MB';
bmfh.bfOffBits = sizeof(bmfh) + sizeof(bmih) + 12;
bmfh.bfSize = bmfh.bfOffBits + nBitmapSize;
bmih.biSize = sizeof(bmih);
bmih.biWidth = m_bmih.biWidth;
bmih.biHeight = m_bmih.biHeight;
bmih.biPlanes = 1;
bmih.biBitCount = 16;
bmih.biCompression = BI_BITFIELDS;
bmih.biSizeImage = nBitmapSize;
BYTE *pData = new BYTE[nBitmapSize];
memset(pData, 0, nBitmapSize);
BYTE *pR = m_pR;
BYTE *pG = m_pG;
BYTE *pB = m_pB;
for(int j = 0; j < abs(bmih.biHeight); j++)
{
WORD *pTemp = (WORD *)(pData + WIDTHBYTES(bmih.biWidth * 16) * j);
for(int i = 0; i < bmih.biWidth; i++)
{
#if 1
*pTemp++ = ((WORD)(*pR++ << 8) & 0xf800) | ((WORD)(*pG++ << 3) & 0x07e0) | ((WORD)(*pB++ >> 3) & 0x001f);
#else
int nR = (*pR++ + 4) >> 3;
int nG = (*pG++ + 2) >> 2;
int nB = (*pB++ + 4) >> 3;
if(nR > 31) nR = 31;
if(nG > 63) nG = 63;
if(nB > 31) nB = 31;
*pTemp++ = (nR << 11) | (nG << 5) | nB;
#endif
}
}
DWORD nRGBMask[3];
nRGBMask[0] = 0xf800;
nRGBMask[1] = 0x07e0;
nRGBMask[2] = 0x001f;
DWORD dwByteWritten = 0;
::WriteFile(hFile, &bmfh, sizeof(bmfh), &dwByteWritten, NULL);
::WriteFile(hFile, &bmih, sizeof(bmih), &dwByteWritten, NULL);
::WriteFile(hFile, nRGBMask, sizeof(nRGBMask), &dwByteWritten, NULL);
::WriteFile(hFile, pData, nBitmapSize, &dwByteWritten, NULL);
delete[] pData;
return TRUE;
}
这是我归纳出来的问题~~
问题:
1、
struct RGB565
{
USHORT R:5;
USHORT G:6;
USHORT B:5;
};
位图的顺序不是这样的,是蓝绿红,同理,后面的
for(int i=0;i<info.bmiHeader.biSizeImage;i=i+3)
{
buffer1[i/3].R = buffer[i]>>3;
buffer1[i/3].G = buffer[i+1]>>2;
buffer1[i/3].B = buffer[i+2]>>3;
}
也是错的~~
2、
UCHAR *buffer=new UCHAR[info.bmiHeader.biSizeImage];
biSizeImage字段的值可能为0,而且大多数情况为0(比如GDI+保存出来的位图就为0).
3、
long height=info.bmiHeader.biHeight;
biHeight字段可能为负值,所以后面的
RGB565 *buffer1 = new RGB565[width*height*2];
的结果你懂的~~同时你还没考虑四字节对齐问题~~
不过这个为负值的情况为少数情况,没问题1来的严重.
4、
bmfh.bfSize=54+width*height*2;
bmih.biSizeImage=width*height*2;
请注意四字节对齐~~
5、
bmih.biCompression=BI_BITFIELDS;
如果等于BI_BITFIELDS,那么前面的偏移量你就已经错了~~
bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);//已经错误
还要加上3个DWORD大小的屏蔽码~~
6、
File.Write(buffer1,bmih.biSizeImage);
前面少写入了3个DWORD大小的屏蔽码,还有写入的内容没考虑四字节对齐~~