经过几天的资料收集和编写,完成了24位图片转unsigner short 型数组的程序,具体设计方案和部分实现分析如下:
1.资料来源:参考embeded bbs论坛上提供的图片转数组BMP2C程序改写。
2.软件开发基于的开发环境和语言:os基于XP SP2 语言C++ 开发环境VS2005 VC++
3.设计思路:
3.1 通过调用WIN32 内部类BITMAPFILEHEADER 对读取的图片文件进行分析处理;
3.2 通过CFile类对文件实现打开读取修改;
3.3 通过使用BITMAPFILEHEADER.biBitCount函数实现对图片位数的获取并分析是否是24位色图,如不是提示用户重新处理图片;
3.4 通过565方式改写图片信息,同时通过写文件将数值写入相应文件中。
3.5 整个过程是通过读文件和写文件方式实现。
4.主要算法:
4.1 565图片处理部分
for
(
int
j
=
0
; j
<
bmInfo.biWidth ; j
++
)
... { // 读取象素的值
BYTE byBlue, byGreen, byRed;
fileInput.Read(&byBlue, sizeof(BYTE));
fileInput.Read(&byGreen, sizeof(BYTE));
fileInput.Read(&byRed, sizeof(BYTE)); // 以 5:6:5 模式合成16位值
byRed = byRed * 0x1F / 0xFF;
byGreen = byGreen * 0x3F / 0xFF;
byBlue = byBlue * 0x1F / 0xFF;
unsigned short nValue = 0x0000;
nValue = byRed << 11 | byGreen << 5 | byBlue; /**//* 写入数组 */ // 8个数据就换一行
if(j % 8 == 0)
...{
strInfo = _T(" ");
fileOutput.Write(strInfo.GetBuffer(strInfo.GetLength()), strInfo.GetLength());
strInfo.ReleaseBuffer();
} // 写入数据
strInfo.Format(_T("%#.4X, "), nValue); fileOutput.Write(strInfo.GetBuffer(strInfo.GetLength()), strInfo.GetLength()); strInfo.ReleaseBuffer(); 4.2 Bmp2array(void)函数整体定义部分
... { // 读取象素的值
BYTE byBlue, byGreen, byRed;
fileInput.Read(&byBlue, sizeof(BYTE));
fileInput.Read(&byGreen, sizeof(BYTE));
fileInput.Read(&byRed, sizeof(BYTE)); // 以 5:6:5 模式合成16位值
byRed = byRed * 0x1F / 0xFF;
byGreen = byGreen * 0x3F / 0xFF;
byBlue = byBlue * 0x1F / 0xFF;
unsigned short nValue = 0x0000;
nValue = byRed << 11 | byGreen << 5 | byBlue; /**//* 写入数组 */ // 8个数据就换一行
if(j % 8 == 0)
...{
strInfo = _T(" ");
fileOutput.Write(strInfo.GetBuffer(strInfo.GetLength()), strInfo.GetLength());
strInfo.ReleaseBuffer();
} // 写入数据
strInfo.Format(_T("%#.4X, "), nValue); fileOutput.Write(strInfo.GetBuffer(strInfo.GetLength()), strInfo.GetLength()); strInfo.ReleaseBuffer(); 4.2 Bmp2array(void)函数整体定义部分
//
得到输入文件
CString strInput;
m_editInput.GetWindowText(strInput); // 得到输出文件
CString strOutput;
m_editOutput.GetWindowText(strOutput);
TRY
... { // 打开输入文件
CFile fileInput;
if(!fileInput.Open(strInput, CFile::modeRead))
...{
AfxMessageBox(_T("输入文件打开失败!"));
return;
} // 读取位图文件头
BITMAPFILEHEADER bmFile;
if(fileInput.Read(&bmFile, sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER))
...{
fileInput.Close();
AfxMessageBox(_T("输入文件格式错误!"));
return;
}
if(bmFile.bfSize != fileInput.GetLength() || bmFile.bfType != 0x4D42)
...{
fileInput.Close();
AfxMessageBox(_T("输入文件格式错误!"));
return;
} // 读取位图信息头
BITMAPINFOHEADER bmInfo;
fileInput.Read(&bmInfo, sizeof(BITMAPINFOHEADER)); // 暂时只支持24位色的位图 if(bmInfo.biBitCount != 24)
...{ fileInput.Close();
AfxMessageBox(_T("暂时只支持24位色的位图!"));
return;
} // 计算每一行的实际字节数
int nLineWidth = bmInfo.biWidth * bmInfo.biBitCount / 8;
if(nLineWidth % 4 != 0)
...{
nLineWidth = nLineWidth + (4 - nLineWidth % 4);
} // 打开输出文件
CFile fileOutput;
if(!fileOutput.Open(strOutput, CFile::modeCreate | CFile::modeWrite))
...{
AfxMessageBox(_T("输出文件打开失败!"));
return;
} // 进度条
m_progress.SetRange(0, 100);
m_progress.SetPos(0);
CString strProgress = _T("0%");
m_staticProgress.SetWindowText(strProgress); // 写入信息
CString strInfo =_T( "/*Author - Mercury Xu Basic by tao. This file was generated by Bmp2c.*/ ")
fileOutput.Write(strInfo.GetBuffer(strInfo.GetLength()), strInfo.GetLength());
strInfo.ReleaseBuffer();
CString strArrayName;
m_editArrayName.GetWindowText(strArrayName);
strInfo =(_T("const unsigned short ") + strArrayName + _T("[] = {"));
fileOutput.Write(strInfo.GetBuffer(strInfo.GetLength()), strInfo.GetLength());
strInfo.ReleaseBuffer(); // 扫描图象数据
for(int i = bmInfo.biHeight - 1 ; i >= 0 ; i--)
...{ // 进度条
m_progress.SetPos((bmInfo.biHeight - i) * 100 / bmInfo.biHeight);strProgress.Format(_T("%d%%"), (bmInfo.biHeight - i) * 100 / bmInfo.biHeight);
m_staticProgress.SetWindowText(strProgress);
// 把文件移动到扫描行的起始位置
fileInput.Seek(bmFile.bfOffBits + nLineWidth * i, CFile::begin);
for(int j = 0 ; j < bmInfo.biWidth ; j++)
...{ // 读取象素的值 BYTE byBlue, byGreen, byRed;
fileInput.Read(&byBlue, sizeof(BYTE));
fileInput.Read(&byGreen, sizeof(BYTE));
fileInput.Read(&byRed, sizeof(BYTE)); // 以 5:6:5 模式合成16位值
byRed = byRed * 0x1F / 0xFF;
byGreen = byGreen * 0x3F / 0xFF;
byBlue = byBlue * 0x1F / 0xFF;
unsigned short nValue = 0x0000;
nValue = byRed << 11 | byGreen << 5 | byBlue;
/**//* 写入数组 */
// 8个数据就换一行
if(j % 8 == 0)
...{
strInfo = _T(" ");
fileOutput.Write(strInfo.GetBuffer(strInfo.GetLength()), strInfo.GetLength()); strInfo.ReleaseBuffer();
} // 写入数据 strInfo.Format(_T("%#.4X, "), nValue);
fileOutput.Write(strInfo.GetBuffer(strInfo.GetLength()), strInfo.GetLength()); strInfo.ReleaseBuffer();
} } // 尾信息
strInfo = (_T(" };"));
fileOutput.Write(strInfo.GetBuffer(strInfo.GetLength()), strInfo.GetLength());
strInfo.ReleaseBuffer();
fileInput.Close();
fileOutput.Close(); // 进度条
m_progress.SetPos(100);
strProgress = _T("100%");
m_staticProgress.SetWindowText(strProgress);
::AfxMessageBox(_T("转换结束!"));
if((::MessageBox(NULL,_T("是否打开生成的文件?"),_T("注意"),MB_YESNO))==IDYES)
...{
ShellExecute(NULL, _T("open"), strOutput, NULL, NULL, SW_SHOWNORMAL);
}
} CATCH_ALL(e)
... { AfxMessageBox(_T("转换失败!"));
return; }
END_CATCH_ALL
CString strInput;
m_editInput.GetWindowText(strInput); // 得到输出文件
CString strOutput;
m_editOutput.GetWindowText(strOutput);
TRY
... { // 打开输入文件
CFile fileInput;
if(!fileInput.Open(strInput, CFile::modeRead))
...{
AfxMessageBox(_T("输入文件打开失败!"));
return;
} // 读取位图文件头
BITMAPFILEHEADER bmFile;
if(fileInput.Read(&bmFile, sizeof(BITMAPFILEHEADER)) != sizeof(BITMAPFILEHEADER))
...{
fileInput.Close();
AfxMessageBox(_T("输入文件格式错误!"));
return;
}
if(bmFile.bfSize != fileInput.GetLength() || bmFile.bfType != 0x4D42)
...{
fileInput.Close();
AfxMessageBox(_T("输入文件格式错误!"));
return;
} // 读取位图信息头
BITMAPINFOHEADER bmInfo;
fileInput.Read(&bmInfo, sizeof(BITMAPINFOHEADER)); // 暂时只支持24位色的位图 if(bmInfo.biBitCount != 24)
...{ fileInput.Close();
AfxMessageBox(_T("暂时只支持24位色的位图!"));
return;
} // 计算每一行的实际字节数
int nLineWidth = bmInfo.biWidth * bmInfo.biBitCount / 8;
if(nLineWidth % 4 != 0)
...{
nLineWidth = nLineWidth + (4 - nLineWidth % 4);
} // 打开输出文件
CFile fileOutput;
if(!fileOutput.Open(strOutput, CFile::modeCreate | CFile::modeWrite))
...{
AfxMessageBox(_T("输出文件打开失败!"));
return;
} // 进度条
m_progress.SetRange(0, 100);
m_progress.SetPos(0);
CString strProgress = _T("0%");
m_staticProgress.SetWindowText(strProgress); // 写入信息
CString strInfo =_T( "/*Author - Mercury Xu Basic by tao. This file was generated by Bmp2c.*/ ")
fileOutput.Write(strInfo.GetBuffer(strInfo.GetLength()), strInfo.GetLength());
strInfo.ReleaseBuffer();
CString strArrayName;
m_editArrayName.GetWindowText(strArrayName);
strInfo =(_T("const unsigned short ") + strArrayName + _T("[] = {"));
fileOutput.Write(strInfo.GetBuffer(strInfo.GetLength()), strInfo.GetLength());
strInfo.ReleaseBuffer(); // 扫描图象数据
for(int i = bmInfo.biHeight - 1 ; i >= 0 ; i--)
...{ // 进度条
m_progress.SetPos((bmInfo.biHeight - i) * 100 / bmInfo.biHeight);strProgress.Format(_T("%d%%"), (bmInfo.biHeight - i) * 100 / bmInfo.biHeight);
m_staticProgress.SetWindowText(strProgress);
// 把文件移动到扫描行的起始位置
fileInput.Seek(bmFile.bfOffBits + nLineWidth * i, CFile::begin);
for(int j = 0 ; j < bmInfo.biWidth ; j++)
...{ // 读取象素的值 BYTE byBlue, byGreen, byRed;
fileInput.Read(&byBlue, sizeof(BYTE));
fileInput.Read(&byGreen, sizeof(BYTE));
fileInput.Read(&byRed, sizeof(BYTE)); // 以 5:6:5 模式合成16位值
byRed = byRed * 0x1F / 0xFF;
byGreen = byGreen * 0x3F / 0xFF;
byBlue = byBlue * 0x1F / 0xFF;
unsigned short nValue = 0x0000;
nValue = byRed << 11 | byGreen << 5 | byBlue;
/**//* 写入数组 */
// 8个数据就换一行
if(j % 8 == 0)
...{
strInfo = _T(" ");
fileOutput.Write(strInfo.GetBuffer(strInfo.GetLength()), strInfo.GetLength()); strInfo.ReleaseBuffer();
} // 写入数据 strInfo.Format(_T("%#.4X, "), nValue);
fileOutput.Write(strInfo.GetBuffer(strInfo.GetLength()), strInfo.GetLength()); strInfo.ReleaseBuffer();
} } // 尾信息
strInfo = (_T(" };"));
fileOutput.Write(strInfo.GetBuffer(strInfo.GetLength()), strInfo.GetLength());
strInfo.ReleaseBuffer();
fileInput.Close();
fileOutput.Close(); // 进度条
m_progress.SetPos(100);
strProgress = _T("100%");
m_staticProgress.SetWindowText(strProgress);
::AfxMessageBox(_T("转换结束!"));
if((::MessageBox(NULL,_T("是否打开生成的文件?"),_T("注意"),MB_YESNO))==IDYES)
...{
ShellExecute(NULL, _T("open"), strOutput, NULL, NULL, SW_SHOWNORMAL);
}
} CATCH_ALL(e)
... { AfxMessageBox(_T("转换失败!"));
return; }
END_CATCH_ALL
5.其他:
设计采用简介的界面处理,没有设计更多功能,完成后用户可以选择是否打开文件进行阅读。方面简洁。