Отображение объекта Bitmap с использованием технологии Blazor
Есть задача отобразить на Web-странице объект типа bitmap, который периодически меняется. В С# для десктоп элементов я бы подписался на событие paint и отрисовывал бы его вот так:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
lock (_bitmapLock)
{
pictureBox1.Size = new Size(_bitmap.Width, _bitmap.Height);
e.Graphics.DrawImage(_bitmap, e.ClipRectangle.X, e.ClipRectangle.Y , e.ClipRectangle, GraphicsUnit.Pixel);
}
}
Но на Blazor я никак не могу найти как это сделать. Я пробовал брать элемент
<img src='tutorial.png'>
Записывать bitmap в tutorial.png и пытаться вызывать InvokeAsync(StateHasChanged), когда объект bitmap меняется, чтобы перерисовать его с новым src. Но это так не работает. Мне удалось добиться обновления всей страницы, но выглядит это ужасно. Пробовал использовать компоненты Radzen(вроде бы они должны динамически меняться), но тоже без успеха. Какие вообще способы существуют по отображение на web bitmap в Blazor? Может есть иной путь?
Ответы (1 шт):
Razor компонент (DynamicImage.razor): комментарии на русском, так наглядней обяъснение
для отрисовки bitmap мы используем canvas
@page "/dynamic-image"
@using System.Drawing.Imaging
@using System.Drawing
@rendermode InteractiveServer // после восьмой версии обратите внимание на интерактивность вашего приложения
@inject IJSRuntime JsRuntime
<canvas id="canvas" width="800" height="600"></canvas>
<button @onclick="UpdateBitmapAsync">Нарисуй точку</button>
@code {
private Bitmap _bitmap;
private byte[] _imageData;
private Random _random = new Random();
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// Инициализация вашего bitmap или загрузка его из файла
_bitmap = new Bitmap(800, 600); // Для примера, создаём пустой bitmap
// Конвертация Bitmap в массив байтов
using (var ms = new MemoryStream())
{
_bitmap.Save(ms, ImageFormat.Png); // Исправлено: ImageFormat
_imageData = ms.ToArray();
}
// Обновление canvas с новым изображением
await UpdateImage(_imageData);
}
}
public async Task UpdateImage(byte[] imageData)
{
try
{
await JsRuntime.InvokeVoidAsync("updateCanvas", imageData);
}
catch (Exception ex)
{
Console.WriteLine($"Error in UpdateImage: {ex.Message}");
}
}
private async Task UpdateBitmapAsync()
{
try
{
// Логика обновления вашего Bitmap
using (Graphics g = Graphics.FromImage(_bitmap))
{
// Очищаем изображение (опционально)
// g.Clear(System.Drawing.Color.White);
// Добавляем точку с случайными координатами
int x = _random.Next(0, _bitmap.Width);
int y = _random.Next(0, _bitmap.Height);
g.FillEllipse(Brushes.DarkMagenta, x, y, 13, 13); // Рисуем точку размером 13x13 пикселей
}
// Конвертация обновленного Bitmap в массив байтов
using (var ms = new MemoryStream())
{
_bitmap.Save(ms, ImageFormat.Png);
_imageData = ms.ToArray();
}
// Обновление canvas с новым изображением
await UpdateImage(_imageData);
}
catch (Exception ex)
{
Console.WriteLine($"Error in UpdateBitmapAsync: {ex.Message}");
}
}
}
скрипт для отрисовки
<script>
window.initializeCanvas = () => {
const canvas = document.getElementById('canvas');
if (canvas) {
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
console.log('Canvas initialized.');
} else {
console.log('Canvas not found.');
}
};
window.updateCanvas = (imageData) => {
const canvas = document.getElementById('canvas');
if (canvas) {
const context = canvas.getContext('2d');
const img = new Image();
img.onload = () => {
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(img, 0, 0, canvas.width, canvas.height);
};
img.src = 'data:image/png;base64,' + arrayBufferToBase64(imageData);
console.log('Canvas updated.');
} else {
console.log('Canvas not found for updating.');
}
};
function arrayBufferToBase64(buffer) {
let binary = '';
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
</script>
Убедитесь, что вы добавили пакет System.Drawing.Common в ваш проект
а если отслеживать события мышки, то можно попробовать рисовать
При нажатии мыши OnMouseDown начинается рисование, и координаты текущей точки сохраняются.
При движении мыши OnMouseMove проверяется, если _isDrawing равно true, и рисуется линия от предыдущей точки до текущей.
При отпускании мыши OnMouseUp рисование завершается.
@page "/dynamic-image"
@using System.Drawing.Imaging
@using System.Drawing
@rendermode InteractiveServer
@inject IJSRuntime JsRuntime
<canvas id="canvas" width="800" height="600"
@onmousedown="OnMouseDown"
@onmousemove="OnMouseMove"
@onmouseup="OnMouseUp"></canvas>
@code {
private Bitmap _bitmap;
private byte[] _imageData;
private bool _isDrawing = false;
private Point _lastPoint;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
_bitmap = new Bitmap(800, 600);
using (var ms = new MemoryStream())
{
_bitmap.Save(ms, ImageFormat.Png);
_imageData = ms.ToArray();
}
await UpdateImage(_imageData);
}
}
public async Task UpdateImage(byte[] imageData)
{
try
{
await JsRuntime.InvokeVoidAsync("updateCanvas", imageData);
}
catch (Exception ex)
{
Console.WriteLine($"Error in UpdateImage: {ex.Message}");
}
}
private async Task OnMouseDown(MouseEventArgs e)
{
_isDrawing = true;
_lastPoint = new Point((int)e.OffsetX, (int)e.OffsetY);
}
private async Task OnMouseMove(MouseEventArgs e)
{
if (_isDrawing)
{
Point currentPoint = new Point((int)e.OffsetX, (int)e.OffsetY);
using (Graphics g = Graphics.FromImage(_bitmap))
{
g.DrawLine(Pens.DarkMagenta, _lastPoint, currentPoint);
}
_lastPoint = currentPoint;
using (var ms = new MemoryStream())
{
_bitmap.Save(ms, ImageFormat.Png);
_imageData = ms.ToArray();
}
await UpdateImage(_imageData);
}
}
private async Task OnMouseUp(MouseEventArgs e)
{
_isDrawing = false;
}
}
<script>
window.initializeCanvas = () => {
const canvas = document.getElementById('canvas');
if (canvas) {
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
console.log('Canvas initialized.');
} else {
console.log('Canvas not found.');
}
};
window.updateCanvas = (imageData) => {
const canvas = document.getElementById('canvas');
if (canvas) {
const context = canvas.getContext('2d');
const img = new Image();
img.onload = () => {
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(img, 0, 0, canvas.width, canvas.height);
};
img.src = 'data:image/png;base64,' + arrayBufferToBase64(imageData);
console.log('Canvas updated.');
} else {
console.log('Canvas not found for updating.');
}
};
function arrayBufferToBase64(buffer) {
let binary = '';
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
</script>

