はじめに
やりたいことはタイトル通りです。「ProcessStart」を使った場合、通常Pythonから受け取れるデータはテキストデータ(コンソールに出力されるデータ)のみです。今回はクリップボードを使って画像を受け取れるようにしました。方法の概略
環境
Windows 10 Visual Studio Community 2019 .NET 5.0 Python 3.8.10
pythonはvenvで仮想環境を作りました。その環境に「pillow」と「pywin32」をpip経由でインストールしました。
pip install pillow pip install pywin32
仮想環境のフルパスをC#のコードに書きますので仮想環境はどこに作っても問題ありません。
C#コードとPythonスクリプト
今回はサンプルとしてPythonのPILを使って画像を開くだけになっています。Pythonスクリプトは「sample.py」という名前でexeファイルと同じフォルダに入れて下さい。自分の場合にはこのようなフォルダになりました。D:\dotnetformpython >> wpf >>wpf >> bin >> Debug >> net5.0-windows画像は適当に用意して「sample.jpg」という名前でやはりexeファイルと同じフォルダに入れて下さい。あとは実行するだけです。WPFのWindowに画像が表示されます。
Pythonスクリプト
import io import sys from PIL import Image import win32clipboard as cb image = Image.open(sys.argv[1]) with io.BytesIO() as f: image.convert('RGB').save(f, 'BMP') data = f.getvalue()[14:] cb.OpenClipboard() cb.EmptyClipboard() cb.SetClipboardData(cb.CF_DIB, data) cb.CloseClipboard()
C#コード
using System.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Imaging; namespace wpf { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); Image pictureBox = new() { Margin = new Thickness(3) }; Content = pictureBox; string myPythonApp = "sample.py"; string img_file = "sample.jpg"; var myProcess = new Process { StartInfo = new ProcessStartInfo(@"D:\dotnetformpython\pythonenv\Scripts\python.exe") { UseShellExecute = false, RedirectStandardOutput = false, CreateNoWindow = true, Arguments = myPythonApp + " " + img_file } }; using (myProcess) { myProcess.Start(); myProcess.WaitForExit(); } BitmapSource image = Clipboard.GetImage(); if (image != null) { pictureBox.Source = new FormatConvertedBitmap(image, PixelFormats.Bgr32, null, 0); } } } }
matplotlibの場合は?
先ほどはPILを使用しました。matplotlibの場合はどうするか?numpy配列を経由してPILのImageに変換すれば動きました。ベストな方法かどうかはわかりません。試しにPythonファイルを以下のように変えてみて下さい。また、「numpy」と「matplotlib」を追加でインストールして下さい。import io import numpy as np from PIL import Image from matplotlib import pyplot as plt import win32clipboard as cb x = [1, 2, 3, 4, 5] y = x plt.plot(x, y) fig = plt.gcf() fig.canvas.draw() im = np.array(fig.canvas.renderer.buffer_rgba()) im = Image.fromarray(im) with io.BytesIO() as f: im.convert('RGB').save(f, 'BMP') data = f.getvalue()[14:] cb.OpenClipboard() cb.EmptyClipboard() cb.SetClipboardData(cb.CF_DIB, data) cb.CloseClipboard()
グラフが表示されます。
plt.plot(x, y) fig = plt.gcf()
この部分は以下のようにも書けます。
fig, ax = plt.subplots() ax.plot(x, y)