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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Direct2D教程(九)渲染位图

發布時間:2025/5/22 编程问答 85 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Direct2D教程(九)渲染位图 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

概述

這篇的標題更確切的說應該叫位圖畫刷,這樣才好和前幾篇對應起來。在Direct2D中,位圖的渲染也是通過畫刷來實現的。

Direct2D中并沒有直接操作位圖的接口,而是借助WIC(Windows Image Component)來完成的。今天我們來看看如何在Direct2D中加載并顯示位圖。這個方法可以用來渲染背景。基本步驟如下。

  • 從文件創建WIC位圖
  • 由WIC位圖創建D2D位圖
  • 使用D2D繪制位圖

在開始之前,首先簡要介紹一下WIC

什么是WIC?

WIC全稱是Windows Image Component,是一套擴展的API,用來處理數字圖像,它是基于COM組件的。該API包含非常豐富的圖像處理函數,比如

  • 內置對于標準web image格式的解碼支持
  • 內置對于標準metadata格式的支持
  • 廣泛的像素格式支持
  • 高色度支持,包含30位擴展,30位及48位高精度像素格式
  • 對于圖像解碼,像素格式及元數據格式的擴展框架支持

WIC包含的組件及每個組件中的接口如下圖所示。

在這里,我們只要知道WIC能夠處理圖像即可,比如位圖操作。關于WIC的詳細信息,大家可以看看MSDN的介紹。

具體步驟

從文件創建WIC位圖

給定一個圖像文件,我們首先使用WIC函數將其讀入內存,并創建一個WIC類型的位圖。

首先我們需要創建一個解碼器,因為圖片是經過編碼的,為了能顯示圖片,我們首先需要將其解碼,創建解碼器需要使用函數CreateDecoderFromFilename,該函數返回一個解碼器指針。稍后的操作都通過這個指針來完成,關于這個函數的詳細介紹,可以參考MSDN,這里不再贅述。

然后,利用創建好的解碼器來獲取圖片的幀,我么這里只要第一幀,因為圖片只有一幀,但是對于視頻文件來說,就有許多幀了。代碼如下:在這里,uri即圖片文件名。

HRESULT LoadBitmapFromFile(ID2D1RenderTarget *pRenderTarget,IWICImagingFactory *pIWICFactory,PCWSTR uri,UINT destinationWidth,UINT destinationHeight,ID2D1Bitmap **ppBitmap) {HRESULT hr = S_OK;IWICBitmapDecoder *pDecoder = NULL;IWICBitmapFrameDecode *pSource = NULL;IWICStream *pStream = NULL;IWICFormatConverter *pConverter = NULL;IWICBitmapScaler *pScaler = NULL;hr = pIWICFactory->CreateDecoderFromFilename(uri,NULL,GENERIC_READ,WICDecodeMetadataCacheOnLoad,&pDecoder);if (SUCCEEDED(hr)){// Create the initial frame.hr = pDecoder->GetFrame(0, &pSource);}

然后創建converter,負責對位圖進行后續的格式轉換。

if (SUCCEEDED(hr)) {hr = pIWICFactory->CreateFormatConverter(&pConverter); }

接下來則要判斷圖像是否被放大或者縮小了,比如一個圖片的原始尺寸是100 x 100,但是我們程序中要以 200 x 200的方式去顯示,那么相當于將圖片放大了一倍,圖片的顯示尺寸通過參數來指定,而實際尺寸則是通過分析圖片文件得到。如果圖片有縮放,那么需要從新生成圖片的數據文件,如果沒有,那么直接進行下一步即可。代碼如下:

// If a new width or height was specified, create an // IWICBitmapScaler and use it to resize the image. if (destinationWidth != 0 || destinationHeight != 0) {UINT originalWidth, originalHeight;hr = pSource->GetSize(&originalWidth, &originalHeight);if (SUCCEEDED(hr)){if (destinationWidth == 0){FLOAT scalar = static_cast<FLOAT>(destinationHeight) / static_cast<FLOAT>(originalHeight);destinationWidth = static_cast<UINT>(scalar * static_cast<FLOAT>(originalWidth));}else if (destinationHeight == 0){FLOAT scalar = static_cast<FLOAT>(destinationWidth) / static_cast<FLOAT>(originalWidth);destinationHeight = static_cast<UINT>(scalar * static_cast<FLOAT>(originalHeight));}hr = pIWICFactory->CreateBitmapScaler(&pScaler);if (SUCCEEDED(hr)){hr = pScaler->Initialize(pSource,destinationWidth,destinationHeight,WICBitmapInterpolationModeCubic);}if (SUCCEEDED(hr)){hr = pConverter->Initialize(pScaler,GUID_WICPixelFormat32bppPBGRA,WICBitmapDitherTypeNone,NULL,0.f,WICBitmapPaletteTypeMedianCut);}} }

由WIC位圖創建D2D位圖

調用函數CreateBitmapFromWicBitmap可以由一個WIC位圖創建一個D2D位圖,代碼如下:

if (SUCCEEDED(hr)) {// Create a Direct2D bitmap from the WIC bitmap.hr = pRenderTarget->CreateBitmapFromWicBitmap(pConverter,NULL,ppBitmap); }

上面這些代碼有個特點,就是要時刻判斷前一次函數調用的返回值,只有前面的操作成功了,才進行下一步操作。這是很好的編程習慣。

最后,需要做一些清理工作,由于WIC是基于COM的,所以,需要手動釋放COM對象,代碼如下:

SAFE_RELEASE(pDecoder); SAFE_RELEASE(pSource); SAFE_RELEASE(pStream); SAFE_RELEASE(pConverter); SAFE_RELEASE(pScaler);

SAFE_RELEASE是一個宏定義

#define SAFE_RELEASE(P) if(P){P->Release() ; P = NULL ;}

使用D2D繪制位圖

這一步就很簡單了,繪制位圖和繪制其他幾何圖形幾乎沒有區別。首先是將render target清空為指定顏色,也就是背景色,然后調用render target的接口DrawBitmap來繪制位圖,這個函數需要指定位圖的尺寸,所以之前還需要獲取位圖的大小。注意繪制代碼要放在BeginDraw和EndDraw之間。

void DrawBitmap() {CreateD2DResource(g_Hwnd) ;pRenderTarget->BeginDraw() ;// Clear background color to dark cyanpRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));D2D1_SIZE_F size = pBitmap->GetSize() ;D2D1_POINT_2F upperLeftCorner = D2D1::Point2F(0.f, 0.f) ;// Draw bitmappRenderTarget->DrawBitmap(pBitmap,D2D1::RectF(upperLeftCorner.x,upperLeftCorner.y,upperLeftCorner.x + size.width,upperLeftCorner.y + size.height)) ;HRESULT hr = pRenderTarget->EndDraw() ;if (FAILED(hr)){MessageBox(NULL, "Draw failed!", "Error", 0) ;return ;} }

最后,來一張效果圖,這是微軟的游戲 4 Elements 2 的截圖,大家一同欣賞一下。這是我平生購買的第一款游戲,值得紀念一下。

總結

以上是生活随笔為你收集整理的Direct2D教程(九)渲染位图的全部內容,希望文章能夠幫你解決所遇到的問題。

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