问题描述
我无法使用 CBitmap :: CreateBitmap(int nWidth,int nHeight,UINT nPlanes,UINT nBitcount,const void * lpBits)创建CBitmap对象;
如何从 RGB 中的现有指针初始化并填充 lpBits 指针BITMAP
这样做的目的是从RGB构建灰度位图
我这样做会导致错误编译
I am unable to create a CBitmap object using CBitmap::CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitcount, const void* lpBits);
How to initialize and fill up the lpBits pointer from an existing one in an RGB BITMAP
The purpose of this is to build a Grayscale Bitmap from an RGB one
I did this which compiles with errors
...
CBitmap bmpRGB; // this is the input RGB bitmap
CBitmap bmpGray; // this will be the output one
BITMAP bm;
bmpRGB.GetBitmap(&bm);
LPBYTE lpBits = new BYTE[bm.bmHeight * bm.bmWidth];
bmpGray.CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 8, lpBits);
BYTE R, G, B;
for (long i = 0; i < bm.bmHeight * bm.bmWidth; i ++)
{
R = GetRValue((DWORD)bm.bmBits[i]);
G = GetGValue((DWORD)bm.bmBits[i]);
B = GetBValue((DWORD)bm.bmBits[i]);
lpBits[i] = (BYTE)(0.2989 * R + 0.5870 * G + 0.1140 * B);
}
...
我做错了代码!?
请帮助我这样做;
Im I doing the wrong code !?
Help me please to do that;
推荐答案
// Bitmap information + palette information
struct CUSTOM_BITMAPINFO
{
// bitmap information
BITMAPINFOHEADER bmiHeader;
/// A 256 colors palette
RGBQUAD bmiColors[256];
};
//saves an 8 bits-per-pixel image with a gray-scaled palette
BOOL SaveGrayScale(const BYTE* image, int width, int height, LPCTSTR fileName)
{
//fullwidth must be multiple of 4
int fullWidth = (width + 3) & 0xfffffffc;
//copy each scan line in a temporary buffer
BYTE* bytes = new BYTE[fullWidth * height];
for (int i = 0; i < height; i++)
CopyMemory(bytes + i * fullWidth, image + i * width, width);
//BMP header
BITMAPFILEHEADER header;
ZeroMemory(&header, sizeof(BITMAPFILEHEADER));
header.bfType = ((WORD) ('M' << 8) | 'B');
header.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(CUSTOM_BITMAPINFO) + fullWidth * height;
header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(CUSTOM_BITMAPINFO);
//Bitmap information
CUSTOM_BITMAPINFO bitmapInfo;
ZeroMemory(&bitmapInfo, sizeof(CUSTOM_BITMAPINFO));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 8;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biSizeImage = 0;
bitmapInfo.bmiHeader.biWidth = width;
//negative height for a top-down bitmap
bitmapInfo.bmiHeader.biHeight = -height;
//create the gray scale palette
for (int i = 0; i < 256; i++)
{
bitmapInfo.bmiColors[i].rgbRed = 0;
bitmapInfo.bmiColors[i].rgbGreen = 0;
bitmapInfo.bmiColors[i].rgbBlue = i;
bitmapInfo.bmiColors[i].rgbReserved = 0;
}
//save the image
HANDLE hFile = CreateFile(fileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
delete [] bytes;
return FALSE;
}
DWORD writtenBytes = 0;
if ( !WriteFile(hFile, &header, sizeof(BITMAPFILEHEADER), &writtenBytes, NULL) || writtenBytes != sizeof(BITMAPFILEHEADER)
|| !WriteFile(hFile, &bitmapInfo, sizeof(CUSTOM_BITMAPINFO), &writtenBytes, NULL) || writtenBytes != sizeof(CUSTOM_BITMAPINFO)
|| !WriteFile(hFile, bytes, fullWidth * height, &writtenBytes, NULL) || writtenBytes != fullWidth * height)
{
delete [] bytes;
CloseHandle(hFile);
return FALSE;
}
CloseHandle(hFile);
return TRUE;
}
//simple test function
void Test()
{
int width = 199;
int height = 200;
BYTE* image = new BYTE[width * height];
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
image[y * width + x] = x;
SaveGrayScale(image, width, height, "c:\\test.bmp");
delete [] image;
}
从现有位图获取信息:
To get the information from an existing bitmap:
CBitmap bitmap;
...
BITMAP bmp;
bitmap.GetBitmap(&bmp);
int width = bmp.bmWidth;
int height = bmp.bmHeight;
int fullWidth = (width + 3) & 0xfffffffc;
BYTE* bytes = (BYTE*)bmp.bmBits;
...
void CChildView::OnPaint()
{
CPaintDC dc(this);
BITMAP bmp;
// get the bitmap dimensions for bitblt
if(_bmp_grey.m_hObject && _bmp_grey.GetObject(sizeof(bmp),&bmp))
{
CDC mdc; mdc.CreateCompatibleDC(&dc);
HGDIOBJ obm = mdc.SelectObject(_bmp_grey);
// draw the bitmap
dc.BitBlt(0,0,bmp.bmWidth,bmp.bmHeight,&mdc,0,0,SRCCOPY);
mdc.SelectObject(obm);
}
}
CChildView::CChildView()
{
_bmp.LoadBitmap(1); // load from resource
ToGrey(_bmp,_bmp_grey,8); // convert to grey
}
void CChildView::ToGrey(CBitmap& color,CBitmap& grey,unsigned int bitspixel)
{
BITMAP bmp;
// get the bitmap dimensions
if(color.m_hObject && color.GetObject(sizeof(bmp),&bmp))
{
BITMAP bmpg = bmp;
unsigned int bpls = bmp.bmWidthBytes; // bytes per line source
unsigned int bpld; // bytes per line dest
unsigned int bpps,bppd; // bytes per pixel source/dest
unsigned char* lps; // source bitmap buffer
unsigned char* lpd; // dest bitmap buffer
unsigned char* lines; // current line source
unsigned char* lined; // current line dest
unsigned char* linee; // line end pointer
unsigned char* lpps; // pixel pointer source
unsigned char* lppd; // pixel pointer dest
unsigned char* lppe; // end of line source
double ar[256]; // map table for grey values corresponding to the rgb (byte) value
double ag[256];
double ab[256];
unsigned int ix; // index
// bitmap info structure to create dib bitmap
// including palette
BITMAPINFO* bmig = (BITMAPINFO*)malloc(sizeof(BITMAPINFO)+(sizeof(RGBQUAD)*256)); if(!bmig) return;
// fill 0
memset(bmig->bmiColors,0,sizeof(RGBQUAD)*256);
// create color mapping tables
for(ix=0;ix<256;ix++) ar[ix] = 0.2989 * ix;
for(ix=0;ix<256;ix++) ag[ix] = 0.5870 * ix;
for(ix=0;ix<256;ix++) ab[ix] = 0.1140 * ix;
// create grey scale palette
for(ix=0;ix<256;ix++) bmig->bmiColors[ix].rgbBlue = bmig->bmiColors[ix].rgbGreen = bmig->bmiColors[ix].rgbRed = ix;
// allocating buffer for the source bitmap bits
lps = (unsigned char*)malloc(bpls * bmp.bmHeight);
if(lps) // only go a head on existing buffer
{
bmpg.bmBitsPixel = bitspixel; // set the pixel width in bits (only 8,24,32 in this demo)
// calculating the line width in bytes for the gray bitmap
bmpg.bmWidthBytes = bpld = ((((bmpg.bmWidth*bmpg.bmBitsPixel)+7)>>3) + 3) & ~3;
// inittializing the bitmap info header
bmig->bmiHeader.biSize = sizeof(BITMAPINFO);
bmig->bmiHeader.biWidth = bmpg.bmWidth;
bmig->bmiHeader.biHeight = bmpg.bmHeight;
bmig->bmiHeader.biPlanes = 1;
bmig->bmiHeader.biBitCount = bmpg.bmBitsPixel;
bmig->bmiHeader.biCompression = 0;
bmig->bmiHeader.biSizeImage = bmpg.bmWidthBytes * bmpg.bmHeight;
bmig->bmiHeader.biXPelsPerMeter = 0;
bmig->bmiHeader.biYPelsPerMeter = 0;
bmig->bmiHeader.biClrUsed = 256;
bmig->bmiHeader.biClrImportant = 0;
// allocating the bitmap buffer for the grey bitmap
lpd = (unsigned char*)malloc(bpld * bmpg.bmHeight);
if(lpd) // continue only if you got the buffer
{
// get the bitmap bits from your original bitmap
color.GetBitmapBits(bpls * bmp.bmHeight,lps);
lines = lps; lined = lpd;
// distinguish between the different bitmap resolutions
// only valid for true color 24 or 32 bits per pixel
switch(bmp.bmBitsPixel)
{
case 24:
case 32:
bpps = bmp.bmBitsPixel>>3;
switch(bmpg.bmBitsPixel)
{
case 8:
// this section makes a bitmap based on palette
// loop through every line in source bitmap
for(linee=lps+(bpls*bmp.bmHeight);lines<linee;lines+=bpls,lined+=bpld)
{
// start of the line, set the pointers for source and dest
lpps = lines; lppd = lined;
// loop through the pixels in one line
for(lppe=lines+bpls;lpps<lppe;lpps+=bpps,lppd+=1)
{
// accumulete the pixel value by table and cast it to 8bit palette index
*lppd = (unsigned char)(ar[lpps[2]]+ag[lpps[1]]+ab[lpps[0]]);
}
}
break;
case 24:
case 32:
// this section creates a bitmap with rgb values
bppd = bmpg.bmBitsPixel>>3;
// loop through every line in source bitmap
for(linee=lps+(bpls*bmp.bmHeight);lines<linee;lines+=bpls,lined+=bpld)
{
lpps = lines; lppd = lined;
// loop through the pixels in one line
for(lppe=lines+bpls;lpps<lppe;lpps+=bpps,lppd+=bppd)
{
// set rgb values to grey value
lppd[0] =
lppd[1] =
lppd[2] = (unsigned char)(ar[lpps[2]]+ag[lpps[1]]+ab[lpps[0]]);
}
}
break;
default: ASSERT(0); /*not implemented*/ break;
}
break;
default: ASSERT(0); /*not implemented*/ break;
}
// create the grey bitmap
// usually the CreateBitmap functions are obsolet, thats why the bitmap is device dependant
// that means if your screen resolution is 32-bit with this functions you can
// only create 32-bit bitmaps
// if you have 256 color resolution you only can create palette based bitmaps
// oh yes i remember to the good old win 3.0 times
switch(bmpg.bmBitsPixel)
{
case 8:
{
HDC hdc = ::GetDC(0);
bmig->bmiHeader.biClrImportant = 256;
// you should use always this function
// DIB stands for device independant bitmap
grey.Attach(CreateDIBitmap(hdc,&bmig->bmiHeader,CBM_INIT,lpd,bmig,DIB_RGB_COLORS));
::ReleaseDC(0,hdc);
}
break;
default:
// this function creates a device dependant bitmap
// you should never use that!
// this function will fail if your screen resolution is 256 or hicolor (16-bit)
grey.CreateBitmapIndirect(&bmpg); // create the bitmap
grey.SetBitmapBits(bpld * bmpg.bmHeight,lpd); // apply the bitmap bits
break;
}
free(lpd); // free the buffer
}
free(lps); // free the buffer
}
free(bmig); // free the buffer
}
}
祝你好运。
Good luck.
这篇关于CBitmap :: CreateBitmap:如何!的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!