gogowaten.hatenablog.com
これの続き
- dllの名前を変更した、MyVisualizerからBitmapSourceVisualizer
- 画像を保存できるようにした
- 画像をクリップボードへコピーできるようにした
- 画像の表示方法を選択出るようにした、実寸とウィンドウに合わせる
これで十分かなあ
ダウンロード先
BitmapSourceVisualizer.zip
ギットハブ
github.com
画像ファイルとして保存
保存形式はpngとbmp
コピーで画像をクリップボードへコピー
表示方式、実寸
実寸だと元のままの大きさ、ウィンドウより画像が大きければスクロールバーが表示される
表示方式、ウィンドウに合わせる
画像がウィンドウより大きいときはウィンドウに収まるように縮小表示、アスペクト比は保ったまま
表示方式、ウィンドウに合わせる
画像がウィンドウより小さいときは引き伸ばして表示される、これもアスペクト比保持
拡大縮小はこれで代替できるかなあと
背景色を黒にする
using Microsoft.VisualStudio.DebuggerVisualizers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
[assembly: System.Diagnostics.DebuggerVisualizer(
typeof(BitmapSourceVisualizer.MyDialog),
typeof(BitmapSourceVisualizer.MySource),
Target = typeof(BitmapSource),
Description = "BitmapSourceVisualizer")]
namespace BitmapSourceVisualizer
{
TODO
<summary>
</summary>
public class MyDialog : DialogDebuggerVisualizer
{
private Form MyForm;
private Bitmap OriginBitmap;
private BitmapSource OriginBitmapSource;
private PictureBox MyPictureBox;
protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
{
if (windowService == null)
throw new ArgumentNullException("windowService");
if (objectProvider == null)
throw new ArgumentNullException("objectProvider");
var data = (MyProxy)objectProvider.GetObject();
OriginBitmapSource = BitmapSource.Create(data.Width, data.Height, 96, 96, PixelFormats.Bgra32, null, data.Pixels, data.Stride);
OriginBitmap = new Bitmap(data.Width, data.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
var bmpData = OriginBitmap.LockBits(new Rectangle(0, 0, OriginBitmap.Width, OriginBitmap.Height), ImageLockMode.ReadOnly, OriginBitmap.PixelFormat);
OriginBitmapSource.CopyPixels(Int32Rect.Empty, bmpData.Scan0, bmpData.Height * bmpData.Stride, bmpData.Stride);
OriginBitmap.UnlockBits(bmpData);
using (MyForm = new Form())
{
AddToolStrip();
MyForm.Text = "BitmapSourceVisualizer";
MyForm.BackColor = System.Drawing.Color.White;
MyForm.Width = Screen.PrimaryScreen.Bounds.Width / 2;
MyForm.Height = Screen.PrimaryScreen.Bounds.Height / 2;
windowService.ShowDialog(MyForm);
}
this.OriginBitmap.Dispose();
}
TODO
<summary>
</summary>
<param name="objectToVisualize"></param>
public static void TestShowVisualizer(object objectToVisualize)
{
VisualizerDevelopmentHost visualizerHost = new VisualizerDevelopmentHost(objectToVisualize, typeof(MyDialog), typeof(MySource));
visualizerHost.ShowVisualizer();
}
private void AddToolStrip()
{
var toolStrip = new ToolStrip();
ToolStripButton button;
button = new ToolStripButton { Text = "保存(&S)" };
button.Click += (s, e) => { SaveImage(OriginBitmap); };
toolStrip.Items.Add(button);
button = new ToolStripButton { Text = "コピー(&C)" };
button.Click += (s, e) => { System.Windows.Forms.Clipboard.SetImage(OriginBitmap); };
toolStrip.Items.Add(button);
button = new ToolStripButton { Text = "ウィンドウに合わせる(&Z)" };
button.Click += (e, x) => { MyPictureBox.SizeMode = PictureBoxSizeMode.Zoom; MyPictureBox.Dock = DockStyle.Fill; };
toolStrip.Items.Add(button);
button = new ToolStripButton { Text = "実寸(&A)" };
button.Click += (o, e) => { MyPictureBox.SizeMode = PictureBoxSizeMode.AutoSize; MyPictureBox.Dock = DockStyle.None; };
toolStrip.Items.Add(button);
button = new ToolStripButton { Text = "背景黒(&B)" };
button.Click += (s, e) => { MyForm.BackColor = System.Drawing.Color.Black; };
toolStrip.Items.Add(button);
button = new ToolStripButton { Text = "背景白(&H)" };
button.Click += (s, e) => { MyForm.BackColor = System.Drawing.Color.White; };
toolStrip.Items.Add(button);
button = new ToolStripButton { Text = "閉じる(&W)" };
button.Click += (s, e) => { MyForm.Close(); };
toolStrip.Items.Add(button);
MyForm.Controls.Add(toolStrip);
MyPictureBox = new PictureBox { SizeMode = PictureBoxSizeMode.AutoSize };
var p = new Panel { AutoScroll = true, Dock = DockStyle.Fill };
p.Controls.Add(MyPictureBox);
MyForm.Controls.Add(p);
MyPictureBox.Image = OriginBitmap;
p.BringToFront();
}
private void SaveImage(Bitmap bmp)
{
SaveFileDialog dialog = new SaveFileDialog();
dialog.Filter = "*.png|*.png|*.bmp|*.bmp";
if (dialog.ShowDialog() == DialogResult.OK)
{
if (dialog.FilterIndex == 1)
{
bmp.Save(dialog.FileName, ImageFormat.Png);
}
else if (dialog.FilterIndex == 2)
{
bmp.Save(dialog.FileName, ImageFormat.Bmp);
}
}
dialog.Dispose();
}
}
public class MySource : VisualizerObjectSource
{
public override void GetData(object target, Stream outgoingData)
{
var source = (BitmapSource)target;
var data = new MyProxy(source);
base.GetData(data, outgoingData);
}
}
<summary>
</summary>
[Serializable]
public class MyProxy
{
public int Width { get; private set; }
public int Height { get; private set; }
public int Stride { get; private set; }
public byte[] Pixels { get; private set; }
public MyProxy(BitmapSource source)
{
if (source.Format != PixelFormats.Bgra32)
{
source = new FormatConvertedBitmap(source, PixelFormats.Bgra32, null, 0);
}
Width = source.PixelWidth;
Height = source.PixelHeight;
Stride = Width * 4;
Pixels = new byte[Height * Stride];
source.CopyPixels(new Int32Rect(0, 0, Width, Height), Pixels, Stride, 0);
}
}
}
最初から作り直したけど、参照に追加したdllは前回と同じ
フィールド
Formにボタンを追加するところ、ボタンはToolStripButtonを使った
これを
Formを作るところで呼んでいる
保存ボタン作成部分
jpegも加えようとしたけど、なんかできなかったのでpngとbmpだけ
クリップボードへコピー
WPFのクリップボードはやっぱりおかしい、アルファ値が255になってしまうのでFormsのクリップボードを使っている、これもアルファ値が変化してしまう?みたいだけどWPFのよりはマシ、透明や半透明のピクセルがない普通(アルファ値255)の画像なら全く問題ない
表示方式の変更は
PictureBoxSizeModeとPictureBoxのDockプロパティを変更しているだけ
Formに追加
- 各ボタンをToolStripに追加してFormに追加
- PanelにPictureBoxを追加してFormに追加
- PictureBoxのImageプロパティに画像を指定
- Panelを最前面にするBringToFront
この順番が大切、2番3番が逆だと大きな画像を表示したときでもPanelにスクロールバーが表示されなかった
めんどくさかった
画像を保存するところのテストで、保存ダイアログを表示するところ
SaveFileDialog dialog = new SaveFileDialog();
でエラー、コードも単純なものだから間違っているとは思えないので、試しにReleaseでビルドしたdllを普通に使ってみたら問題なく保存ダイアログが表示されて画像保存もできた!
よくわからんけどこのエラーのおかげで、保存ダイアログを使った動作を確認するときには、毎回Releaseでビルド→dllをVisualizersフォルダにコピー→別のプロジェクトを開いて動作確認、っていうめんどくさいことになっていた
元の画像
切り抜き後の画像をクリップボードへコピーして
Pixtack紫陽花に貼り付けたところ、コピペできてる
切り抜き後の画像を保存
保存された画像
ウィンドウに合わせるで拡大縮小表示していても、保存やコピーされるのは元の実寸サイズ
関連記事
gogowaten.hatenablog.com
次のVerは1年後
gogowaten.hatenablog.com