日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Windows 2D 绘图 (GDI, GDI+, Direct2D)

發布時間:2024/3/13 windows 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows 2D 绘图 (GDI, GDI+, Direct2D) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Windows 2D 繪圖

  • GDI
    • GDI 函數
  • GDI+
    • GDI 和 GDI+ 的區別
    • GDI+ 新特性
  • Direct2D
    • 視覺效果
  • demo

GDI

GDI 是 Graphics Device Interface 的縮寫,含義是圖形設備接口,它的主要任務是負責系統與繪圖程序之間的信息交換,處理所有 Windows 程序的圖形輸出。

在 Windows 操作系統下,絕大多數具備圖形界面的應用程序都離不開 GDI,我們利用 GDI 所提供的眾多 API 就可以方便的在屏幕、打印機及其它輸出設備上輸出圖形、文本等操作。

GDI 具有如下特點:

  • 不允許程序直接訪問物理顯示硬件,通過稱為“設備環境”的抽象接口間接訪問顯示硬件
  • 程序需要與顯示硬件(顯示器、打印機等) 進行通訊時,必須首先獲得與特定窗口相關聯的設備環境
  • 用戶無需關心具體的物理設備類型
  • Windows 參考設備環境的數據結構完成數據的輸出

GDI 函數

GDI 函數大致可分類為:

  • 設備上下文函數(如 GetDC、CreateDC、DeleteDC)
  • 畫線函數(如 LineTo、Polyline、Arc)
  • 填充畫圖函數(如 Ellipse、FillRect、Pie)
  • 畫圖屬性函數(如 SetBkColor、SetBkMode、SetTextColor)
  • 文本、字體函數(如 TextOut、GetFontData)
  • 位圖函數(如 SetPixel、BitBlt、StretchBlt)
  • 坐標函數(如 DPtoLP、LPtoDP、ScreenToClient、ClientToScreen)
  • 映射函數(如 SetMapMode、SetWindowExtEx、SetViewportExtEx)
  • 元文件函數(如 PlayMetaFile、SetWinMetaFileBits)
  • 區域函數(如 FillRgn、FrameRgn、InvertRgn)
  • 路徑函數(如 BeginPath、EndPath、StrokeAndFillPath)
  • 裁剪函數(如 SelectClipRgn、SelectClipPath)

GDI+

GDI+ 是 GDI 的后續版本,最早于 2000 年隨 Windows 2000 一起推出,后來又被包裝進 .NET 框架的托管類庫中,成為 .NET 中窗體繪圖的主要工具。

GDI+ 主要提供了以下三類服務:

  • 二維矢量圖形:GDI+ 提供了存儲圖形基元自身信息的類(或結構體)、存儲圖形基元繪制方式信息的類以及實際進行繪制的類;
  • 圖像處理:大多數圖片都難以劃定為直線和曲線的集合,無法使用二維矢量圖形方式進行處理。因此,GDI+ 為我們提供了 Bitmap、Image 等類。它們可用于顯示、操作和保存 BMP、JPG、GIF 等圖像。
  • 文字顯示:GDI+ 支持使用各種字體、字號和樣式來顯示文本。

GDI 接口是基于函數的,而 GDI+ 是基于 C++ OO 的編程接口,因此使用起來比 GDI 要方便。因為 GDI+ 實際上是 GDI 的封裝和擴展,所以執行效率一般要低于 GDI。

GDI 和 GDI+ 的區別

GDI 的核心是設備上下文,GDI 函數都依賴于設備上下文句柄,其編程方式是基于句柄的;GDI+ 無需時刻依賴于句柄或設備上下文,用戶只需創建一個 Graphics 對象,就可以用面向對象的方式調用其成員函數進行圖形操作,編程方式是基于對象的。

GDI 在使用設備上下文繪制線條之前,必須先調用 SelectObject 以使鋼筆對象和設備上下文關聯。其后,在設備上下文中繪制的所有線條均使用該鋼筆,直到選擇另一支不同的鋼筆為止。GDI 中有當前位置的概念,所以在使用 GDI 繪制線條前應該先使用MoveTo 移動當前位置,再使用 LineTo 畫線。

CPen pen(PS_SOLID, 1, RGB(255, 0, 0));dc.SelectObject(pen.GetSafeHandle());dc.MoveTo(0, 0);dc.LineTo(100, 100);

在 GDI+ 中,只需將 Pen 對象直接作為參數傳遞給 Graphics 類的 DrawLine 等方法即可,而不必使 Pen 對象與 Graphics 對象關聯。且 GDI+ 中則沒有當前位置的概念,畫線函數中可以直接指定起點和終點。

Pen myPen(Color::Red);graphics.DrawLine(&myPen, 0, 0, rect.right, 0);

