下面一段代码对BMP的象素操作非常有用:
void CBmpTryView::OnDraw(CDC* pDC)
{
CBmpTryDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CDC memdcX,memdcY;
memdcX.CreateCompatibleDC(pDC);
//map these CDC objects to your window DC
memdcY.CreateCompatibleDC(pDC);
BITMAP bmpX,bmpY;
CBitmap mybmp,bmpClone;
bmpClone.LoadBitmap(IDB_BITMAP2);
//initialize the clone bitmap object(empty image in
//this case) before using
DWORD dwValue,dwValue2;
if(TRUE == mybmp.LoadBitmap(IDB_BITMAP1))
{
mybmp.GetBitmap(&bmpX); //Get bitmap dimensions
//into BITMAP structure.
BYTE* bmpBuffer=(BYTE*)GlobalAlloc(GPTR,
bmpX.bmWidthBytes*bmpX.bmHeight);//allocate memory for image
//byte buffer
dwValue=mybmp.GetBitmapBits(bmpX.bmWidthBytes*bmpX.bmHeight,
bmpBuffer);//Get the bitmap bits
//into a structure
dwValue2 = bmpClone.SetBitmapBits(bmpX.bmWidthBytes*bmpX.bmHeight,
bmpBuffer);//generate image from
//above buffer
bmpClone.GetBitmap(&bmpY);
memdcX.SelectObject(mybmp);//select original bitmap
memdcY.SelectObject(bmpClone);//select clone
//Draw the original bitmap
pDC->BitBlt(10,10,bmpX.bmWidthBytes,bmpX.bmHeight ,&memdcX,
0,0,SRCCOPY);
//Draw the cloned bitmap image
pDC->BitBlt(10,40,bmpX.bmWidthBytes,bmpX.bmHeight ,&memdcY,
0,0,SRCCOPY);
GlobalFree((HGLOBAL)bmpBuffer);//Free memory
}
}
下面是我的3D浏览控件的部分代码:
主要实现把场景内容复制到剪贴板上,格式是CF_BITMAP
void CHoopsView::OnMCopy()
{
if ( !OpenClipboard() )
{
AfxMessageBox( "无法打开剪贴板" );
return;
}
// 删除目前剪贴板的内容
if( !EmptyClipboard() )
{
AfxMessageBox( "无法清除剪贴板" );
return;
}
//CopyBmp2Clipboard() ;
SaveDIB("D:\\1_1.bmp");
// Save2Hsf("D:\\1_1.hsf");
//下面一段程序有问题,关闭程序时有问题
HGLOBAL hStr = ::GlobalAlloc(GMEM_FIXED,11);
LPTSTR lpStr =(LPTSTR) ::GlobalLock(hStr);
sprintf(lpStr,"D:\\1_1.hsf");
::GlobalUnlock(hStr);
if ( ::SetClipboardData( CF_TEXT, hStr ) == NULL )
{
AfxMessageBox( "无法将数据复制到剪贴板当中" );
}
::GlobalFree(hStr);
CloseClipboard();
}
void CHoopsView::OnMPaste()
{
BITMAP bm;
CBitmap *pBmp = new CBitmap();
pBmp->LoadBitmap(IDB_BITMAP1);
pBmp->GetBitmap(&bm);
BYTE* lpBits =
(BYTE*)GlobalAlloc(GPTR, bm.bmWidthBytes*bm.bmHeight);
pBmp->GetBitmapBits(bm.bmWidthBytes*bm.bmHeight,lpBits);
if ( !OpenClipboard() )
{
AfxMessageBox( "无法打开剪贴板" );
return;
}
// 删除目前剪贴板的内容
if( !EmptyClipboard() )
{
AfxMessageBox( "无法清除剪贴板" );
return;
}
if ( ::SetClipboardData( CF_BITMAP, (HBITMAP)(*pBmp) ) == NULL )
{
AfxMessageBox( "无法将数据复制到剪贴板当中" );
}
CloseClipboard();
}
BOOL CHoopsView::SaveDIB(const char * filename)
{
char temp[MVO_BUFFER_SIZE];
char cwidth[MVO_BUFFER_SIZE], cheight[MVO_BUFFER_SIZE];
HC_Open_Segment_By_Key(m_pHView->GetViewKey());
HC_Show_Device_Info(".", "pixels", temp);
HC_Close_Segment();
HC_Parse_String(temp, ",", 0, cwidth);
int width = atoi(cwidth);
HC_Parse_String(temp, ",", 1, cheight);
int height = atoi(cheight);
HOutputHandlerOptions local_options;
HOutputHandlerOptions * options = &local_options;
options->m_Width = width;
options->m_Height = height;
CFile file;
CFileException fe;
if (!file.Open(filename, CFile::modeCreate |
CFile::modeWrite ,&fe))
{
fe.ReportError();
fe.Delete();
return false;
}
HPoint m_WindowColor,m_WindowColorBottom;
m_pHView->GetWindowColor(m_WindowColor,m_WindowColorBottom);
char hsra_options[MVO_BUFFER_SIZE];
char hlr_options[MVO_BUFFER_SIZE];
char current_hsra[MVO_BUFFER_SIZE];
/* first find out the relevant options associated with the view */
HC_Open_Segment_By_Key(m_pHView->GetViewKey());
{
HC_Show_One_Net_Rendering_Optio("hidden surface removal algorithm", current_hsra);
HRenderMode rndrmode = m_pHView->GetRenderMode();
if (rndrmode == HRenderHiddenLine || rndrmode == HRenderHiddenLineFast)
{
HC_Show_One_Net_Rendering_Optio("hidden line removal options", hlr_options);
sprintf(hsra_options, "hsra = hidden line, hidden line removal options = (%s)", hlr_options);
}
else
{
sprintf(hsra_options, "hsra = szb, technology = software frame buffer");
}
}
HC_Close_Segment();
char image_segment[MVO_SEGMENT_PATHNAME_BUFFER];
char driver_segment[MVO_SEGMENT_PATHNAME_BUFFER];
sprintf(image_segment,"?driver/null/hbaseview_%p", (void*)this);
sprintf(driver_segment,"?driver/image/hbaseview_%p", (void*)this);
// prepare image for rendering
HC_Open_Segment(image_segment);
HPixelRGB *image = new HPixelRGB[options->m_Width * options->m_Height];
HC_KEY image_key = HC_KInsert_Image (0.0, 0.0, 0.0, "rgb", options->m_Width, options->m_Height, image);
HC_Close_Segment ();
// prepare data to render
HC_Open_Segment(driver_segment);
//HC_Set_Rendering_Options("attribute lock = (color = (window))");
//HC_Set_Color_By_Value("windows", "RGB", m_WindowColor.x, m_WindowColor.y, m_WindowColor.z);
HC_Set_Window_Frame("off");
HC_Set_Rendering_Options(hsra_options);
char buffer[MVO_BUFFER_SIZE];
sprintf (buffer, "use window id = %s%p, subscreen = (-1, 1, -1, 1)", H_EXTRA_POINTER_FORMAT, (void*)image_key);
HC_Set_Driver_Options (buffer);
HC_Set_Driver_Options ("isolated, no gamma correction");
char color[MVO_BUFFER_SIZE];
HCLOCALE(sprintf(color, "windows=(r=%f g=%f b=%f), window contrast = (r=%f g=%f b=%f)", m_WindowColor.x, m_WindowColor.y, m_WindowColor.z, m_WindowColorBottom.x, m_WindowColorBottom.y, m_WindowColorBottom.z));
HC_Set_Color(color);
HC_Set_Window_Pattern("Down");
//ss if (GetAxisMode() != AxisOff)
//ss HC_Include_Segment_By_Key(GetAxisTriadKey());
HC_Include_Segment_By_Key (m_pHView->GetSceneKey());
HC_Close_Segment ();
HC_Update_One_Display(driver_segment);
BITMAPFILEHEADER bmfHdr;
bmfHdr.bfType=0x4d42;
int sizeHdr=sizeof(BITMAPINFOHEADER);
LPBITMAPINFOHEADER lpBI=( LPBITMAPINFOHEADER)::GlobalAlloc(LMEM_FIXED,sizeHdr);
if(!lpBI)
{
AfxMessageBox("内存申请失败,请稍后再试");
}
BYTE *pDib;
BYTE *pDib2;
long lPixelCount = options->m_Width*options->m_Height;
long lByteCount = lPixelCount*3;
pDib=(BYTE*)::GlobalAlloc(LMEM_FIXED,lByteCount);
HPixelRGB *pPixel = (HPixelRGB*)pDib;
// pPixel = new HPixelRGB[lPixelCount];
if(!pDib)
{
AfxMessageBox("内存申请失败,请稍后再试");
return false;
}
HC_Show_Partial_Image (image_key, 0, 0, options->m_Width , options->m_Height, pPixel) ;
HC_Delete_Segment(driver_segment);
HC_Delete_Segment(image_segment);
delete[] image;
lpBI->biSize=(LONG)sizeof(BITMAPINFOHEADER);
lpBI->biWidth=(LONG)options->m_Width;
lpBI->biHeight=(LONG)options->m_Height;
lpBI->biPlanes=1;
lpBI->biBitCount=24;
lpBI->biCompression=BI_RGB;
lpBI->biSizeImage=0;
lpBI->biXPelsPerMeter=0;
lpBI->biYPelsPerMeter=0;
lpBI->biClrUsed=0;
lpBI->biClrImportant=0;
long rows = options->m_Height;
long cols = options->m_Width;
pDib2=(BYTE*)::GlobalAlloc(LMEM_FIXED,(lByteCount/4+1)*4); //DWORD对齐的
if(!pDib2)
{
AfxMessageBox("内存申请失败,请稍后再试");
return false;
}
for(int j=0;j<rows;j++)
for(int i=0;i<cols;i++)
{
//pDib2[i+j*cols]=pDib[options->m_Width*(options->m_Height-1-j)*3+ll];
pDib2[i*3+j*cols*3] = pPixel[cols*(rows-1-j)+i].b;
pDib2[i*3+j*cols*3+1] = pPixel[cols*(rows-1-j)+i].g;
pDib2[i*3+j*cols*3+2] = pPixel[cols*(rows-1-j)+i].r;
}
// delete pPixel;
bmfHdr.bfSize=(DWORD) (sizeof(BITMAPFILEHEADER) +
sizeHdr + (lByteCount/4+1)*4);
bmfHdr.bfReserved1=bmfHdr.bfReserved2=0;
bmfHdr.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeHdr;
//CBitmap* pBmp = new CBitmap();
CBitmap bmp;
CBitmap* pBmp = &bmp;
//pBmp->CreateBitmapIndirect(&bm);
//pBmp->CreateBitmap(image_width,image_height,24,image_buffer);
CClientDC cdc(this);
struct RGBX
{
BYTE r;
BYTE g;
BYTE b;
BYTE x;
};
RGBX* pData = new RGBX[width*height];
//RGBX* pData = (RGBX*)::GlobalAlloc(GMEM_FIXED,width*height*4);
for(int i=0;i<height;i++)//行数
for(int j=0;j<width;j++)//列数
{
pData[i*width+j].b = pPixel[i*width+j].r;
pData[i*width+j].g = pPixel[i*width+j].g;
pData[i*width+j].r = pPixel[i*width+j].b;
pData[i*width+j].x = 0;
}
pBmp->CreateCompatibleBitmap(&cdc,width,height);
pBmp->SetBitmapBits(width*height*4,(void*)pData);
if ( ::SetClipboardData( CF_BITMAP, (HBITMAP)(*pBmp) ) == NULL )
{
AfxMessageBox( "无法将数据复制到剪贴板当中" );
}
::GlobalFree(pDib);
delete pData;
// delete pBmp;
try
{
file.Write((LPVOID)&bmfHdr,sizeof(BITMAPFILEHEADER));
file.Write((LPVOID)lpBI,sizeHdr);
file.WriteHuge((LPVOID)pDib2,(lByteCount/4+1)*4);
// file.WriteHuge((LPVOID)pDib,lByteCount);
}
catch(CException*Fe)
{
Fe->ReportError();
Fe->Delete();
return false;
}
//::GlobalFree(pDib);
::GlobalFree(lpBI);
::GlobalFree(pDib2);
file.Close();
return true;
}