アルファチャネルを持つ画像をクリップボードを経由してやり取りしたい。
普通に SetImage() と GetImage() を使うとうまくいかない。 ちょっとやってみよう。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Drawing.Imaging; using System.Drawing.Drawing2D; namespace Clipboard32 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Bitmap bmp = new Bitmap(200, 200, PixelFormat.Format32bppArgb); Graphics g = Graphics.FromImage(bmp); g.SmoothingMode = SmoothingMode.AntiAlias; g.FillEllipse(Brushes.Crimson, 10, 10, 180, 180); g.Dispose(); g = this.CreateGraphics(); g.DrawImage(bmp, 10, 10); g.Dispose(); Clipboard.SetImage(bmp); bmp.Dispose(); } private void button2_Click(object sender, EventArgs e) { if (Clipboard.ContainsImage()) { Bitmap bmp = (Bitmap)Clipboard.GetImage(); Graphics g = this.CreateGraphics(); g.DrawImage(bmp, 10, 220); g.Dispose(); bmp.Dispose(); } else MessageBox.Show("There is no Image in the Clipboard!"); } } }
button1 を押してから、button2 を押すと
![](https://blogimg.goo.ne.jp/user_image/16/4d/6a79b9922b60e74661777e6eccd5c4e3.png)
のようになり、GetImage() でクリップボードからえられるビットマップは、本来、透過している
部分が青になってしまいアルファ値が無視される。 MSPaint に貼り付けると
![](https://blogimg.goo.ne.jp/user_image/2c/3f/1538e3096ad8ad22190e4721a376feaa.png)
となり、同じくアルファ値が無視されている。 また、Windows のユーティリティー Clipbrd.exe を
つかって、クリップボードを内容を見てみると
![](https://blogimg.goo.ne.jp/user_image/44/af/619f45be44e911b1b5d7189a6229d6c5.png)
となっており、クリップボードが勝手にレンダリングしてアルファ値を失っている。
WEB を検索してみると、この問題は FAQ であることが分かるが、回避策のコードを探し出せなかった。
そこで、ここを参考にして、内部に Bitmap を抱えたクラスをつくり、そのインスタンスをカスタムフォーマット
としてクリップボードを介してやり取りすることを試してみた。
private void button3_Click(object sender, EventArgs e) { Bitmap bmp = new Bitmap(200, 200, PixelFormat.Format32bppArgb); Graphics g = Graphics.FromImage(bmp); g.SmoothingMode = SmoothingMode.AntiAlias; g.FillEllipse(Brushes.Crimson, 10, 10, 180, 180); g.Dispose(); g = this.CreateGraphics(); g.DrawImage(bmp, 10, 10); g.Dispose(); Bitmap32 bmp32 = new Bitmap32(bmp); Clipboard.SetData("Bitmap32Format", bmp32); bmp.Dispose(); } private void button4_Click(object sender, EventArgs e) { if (Clipboard.ContainsData("Bitmap32Format")) { Bitmap32 bmp32 = Clipboard.GetData("Bitmap32Format") as Bitmap32; Bitmap bmp = bmp32.Bmp32; Graphics g = this.CreateGraphics(); g.DrawImage(bmp, 10, 220); g.Dispose(); bmp.Dispose(); } } } [Serializable] public class Bitmap32 { private Bitmap bmp = null; public Bitmap32(Bitmap bmp32) { bmp = bmp32; } ~Bitmap32() { if (bmp != null) { bmp.Dispose(); } } public Bitmap Bmp32 { get { return bmp.Clone() as Bitmap; } set { if (bmp != null) { bmp.Dispose(); } bmp = value.Clone() as Bitmap; } } }
この結果は
![](https://blogimg.goo.ne.jp/user_image/5c/d7/b1a8547891839dd4387977190864f6e2.png)
となり、うまくいく。 当然、カスタムフォーマットなので、他のアプリケーションには貼り付けられない。
![](https://blogimg.goo.ne.jp/user_image/1b/53/c1329cf2e51b890ecf47e858c0c7e125.png)
このようにして、すくなくとも自作の C# アプリケーション間では、アルファ値を保ったままクリップボードを
介したやり取りができるようになった。
さらに進んで、Bitmap オブジェクトそのものをカスタムフォーマットとしてやり取りすることを試した。
private void button5_Click(object sender, EventArgs e) { Bitmap bmp = new Bitmap(200, 200, PixelFormat.Format32bppArgb); Graphics g = Graphics.FromImage(bmp); g.SmoothingMode = SmoothingMode.AntiAlias; g.FillEllipse(Brushes.Crimson, 10, 10, 180, 180); g.Dispose(); g = this.CreateGraphics(); g.DrawImage(bmp, 10, 10); g.Dispose(); Clipboard.SetData("Bitmap32Format2", bmp); bmp.Dispose(); } private void button6_Click(object sender, EventArgs e) { if (Clipboard.ContainsData("Bitmap32Format2")) { Bitmap bmp = Clipboard.GetData("Bitmap32Format2") as Bitmap; Graphics g = this.CreateGraphics(); g.DrawImage(bmp, 10, 220); g.Dispose(); bmp.Dispose(); } }
結果は、
![](https://blogimg.goo.ne.jp/user_image/4c/ee/b16e149d044c9df337e6e0a55cd4963a.png)
となり、うまくいく。
この方法では、パレットをもったビットマップの場合でも、その情報を失わずにやり取りできるだろう。
※コメント投稿者のブログIDはブログ作成者のみに通知されます