GDI+ 新特性

  • 改進了顏色管理
    GDI+ 不僅提供了更多可供選擇使用的顏色,使其支持 Alpha 通道合成運算,而且還保持了與其他顏色的兼容性。
  • 繪圖支持反鋸齒
    通過設置 GDI+ 對象的相關屬性,GDI+ 可以與相關的顯示驅動程序搭配完成圖形繪制時的反鋸齒功能,使得繪制的圖形更加平滑、美觀,而整個過程是由 GDI+ 對象自動計算完成的。
  • 提供漸變畫刷
    GDI+ 拓展了 GDI 的功能,提供線性漸變和路徑漸變畫刷來填充圖形、路徑和區域,甚至也可用來繪制直線、曲線等。
  • 獨立的路徑對象
    GDI+ 使用 Graphics 對象來進行繪圖操作,并將路徑操作從 Graphics 對象分離出來,提供一個 Graphics 類供用戶使用,用戶不必擔心對象會受到 Graphics 對象操作的影響,從而可以使用同一個操作對象進行多次的路徑繪制操作。
  • 樣條曲線
    GDI+ 封裝了繪制基數樣條曲線和貝塞爾樣條曲線的方法。
  • 變形和矩陣運算
    GDI+ 提供了功能強大的 Matrix 類來實現矩陣的旋轉,錯切、平移、比例等變換操作,以便產生復雜的新圖形。
  • 多圖片格式的支持
    GDI+ 改進了圖形處理能力,通過 GDI+,用戶能夠訪問多種格式的圖片文件,轉換文件格式等,還能進行圖像重新著色、色彩修正、消除走樣等圖像處理。

Direct2D

Direct2D 是一個基于 Direct3D 的 2D 圖形 API,可以利用硬件加速特性來提供高性能、高質量的 2D 渲染。而且十分方便的是,Direct2D 與 GDI,GDI+ 和 D3D 都是可以交互的。一項技術總是有其受眾面,看看微軟怎么說的:

  • 大型企業級本機應用程序開發人員。
  • 創建供下游開發人員使用的控件工具包和庫的開發人員。
  • 需要對二維圖形進行服務器端呈現的開發人員。
  • 使用 Direct3D 圖形,并且需要在菜單、用戶界面 (UI) 元素和抬頭顯示器 (HUD) 中使用高性能的簡單二維和文本呈現的開發人員。

    在 Direct2D 架構的右下方,有一個軟件光柵化(software rasterizer),假如顯卡不支持硬件加速,那么 Direct2D 可以使用軟件方式渲染,即便是這樣,其效果還是要優于 GDI。

視覺效果

使用 Direct2D 渲染出來的效果要比 GDI 要好的多。因為 Direct2D 使用基于圖元的反鋸齒效果(這樣會使線條更加的平滑),而且在渲染二維圖元的時候,完全支持透明和 Alpha 混合。以下是對比的照片:

顯然,右邊的 Direct2D 的線條效果要好于左邊的 GDI。

demo

  • GDI
    正弦曲線
  • GDI+
    漸變色,Alpha混合
  • D2D
    螺旋路徑動畫

GDI 繪圖代碼:

