RGB888转RGB565,图片保存的问题!!

shen_wei 2010-11-10 09:37:01

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


以上是我转换的主要代码。。。现在转换保存的图片出来。。。全是乱的。。有基本的图形,基本上不是原图。。。
不知道以上代码那里出错了!请高人解答下。。谢谢了!!
MSN:shenweiwei2005@sina.com 在线等待你的解答!!!
...全文
2023 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
tufaqing 2010-11-10
  • 打赏
  • 举报
回复
0xf800 = 11111000 00000000
0x07e0 = 00000111 11100000
0x001f = 00000000000011111
1表示颜色在WORD数据中的位置,自己看一下MSDN的BITMAPINFOHEADER
shen_wei 2010-11-10
  • 打赏
  • 举报
回复

DWORD nRGBMask[3];
nRGBMask[0] = 0xf800;
nRGBMask[1] = 0x07e0;
nRGBMask[2] = 0x001f;
WriteFile(hFile, nRGBMask, sizeof(nRGBMask), &dwByteWritten, NULL);



添加上了这个掩码。。。图片就显示正常了。。这个是什么意思?需要的掩码怎么解释。。。
tufaqing 2010-11-10
  • 打赏
  • 举报
回复

#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;
}
shen_wei 2010-11-10
  • 打赏
  • 举报
回复
图片没有保存失败。。。只是图片显示的都是乱的,。。。

对于你的说的那些。。1,虽然RGB你认为有错误,但是调换了位置还是一样。。。

2 对于取零是有这样的情况。。但我调试时没有发现一次。。。写法上不严谨。

对于字节对齐的问题。。请教你给详细解答下!!
hastings 2010-11-10
  • 打赏
  • 举报
回复
既然保存失败了,那就说明你还没搞清楚格式~~
hastings 2010-11-10
  • 打赏
  • 举报
回复
这是我归纳出来的问题~~
问题:
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大小的屏蔽码,还有写入的内容没考虑四字节对齐~~

shen_wei 2010-11-10
  • 打赏
  • 举报
回复
图片格式已经在代码中。。也能保存就是。。显示出来的是乱的。。。不是原图片!!
hastings 2010-11-10
  • 打赏
  • 举报
回复
这种东西一般建议直接用别人的类库~~
否则想亲自来,得仔细搞清楚位图格式~~
shen_wei 2010-11-10
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 tufaqing 的回复:]
0xf800 = 11111000 00000000
0x07e0 = 00000111 11100000
0x001f = 00000000000011111
1表示颜色在WORD数据中的位置,自己看一下MSDN的BITMAPINFOHEADER
[/Quote]

谢谢你的解答了!!!

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