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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ 使用 Skia 绘图(已停更)

發(fā)布時間:2024/3/24 c/c++ 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 使用 Skia 绘图(已停更) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

注意:因篇幅問題,該文已停更,作者將重新劃分章節(jié)以便持續(xù)更新!本文將會被刪除!

索引

Skia API C++ 文檔(非官方)

  • 前言

  • Skia 準備

  • 項目實踐——Hello World(使用Skia繪制并輸出為PNG圖片)

  • Skia 繪制流程(對Skia的繪制流程進行闡述)

  • 項目實踐——繪制圖形(使用Skia繪制平面圖形并輸出為PNG圖片)

前言

筆者曾經(jīng)編譯過一款使用了Skia的軟件,于是查詢了一些資料,了解到Skia是一個2D向量圖形處理函數(shù)庫。只是可惜,筆者嘗試用它寫程序,但是官方文檔國內(nèi)無法訪問,網(wǎng)上資料極少,并且歷史悠久,不適合新版。于是筆者在自己查閱大量文章慢慢摸索,一點一點地完成這篇文章,為他人提供資料

Skia 準備

  • 下載Skia,國內(nèi)skia編譯門檻搞,所以此處直接使用Jetbrain在GitHub上的庫(本文使用m93)

    Releases · JetBrains/skia-build (github.com)

  • 分別下載Debug和Release兩個版本,放至一個目錄下(建議目錄)

    Skia | Debug | | Debug壓縮包解壓 | Release | | Release壓縮包解壓
  • 項目實踐——【Hello World】

  • 創(chuàng)建項目并設(shè)置項目屬性

    創(chuàng)建控制臺項目,建議使用預(yù)編譯頭。此處開始筆者將指引您如何配置項目屬性。首先,右鍵單擊項目→屬性(Properties)→C/C++→常規(guī)(General)→附加包含目錄(Additional Include Directories),按照上一步建議的目錄,分別對應(yīng)Debug和Release填入。

    注意:Debug和Release一定要區(qū)分

  • 鏈接靜態(tài)庫

    因為是初學(xué),暫時只用得到skia.lib

    同樣的,右鍵單擊項目→屬性(Properties)→鏈接器(Linker)→常規(guī)(General)→附加庫目錄(Additional Library Directories),將Debug和Release中靜態(tài)庫的目錄分別對應(yīng)輸入。

    執(zhí)行完上述步驟,再轉(zhuǎn)到鏈接器(Linker)→輸入(Input)→附加依賴項(Additional Dependencies)

  • 引入頭文件

    我們已經(jīng)配置好了Debug和Release環(huán)境,但是實際還需要一些東西。

    在預(yù)編譯頭末尾添加以下代碼:

    // Skia Dependencies #include <d3d12.h> #pragma comment(lib, "D3D12.lib") #include <d3dcompiler.h> #pragma comment(lib, "d3dcompiler.lib") #pragma comment(lib, "Opengl32.lib") #ifdef _DEBUG #include <dxgi1_3.h> #pragma comment(lib, "DXGI.lib") #endif // _DEBUG

    解釋一下,這些東西是Skia的依賴項,所以一定要加上,因為有用到DXGIGetDebugInterface1(具體是什么我也不知道)但這是DXGI.lib的一個函數(shù),并且Debug環(huán)境下不可缺少,所以用預(yù)編譯命令設(shè)置在Debug模式下鏈接DXGI.lib。這樣就可以通過編譯。

    注意:如果要引用Skia的頭文件,須在上述代碼片段前引入;如果預(yù)編譯頭文件中有Windows.h,請將其移至上述代碼后,否則會出現(xiàn)大量錯誤

  • 編寫代碼

    預(yù)編譯頭(筆者是pch.h文件)

    // pch.h: This is a precompiled header file. // Files listed below are compiled only once, improving build performance for future builds. // This also affects IntelliSense performance, including code completion and many code browsing features. // However, files listed here are ALL re-compiled if any one of them is updated between builds. // Do not add files here that you will be updating frequently as this negates the performance advantage.#ifndef PCH_H #define PCH_H// add headers that you want to pre-compile here#endif //PCH_H// Skia #include <include/core/SkCanvas.h> #include <include/core/SkPaint.h> #include <include/core/SkPath.h> #include <include/core/SkShader.h> #include <src/utils/SkShaderUtils.h> #include <include/core/SkTypeface.h> #include <include/core/SkTypes.h> #include <include/core/SkFont.h> #include <include/core/SkFontStyle.h> #include <include/core/SkFontTypes.h> #include <include/core/SkSurface.h> #include <include/codec/SkCodec.h> #include <include/core/SkPngChunkReader.h> #include <src/core/SkShaderCodeDictionary.h> #include <src/core/SkBitmapDevice.h>// Skia Depency #include <d3d12.h> #pragma comment(lib, "D3D12.lib") #include <d3dcompiler.h> #pragma comment(lib, "d3dcompiler.lib") //#include <wingdi.h> #pragma comment(lib, "Opengl32.lib") #ifdef _DEBUG #include <dxgi1_3.h> #pragma comment(lib, "DXGI.lib") #endif // _DEBUG#include <Windows.h>

    主程序代碼(main.cpp)

    #include "pch.h" #include <iostream>int main() {SkBitmap bitmap; //創(chuàng)建一個位圖設(shè)備SkImageInfo imageInfo = SkImageInfo::Make(480, 320, kBGRA_8888_SkColorType, kPremul_SkAlphaType); //設(shè)置位圖信息bitmap.allocPixels(imageInfo, imageInfo.minRowBytes()); //為位圖設(shè)備綁定信息和分配內(nèi)存SkCanvas canvas(bitmap); //創(chuàng)建畫布SkPaint paint; //創(chuàng)建畫筆canvas.clear(0x00000000); //將畫布清空并填充一種顏色,此處為黑色透明paint.setColor(SK_ColorBLACK); //設(shè)置畫筆顏色SkFont font; //創(chuàng)建字體設(shè)備font.setSize(64); //設(shè)置字體尺寸font.setTypeface(SkTypeface::MakeFromName("Microsoft YaHei", SkFontStyle::Normal())); //設(shè)置字體canvas.drawSimpleText("Hello World", sizeof("Hello World") - 1, SkTextEncoding::kUTF8, 0, 64, font, paint); //在畫布上繪制字體SkFILEWStream stream("D:\\test.png"); //創(chuàng)建文件輸出流SkEncodeImage(&stream, bitmap, SkEncodedImageFormat::kPNG, 100); //將位圖數(shù)據(jù)按照指定格式編碼并輸出到文件中return 0; }

    編譯運行,此時,代碼中對應(yīng)目錄下會出現(xiàn)一張圖片,上面有Hello World。至此,我們已經(jīng)完成了Skia的Hello World項目。

    思路很簡單,首先創(chuàng)建一個SkBitmap位圖設(shè)備,再創(chuàng)建一個SkImageInfo并填充圖片信息,然后與位圖設(shè)備綁定并為其分配內(nèi)存。

    接著創(chuàng)建一個與之關(guān)聯(lián)的畫布SkCanvas,并對畫布進行初始化(即清空畫布并填充顏色,注意這并非是必須的步驟,若忽略此步,將默認為透明背景)。

    創(chuàng)建一個SkPaint畫筆并設(shè)置顏色,再創(chuàng)建一個SkRect矩陣填充信息,畫筆用于控制繪制文本的顏色,矩陣用于控制文本所在的空間位置。

    接著創(chuàng)建一個SkFont字體對象,設(shè)置字體與樣式,最后調(diào)用SkCanvas類中的drawSimpleText方法完成繪制。

    最后用SkEncodeImage函數(shù)按照PNG格式對位圖設(shè)備中的圖像數(shù)據(jù)編碼并輸出到SkFILEWStream文件輸出流中。

  • 代碼后的有關(guān)注釋如有錯誤,請一定提出,筆者一定嚴加改正,萬分感激!

    注意!該代碼筆者測試時中文字符將不會顯示或顯示為方框,原因未知,測試時請盡量使用英文字符!如有朋友了解其原因,可向筆者發(fā)送私信,亦可評論區(qū)告知,筆者必將認真閱讀!Skia作為一個工具,國內(nèi)有關(guān)其的文檔屈指可數(shù),大部分為老舊版本,難以與現(xiàn)今易得版本適配,為了補充這方面的空白,筆者誠心希望廣大朋友共同努力!!!

    另外,關(guān)于代碼中所用的類與方法等信息,為方便大家學(xué)習(xí),筆者打算另開一條博文專門介紹。
    API 文檔

    Skia 繪制流程

    本節(jié)我們將一起理清上述代碼的繪制思路。

    在繪制前,我們有一下幾個問題:

  • 在哪里進行繪制?
  • 如何進行繪制?
  • 繪制完如何保存?
  • 圍繞這三個問題,我們逐一解決。

    首先是在哪里進行繪制?我們知道,要想進行繪制,就需要一個載體來存儲圖像數(shù)據(jù)。因此,我們需要一塊內(nèi)存,而為了方便對這塊內(nèi)存的管理,Skia為我們準備好了這樣一個設(shè)備——SkBitmap。這樣一個類,完美解決了我們的需求。接下來便是進行繪制。

    那如何進行繪制?我們可以類比畫油畫,SkBitmap相當(dāng)于配好了畫板。但我們并不知道我們需要畫多大,多寬,這是我們就需要為畫板固定好一張白紙用于承載我們的筆跡,這就相當(dāng)于讓SkBitmap分配一塊指定大小的內(nèi)存。同時,我們不光還要知道內(nèi)存有多大,還需要知道用的是什么樣的顏色空間等等。于是,我們選擇使用Skia為我們準備好的另一個設(shè)備——SkImageInfo,這個設(shè)備包含了關(guān)于“白紙”的長寬,顏色標準等。接下來就是讓SkBitmap按照這些信息分配內(nèi)存。

    再接下來

    項目實踐——繪制圖形

    繪制完歷史性的“Hello World”,想必讀者已經(jīng)迫不及待地渴望用Skia繪制圖形了。別急,本節(jié)我們將介紹使用Skia繪制基本圖形。

    代碼如下,預(yù)編譯頭等不用修改,再次只貼出main()的代碼:

    int main() {SkBitmap bitmap;SkImageInfo imageInfo = SkImageInfo::Make(500, 400, kBGRA_8888_SkColorType, kPremul_SkAlphaType);bitmap.allocPixels(imageInfo, imageInfo.minRowBytes());SkCanvas canvas(bitmap);SkPaint paint;canvas.clear(0xFFFFFFFF);paint.setColor(SK_ColorRED);SkPoint point; //創(chuàng)建一個點,并設(shè)置坐標point.fX = 50;point.fY = 50;canvas.drawCircle(point, (SkScalar)50, paint); //以上方創(chuàng)建的點為圓心繪制圓半徑為50pxpaint.setColor(SK_ColorBLUE);SkRect rect; //創(chuàng)建矩陣信息rect.fLeft = 100;rect.fRight = 250;rect.fTop = 0;rect.fBottom = 100;canvas.drawRect(rect, paint);paint.setColor(SK_ColorCYAN); //設(shè)置畫筆顏色rect.fLeft = 250; //重新填充矩陣信息rect.fRight = 500;rect.fTop = 0;rect.fBottom = 100;canvas.drawOval(rect, paint); //以新的矩陣信息,在其中繪制橢圓paint.setColor(SK_ColorGRAY); //設(shè)置畫筆顏色rect.fLeft = 0;rect.fRight = 250;rect.fTop = 100;rect.fBottom = 200;canvas.drawRoundRect(rect, (SkScalar)10, (SkScalar)10, paint); //以新的矩陣信息,按照10px的半長軸和10px的半短軸繪制圓角矩形(因為半長軸半短軸相等所描述的是一個圓,但其本質(zhì)描述的是橢圓,因此會有兩個參數(shù)用于確定圓角程度)SkFILEWStream stream("D:\\test.png");SkEncodeImage(&stream, bitmap, SkEncodedImageFormat::kPNG, 100);return 0; }

    思路和上一個項目很像,便不過多贅述。這里總結(jié)一下SkCanvas中的幾個繪制圖形的方法:

    drawCircle:繪制圓
    drawRect:繪制矩形
    drawOval:繪制橢圓
    drawRoundRect:繪制圓角矩形

    項目實踐——繪制中文字符

    想必各位讀者在嘗試《項目實踐——【Hello World】》的時候,一定視圖講"Hello World"替換為其他字符,但是或許有的讀者視圖利用Skia繪制出中文字符,而最后的結(jié)果可能是中文字符變成方框、中文字符變成別的亂七八糟的字符或者含有中文字符而導(dǎo)致整個字符串繪制不出來。這些問題筆者都經(jīng)常遇到過。所以本節(jié)我們將重點介紹利用Skia繪制中文字符。

    【停更】

    總結(jié)

    以上是生活随笔為你收集整理的C++ 使用 Skia 绘图(已停更)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。