Finally, I found a better (faster) way with Stream conversion, (Bitmap.SetPixel() is too slow)
import sys
import clr
import System
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
dirAppLoc = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData)
sys.path.append(dirAppLoc + r'\python-3.8.3-embed-amd64\Lib\site-packages')
clr.AddReference('System.Drawing')
import System.Drawing
from System.Drawing import *
from System.Drawing.Imaging import *
from System.IO import MemoryStream
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import io
import math
def plt2arr(fig):
"""
need to draw if figure is not drawn yet
"""
fig.canvas.draw()
rgba_buf = fig.canvas.buffer_rgba()
(w,h) = fig.canvas.get_width_height()
rgba_arr = np.frombuffer(rgba_buf, dtype=np.uint8).reshape((h,w,4))
return rgba_arr
def convertToBitmap2(npImgArray):
bitmap_ = None
# remove alpha
if npImgArray.ndim == 3 and npImgArray.shape[-1] == 4:
npImgArray = npImgArray[:, :, :-1]
# convert to PIL Image
if npImgArray.ndim == 3:
image = Image.fromarray(npImgArray, "RGB")
else:
image = Image.fromarray(npImgArray, "L")
# convert to Python ByteArray
byteIO = io.BytesIO()
image.save(byteIO, format='BMP')
byteArr = byteIO.getvalue()
# convert to Net ByteArray
netBytes = System.Array[System.Byte](byteArr)
with MemoryStream(netBytes) as ms:
bitmap_ = Bitmap(ms)
return bitmap_
# plot sin and cos wave
fig = plt.figure()
ax = fig.add_subplot(111)
x = np.linspace(-np.pi, np.pi)
ax.set_xlim(-np.pi, np.pi)
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.plot(x, np.sin(x), label="sin")
ax.plot(x, np.cos(x ), label="cos")
ax.legend()
ax.set_title("sin(x) and cos(x)")
image_from_plot = plt2arr(fig)
bitmap1 = convertToBitmap2(image_from_plot)
OUT = bitmap1