📄 dib.cpp
字号:
* 如果位数是8:color=256;
* 如果位数是24,在颜色表中没有相应的颜色
************************************************************************/
WORD CDib::NumColors() const
{
if (!m_pBMI)
return 0;
WORD wBitCount; // DIB位的数量
// 颜色表中的颜色数目可以小于每相素允许的位数 (例如: lpbi->biClrUsed
// 可以被设置为某些值).
// 如果是这种情况,则返回合适的值
DWORD dwClrUsed;
dwClrUsed = m_pBMI->bmiHeader.biClrUsed;
if (dwClrUsed != 0)
return (WORD)dwClrUsed;
// 根据用于DIB的每个相素位的数目,来计算在颜色表中的颜色数
wBitCount = m_pBMI->bmiHeader.biBitCount;
// 返回根据每个相素的位数目得到的颜色数
switch (wBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
/*************************************************************************
*
* Save()
*
* Saves the specified DIB into the specified CFile. The CFile
* is opened and closed by the caller.
*
* Parameters:
*
* CFile& file - open CFile used to save DIB
*
* Return value: Number of saved bytes or CFileException
*
*************************************************************************/
DWORD CDib::Save(CFile& file) const
{
BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
DWORD dwDIBSize;
if (m_pBMI == NULL)
return 0;
// Fill in the fields of the file header
// Fill in file type (first 2 bytes must be "BM" for a bitmap)
bmfHdr.bfType = DIB_HEADER_MARKER; // "BM"
// Calculating the size of the DIB is a bit tricky (if we want to
// do it right). The easiest way to do this is to call GlobalSize()
// on our global handle, but since the size of our global memory may have
// been padded a few bytes, we may end up writing out a few too
// many bytes to the file (which may cause problems with some apps).
//
// So, instead let's calculate the size manually (if we can)
//
// First, find size of header plus size of color table. Since the
// first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
// the size of the structure, let's use this.
dwDIBSize = *(LPDWORD)&m_pBMI->bmiHeader + PaletteSize(); // Partial Calculation
// Now calculate the size of the image
if ((m_pBMI->bmiHeader.biCompression == BI_RLE8) || (m_pBMI->bmiHeader.biCompression == BI_RLE4))
{
// It's an RLE bitmap, we can't calculate size, so trust the
// biSizeImage field
dwDIBSize += m_pBMI->bmiHeader.biSizeImage;
}
else
{
DWORD dwBmBitsSize; // Size of Bitmap Bits only
// It's not RLE, so size is Width (DWORD aligned) * Height
dwBmBitsSize = WIDTHBYTES((m_pBMI->bmiHeader.biWidth)*((DWORD)m_pBMI->bmiHeader.biBitCount)) * m_pBMI->bmiHeader.biHeight;
dwDIBSize += dwBmBitsSize;
// Now, since we have calculated the correct size, why don't we
// fill in the biSizeImage field (this will fix any .BMP files which
// have this field incorrect).
m_pBMI->bmiHeader.biSizeImage = dwBmBitsSize;
}
// Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
/*
* Now, calculate the offset the actual bitmap bits will be in
* the file -- It's the Bitmap file header plus the DIB header,
* plus the size of the color table.
*/
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + m_pBMI->bmiHeader.biSize + PaletteSize();
// Write the file header
file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
DWORD dwBytesSaved = sizeof(BITMAPFILEHEADER);
// Write the DIB header
UINT nCount = sizeof(BITMAPINFO) + (NumColors()-1)*sizeof(RGBQUAD);
dwBytesSaved += nCount;
file.Write(m_pBMI, nCount);
// Write the DIB bits
DWORD dwBytes = m_pBMI->bmiHeader.biBitCount * Width();
// Calculate the number of bytes per line
if (dwBytes%32 == 0)
dwBytes /= 8;
else
dwBytes = dwBytes/8 + (32-dwBytes%32)/8 + (((32-dwBytes%32)%8 > 0) ? 1 : 0);
nCount = dwBytes * Height();
dwBytesSaved += nCount;
file.WriteHuge(m_pBits, nCount);
return dwBytesSaved;
}
/*************************************************************************
* 函数名:
*
* Read (CFile&)
*
*返回值:
* 读取的字节数
*
*函数功能:
* 把指定的DIB文件读入一块大内存区
*
*************************************************************************/
DWORD CDib::Read(CFile& file)
{
// 确保不会发生内存泄露的现象
Free();
BITMAPFILEHEADER bmfHeader;
// 读取DIB文件头,并检查它是否有效
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
return 0;
if (bmfHeader.bfType != DIB_HEADER_MARKER)
return 0;
DWORD dwReadBytes = sizeof(bmfHeader);
// 为DIB分配内存
m_pBMI = (LPBITMAPINFO)GlobalAllocPtr(GHND, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER) + 256*sizeof(RGBQUAD));
if (m_pBMI == 0)
return 0;
// 读头文件。
if (file.Read(m_pBMI, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER)) != (UINT)(bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER)))
{
GlobalFreePtr(m_pBMI);
m_pBMI = NULL;
return 0;
}
dwReadBytes += bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER);
DWORD dwLength = file.GetLength();
// 读取各位.
m_pBits = (LPBYTE)GlobalAllocPtr(GHND, dwLength - bmfHeader.bfOffBits);
if (m_pBits == 0)
{
GlobalFreePtr(m_pBMI);
m_pBMI = NULL;
return 0;
}
if (file.ReadHuge(m_pBits, dwLength-bmfHeader.bfOffBits) != (dwLength - bmfHeader.bfOffBits))
{
GlobalFreePtr(m_pBMI);
m_pBMI = NULL;
GlobalFreePtr(m_pBits);
m_pBits = NULL;
return 0;
}
dwReadBytes += dwLength - bmfHeader.bfOffBits;
CreatePalette();
return dwReadBytes;
}
#ifdef _DEBUG
void CDib::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
}
#endif
//////////////////////////////////////////////////////////////////////////
//// Clipboard support
//---------------------------------------------------------------------
//
// Function: CopyToHandle
//
// Purpose: Makes a copy of the DIB to a global memory block. Returns
// a handle to the new memory block (NULL on error).
//
// Returns: Handle to new global memory block.
//
//---------------------------------------------------------------------
/*HGLOBAL CDib::CopyToHandle() const
{
CSharedFile file;
try
{
if (Save(file)==0)
return 0;
}
catch (CFileException* e)
{
e->Delete();
return 0;
}
return file.Detach();
}
*/
//---------------------------------------------------------------------
//
// Function: ReadFromHandle
//
// Purpose: Initializes from the given global memory block.
//
// Returns: Number of read bytes.
//
//---------------------------------------------------------------------
DWORD CDib::ReadFromHandle(HGLOBAL hGlobal)
{
CSharedFile file;
file.SetHandle(hGlobal, FALSE);
DWORD dwResult = Read(file);
file.Detach();
return dwResult;
}
///////////////////////////////////////
/////////
/*************************************************************************
*
* 函数名称:
* FindDIBBits()
*
* 参数:
* LPSTR lpbi - 指向DIB对象的指针
*
* 返回值:
* LPSTR - 指向DIB图像象素起始位置
*
* 说明:
* 该函数计算DIB中图像象素的起始位置,并返回指向它的指针。
*
************************************************************************/
LPSTR CDib::FindDIBBits(LPSTR m_pBMI)
{
return (m_pBMI + *(LPDWORD)m_pBMI + PaletteSize());
}
//////////////////////////////////////////////////////////////////////////
//// Serialization support
void CDib::Serialize(CArchive& ar)
{
CFile* pFile = ar.GetFile();
ASSERT(pFile != NULL);
if (ar.IsStoring())
{ // storing code
Save(*pFile);
}
else
{ // loading code
Read(*pFile);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -