SkSurface---像素的容器:表面

如果說?SkCanvas?是畫布,是所有繪圖操作的提供者的話,那么?SkSurface?就是畫布的容器,我們稱之為表面,它負責管理畫布對應的像素數據。這些像素數據可以是在內存中創建的,也可以是在 GPU 顯存中創建的。

創建一個空白表面

如何創建和使用 Skia 的?SkSurface?對象,如下代碼所示:

SkImageInfo imgInfo = SkImageInfo::MakeN32Premul(800, 600);
sk_sp<SkSurface> surface = SkSurfaces::Raster(imgInfo);

SkSurfaces::Raster?方法執行后,應用程序將在內存中分配指定數量的像素。

若需要使用?SkSurface?對象管理的像素,可以通過如下方法來完成工作:

SkPixmap pixmap;
surface->peekPixels(&pixmap);
auto addr = pixmap.addr();

pixmap.addr()?用于獲取像素數據的內存地址,一般情況下,開發者不會使用這個地址來改變具體的某個像素的值。

因為內存中存儲的像素數據是被格式化過的,并不是A,R,G,B顏色分量依次排列的數值。像素數據在內存中的排布方式與?SkSurface?的顏色空間有關。

通過如下代碼,你可以獲取某個具體位置的顏色:

SkColor color = pixmap.getColor(0, 0);  //畫布上位置 0,0 的顏色

根據現有像素數據創建表面

如果你已經擁有了像素數據,就可以直接基于你的像素數據創建?SkSurface?對象,如下代碼所示:

std::vector<SkColor> surfaceMemory;
surfaceMemory.resize(w * h);
SkImageInfo info = SkImageInfo::MakeN32Premul(w, h);
sk_sp<SkSurface> surface = SkSurfaces::WrapPixels(info, &surfaceMemory.front(), w * sizeof(SkColor));

上面代碼中使用?std::vector<SkColor>?來存儲像素數據。

每個像素就是一個?SkColor?類型的數據(SkColor就是?uint32_t?)。

像素容器的大小是?w * h,(二維數組的列數 w 和行數 h ,與窗口的寬和高相同)

SkSurfaces::WrapPixels?方法基于像素數據創建?SkSurface?對象。

其中?&surfaceMemory.front()?用于獲取容器內第一個像素的地址,

w * sizeof(SkColor)?是每行數據的大小。

同樣道理,如果你有一個?SkBitmap?對象,就可以根據這個對象的像素數據創建表面:

SkBitmap bitmap;
bitmap.allocN32Pixels(w, h);
sk_sp<SkSurface> surface = SkSurfaces::WrapPixels(bitmap.pixmap());

上述代碼使用?SkBitmap?對象的?allocN32Pixels?方法為此對象創建了指定大小的內存空間用于存儲像素數據。

SkBitmap?對象的?pixmap?方法負責獲取?SkBitmap?對象的像素數據的內存地址。

重置表面像素數據

如果你想批量把一個表面的像素數據全部設置為某個顏色值。

就可以用以下兩個辦法達到這個目的:

auto canvas = surface->getCanvas();
canvas->clear(0x66778899);  //方法1
canvas->drawColor(0x22FF8899); //方法2
SkPaint paintObj;
canvas->drawPaint(paintObj); //方法3

這都是通過畫布對象?SkCanvas?完成的。

也可以在源頭設置所有像素的值,如下代碼所示

std::vector<SkColor> surfaceMemory(w * h, 0xffff00); //初始化像素數組時,即設置好像素顏色surfaceMemory.resize(w * h,0xffff00); //更改像素容器大小時,重置整個容器的像素顏色

覆蓋表面像素數據

如果你已經有了一組像素數據,需要把這些像素寫入目標表面,可以通過如下方法完成:

void surfaceWritePixels(SkSurface *surface)
{std::vector<SkColor> srcMem(200 * 200, 0xff00ffff);SkBitmap dstBitmap;dstBitmap.setInfo(SkImageInfo::MakeN32Premul(200, 200));dstBitmap.setPixels(&srcMem.front());surface->writePixels(dstBitmap, 100, 100);
}

在這段代碼中,使用?SkBitmap?類型包裝了像素數據。

SkBitmap?對象的?setPixels?方法會把?srcMem?管理的像素地址拷貝到?SkBitmap?對象中(只復制了地址)

SkSurface?對象的?writePixels?方法會把?dstBitmap?對象管理的像素數據復制到自己管理的內存數據中。

復制是從?100,100?的位置開始的,由于?dstBitmap?只管理了?200×200?的像素數據,所以復制工作執行到坐標?300,300?就結束了。

程序運行的結果如下圖所示:

覆蓋表面像素.png

表面與畫布的互訪

通過?SkSurface?對象的?getCanvas?方法得到一個與此表面有關的畫布。

也可以通過?SkCanvas?對象的?getSurface?方法得到一個與此畫布有關的表面。

