请文各位高手,如何在vc++创建直方图,并且如何操作,给出相应代码?
解决方案 »
- 关于dshow的CTransInPlaceFilter求教
- 菜鸟问~~~搞开发要不要学数据库?
- 初学windows程序设计遇到的一个问题。
- CAsyncSocket发送大数据。在Client,一开始先Send 4096这个长度到Server,但Server有时会收到正确长度,但有时不会,比如-1094666771,858958007等。
- 读取INI文件的问题
- 郁闷:Invalid Address specified to RtlValidateHeap,这个错误该怎么办
- 如何在主窗口中加一个状态栏?
- 编辑对话框资源时的复制问题
- 如何用VC++读取word的文档结构图或者大纲
- MFC/SDI/ODBC/VC看了两天了有一些问题:怎么创建表?
- 在VC++中怎样连接SQL SERVER 数据库,ODBC的,ADO的,请出示源代码,100分
- 十年MFC经历认识的Microsoft技术(精彩的延续)
bmp图象格式、调色板、rgb什么的,默认为熟悉。*_*
还有,至于怎么gui显示出来,呵呵,俺就不管啦。自定义的图象类中的得到直方图函数,参数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;
}