質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

4046閲覧

C# wpf OpacityMaskで透明部分を抜き出す方法

kkjiji

総合スコア40

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

1グッド

0クリップ

投稿2021/12/17 08:50

前提・実現したいこと

タイトル通りOpacityMaskで透明部分を切り出す方法が知りたいです。

ImageやRectangleのプロパティにOpacityMaskというものがあります。

https://czpanel.com/blog/opacitymask-and-resources/
上記のサイトをご覧いただくとわかると思いますが、
塗りつぶしたRectangleにOpacitiMaskとして画像をセットすると、
画像の色のある部分(サイトだとオレンジの部分)が切り取ることができます。
ちなみにオレンジ画像の背景はTransparent(透明)です。

この逆のこと(オレンジの周りが青色になる)をしたいのですがいい方法はありますか?

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TN8001

2021/12/17 10:51

まともにやるとなるとアルファを反転した画像を作るしかないと思いますけどねぇ。 例えば青いRectangleの **上に** 、OpacityMaskで抜いた白いRectangleを載せれば、見た目は逆になったように見えますけど(もちろん白い部分が透過しているわけではないが^^; これをどう使いたいのかがちょっと見えません。
kkjiji

2021/12/17 11:32

TN8001さん 返信ありがとうございます。以前お世話になりました。 特に意味はないのですが、WPFの勉強をしていてOpacityMaskの存在を知ったので逆はできないのかと疑問に思った次第です。
guest

回答1

0

ベストアンサー

普通に考えるとこの辺を使って、アルファを反転させた画像を作るんでしょうね。
BitmapSource.CopyPixels メソッド (System.Windows.Media.Imaging) | Microsoft Docs

WPFにおける画像のピクセル値への高速アクセス - Qiita

わたしはこういった(めんどくさそうな)ことは嫌いなので、調べている途中で見たこれでやってみました。
wpf - How to Invert Color of XAML PNG Images using C#? - Stack Overflow

注)私はシェーダーについて何ひとつわかっていません。

xml

1<Window 2 x:Class="Questions374313.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="clr-namespace:Questions374313" 6 Width="800" 7 Height="450" 8 Background="MistyRose"> 9 <Window.Resources> 10 11 <!--<BitmapImage x:Key="original" UriSource="orange.png" />--> 12 <!-- オレンジ画像を使う場合↑を生かして、↓をコメント化 --> 13 <DrawingImage x:Key="original"> 14 <DrawingImage.Drawing> 15 <DrawingGroup> 16 <GeometryDrawing Brush="Transparent"> 17 <GeometryDrawing.Geometry> 18 <RectangleGeometry Rect="0,0,300,277" /> 19 </GeometryDrawing.Geometry> 20 </GeometryDrawing> 21 <GeometryDrawing> 22 <GeometryDrawing.Geometry> 23 <GeometryGroup> 24 <EllipseGeometry 25 Center="150,138.5" 26 RadiusX="140" 27 RadiusY="100"> 28 <EllipseGeometry.Transform> 29 <TransformGroup> 30 <ScaleTransform CenterX="150" CenterY="138.5" /> 31 <SkewTransform CenterX="150" CenterY="138.5" /> 32 <RotateTransform Angle="140" CenterX="150" CenterY="138.5" /> 33 <TranslateTransform /> 34 </TransformGroup> 35 </EllipseGeometry.Transform> 36 </EllipseGeometry> 37 </GeometryGroup> 38 </GeometryDrawing.Geometry> 39 <GeometryDrawing.Brush> 40 <LinearGradientBrush> 41 <GradientStop Offset="0.0" Color="#FFDD6200" /> 42 <GradientStop Offset="1.0" Color="#0000" /> 43 </LinearGradientBrush> 44 </GeometryDrawing.Brush> 45 <GeometryDrawing.Pen> 46 <Pen Brush="#FFFFD250" Thickness="20" /> 47 </GeometryDrawing.Pen> 48 </GeometryDrawing> 49 </DrawingGroup> 50 </DrawingImage.Drawing> 51 </DrawingImage> 52 53 <Image x:Key="invert" Source="{StaticResource original}"> 54 <Image.Effect> 55 <local:InvertEffect /> 56 </Image.Effect> 57 </Image> 58 </Window.Resources> 59 60 <UniformGrid 61 HorizontalAlignment="Left" 62 VerticalAlignment="Top" 63 Rows="1"> 64 <UniformGrid.Resources> 65 <Style TargetType="Rectangle"> 66 <Setter Property="Width" Value="300" /> 67 <Setter Property="Height" Value="277" /> 68 <Setter Property="Fill" Value="Blue" /> 69 </Style> 70 </UniformGrid.Resources> 71 72 <GroupBox Header="original"> 73 <Image Source="{StaticResource original}" /> 74 </GroupBox> 75 76 <GroupBox Header="original - OpacityMask"> 77 <Viewbox> 78 <Rectangle> 79 <Rectangle.OpacityMask> 80 <ImageBrush ImageSource="{StaticResource original}" /> 81 </Rectangle.OpacityMask> 82 </Rectangle> 83 </Viewbox> 84 </GroupBox> 85 86 <GroupBox Header="fake"> 87 <Viewbox> 88 <Grid> 89 <Rectangle /> 90 <Rectangle Fill="White"> 91 <Rectangle.OpacityMask> 92 <ImageBrush ImageSource="{StaticResource original}" /> 93 </Rectangle.OpacityMask> 94 </Rectangle> 95 </Grid> 96 </Viewbox> 97 </GroupBox> 98 99 <GroupBox Header="invert - OpacityMask"> 100 <Viewbox> 101 <Rectangle> 102 <Rectangle.OpacityMask> 103 <VisualBrush Visual="{StaticResource invert}" /> 104 </Rectangle.OpacityMask> 105 </Rectangle> 106 </Viewbox> 107 </GroupBox> 108 </UniformGrid> 109</Window>

cs

1using System; 2using System.IO; 3using System.Windows; 4using System.Windows.Media; 5using System.Windows.Media.Effects; 6 7namespace Questions374313 8{ 9 public partial class MainWindow : Window 10 { 11 public MainWindow() => InitializeComponent(); 12 } 13 14 15 // [wpf - How to Invert Color of XAML PNG Images using C#? - Stack Overflow](https://stackoverflow.com/questions/45093399/how-to-invert-color-of-xaml-png-images-using-c) 16 internal class InvertEffect : ShaderEffect 17 { 18 public Brush Input { get => (Brush)GetValue(InputProperty); set => SetValue(InputProperty, value); } 19 public static readonly DependencyProperty InputProperty = RegisterPixelShaderSamplerProperty("Input", typeof(InvertEffect), 0); 20 21 private const string _kshaderAsBase64 = @"AAP///7/HwBDVEFCHAAAAE8AAAAAA///AQAAABwAAAAAAQAASAAAADAAAAADAAAAAQACADgAAAAAAAAAaW5wdXQAq6sEAAwAAQABAAEAAAAAAAAAcHNfM18wAE1pY3Jvc29mdCAoUikgSExTTCBTaGFkZXIgQ29tcGlsZXIgMTAuMQCrUQAABQAAD6AAAIA/AAAAAAAAAAAAAAAAHwAAAgUAAIAAAAOQHwAAAgAAAJAACA+gQgAAAwAAD4AAAOSQAAjkoAIAAAMAAAiAAAD/gQAAAKAFAAADAAgHgAAA/4AAAOSAAQAAAgAICIAAAP+A//8AAA=="; 22 23 private static readonly PixelShader _shader; 24 25 static InvertEffect() 26 { 27 _shader = new PixelShader(); 28 _shader.SetStreamSource(new MemoryStream(Convert.FromBase64String(_kshaderAsBase64))); 29 } 30 31 public InvertEffect() 32 { 33 PixelShader = _shader; 34 UpdateShaderValue(InputProperty); 35 } 36 } 37}

HLSL

1sampler2D input : register(s0); 2 3float4 main(float2 uv : TEXCOORD) : COLOR 4{ 5 float4 color = tex2D(input, uv); 6 float alpha = 1 - color.a; 7 8// color = 1 - color; 9 color.a = alpha; 10 color.rgb *= alpha; 11 12 return color; 13}

ぶっちゃけシェーダーなら何でもありみたいなものでしょうから、こんな回りくどいことをしなくてももっと直接適用できるでしょうが^^;
アプリ画像


途中まで調べていたので回答しましたが、「特に意味はない」と言われてしまうと萎えますね^^;
仮絵(DrawingImage)を作るのが、一番時間がかかりましたw

投稿2021/12/17 15:40

編集2023/07/29 12:42
TN8001

総合スコア9862

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kkjiji

2021/12/18 04:10

ご回答ありがとうございました。 個人的にはペイントソフトを作成しているのでそれに使えないかなと思っています。 例えばCanvasの背景に画像をセットしてその上に一部の消したいところを色塗りします。 その後、それをマスク画像して保存しておけば、他の画像にもそれを使い回せる?と考えていたところです。 その場合だと、色塗りしたところが消えたほうが都合がいいなと思ったのでこのような質問をしました。 できたらいいなと思っていたくらいだったので、「特に意味はない」と言ったんですが、不快に思わせていたらすみません。 プログラム参考にさせてもらいます。
TN8001

2021/12/18 04:26

ShaderEffectも一度やってみたかったので、別に怒ってはいませんよ^^ 試すだけなら想像以上に簡単でした。 とはいえHLSLがわからないので、何にもならんのですが^^;
kkjiji

2021/12/20 10:01

TN8001さん WPFにおける画像のピクセル値への高速アクセス - Qiita を参考にマスク画像のアルファ値を反転させることができました。 これを使って、Rectangleなどのオブジェクトの消しゴムを作成することができました。 ○手順 1.Rectangleと同じサイズのRectを準備 2.drawingContext.DrawLineで書いたものをRectに加えて、bitmapに変換(背景は透明) 3.bitmapの各ピクセルにアクセスして、アルファ値を反転 4.オブジェクトのマスク画像としてセット これをマウスが動くごとに繰り返しています。 正確にはすでにマスク画像がある場合は反転させて、それに新たに線を加えて、また反転させているのですが。 手順が書きにくくて分かりにくいのですが、めちゃめちゃ面倒なことしてます笑 とはいえ、TN8001さんのアドバイスがあったので、やりたいことができました。 お礼をと思いまして、返信を書かせてもらいました。 本当にありがとうございました。
TN8001

2021/12/20 10:23

いえいえ何かの役に立ったようで何よりです。 ご丁寧にありがとうございました。 いいアプリができるといいですね^^
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問