但需要注意的是,SkCanvas?對象的?getSurface?方法并不是總能得到與之對應的?SkSurface?對象。

比如:

auto canvas = SkCanvas::MakeRasterDirect(info, &surfaceMemory.front(), 4 * w);
auto surface = canvas->getSurface();

這個?canvas?對象是手動創建的,它不依賴任何surface,它的?getSurface?方法的返回值就是一個空指針。

雖然這個?canvas?沒有與之對應的?surface,可以通過如下方法創建一個:

SkImageInfo info = SkImageInfo::MakeN32Premul(w, h);
auto surface = canvas->makeSurface(info);

需要注意的是,這樣做會導致?canvas?對應的像素數據被復制到?surface?內(內存占用加倍)

所以要么先創建surface再通過surface得到canvas,要么僅使用canvas,不使用surface

盡量不要通過canvas去創建surface

當一個應用中存在多個surface的時候,往往需要合并這些surface

有很多辦法可以完成這項任務,其中之一就是把一個?surface?繪制到另一個?canvas?中,如下代碼所示:

surface->draw(canvas.get(), 0, 0);

這行代碼會把?surface?管理的像素數據,繪制到?canvas?畫布上(從坐標?0,0?位置開始繪制),這就達到了合并兩個?surface?的效果。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/93710.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/93710.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/93710.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

26.(vue3.x+vite)以pinia為中心的開發模板

效果截圖 代碼實現 HelloWorld.vue <template><div style="padding: 20px;">介紹:<br>1:使用class 來減少pinia(store)的代碼量<br>

華為AI Agent智能園藝助手開發案例

一、引言與行業背景 在數字化與智能化日益滲透我們生活的今天&#xff0c;園藝這一傳統而充滿生機的領域&#xff0c;也迎來了智能化的革新。華為AI Agent智能園藝助手通過融合人工智能與園藝專業知識&#xff0c;為用戶提供一站式、個性化的園藝養護解決方案&#xff0c;徹底改…

Linux Flathub軟件管理方法 使用指南

Flathub 使用指南&#xff1a;軟件安裝、管理及常用軟件推薦 一. 什么是 Flathub&#xff1f; Flathub 是 Flatpak 應用程序的主要分發中心&#xff0c;類似于 Linux 上的"應用商店"。它提供了一種跨發行版的軟件打包和分發方式&#xff0c;讓用戶可以在任何 Linux 發…

GitLab 18.2 發布幾十項與 DevSecOps 有關的功能,可升級體驗【二】

沿襲我們的月度發布傳統&#xff0c;極狐GitLab 發布了 18.2 版本&#xff0c;該版本帶來了議題和任務的自定義工作流狀態、新的合并請求主頁、新的群組概覽合規儀表盤、下載安全報告的 PDF 導出文件、中心化的安全策略管理&#xff08;Beta&#xff09;等幾十個重點功能的改進…

??免費語音轉換服務(TTS)全面指南

????1. TTS技術概述?? TTS&#xff08;Text-to-Speech&#xff09;通過AI將文字轉化為自然語音&#xff0c;核心技術包括??深度神經網絡&#xff08;DNN&#xff09;??、??語音韻律建模??和??聲學合成??。其核心優勢在于&#xff1a; ??多語言支持??&a…

正則化都是放在模型的哪個位置呢?

? 什么是“正則化”&#xff1f;在神經網絡中&#xff0c;正則化&#xff08;Regularization&#xff09; 抑制過擬合的技巧 目的是讓模型在訓練集和測試集上都表現得好&#xff08;泛化能力強&#xff09;。&#x1f9e0; 常見的正則化手段包括&#xff1a;方法類型通常放在哪…

Python畢業設計 | 基于協同過濾的智能商品推薦與數據大屏系統(Vue+Flask+Scikit-learn,附源碼+文檔)

個人介紹&#x1f3af; 畢業設計私人教練 專注計算機畢設輔導第 6 年&#xff0c;累計 1v1 帶飛 800 同學順利通關。從選題、開題、代碼、論文到答辯&#xff0c;一條龍陪跑&#xff1b;擅長把導師的 “模糊要求” 變成能落地的技術方案。白天寫方案&#xff0c;晚上改論文&…

基于千問2.5-VL-7B訓練識別人的表情

一、安裝LLaMA-Factory 我們使用LLaMA-Factory來進行微調&#xff0c;安裝LLaMA-Factory來參考文章&#xff1a; 大模型微調工具LLaMA-Factory的安裝流程-CSDN博客 二、下載千問2.5-VL-7B模型 我們使用千問2.5-VL-7B多模態模型來進行微調 通義千問2.5-VL-7B-Instruct 下載…

Android屏幕適配:從dp到px的轉換與今日頭條適配方案詳解

