1. 程式人生 > >VC 呼叫GDI+繪圖

VC 呼叫GDI+繪圖

GDI+繪圖功能強大,這裡簡單演示VC呼叫的方法和步驟

主要涉及,調入已有的圖形檔案,在螢幕上繪圖,擷取螢幕上需要的部分,儲存為BMP 或JPG檔案等。

還是直接上程式碼:

//一 首先下載,gdi 有關的標頭檔案和庫檔案

//二 以下部分語句最好放到檔案 StdAfx.h中
#ifndef ULONG_PTR
typedef  unsigned long*   ULONG_PTR;
#include "Include\\GdiPlus.h"//標頭檔案
using namespace Gdiplus;//名稱空間
#pragma comment(lib, "lib\\gdiplus.lib")//庫檔案
#endif


//三以下功能最好分散到不同的檔案中,這裡為了簡單,集中到一個函式內演示
void CGdiDlg::OnButton1()
{
 // TODO: Add your control notification handler code here

//1 初始化,最好在App的 InitInstance()實現
 ULONG_PTR m_gdiplusToken;
 GdiplusStartupInput gdiplusStartupInput;
 GdiplusStartup(&m_gdiplusToken,&gdiplusStartupInput,NULL);

//2 繪圖物件 
 CDC *pDC=GetDC();
 Graphics graphics(pDC->m_hDC);

//-------------------------

//3 字型處理
 FontFamily fontFamily2(L"楷體_GB2312");
 Font font1(&fontFamily2,20,FontStyleRegular,UnitPixel);
 SolidBrush solidBrush(Color(255,0,0,255));
 WCHAR str1[]=L"沒有任何優化處理";

 graphics.SetTextRenderingHint(TextRenderingHintSingleBitPerPixel);
 graphics.DrawString(str1,(int)wcslen(str1),&font1,PointF(10,10),&solidBrush);

 WCHAR str2[]=L"字型優化,但邊不做平滑處理";
 graphics.SetTextRenderingHint(TextRenderingHintSingleBitPerPixelGridFit);
 graphics.DrawString(str2,(int)wcslen(str2),&font1,PointF(10,30),&solidBrush);

 WCHAR str3[]=L"消除走樣,且邊做平滑處理";
 graphics.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);
 graphics.DrawString(str3,(int)wcslen(str3),&font1,PointF(10,50),&solidBrush);

//-------------------------

//4 調入jpg圖片
 Image image(L"2.jpg");
 UINT width=image.GetWidth();
 UINT height=image.GetHeight();

//-------------------------

//5 背景刷子
 FontFamily fontFamily(L"幼圓");
 Font font(&fontFamily,20,FontStyleRegular,UnitPoint);
 TextureBrush tBrush(&image);
 LinearGradientBrush linGrBrush(Point(30,50), Point(100,50), Color(255, 255, 0, 0), Color(255, 0, 0, 255) );
 WCHAR str5[256];
 wcscpy(str5, L"圖片刷子");

 PointF pointF(30,70);
 graphics.DrawString(str5,(int)wcslen(str5),&font,pointF,&tBrush);

 wcscpy(str5, L"漸變色刷子");
 pointF.Y+=30;
 graphics.DrawString(str5,(int)wcslen(str5),&font,pointF,&linGrBrush);

//-------------------------

//6 筆的種類
 Pen newPen(Color(255,0,0),3);
 HatchBrush newBrush(HatchStyleCross,Color(255,0,266,0),Color(255,0,0,255));
 graphics.DrawRectangle(&newPen,260,70,100,60);
 graphics.FillRectangle(&newBrush,260,70,100,60);

//-------------------------

//7 調入圖片影像,各種畫法
 int posY=160;
 //不進行縮放
 graphics.DrawImage(&image,10,posY);
 //使用低質量的插補演算法
 posY+=50;
 graphics.SetInterpolationMode(InterpolationModeNearestNeighbor);
 graphics.DrawImage(&image,Rect(170,posY,(INT)(0.6*width),(INT)(0.6*height)));
 //使用中等質量的插補演算法
 posY+=50;
 graphics.SetInterpolationMode(InterpolationModeHighQualityBilinear);
 graphics.DrawImage(&image,Rect(270,posY,(INT)(0.6*width),(INT)(0.6*height)));
 //使用高等質量的插補演算法
 posY+=50;
 graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
 graphics.DrawImage(&image,Rect(370,posY,(INT)(0.6*width),(INT)(0.6*height)));
//-------------------------

//8 圖片的旋轉和拉伸
 //1 原點,2 X軸的方法和影象X方向的大小,3 Y軸的方法和影象Y方向的大小
 Point points[]={Point(0,0),Point(image.GetWidth(),0),Point(0,image.GetHeight())};
 Matrix matrix(1,0,0,1,230,10);//定義一個單位矩陣,座標原點(230,10)
 matrix.Rotate(30);//順時針旋轉30度
 matrix.Scale(0.63,0.6);//X,Y方向分別乘以0.63 0.6比例因子
 matrix.TransformPoints(points,3);//用該矩陣轉換points
 graphics.DrawImage(&image,points,3);//平行四邊形,三個點就夠了,第4點系統自動算出

 Point newpoints[]={Point(450,10),Point(510,60),Point(350,80) };
 graphics.DrawImage(&image,newpoints,3);

 //另外旋轉的方法
 graphics.TranslateTransform(330,10);//將原點移動到(330,10)
 graphics.RotateTransform(60);//順時針旋轉60度
 graphics.DrawImage(&image,0,0);

//-------------------------

//9 儲存jpg檔案
//儲存檔案
 CRect rect;
 GetClientRect(&rect);//    ClientToScreen(&rect);