void CChildView::_drawWithGDI( CPaintDC& dc ) {CRect rect;GetClientRect(&rect);// 繪制 titledc.TextOut(10, 10, _T("GDI"), 3);//邏輯坐標與設備坐標變換dc.SetMapMode(MM_ANISOTROPIC);dc.SetWindowOrg(0, 0);dc.SetWindowExt(rect.right, rect.bottom);dc.SetViewportOrg(0, rect.bottom / 2);dc.SetViewportExt(rect.right, - rect.bottom);//創建繪制 x 軸的 pen 并將其選入設備上下文CPen penx(PS_SOLID, 1, RGB(0, 0, 255));HGDIOBJ oldObject = dc.SelectObject(penx.GetSafeHandle());//繪制 x 軸dc.MoveTo(0, 0);dc.LineTo(rect.right, 0);//創建繪制正旋曲線的 pen 并將其選入設備上下文CPen pen(PS_SOLID, 1, RGB(255, 0, 0));dc.SelectObject(pen.GetSafeHandle());//繪制正弦曲線dc.MoveTo(0, 0);for (int i = 0; i < rect.right; i++)dc.LineTo(i, (int)(100 * sin(2 *(i / (rect.right / 5.0)) * M_PI)));//恢復原先的 pendc.SelectObject(oldObject);// 恢復邏輯坐標與設備坐標變換dc.SetViewportOrg(0, 0);dc.SetViewportExt(rect.right, rect.bottom); }

GDI+ 繪圖代碼:

void CChildView::_drawWithGDIPlus( CPaintDC& dc ) {using namespace Gdiplus;CRect rect;GetClientRect(&rect);Graphics graphics(dc);//創建漸變畫刷LinearGradientBrush lgb(Point(0, 0), Point(rect.right, rect.bottom), Color::Blue, Color::Purple);graphics.FillRectangle(&lgb, 0, 0, rect.right, rect.bottom);//創建ColorMatrixColorMatrix ClrMatrix ={1.0f, 0.0f, 0.0f, 0.0f, 0.0f,0.0f, 1.0f, 0.0f, 0.0f, 0.0f,0.0f, 0.0f, 1.0f, 0.0f, 0.0f,0.0f, 0.0f, 0.0f, 0.5f, 0.0f,0.0f, 0.0f, 0.0f, 0.0f, 1.0f};//將 ColorMatrix 賦給 ImageAttributesImageAttributes ImgAttr;ImgAttr.SetColorMatrix(&ClrMatrix, ColorMatrixFlagsDefault,ColorAdjustTypeBitmap);FontFamily fontFamily1(_T("Calibri"));Font font1(&fontFamily1, 12, FontStyleRegular, UnitPoint);//Alpha 混合graphics.DrawString(_T("LENA"), 4, &font1, PointF(140.0f, 140.0f), &SolidBrush(Color::White));TCHAR szImgPath[MAX_PATH] = {0};//確保程序所在目錄下存在 lena.png (res 文件夾下有)PathHelper::makeFullPathWithModuleDir(szImgPath, MAX_PATH, _T("lena.png"));Image img(szImgPath);graphics.DrawImage(&img, RectF(60, 140, 200, 200), 0, 0, (REAL)img.GetWidth(), (REAL)img.GetHeight(), UnitPixel, &ImgAttr);// 繪制 titlegraphics.DrawString(_T("GDI+"), 4, &font1, PointF(10.0f, 10.0f), &SolidBrush(Color::White)); }

Direct2D 繪制代碼(部分):

HRESULT D2DImpl::render(HWND hwnd) {using namespace D2D1;HRESULT hr;hr = createDeviceResources(hwnd);RETURN_IF_FAILED(hr);int wndState = m_pRenderTarget->CheckWindowState();RETURN_IF_TRUE(wndState & D2D1_WINDOW_STATE_OCCLUDED, E_FAIL);D2D1_SIZE_F rtSize = m_pRenderTarget->GetSize();// Prepare to draw.m_pRenderTarget->BeginDraw();// Reset to identity transformm_pRenderTarget->SetTransform(Matrix3x2F::Identity());m_pRenderTarget->Clear(ColorF(ColorF::Black));TCHAR szTitle[] = _T("Direct2D");m_pRenderTarget->DrawText(szTitle,_tcslen(szTitle),m_pTextFormat,D2D1::RectF(10, 10, rtSize.width, rtSize.height),m_pTextBrush);//center the pathfloat minWidthHeightScale = min(rtSize.width, rtSize.height) / 512;Matrix3x2F scale = Matrix3x2F::Scale(minWidthHeightScale, minWidthHeightScale);Matrix3x2F translation = Matrix3x2F::Translation(rtSize.width / 2, rtSize.height / 2);m_pRenderTarget->SetTransform(scale * translation);//draw the path in redm_pRenderTarget->DrawGeometry(m_pPathGeometry, m_pRedBrush);static float float_time = 0.0f;float length = m_animation.GetValue(float_time);D2D1_POINT_2F point;D2D1_POINT_2F tangent;// Ask the geometry to give us the point that corresponds with the length at the current time.hr = m_pPathGeometry->ComputePointAtLength(length, NULL, &point, &tangent);// Reorient the triangle so that it follows the direction of the path.D2D1_MATRIX_3X2_F triangleMatrix = Matrix3x2F(tangent.x, tangent.y,-tangent.y, tangent.x,point.x, point.y );m_pRenderTarget->SetTransform(triangleMatrix * scale * translation);// Draw the yellow triangle.m_pRenderTarget->FillGeometry(m_pObjectGeometry, m_pYellowBrush);// Commit the drawing operations.hr = m_pRenderTarget->EndDraw();if (hr == D2DERR_RECREATE_TARGET) {hr = S_OK;discardDeviceResources();}// When we reach the end of the animation, loop back to the beginning.if (float_time >= m_animation.GetDuration())float_time = 0.0f;elsefloat_time += (float)(m_dwmTiming.rateCompose.uiDenominator) / (m_dwmTiming.rateCompose.uiNumerator);InvalidateRect(hwnd, NULL, FALSE);return hr; }


EOF

總結

以上是生活随笔為你收集整理的Windows 2D 绘图 (GDI, GDI+, Direct2D)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。