file.Close(); ::GlobalUnlock((HGLOBAL) hBMP); return hBMP; }GetBmpBits函数用来得到图象数据。 LPSTR WINAPI GetBmpBits(LPSTR lpBmp) { return (lpBmp + *(LPDWORD)lpBmp + PaletteSize(lpBmp)); }对24位色图象来说,用上边的东东就可以得到灰度直方图。对8位(256)色图象来说,需要调色板的介入。 WORD WINAPI PaletteSize(LPSTR lpBmp) { // calculate the size required by the palette if (IS_WIN30_BMP (lpBmp)) return (WORD)(::BmpNumColors(lpBmp) * sizeof(RGBQUAD)); else return (WORD)(::BmpNumColors(lpBmp) * sizeof(RGBTRIPLE)); }WORD WINAPI BmpNumColors(LPSTR lpBmp) { WORD wBitCount; // Bmp bit count /* Calculate the number of colors in the color table based on * the number of bits per pixel for the Bmp. */ if (IS_WIN30_BMP(lpBmp)) wBitCount = ((LPBITMAPINFOHEADER)lpBmp)->biBitCount; else wBitCount = ((LPBITMAPCOREHEADER)lpBmp)->bcBitCount; /* return number of colors based on bits per pixel */ switch (wBitCount) { case 1: return 2; case 4: return 16; case 8: return 256; default: return 0; } }得到调色板: BOOL WINAPI CreateBmpPalette(HANDLE hBmp, CPalette* pPal) { LPLOGPALETTE lpPal; // pointer to a logical palette HANDLE hLogPal; // handle to a logical palette WORD wNumColors; // number of colors in color table LPSTR lpBmp; // pointer to packed-Bmp LPBITMAPINFO lpbmi; // pointer to BITMAPINFO structure (Win3.0) LPBITMAPCOREINFO lpbmc; // pointer to BITMAPCOREINFO structure (OS/2) BOOL bResult=FALSE; // return value //if handle to Bmp is invalid, return FALSE if (hBmp == NULL) return FALSE; lpBmp = (LPSTR) ::GlobalLock((HGLOBAL) hBmp); // get pointer to BITMAPINFO (Win 3.0) lpbmi = (LPBITMAPINFO)lpBmp; // get pointer to BITMAPCOREINFO (OS/2) lpbmc = (LPBITMAPCOREINFO)lpBmp; // get the number of colors in the Bmp wNumColors = BmpNumColors(lpBmp); if(wNumColors ==0 ) //there is no palette in the bmp return FALSE; // allocate memory block for logical palette hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * wNumColors); // if three is not enough memory, clean up and return NULL if (hLogPal == 0) { ::GlobalUnlock((HGLOBAL) hBmp); return FALSE; } lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal); //set version and number of palette entries lpPal->palVersion = PALVERSION; lpPal->palNumEntries = (WORD)wNumColors; if (IS_WIN30_BMP(lpBmp)) // is this a Win 3.0 Bmp? for (int i = 0; i < (int)wNumColors; i++) { lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed; lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen; lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue; lpPal->palPalEntry[i].peFlags = 0; } else for (int i = 0; i < (int)wNumColors; i++) { lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed; lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen; lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue; lpPal->palPalEntry[i].peFlags = 0; } //create the palette and get handle to it bResult = pPal->CreatePalette(lpPal); ::GlobalUnlock((HGLOBAL) hLogPal); ::GlobalFree((HGLOBAL) hLogPal); ::GlobalUnlock((HGLOBAL) hBmp); return bResult; }
自定义的图象类中的得到直方图函数,参数iClrChannel为rgb分量之一,piGrays为该分量的256灰度级。
void CImage::GetHistogram(int *piGrays, int iClrChannel)
{
if(m_hBmp == NULL) return;
for(int i = 0; i < 256; i++)
{
piGrays[i] = 0;
}
ASSERT(iClrChannel >= 0 && iClrChannel <= 3);
LPSTR lpBmp = (LPSTR)GlobalLock(m_hBmp);
BYTE* lpBmpBits = (BYTE*)GetBmpBits(lpBmp); CRect rcData = GetDataRect();
int row, col;
int iPixel=0;
BYTE r, g, b;
r = g = b = 0; switch(m_nBitCount)
{
case 24:
{
if(iClrChannel == 3/*luminary*/)
{
BYTE* pData = NULL;
for(row=rcData.top; row<rcData.bottom; row++)
{
for(col=rcData.left;col<rcData.right;col++)
{
pData = (BYTE*)lpBmpBits
+ row * m_nScanWidth + 3*col;
piGrays[(pData[0]+pData[1]+pData[2])/3]++;
}
}
}
else
{
for(row = rcData.top; row < rcData.bottom; row++)
{
iPixel = iClrChannel + row * m_nScanWidth
+ rcData.left*3;//origin pix of the row
for(col = rcData.left; col < rcData.right; col++)
{
piGrays[lpBmpBits[iPixel]]++;
iPixel += 3;
}
}
}
break;
}
case 8:
{
PALETTEENTRY PaletteColors[256];
if(m_pPalBmp->GetPaletteEntries(0, 256, PaletteColors)
!= 256 ) break;
for(row = rcData.top; row < rcData.bottom; row++)
{
iPixel = row * m_nScanWidth + rcData.left;
for(col = rcData.left; col < rcData.right; col++)
{
r = PaletteColors[lpBmpBits[iPixel]].peRed;
g = PaletteColors[lpBmpBits[iPixel]].peGreen;
b = PaletteColors[lpBmpBits[iPixel]].peBlue;
iPixel++;
switch(iClrChannel)
{
case 3:/*lum*/ piGrays[(r+g+b)/3]++;break;
case 2:/*red*/ piGrays[r]++;break;
case 1:/*green*/
piGrays[g]++;break;
case 0:/*blue*/ piGrays[b]++;break;
}
}
}
break;
}
}
GlobalUnlock(m_hBmp);
}m_hBmp为bmp图象中除去bmpfileheader后的数据,也就是PBMPINFOHEADER这个指针。用的HANDLE,所以需要先“GlobalLock”。
用这个函数得到:HANDLE WINAPI ReadBmpFile(CFile& file)
{
BITMAPFILEHEADER bmfHeader;
DWORD dwBitsSize;
HANDLE hBMP;
LPSTR pBMP; //get length of Bmp in bytes for use when reading
dwBitsSize = file.GetLength(); //Go read the Bmp file header and check if it's valid.
file.SeekToBegin();
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
{
file.Close();
return NULL;
} if (bmfHeader.bfType != BMP_FILE_TYPE)
{
CString str1, str2;
str1.Format("此程序只能处理 BMP 图片!");
str2.Format("文件格式错误");
::MessageBox(NULL,str1,str2,MB_ICONERROR|MB_OK); file.Close();
return NULL;
}
//Allocate memory for Bmp
hBMP = (HANDLE) ::GlobalAlloc(GHND, dwBitsSize);
if (hBMP == 0)
{
file.Close();
return NULL;
}
pBMP = (LPSTR) ::GlobalLock((HGLOBAL) hBMP); // read the bits.
if (file.ReadHuge(pBMP, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
dwBitsSize - sizeof(BITMAPFILEHEADER) )
{
::GlobalUnlock((HGLOBAL) hBMP);
::GlobalFree((HGLOBAL) hBMP);
file.Close();
return NULL;
}
file.Close();
::GlobalUnlock((HGLOBAL) hBMP);
return hBMP;
}GetBmpBits函数用来得到图象数据。
LPSTR WINAPI GetBmpBits(LPSTR lpBmp)
{
return (lpBmp + *(LPDWORD)lpBmp + PaletteSize(lpBmp));
}对24位色图象来说,用上边的东东就可以得到灰度直方图。对8位(256)色图象来说,需要调色板的介入。
WORD WINAPI PaletteSize(LPSTR lpBmp)
{
// calculate the size required by the palette
if (IS_WIN30_BMP (lpBmp))
return (WORD)(::BmpNumColors(lpBmp) * sizeof(RGBQUAD));
else
return (WORD)(::BmpNumColors(lpBmp) * sizeof(RGBTRIPLE));
}WORD WINAPI BmpNumColors(LPSTR lpBmp)
{
WORD wBitCount; // Bmp bit count /* Calculate the number of colors in the color table based on
* the number of bits per pixel for the Bmp.
*/
if (IS_WIN30_BMP(lpBmp))
wBitCount = ((LPBITMAPINFOHEADER)lpBmp)->biBitCount;
else
wBitCount = ((LPBITMAPCOREHEADER)lpBmp)->bcBitCount; /* return number of colors based on bits per pixel */
switch (wBitCount)
{
case 1:
return 2; case 4:
return 16; case 8:
return 256; default:
return 0;
}
}得到调色板:
BOOL WINAPI CreateBmpPalette(HANDLE hBmp, CPalette* pPal)
{
LPLOGPALETTE lpPal; // pointer to a logical palette
HANDLE hLogPal; // handle to a logical palette
WORD wNumColors; // number of colors in color table
LPSTR lpBmp; // pointer to packed-Bmp
LPBITMAPINFO lpbmi; // pointer to BITMAPINFO structure (Win3.0)
LPBITMAPCOREINFO lpbmc; // pointer to BITMAPCOREINFO structure (OS/2)
BOOL bResult=FALSE; // return value //if handle to Bmp is invalid, return FALSE
if (hBmp == NULL)
return FALSE; lpBmp = (LPSTR) ::GlobalLock((HGLOBAL) hBmp); // get pointer to BITMAPINFO (Win 3.0)
lpbmi = (LPBITMAPINFO)lpBmp; // get pointer to BITMAPCOREINFO (OS/2)
lpbmc = (LPBITMAPCOREINFO)lpBmp; // get the number of colors in the Bmp
wNumColors = BmpNumColors(lpBmp); if(wNumColors ==0 ) //there is no palette in the bmp
return FALSE; // allocate memory block for logical palette
hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
+ sizeof(PALETTEENTRY)
* wNumColors); // if three is not enough memory, clean up and return NULL
if (hLogPal == 0)
{
::GlobalUnlock((HGLOBAL) hBmp);
return FALSE;
} lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal); //set version and number of palette entries
lpPal->palVersion = PALVERSION;
lpPal->palNumEntries = (WORD)wNumColors; if (IS_WIN30_BMP(lpBmp)) // is this a Win 3.0 Bmp?
for (int i = 0; i < (int)wNumColors; i++)
{
lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
lpPal->palPalEntry[i].peFlags = 0;
}
else
for (int i = 0; i < (int)wNumColors; i++)
{
lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
lpPal->palPalEntry[i].peFlags = 0;
} //create the palette and get handle to it
bResult = pPal->CreatePalette(lpPal);
::GlobalUnlock((HGLOBAL) hLogPal);
::GlobalFree((HGLOBAL) hLogPal); ::GlobalUnlock((HGLOBAL) hBmp); return bResult;
}