午後わてんのブログ

ベランダ菜園とWindows用アプリ作成(WPFとC#)

画像にマウスカーソル画像を重ねて表示、アルファブレンドとビット演算のANDとXOR

前回でマウスカーソル画像を取得できたので、ウィンドウのキャプチャ画像に重ねてみた

f:id:gogowaten:20201122191848p:plain
普通の矢印カーソル
普通の矢印カーソルはアルファブレンド

f:id:gogowaten:20201122192505p:plain
テキストエディタとかでのI型カーソル
I型カーソルはマスク画像上半分をビット演算のANDしてから、下半分をXOR

普通の矢印カーソル

f:id:gogowaten:20201122235249p:plain
矢印カーソル
白と黒の2色だと思ってたけど違った
f:id:gogowaten:20201122235524p:plain
24色
数えたら24色もあった、一番多いのは完全透明色(アルファ値が0)で全体の86%、 他の色もほとんどが半透明で、アルファ値が255の不透明な色は少ない

アルファブレンド
画像を重ねたとき、完全透明色のところは下の画像の色をそのまま残せば良くて、不透明色のところはカーソルの色に置き換えればいい、それはわかるけどその他の半透明色のところは計算方法が思いつかなくて
半透明画像合成 計算
とかでググって

■CharatSoft.com
www.charatsoft.com こちらの左下のおとゲマZから
音ゲーをつくろ~ ♪(^^)♪
http://www.charatsoft.com/develop/otogema/ ここの5-5.効果に

確定色 = 背景色 + (重ねる色 - 背景色) * (アルファ値 / 255)

この計算式を使ったら期待通りの色になった。アルファブレンドって聞いたことはあったけど、半透明合成ってことだったのねえ

変数に入っている画像の閲覧と保存
gogowaten.hatenablog.com このときに作ったBitmapSourceVisualizerがようやく日の目を見た

f:id:gogowaten:20201123003216p:plain
カーソル画像が入っている変数から
デバッグ中に画像の入った変数から、画像の確認と保存もできる
f:id:gogowaten:20201123003353p:plain
BitmapSourceVisualizer
作っといてよかったわ(自画自賛)

マウスカーソル画像の半透明具合
f:id:gogowaten:20201123004338p:plain
拡大したマウスカーソル画像
拡大してみるとんなかんじで
半透明具合を見るためにエクセルのシート画像に重ねてみると
f:id:gogowaten:20201123004550p:plain
半透明具合
灰色に見えるところも、かなり透けているのがわかる

アルファ値

f:id:gogowaten:20201123005049p:plain
アルファ値
斜めに連なっている灰色部分の色はARGBの順に、55, 0, 4, 23でアルファ値は55だった、透=55がアルファ値
黒(0, 0, 0)の半透明かと思ってたけど、(0, 4, 23)だから色相で言ったら青だねえ


計算してみる

f:id:gogowaten:20201123011259p:plain
RGB(255, 0, 128)
マゼンタRGB(255, 0, 128)、これにARGB(55, 0, 4, 23)を重ねた場合

確定色 = 背景色 + (重ねる色 - 背景色) * (アルファ値 / 255)

さっきのこれを使って
R = 255 + (0 - 255) * (55 / 255) = 200
G = 0 + (4 - 0) * (55 / 255) = 0.8627451
B = 128 + (23 - 128) * (55 / 255) = 105.35294
小数点以下を四捨五入で
RGB(200, 1, 105)になった

実際に重ねてみる

f:id:gogowaten:20201123023422p:plain
重ねたところをキャプチャ


拡大して確認

f:id:gogowaten:20201123024340p:plain
拡大
さっきの計算結果と同じ!アルファブレンド



マスク画像を使うマウスカーソルの場合

f:id:gogowaten:20201122192505p:plain
マスク画像が必要なカーソル
マスク画像を使って描画する場合もあるみたいで、条件はマスク画像が白黒2値かつ、高さが幅の2倍のとき
C#-マウスカーソル画像のキャプチャ-スタックオーバーフロー
https://stackoverflow.com/questions/918990/c-sharp-capturing-the-mouse-cursor-image
ICONINFO (winuser.h) - Win32 apps | Microsoft Docs
https://docs.microsoft.com/ja-jp/windows/win32/api/winuser/ns-winuser-iconinfo
この辺をGoogle翻訳してみると、そんなかんじで、使い方は上半分とANDしたあとに、下半分をXOR…なんのことかよくわからん、けど.NETにはビット演算してくれる演算子があるから、それを使ってみたらできた
ANDは&
XORは^
変数 = 背景色 & 重ねる色
確定色 = 変数 ^ 重ねる色

f:id:gogowaten:20201123034132p:plain
紫の文字の上にカーソル
黒っぽく見える、拡大してみると

f:id:gogowaten:20201123034308p:plain
拡大
カーソルが重なったところは紫から緑になっている
RGBそれぞれを足してみると
167+88=255
70+185=255
255+0=255
全部255になるからビット演算を使わなくても、計算は(255-元の色)とかでもできそうねえ

ビット演算
167のRで見てみる
ANDするマスク画像の色は全部白で値は255
XORするマスク画像はカーソル部分だけが白(255)、それ以外は黒(0) 167 AND 255 = 167 これは
1010_0111 = 167
AND
1111_1111 = 255

1010_0111 = 167
つまり全く色変化しない

続けてXORでのカーソル部分だった場合、重ねる色は白(255)
167 XOR 255 = 88 これは
1010_0111 = 167
XOR
1111_1111 = 255

0101_1000 = 88
ってなるみたい、へー

もしカーソル部分じゃない部分の色、黒(0)を重ねると
167 XOR 0 = 167 これは
1010_0111 = 167
XOR
0000_0000 = 0

1010_0111 = 167
色変化しない

f:id:gogowaten:20201123041315p:plain
いろいろ保持用フィールド

f:id:gogowaten:20201123041631p:plain
カーソル情報取得
マウスクリックで実際にクリックされる座標がホットスポット。描画するときはこの値をオフセットするとピッタリの位置になる

f:id:gogowaten:20201123041945p:plain
カーソル画像描画
100行超える関数とか長すぎだと思うけど、こうなった。最初のifで半分づつにできるけど、どのみち汎用性皆無だからいいわ

f:id:gogowaten:20201123042924p:plain
ビット演算部分
準備が長いだけで計算部分はこれだけなんだよねえ

f:id:gogowaten:20201123043304p:plain
アルファブレンド部分
アルファブレンド部分、計算結果を(byte)でキャストしているから、小数点以下は切り捨てになっている?四捨五入のほうがいいかなあ

2020WPF/20201119_マウスカーソル描画

github.com

テストアプリダウンロード

https://github.com/gogowaten/2020WPF/releases/download/1.1/20201119_.7z

f:id:gogowaten:20201123045154p:plain
テストアプリ
右シフトキーでウィンドウキャプチャ
のはずなんだけど、これが効かないアプリがあって、タスクマネージャーとデスクトップ検索のEverythingで、これが訊いてくれない



関連記事
前回は3日前

gogowaten.hatenablog.com