前言 在Android開發中&#xff0c;屏幕適配一直是一個重要且復雜的話題。不同設備有著不同的屏幕尺寸、分辨率和像素密度&#xff0c;如何讓應用在各種設備上都能良好顯示&#xff0c;是每個開發者都需要面對的問題。本文將深入探討Android系統中dp到px的轉換原理&#xff0c;并…

nvim 縮進4空格

要把 Neovim 配置為縮進 4 空格&#xff0c;并適用于所有語言&#xff08;或某些語言如 C/C&#xff09;&#xff0c;你只需要設置這三個核心選項即可&#xff1a;? 通用方式&#xff1a;在 init.lua 或 options.lua 中添加 vim.opt.tabstop 4 -- 一個 <Tab> 等…

pdw估計edw怎么估計

問題一、pdw估計edw怎么估計PDW&#xff08;Pulse Descriptor Word&#xff09;數據是雷達接收到的每一個脈沖的瞬時特征數據&#xff0c;EDW&#xff08;Emitter Descriptor Word&#xff09;是對某一輻射源&#xff08;發射機&#xff09;整體特性的估計。PDW 是每一個脈沖的…

TS語法最佳實踐

switch 的 case不能使用條件表達式JavaScript 允許在 switch 的 case 中使用條件表達式&#xff0c;但這種用法實際上是無效的&#xff0c;因為 case 的值會被隱式地轉換為布爾值。TypeScript 明確禁止這種用法&#xff0c;以避免隱式類型轉換導致的邏輯錯誤。建議使用 if-else…

行業熱點丨仿真歷史數據難以使用?如何利用幾何深度學習破局,加速汽車工程創新

01、AI 驅動研發升級&#xff1a;幾何深度學習創造行業新價值人工智能正加速推動各行業研發能力升級。麥肯錫最新報告顯示&#xff0c;該技術在制藥、化工和航空航天等領域的應用&#xff0c;有望為相關企業創造高達5600億美元的經濟價值。 AI 技術應用的先行者&#xff0c;全球…

JSBridge原理與實現全解析

JSBridge 是用于連接 JavaScript&#xff08;H5&#xff09; 和原生應用&#xff08;iOS/Android&#xff09;的橋梁&#xff0c;允許它們之間相互調用方法。 &#x1f309; 一、JSBridge 雙向通信流程圖 #mermaid-svg-AoDVdJL2VJBnTJ2Q {font-family:"trebuchet ms"…

Mockito:Java單元測試Mock框架

文章目錄一、寫在前面1、簡介2、依賴二、使用1、基本使用2、注解&#xff08;1&#xff09;開啟注解&#xff08;2&#xff09;Mock 注解&#xff08;3&#xff09;DoNotMock 注解&#xff08;4&#xff09;Spy 注解&#xff08;5&#xff09;Captor 注解&#xff08;6&#xf…

群暉Synology Drive:打造高效安全的私有云協作平臺

隨著企業與個人對數據協作、安全與自主性的需求不斷提升&#xff0c;群暉&#xff08;Synology&#xff09;推出的 Synology Drive 成為了私人云存儲與團隊協作的利器。下面將從功能亮點、使用方式、安全管理、適用場景等角度&#xff0c;為你全面解讀這款強大的私有云方案。Sy…

開發避坑短篇(11):Oracle DATE(7)到MySQL時間類型精度沖突解決方案

異常信息 [Err] [Dtf] 1426 - Too-big precision 7 specified for CREATE_TIME. Maximum is 6.異常背景 用Navicat的數據傳輸功能進行oracle的數據表遷移到到mysql時報錯。 異常分析 oracle的DATE類型的長度是7位&#xff0c;而mysql的datetime類型的長度最多6位&#xff0c;所…

怎么判斷一個DAPP是否真正去中心化

判斷一個DAPP&#xff08;去中心化應用&#xff09;是否真正去中心化&#xff0c;需要從多個維度進行考察。以下是關鍵評估標準&#xff1a;1. 區塊鏈依賴程度? 真正去中心化&#xff1a;核心邏輯和數據處理完全依賴智能合約&#xff0c;運行在區塊鏈上&#xff08;如以太坊、…

F12 開發者工具 使用指北

F12 開發者工具 使用指北元素 Elements控制臺 Console源代碼 Sources網絡 Network請求文件具體說明首先介紹Chrome開發者工具中&#xff0c;調試時使用最多的三個功能頁面是&#xff1a;元素&#xff08;ELements&#xff09;、控制臺&#xff08;Console&#xff09;、源代碼&…

AD域設計與管理-域策略-進階

AD域安全保密要求&#xff0c;也是最為常見的一些組策略配置需求 目錄 1.禁止U盤&#xff0c;DVD&#xff0c;軟盤等可移動存儲使用 2.禁止員工自行安裝軟件 3.硬盤全部采用bitlocker上鎖&#xff0c;密碼保存至AD域控 4.密碼復雜度要求 5.開啟windows防火墻且不允許員工…