網站首頁 編程語言 正文
三元光柵操作
根據在網上的搜索總結得到兩種方案,最常見的繪制帶有透明背景的圖像的方案都是采用如下的源圖像和掩碼圖像疊加來消去邊緣部分:
IMAGE img[2]; loadimage(&img[0], "sun1.png", 100, 100); // 掩碼圖像 loadimage(&img[1], "sun0.png", 100, 100); // 源圖像 putimage(0, 0, &img[0], NOTSRCERASE); // 掩碼圖與背景或取反 putimage(0, 0, &img[1], SRCINVERT); // 源圖像與背景異或
直觀理解:由于按位運算是依次對某一位做運算,因此只需要考察一位數字的變化
// 不妨假設白色為 1,黑色為 0 // 需要變成透明的部分,需要顯示最初的背景色 // 背景色為 a,~a 表示反 a,掩碼此部分是黑色 0,源圖像此部分是白色 1 ~ (a | 0); //-> ~a 或取反 (~a) ^ 1; //-> a 異或 // 結果仍為背景色 // 需要顯示源圖像的部分 // 背景色為 a,源圖像此部分為 b,掩碼此部分是白色 1 ~ (a | 1); //-> 0 或取反(可以看到第一部分與 a 無關) 0 ^ b; //-> b 異或 // 結果為源圖像
然而,上面的方案雖然足夠解決問題,但是未免太過繁瑣,不僅需要源圖像,還需要花時間來制作掩碼圖。最糟糕的就是技術問題導致掩碼圖和原圖不能完全重合,繪制出的圖像有黑邊。
于是,經過長期搜索,終于找到一種不需要掩碼圖,而是直接對圖像進行處理的方案。
優化方案
此方案使用了貝葉斯定理來對圖像的每個像素進行計算,原版代碼的具體來源因為時間比較久,已經找不到了。這里的方案和原版本有所不同,因為實際需求,我根據原版本添加了透明度參數 AA ,并且修改了部分代碼使得它與我的需求相契合。
函數聲明為:
void drawAlpha( IMAGE* image, // 圖像指針 int x, int y, // 輸出坐標 int width, int height, // 輸出尺寸 int pic_x, int pic_y, // 圖像中的位置 double AA = 1 // 透明度 );
也就是說它會在?x,y
?位置輸出從圖像中?pic_x,pic_y
?位置開始,寬高為?width,height
?的部分,且透明度為?AA
?。
函數定義部分:
// 繪圖函數,補充透明度 AA void drawAlpha(IMAGE* image, int x, int y, int width, int height, int pic_x, int pic_y, double AA = 1) { // 變量初始化 DWORD* dst = GetImageBuffer(); // GetImageBuffer() 函數,用于獲取繪圖設備的顯存指針, EasyX 自帶 DWORD* draw = GetImageBuffer(); DWORD* src = GetImageBuffer(image); // 獲取 picture 的顯存指針 int imageWidth = image->getwidth(); // 獲取圖片寬度 int imageHeight = image->getheight(); // 獲取圖片寬度 int dstX = 0; // 在 繪圖區域 顯存里像素的角標 int srcX = 0; // 在 image 顯存里像素的角標 // 實現透明貼圖 公式: Cp=αp*FP+(1-αp)*BP , 貝葉斯定理來進行點顏色的概率計算 for (int iy = 0; iy < height; iy++) { for (int ix = 0; ix < width; ix++) { // 防止越界 if (ix + pic_x >= 0 && ix + pic_x < imageWidth && iy + pic_y >= 0 && iy + pic_y < imageHeight && ix + x >= 0 && ix + x < WindowWidth && iy + y >= 0 && iy + y < WindowHeight) { // 獲取像素角標 int srcX = (ix + pic_x) + (iy + pic_y) * imageWidth; dstX = (ix + x) + (iy + y) * WindowWidth; int sa = ((src[srcX] & 0xff000000) >> 24) * AA; // 0xAArrggbb; AA 是透明度 int sr = ((src[srcX] & 0xff0000) >> 16); // 獲取 RGB 里的 R int sg = ((src[srcX] & 0xff00) >> 8); // G int sb = src[srcX] & 0xff; // B // 設置對應的繪圖區域像素信息 int dr = ((dst[dstX] & 0xff0000) >> 16); int dg = ((dst[dstX] & 0xff00) >> 8); int db = dst[dstX] & 0xff; draw[dstX] = ((sr * sa / 255 + dr * (255 - sa) / 255) << 16) //公式: Cp=αp*FP+(1-αp)*BP ; αp=sa/255 , FP=sr , BP=dr | ((sg * sa / 255 + dg * (255 - sa) / 255) << 8) //αp=sa/255 , FP=sg , BP=dg | (sb * sa / 255 + db * (255 - sa) / 255); //αp=sa/255 , FP=sb , BP=db } } } }
注意其中 WindowWidth 和 WindowHeight 都是預先定義的全局變量。實際應用時,先在頭文件中定義窗口尺寸,然后就可以直接使用
IMAGE img; loadimage(&img, "sun.png", 100, 100); int x = 100, y = 100; int width = 50, height = 50; int pic_x = 50, pic_y = 50; drawAlpha(img, x, y, width, height, pic_x, pic_y, 0.8);
還可以調整透明度為 0.8 ,比方案 1 更為實用。
原文鏈接:https://www.cnblogs.com/Bluemultipl/p/15947876.html
相關推薦
- 2022-09-30 C#?wpf?Bitmap轉換成WriteableBitmap的方法_C#教程
- 2022-07-21 Pandas常用數據結構
- 2022-01-22 linux系統raid0測試實驗
- 2022-09-05 C語言深入淺出分析函數指針_C 語言
- 2022-08-29 Python基礎語法之變量與數據類型詳解_python
- 2022-07-08 C語言算法學習之雙向鏈表詳解_C 語言
- 2022-03-15 使用Sqlyog遠程連接數據庫報錯解決方案_數據庫其它
- 2022-05-10 原生ajax 斷網和請求超時
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支