TIF格式图像文件初探
2009-10-27 20:31:22 来源:WEB开发网回到OnOpenDocument成员函数中调用工具函数并获得全局内存块指针
//构造BMP图象内存块
if(!CreateBmpBuffer())
{
AfxMessageBox("构造BMP图象内存块失败");
delete []pde;
return FALSE;
}
//获得BMP内存块指针
pDIB = (BYTE*)GlobalLock(m_hDIB);
if(NULL == pDIB)
{
AfxMessageBox("获得BMP内存块指针失败");
GlobalUnlock(m_hDIB);
delete []pde;
return FALSE;
}
以下是将图像信息填充到BMP内存块中,网上介绍BMP格式的文章很多,这里就不详述了。因测试图像数据表达的是0x00-0xff灰度,正好和BMP文件调色板索引值巧合。 故在代码中直接把图像数据信息当成索引即可,减少了编码复杂度。注:BMP文件中图像数据的第一行代表的是最终显示光栅的最后一行,所以在数据排列中要颠倒过来。
//构造BITMAPFILEHEADER并复制到BMP内存块
BITMAPFILEHEADER bmfHdr;
memset(&bmfHdr, 0, sizeof(BITMAPFILEHEADER));
bmfHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
256*sizeof(RGBQUAD);
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfSize = bmfHdr.bfOffBits + m_dwBmSize;
bmfHdr.bfType = 0x4d42;
memmove(pDIB, &bmfHdr, sizeof(BITMAPFILEHEADER));
//构造BITMAPINFOHEADER并复制到BMP内存块
BITMAPINFOHEADER bmiHdr;
memset(&bmiHdr, 0, sizeof(BITMAPINFOHEADER));
bmiHdr.biBitCount = 8;
bmiHdr.biClrImportant = 0;
bmiHdr.biClrUsed = 0;
bmiHdr.biCompression = 0;
bmiHdr.biHeight = m_sizeDoc.cy;
bmiHdr.biPlanes = 1;
bmiHdr.biSize = sizeof(BITMAPINFOHEADER);
bmiHdr.biSizeImage = 0;
bmiHdr.biWidth = m_sizeDoc.cx;
bmiHdr.biXPelsPerMeter = 2834;
bmiHdr.biYPelsPerMeter = 2834;
memmove((BITMAPFILEHEADER*)pDIB + 1, &bmiHdr, sizeof(BITMAPINFOHEADER));
//构造256个RGBQUAD并复制到BMP内存块
RGBQUAD* pRgbQuad = (RGBQUAD*)(pDIB + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
RGBQUAD* pOldQuad = pRgbQuad;
RGBQUAD rgbQuad;
memset(&rgbQuad, 0, sizeof(RGBQUAD));
for(i=0; i<256; i++)
{
rgbQuad.rgbBlue = i;
rgbQuad.rgbGreen = i;
rgbQuad.rgbRed = i;
rgbQuad.rgbReserved = 0;
pRgbQuad = pOldQuad + i;
memmove(pRgbQuad, &rgbQuad, sizeof(RGBQUAD));
}
//填充所有像素数据, 颠倒图象数据从最后一行开始读起
int j = 0;
for(i=m_sizeDoc.cy-1; i>=0; i--)
{
file.Seek(sizeof(IFH) + i*m_sizeDoc.cx, CFile::begin);
file.Read((BYTE*)(pRgbQuad + 1) + j*m_sizeDoc.cx, m_sizeDoc.cx);
j++;
}
初始化BMP调色板,为显示BMP文件做准备
//初始化专用调色板
BYTE buf[2+2+4*256];
LOGPALETTE* pPal = (LOGPALETTE*)buf;
pPal->palVersion = 0x300;
pPal->palNumEntries = 256;
for(i=0; i<255; i++)
{
pPal->palPalEntry[i].peBlue = i;
pPal->palPalEntry[i].peFlags = 0;
pPal->palPalEntry[i].peGreen = i;
pPal->palPalEntry[i].peRed = i;
}
m_palDIB.CreatePalette(pPal);
最后是OnOpenDocument成员函数返回前的清理工作
GlobalUnlock(m_hDIB);
delete []pde;
return TRUE;
至此,TIF文件信息已转换为BMP图像并保存在全局内存块中了,接下来就可以在OnDraw中调用WinAPI函数StretchDIBits来显示它。
if(NULL == pDoc->m_hDIB)
{
return;
}
HDC hdc = pDC->m_hDC;
BYTE* pBuf = (BYTE*)GlobalLock(pDoc->m_hDIB);
pBuf += sizeof(BITMAPFILEHEADER);
BYTE* pData = pBuf + sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD);
CPalette* pOldPal = pDC->SelectPalette(&pDoc->m_palDIB, TRUE);
pDC->RealizePalette();
::SetStretchBltMode(hdc, COLORONCOLOR);
::StretchDIBits(hdc, 10, 10, pDoc->m_sizeDoc.cx, pDoc->m_sizeDoc.cy,
0, 0, pDoc->m_sizeDoc.cx, pDoc->m_sizeDoc.cy, pData,
(BITMAPINFO*)pBuf, DIB_RGB_COLORS, SRCCOPY);
pDC->SelectPalette(pOldPal, FALSE);
GlobalUnlock(pDoc->m_hDIB);
最后别忘了在文档类析构函数~CTiffTestDoc中销毁全局内存块
if(NULL != m_hDIB)
{
GlobalFree(m_hDIB);
m_hDIB = NULL;
}
四、结束语
测试用的TIF文件在工程目录下,文件名为SSS00.TIF。本人学习图形图像编程不久,文章难免挂一漏万,请高手指教。
更多精彩
赞助商链接