Мы проиллюстрируем процесс вывода изображения с помощью примера DisplayImage
. Этот пример просто выводит файл .jpg
в основном окне приложения. Чтобы упростить код, путь доступа файла .jpg
жестко закодирован в приложении (поэтому при выполнении приложения необходимо изменить его в соответствии с местоположением файла на используемой системе). Выводимый файл .jpg
является групповой фотографией участников встречи COMFest.
Как обычно в этой главе, проект DisplayImage
является стандартным приложением Windows, созданным с помощью VisualStudio.NET. Мы добавляем следующее поле в класс Form1
:
Image Piccy;
Затем загружаем файл в процедуру InitializeComponent
.
private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
this.Size = new System.Drawing.Size(600, 400);
this.Text = "Display COMFEst Image";
this.BackColor = Color.White;
Piccy =
Image.FromFile(@"C:\ProCSharp\Chapter21\Display Image\CF4Group.jpg");
this.AutoScrollMinSize = Piccy.Size;
}
Отметим, что размер изображения в пикселях задается как его свойство Size
, которое используется для задания области документа. Изображение выводится в методе OnPaint()
:
protected override void OnPaint(PaintEventArgs e) {
Graphics dc = e.Graphics;
dc.DrawImageUnscaled(Piccy, this.AutoScrollPosition);
base.OnPaint(e);
}
Выбор this.AutoScrollPosition
в качестве координатного устройства гарантирует, что окно будет прокручиваться правильно, при этом до начала прокручивания изображение будет располагаться с верхнего левого угла клиентской области.
Наконец, сделаем еще одно замечание об изменениях, сделанных в коде метода Form1.Dispose()
, созданном мастером:
public override void Dispose() {
base.Dispose();
if (components != null) components.Dispose();
Piccy.Dispose();
}
Удаление изображения, когда оно не требуется, является важной задачей, так как изображения обычно требуют много памяти. После вызова Image.Dispose()
экземпляр Image
больше не ссылается на какое-либо реальное изображение и поэтому не может больше выводиться (если не будет загружено новое изображение).
Выполнение этого кода создает результат:
COMFest (www.comfest.co.uk) является неформальной группой разработчиков в Великобритании, которые встречаются для обсуждения самых новых технологий, обмена идеями и т. д. Снимок включает всех участников COMFest 4, за исключением автора этой главы, который фотографировал.
Вопросы, возникающие при манипуляциях с изображениями
Вывод изображений выполнить легко, но все же требуется некоторое понимание описанной ниже технологии.
Наиболее важным моментом при работе с изображениями является то, что они всегда прямоугольные. Это не просто удобство для людей. Такая форма связана с тем, что все современные графические платы имеют встроенное оборудование, которое может очень эффективно копировать блоки пикселей из одного участка памяти в другой. При условии, что блок пикселей представляет прямоугольную область, аппаратное ускорение выполняется практически как одна операция, и поэтому будет очень быстрым. На самом деле это ключ к современной высокопроизводительной графике. Такая операция называется переносом битовых блоков (BitBlt). Image.DrawImageUnscaled()
внутренне использует BitBlt, вот почему можно видеть огромное изображение, содержащее, возможно, миллионы пикселей (фотография из примера имеет 104975 пикселей) появляющимся почти мгновенно. Если бы компьютер должен был копировать изображение на экран пиксель за пикселем, то изображение постепенно появлялось бы в течение нескольких секунд.
Метод BitBlt
очень эффективен, поэтому почти все операции рисования и манипуляции с изображениями выполняются с его помощью. Даже некоторое редактирование изображений будет делаться с помощью BitBlt
, перенося части изображений между контекстами устройств, которые представляют области памяти. При использовании GDI функция BitBlt()
из API Windows 32 была, наверное, самой важной и широко используемой функцией для манипуляции изображениями, хотя в GDI+ операции BitBlt
по большей части скрыты объектной моделью GDI+.
Невозможно использовать BitBlt
для областей, которые не являются прямоугольными, что можно легко смоделировать. Один из способов состоит в пометке некоторого цвета как прозрачного для целей BitBlt
поэтому данная область цвета в изображении-источнике не будет перезаписывать существующий цвет соответствующего пикселя на получающем устройстве. Можно также определить, что в процессе выполнения BitBlt
каждый пиксель получающегося изображения будет сформирован перед BitBlt
некоторой логической операцией (такой, как побитовое AND) на цветах этого пикселя в изображении-источнике и в получающем устройстве. Такие операции поддерживаются аппаратным ускорителем и могут использоваться для задания ряда тонких эффектов. Не рассматривая детали процесса, отметим что объект Graphics
реализует другой метод DrawImage()
. Он аналогичен методу DrawImageUnscaled()
, но поставляется с большим числом перезагружаемых версий, которые позволяют определить более сложные формы BitBlt
для использования в процессе рисования. DrawImage()
позволяет также рисовать ( BitBlt
) только определенную часта изображения, или выполнить на нем некоторые другие операции, такие как масштабирование (увеличение или уменьшение размера) при его рисовании.
Читать дальше