午後わてんのブログ

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

四角形の2色グラデーションが正確になったPixtack紫陽花

四角形の2色グラデーションを正確にした
LinearGradientBrushを使やめた
ガンマ補正が無効になった
四角形の作成で単色塗りの時の不透明度が反映されていなかったのを修正

f:id:gogowaten:20191014115542p:plain

↑前回、↓今回

f:id:gogowaten:20191014115557p:plain

10x10の赤から黒への横グラデーションを拡大、数値は赤要素
 
 
 

f:id:gogowaten:20191014115620p:plain

縦と斜めも設定した期待通り正確になった
 
イメージ 4
イメージ 5
赤の不透明度を255、黒の不透明度を128
これも今回の方であっていると思う
 
今まではVisualBasic2010Expressに最初から用意されている
LinearGradientBrushっていうグラデーション用の色を塗るブラシを使っていたけど
反対側の色が出たり指定した色にならなかった
 
一つ一つのピクセルの色の指定はできるから
グラデーションになるような色の指定の仕方がわかればなんとかなりそう
ってことでグラデーションの色の変化を調べてみた

f:id:gogowaten:20191014115642p:plain

微妙なオレンジと青緑でLinearGradientBrushを使って作成
拡大してr赤、g緑、b青の変化をみると
2色の赤同士、緑同士、青同士だけが関係しているみたい
オレンジのrが255で青緑のrが0なら
オレンジから見たら右へ行くごとに減っていって最後は0になるはず
b青は逆に増えていく、最後右端は192になるはず
緑はお互い128同士なので変化なし
 
 

f:id:gogowaten:20191014115703p:plain

オレンジの方の緑を128から120にして緑の変化を見る
やっぱり反対側の色へだんだん変化させている
これでわかったつもりになってやってみたらできました
 
ダウンロード
ファイル名 Pixtack_20140207.zip
 
 
赤から青への横のグラデーションの場合
Dim bmp As New Bitmap(10, 10, PixelFormat.Format32bppArgb)
Dim col1 As Color = Color.Red
Dim col2 As Color = Color.Blue
Dim x As Integer = 0
Dim y As Integer = 0
Dim rw As Integer = bmp.Width
Dim rh As Integer = bmp.Height
Dim rect As New Rectangle(0, 0, rw, rh)
Dim col1R As Integer = col1.R
Dim col1G As Integer = col1.G
Dim col1B As Integer = col1.B
Dim col2R As Integer = col2.R
Dim col2G As Integer = col2.G
Dim col2B As Integer = col2.B
Dim rAdd As Double = (col2R - col1R) / (rw - 1)
Dim gAdd As Single = (col2.G - col1.G) / (rw - 1)
Dim bAdd As Single = (col2.B - col1.B) / (rw - 1)
 
Dim bmpdata As BitmapData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat)
Dim ptr As Integer = bmpdata.Scan0
Dim data As Integer = bmpdata.Stride * rh - 1
Dim pixels(data) As Byte
System.Runtime.InteropServices.Marshal.Copy(ptr, pixels, 0, pixels.Length)
 
For x = 0 To rw - 1
    For y = 0 To rh - 1
        Dim pos As Integer = y * bmpdata.Stride + x * 4
        pixels(pos) = CByte((bAdd * x) + col1.B)
        pixels(pos + 1) = CByte((gAdd * x) + col1.G)
        pixels(pos + 2) = CByte((rAdd * x) + col1.R)
        pixels(pos + 3) = CByte(255)
    Next
Next

System.Runtime.InteropServices.Marshal.Copy(pixels, 0, ptr, pixels.Length)
bmp.UnlockBits(bmpdata)
 
長いけど色の計算をしているのは背景色が付いているところだけ
横のグラデーションは縦には色の変化がないんだから
その場合の計算が省けるはずなんだけど、いい方法が思いつかない
1000x1000ピクセルで0.32-0.33秒 PhenomⅡ720(1.6GHzに固定)