Class MainWindow
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
Dim b As BitmapImage
Dim path As Uri
path = New Uri("D:\ブログ用\テスト用画像\TransparentRect.png")
b = New BitmapImage(path)
image1.Source = b
image1.Stretch = Stretch.None
End Sub
Private Sub image1_MouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs) Handles image1.MouseLeftButtonDown
Dim clickPoint As Point = e.GetPosition(image1)
textblock1.Text = $"Locate={clickPoint.ToString}"
Dim x As Integer = clickPoint.X
Dim y As Integer = clickPoint.Y
Dim b As BitmapSource = image1.Source
Dim wb As Integer = b.PixelWidth
Dim hb As Integer = b.PixelHeight
If x >= wb Then x = wb - 1
If y >= hb Then y = hb - 1
Dim col As Color = neko2(x, y)
rectangle1.Fill = New SolidColorBrush(col)
tbARGB.Text = $"ARGB={col.ToString}"
End Sub
Private Function neko2(x As Integer, y As Integer) As Color
Dim bmp As BitmapSource = image1.Source
Dim cb As New CroppedBitmap(bmp, New Int32Rect(x, y, 1, 1))
Dim fcb As New FormatConvertedBitmap(cb, PixelFormats.Bgra32, Nothing, 0)
Dim pixels(3) As Byte
fcb.CopyPixels(pixels, 4, 0)
Dim c As Color
c = Color.FromArgb(pixels(3), pixels(2), pixels(1), pixels(0))
Return c
End Function
End Class
余計なコメントや名前が変だけどこんな感じ
Windowsフォームアプリの時は簡単に取得できるGetPixelメソッドが
用意されていたんだけど
ここを参考にして(またしーしゃーぷか!しかも英語)
Private Function GetPixelColor(x As Integer, y As Integer, bmp as BitmapSource) As Color
Dim cb As New CroppedBitmap(bmp, New Int32Rect(x, y, 1, 1))
Dim fcb As New FormatConvertedBitmap(cb, PixelFormats.Bgra32, Nothing, 0)
Dim pixels(3) As Byte
fcb.CopyPixels(pixels, 4, 0)
Dim c As Color
c = Color.FromArgb(pixels(3), pixels(2), pixels(1), pixels(0))
Return c
End Function
xとyがクリックした位置、
bmpがクリックした画像
CroppedBitmapで
bmpから1x1の大きさの画像を取り出す
これがクリックされたPixelになるので
あとはCopyPixelsで色の値を取り出すだけなんだけど
その前にFormatConvertedBitmapで
ピクセルフォーマットをBgra32に変換している
これは
CopyPixelsの引数に必要なBitmapのstrideをいくつにすればいいのかわかりやすくなるから
Strideは
このふたつが関係しているみたいで
ピクセルフォーマットがBgra32で横幅100の画像の時Strideは
4*100=400
になる
今回はクリックした位置の1x1の画像だから横幅1で4*1=4
つまりBgra32なら横幅x4でいいみたい
どんな画像でも
ピクセルフォーマットがBgra32ならいいけど
いろいろあってそれによってx4の部分が変わるらしいけどよくわかんないので
FormatConvertedBitmapっていう便利なのがあったのでBgra32に統一した
なので画像によっては違う色になるかも?
適当な画像で試した限りでは問題なかった
同じ形式でもいろいろな
ピクセルフォーマットはあるみたいでよくわからん
コピーした値
BGRAそれぞれの4つの値が配列にコピーされたところ
画像を表示させているimage1のMouseLeftDownイベントに
Private Sub image1_MouseLeftDown(sender As Object, e As MouseButtonEventArgs) Handles image1.MouseLeftButtonDown
Dim clickPoint As Point = e.GetPosition(image1)
textblock1.Text = $"Locate={clickPoint.ToString}"
Dim x As Integer = clickPoint.X
Dim y As Integer = clickPoint.Y
Dim b As BitmapSource = image1.Source
Dim wb As Integer = b.PixelWidth
Dim hb As Integer = b.PixelHeight
If x >= wb Then x = wb - 1
If y >= hb Then y = hb - 1
Dim col As Color = GetPixelColor(x, y, b)
rectangle1.Fill = New SolidColorBrush(col)
tbARGB.Text = $"ARGB={col.ToString}"
End Sub
クリックした場所は
マウスイベントのGetPositionで取得できる
けどなんかおかしくて
端ギリギリをクリックした時に101とかが返ってくる時があるので
サイズを超えていた時は-1してからGetPixelColorに渡している
マウスカーソルの形を変えて色取得モードに
カーソル下の色を常に表示
画像クリックで色確定して色取得モード終了
途中でやめるときはもう一度色取得ボタン押す
WPFではクリックした場所の色取得がこんなに面倒だとは思わなかった
なんでもかんでも
WPFのほうがいいってわけでもないんだなあと
複数画像をまとめるのが目的のアプリだし保存するときは画像形式によって
画像読み込み時にピクセルフォーマットをBgra32に変換するようにした
これなら色取得の度に
ピクセルフォーマットを変換する手間が省ける
Pixtack2nd_20160303.zipダウンロード
これで色取得はできたと思ったけど終わってなかった
3年後の