Работа с изображениями в Windows Phone 7
Цель лекции: научиться работать с изображениями как в XNA, так и в Silverlight.
Еще одним объектом, который применяется в приложениях на Silverlight и XNA так же широко, как и текст, является растровое изображение. Ранее растровое изображение определялось как двумерный массив битов, соответствующих пикселям графического устройства.
В Silverlight растровое изображение иногда называют просто изображением, но это, главным образом, наследие Windows Presentation Foundation, где изображениями называют и растровые изображения, и векторные рисунки. И в WPF, и в Silverlight элемент Image обеспечивает вывод на экран растровых изображений, но сам не является растровым изображением.
В XNA растровое изображение типа Texture2D и, следовательно, часто называется текстурой, но этот термин преимущественно относится к 3D-графике, где растровые изображения используются для заполнения поверхностей 3D-объектов. В 2D-графике на XNA растровые изображения часто используются как спрайты.
Растровые изображения также используются в качестве значков приложений в телефоне. При создании нового проекта на XNA или Silverlight в Visual Studio для различных целей создается три растровых изображения.
Форматом растровых изображений в Windows является BMP, но в последние годы он утратил свою былую популярность, поскольку большее распространение получили форматы со сжатием. В настоящее время самыми широко используемыми форматами являются:
- JPEG (Joint Photography Experts Group) — один из популярных графических форматов, применяемый для хранения фотоизображений и подобных им изображений. Файлы, содержащие данные JPEG, обычно имеют расширения (суффиксы) .jpeg, .jfif, .jpg, .JPG, или .JPE.
- PNG (Portable Network Graphics) — растровый формат хранения графической информации, использующий сжатие без потерь по алгоритму Deflate.
- GIF (Graphics Interchange File) — популярный формат графических изображений. Способен хранить сжатые данные без потери качества в формате не более 256 цветов. Имеет поддержку прозрачности и анимации.
XNA поддерживает все три (и многие другие). Silverlight поддерживает только JPEG и PNG. (Разработчики на Silverlight не всегда помнят об этом и часто удивляются, почему это приложение на Silverlight отказывается выводить на экран GIF или BMP.)
Применяемые форматами PNG и GIF алгоритмы сжатия не приводят к потере данных. Исходное растровое изображение может быть восстановлено со 100% точностью. Поэтому эти алгоритмы часто называют алгоритмами сжатия "без потерь".
JPEG реализует алгоритм "с потерями", потому что отбрасывает визуальные данные, которые не воспринимаются человеческим глазом. Такой тип сжатия хорош для реалистичных изображений, таких как фотографии, но менее подходит для растровых изображений, производных от текста или векторных рисунков, таких как архитектурные чертежи или мультфильмы.
И Silverlight, и XNA обеспечивает возможность интерактивной или алгоритмической обработки растровых изображений на уровне пикселей для формирования или изменения имеющихся растровых изображений.
Создание текстуры на XNA
Разработка 2D-графики в XNA – практически исключительно процесс перемещения спрайтов по экрану. Поэтому можно ожидать, что загрузка и отрисовка растровых изображений в приложении на XNA не составляет никакого труда, и это действительно так.
Назовем первый проект XnaLocalBitmap, потому что это растровое изображение будет храниться как часть содержимого приложения. Создадим любое растровое 320 пиксела шириной и 160 пикселов высотой, назовём его Hello.png.
Чтобы добавить растровое изображение в проект содержимого приложения, щелкните правой кнопкой мыши имя проекта XnaLocalBitmapContent, выберите Add, затем Existing Item (Существующий элемент). После этого перейдите к файлу. Когда файл появится в проекте, его можно щелкнуть правой кнопкой мыши и просмотреть Properties. Вы увидите, что его свойство Asset Name имеет значение "Hello".
Наша задача – вывести растровое изображение посередине экрана. В файле Game1.cs описываем поле для хранения Texture2D и еще одно поле для координат:
Проект XNA: XnaLocalBitmap Файл: Game1.cs (фрагмент, демонстрирующий поля)
public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; Texture2D helloTexture; Vector2 position; … }
Оба поля задаются во время выполнения метода LoadContent. Для загрузки Texture2D используем тот же универсальный метод, который применялся для загрузки SpriteFont. Класс Texture2D имеет свойства Width и Height, определяющие размеры растрового изображения в пикселях. Как и в приложении с выводом текста посередине экрана из главы 1, поле position обозначает координаты верхнего левого угла растрового изображения на экране в пикселях:
Проект XNA: XnaLocalBitmap Файл: Game1.cs (фрагмент)
protected override void LoadContent() { spriteBatch = new SpriteBatch(GraphicsDevice); helloTexture = this.Content.Load<Texture2D>("Hello"); Viewport viewport = this.GraphicsDevice.Viewport; position = new Vector2((viewport.Width - helloTexture.Width) / 2, (viewport.Height - helloTexture.Height) / 2); }
Класс SpriteBatch имеет семь методов Draw для формирования визуального представления растровых изображений. Этот, безусловно, самый простой:
Проект XNA: XnaLocalBitmap Файл: Game1.cs (фрагмент)
protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.Navy); spriteBatch.Begin(); spriteBatch.Draw(helloTexture,position, Color.White); spriteBatch.End(); base.Draw(gameTime); }
Последний аргумент Draw – это цвет, который может использоваться для смягчения существующих цветов растрового изображения. Используйте Color.White, если хотите, чтобы цвета растрового изображения отображались без искажения.
И вот, что мы получили:
Элемент Image в Silverlight
Аналогичное приложение на Silverlight даже еще проще. Создадим проект SilverlightLocalBitmap. Сначала создадим в проекте папку для хранения растрового изображения. Это не обязательно, но делает проект более аккуратным. Обычно разработчики называют эту папку Images (Рисунки), Media (Мультимедиа) или Assets (Ресурсы) в зависимости от типов файлов, для которых она предназначается. Щелкните правой кнопкой мыши имя проекта, выберите Add и затем New Folder (Новая папка). Назовем ее Images. Затем щелкаем правой кнопкой мыши имя папки и выбираем Add и Existing Item. Переходим к файлу Hello.png. (Если вы самостоятельно создали другой растровый рисунок, не забывайте, что Silverlight поддерживает только файлы в формате JPEG и PNG.)
Из кнопки Add выберите Add или Add as Link (Добавить как ссылку). Если выбрана опция Add, файл будет физически скопирован в подпапку проекта. При выборе Add as Link в проекте будет сохранена только ссылка на файл, но файл изображения все равно будет скопирован в исполняемый файл.
Заключительный шаг – щелкаем правой кнопкой мыши имя файла растрового изображения и открываем Properties. Убеждаемся, что Build Action (Действие при сборке) имеет значение Resource (Ресурс). Можно изменить значение Build Action на Content, но давайте пока оставим его неизменным, и остановимся на различиях несколько позже.
В Silverlight элемент Image используется для отображения растровых изображений точно так же, как элемент TextBlock используется для отображения текста. Задайте в качестве значения свойства Source (Источник) элемента Image путь к файлу растрового изображения в проекте:
Проект Silverlight: SilverlightLocalBitmap Файл: MainPage.xaml (фрагмент)
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Image Source="Images/Hello.png" /> </Grid>
Изображение несколько отличается от обеспечиваемого приложением на XNA, и дело не только в заголовках. По умолчанию элемент Image расширяет или растягивает растровое изображение максимально, как только возможно, для заполнения контейнера (сетки для содержимого), сохраняя при этом его пропорции. Особенно это заметно, если задать атрибуту SupportedOrientations начального тега PhoneApplicationPage значение PortraitOrLandscape и повернуть телефон на бок:
Если требуется вывести растровое изображение в его натуральную величину, задайте свойству Stretch элемента Image значение None:
<Image Source="Images/Hello.png" Stretch="None" />