自定义的图象类中的得到直方图函数,参数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;
}
直方图
最新推荐文章于 2024-01-14 18:37:13 发布