BMP位图操作(象素操作)

类别:VC语言 点击:0 评论:0 推荐:

下面一段代码对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;
  
}

本文地址:http://com.8s8s.com/it/it225.htm