// GetWindowRect(&rect);
 SaveScreenJpg("win.jpg",  rect,GetDC())  ; //儲存本視窗
 SaveScreenJpg("screen.jpg",  rect); //儲存整個螢幕

    ReleaseDC(pDC);

//-------------------------

//10 退出時,釋放gdi
//最好在App的 ExitInstance()
// Gdiplus::GdiplusShutdown(m_gdiplusToken);
}

// 四這中間使用的圖形格式轉換函式,以及儲存圖形函式
////========================
//VC實現:bmp轉jpg、jpg轉bmp、截圖儲存jpg(GDI+)
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) 

   UINT  num = 0;          // number of image encoders  
   UINT  size = 0;         // size of the image encoder array in bytes  
 
   ImageCodecInfo* pImageCodecInfo = NULL; 
    
   //2.獲取GDI+支援的影象格式編碼器種類數以及ImageCodecInfo陣列的存放大小  
   GetImageEncodersSize(&num, &size); 
   if(size == 0) 
      return -1;  // Failure  
 
   //3.為ImageCodecInfo陣列分配足額空間  
   pImageCodecInfo = (ImageCodecInfo*)(malloc(size)); 
   if(pImageCodecInfo == NULL) 
      return -1;  // Failure  
 
   //4.獲取所有的影象編碼器資訊  
   GetImageEncoders(num, size, pImageCodecInfo); 
 
   //5.查詢符合的影象編碼器的Clsid  
   for(UINT j = 0; j < num; ++j) 
   { 
      if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 ) 
      { 
         *pClsid = pImageCodecInfo[j].Clsid; 
         free(pImageCodecInfo); 
         return j;  // Success  
      }     
   } 
 
   //6.釋放步驟3分配的記憶體  
   free(pImageCodecInfo); 
   return -1;  // Failure  

//void SaveFile(Bitmap* pImage, const wchar_t* pFileName)//
void SaveBmpToJpg(Bitmap* pImage, const wchar_t* pFileName)//
{
    EncoderParameters encoderParameters;
    CLSID jpgClsid;
 GetEncoderClsid(L"image/jpeg", &jpgClsid);
    encoderParameters.Count = 1;
    encoderParameters.Parameter[0].Guid = EncoderQuality;
    encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
    encoderParameters.Parameter[0].NumberOfValues = 1;

    // Save the image as a JPEG with quality level 100.
    ULONG             quality;
    quality = 80;
    encoderParameters.Parameter[0].Value = &quality;
    Status status = pImage->Save(pFileName, &jpgClsid, &encoderParameters);
    if (status != Ok)
    {
        wprintf(L"%d Attempt to save %s failed.\n", status, pFileName);
    }
}


HBITMAP   ReturnHBITMAP(CString   FileName)//FileName可能是bmp、dib、png、gif、jpeg/jpg、tiff、emf等檔案的檔名
{
          Bitmap   tempBmp(FileName.AllocSysString())   ;
        Color       backColor;      
        HBITMAP       HBitmap;  
        tempBmp.GetHBITMAP(backColor,&HBitmap);
        return   HBitmap;

}


////========================
// 將當前螢幕儲存成為jpg圖片      
// 引數      quality = jpeg圖象質量      
void SaveScreenJpg(CString   pszFileName, CRect rect=NULL, CDC *pDC=NULL, int quality=80)  
{  
//bmp
 int left=0,   top=0,   width=100,   height=100;
 HDC sourceDC;
 HBITMAP hold, hCompBmp;
 HDC hMemDC ;
 if (pDC==NULL)
 {// 為空得到整個螢幕 HWND hwnd = ::GetDesktopWindow();  
  sourceDC = GetWindowDC(NULL);  
  left=0;  top=0;
  width = GetDeviceCaps(sourceDC, HORZRES);  
  height = GetDeviceCaps(sourceDC, VERTRES);
 }
 else
 {
  sourceDC=pDC->m_hDC;
  left=rect.left; top=rect.top;
  width=rect.Width(); height=rect.Height();
 }

 hCompBmp = CreateCompatibleBitmap(sourceDC, width, height);  
 hMemDC = CreateCompatibleDC(sourceDC);  
 hold = (HBITMAP)::SelectObject(hMemDC,   hCompBmp);  

 BitBlt(hMemDC, 0, 0, width, height, sourceDC, left, top, SRCCOPY);  
 SelectObject(hMemDC, hold);  
 
    Bitmap bit(width, height), bit2(hCompBmp, NULL);  
    Graphics g(&bit);  
   // g.ScaleTransform((float)width/wx,   (float)height/hy);  
    g.DrawImage(&bit2,   0,   0);  

// --> jpg   
    CLSID  encoderClsid;  
    EncoderParameters   encoderParameters;  
   
    encoderParameters.Count   =   1;  
    encoderParameters.Parameter[0].Guid   =   EncoderQuality;  
    encoderParameters.Parameter[0].Type   =   EncoderParameterValueTypeLong;  
    encoderParameters.Parameter[0].NumberOfValues   =   1;  
    encoderParameters.Parameter[0].Value   =   &quality;  
   
    GetEncoderClsid(L"image/jpeg",   &encoderClsid);  
 WCHAR pzWch[MAX_PATH];
 for (int k=0;k<pszFileName.GetLength();k++)
  pzWch[k]=pszFileName.GetAt(k);
 pzWch[k]=0x00;
   // bit.Save((LPCWSTR)L"wuchao.jpg",   &encoderClsid,   &encoderParameters);  
     bit.Save(pzWch,   &encoderClsid,   &encoderParameters);  
 
    ::DeleteObject(hCompBmp);  
    ::DeleteObject(hMemDC);  
    return;  

}

原文轉載自:http://blog.sina.com.cn/s/blog_45eaa01a0102vfhv.html