камрады!
Суть проблемы: нужно в интерактивном режиме ресайзить Bitmap порядка 3*4 тыщи пикселей или даже больше. Грубо говоря, зум.
Пробовал:
scaled = new Bitmap(baseImage, newSize);
Второй вариант:
Bitmap scaled = new Bitmap(size.Width, size.Height);
using (Graphics g = Graphics.FromImage((Image)scaled))
{
g.DrawImage(baseImage, 0, 0, size.Width, size.Height);
}
return scaled;
И разные вариации, но толку чуть меньше чем ноль. Единственное, что даёт прирост производительности - подключить OpenCV и использовать их ресайз, но таскать за собой такой хвост - идея не лучшая.
Возможно есть существующие библиотеки как на чистом C# или обёртки (у меня WinForms .net 3.5 проект) полегче того же OpenCV... ТОП Nugeta - обёртки над тем же new Bitmap и результата не дают. Или я плохо искал. В общем, я открыт для предложений.
UPD: информация к размышлению. У меня уже черепушка плавится.
Запускаю вот такой код с отрисовкой получившегося изображения прямо на контрол. Всё летает.
//прицеплено на Form1.paint
protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
g.DrawImage(baseImage, new RectangleF(0, 0, baseImage.Width * Scale, baseImage.Height * Scale));
}
Но! Если получать Graphics объект не из PaintEventArgs, а из Graphics.FromImage(baseImage), то скорость работы строчки
g.DrawImage(baseImage, new RectangleF(0, 0, width, height));
разнится в разы. Вот это-то и смущает. Мне нужно не просто отрисовать изображение на контрол, а отрисовать его именно в конкретный объект. То есть, код:
scaledImage.Dispose();
scaledImage = new Bitmap(width, height);
var g = Graphics.FromImage(scaledImage);
g.DrawImage(baseImage, new RectangleF(0, 0, width, height));
Работает примерно в 10-12 раз медленнее кода:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var g = e.Graphics;
g.DrawImage(baseImage, new RectangleF(0, 0, baseImage.Width * Scale, baseImage.Height * Scale));
pictureBox1.Invalidate();
}
Здесь идёт отрисовка на контрол сразу и выполняется это почти моментально. Но мне нужно записать всё в Bitmap объект.
Самое забавное, что если перейти внутрь g.DrawImage(), то в обоих случаях вызывается один и тот же метод DrawImage из System.Drawing, но при одном объекте Graphics он летает, а при том, что мне нужно - полученном через Graphics.FromImage() - тормозит
Может быть выгодно разбить битмап на прямоугольные части.
Изображение такого размера ведь в большинстве случаев целиком не показывают, а масштабирование одной или, скажем, четырёх из 16 частей явно быстрее, чем всего большого битмапа.
Кроме того, можно предрассчитать - или заранее, или в начале работы программы - несколько копий в других масштабах.
Для показа целой картинки на стандартных мониторах отображаем готовую копию с масштабом 0.5 или 0.25. Если масштаб промежуточный - можно из тех же уменьшенных сделать.
Для увеличенного масштаба нарезанные куски хорошо подойдут.
Может, я что-то упустил, но почему-бы не использовать функционал доступный из коробки?
Ты используешь Winforms. У него есть PictureBox. У него есть режим Zoom. Просто меняешь скролом размер этого PictureBox и получаешь зум. Перемещение по картинке -- реализуй перетягивание PictureBox внутри некой панели по клику.
Ни тормозов не должно быть ни излишних ресайзов оригинального битмапа.
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости