Наверное все разработчики хоть раз сталкивались с задачей нарисовать или модифицировать изображение. В WP8 и WPF для решения этой задачи есть класс WriteableBitmap.
Однако у него есть один существенный недостаток – работа с ним должна происходить в GUI потоке. Для фоновых потоков есть различные пути обхода этой ситуации. Например, сначала сформировать изображение в отдельном массиве, потом передать его в основной поток, там создать экземпляр WriteableBitmap и, например, сохранить в файл. При этом стоит учитывать, что операции в основном потоке могут сделать UI менее отзывчивым в этот момент.
В процессе создания одного WP8-приложения, пришла идея написать для .NET класс, позволяющий работать с изображениями в фоновом потоке без применения "костылей". Так появилась небольшая библиотека Portable Imaging Library for .NET.
После такого длинного вступления перейдем к её подробностям.
Возможности Portable Imaging Library for .NET
- Создание изображение заданного размера или его асинхронная загрузка;
- Модификация изображения;
- Асинхронное сохранение изображения;
Все это происходит без необходимости обращения к GUI потоку.
Кроме того, как подсказывает название, это Portable Class Library. А значит поддерживаются такие целевые платформы как .NET 4.5 (WPF, ASP.NET) / WP8 / Windows Store. И, разумеется, библиотеку можно использовать в проектах, ориентированных на PCL.
Однако, в текущей версии есть следующие ограничения:
- Поддерживается только PNG формат, исключая grayscale PNG;
- Сохранение возможно только в RGB (true color) и ARGB (true color with alpha) PNG формате.
В дальнейшем, в случае востребованности библиотеки, будут сняты эти ограничения и добавлена поддержка других графических форматов.
Установка
Добавить библиотеку в свой проект можно с помощью консоли NuGet:
PM> Install-Package PortableImagingLibrary
Использование
Библиотека достаточно проста,а её использование достаточно интуитивно. В этом можно будет убедиться на примерах чуть ниже.
Основным классом библиотеки является Image. Внутри него изображение хранится в 32bit ARGB формате и доступно для изменения в любой момент времени.
Чтобы обеспечить совместимость с различными целевыми платформами, для чтения и записи изображений используется Stream.
Давайте посмотрим на пару примеров:
Код для WP8
// Loading PNG image from WP8 resource
var image = new PngImage();
var uri = new Uri("Assets/Tiles/logo.png", UriKind.Relative);
StreamResourceInfo sri = Application.GetResourceStream(uri);
await image.LoadPngAsync(sri.Stream);
// Modifying
int x = 1;
int y = 1;
uint colorARGB = image.GetPixel(x,y); // Get color of the specified point.
colorARGB = colorARGB / 2; // Modifying color value.
image.SetPixel(x, y, colorARGB); // Set color for specified pixel.
// Saving PNG image into isolated storage
var fileName = "Shared/ShellContent/newLogo.png";
using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication()) {
using (var pngSteam = new IsolatedStorageFileStream(fileName, FileMode.Create, isoStore))
await image.SavePngAsync(pngSteam, new PngSaveOptions() {
BitDepth = 8,
ColorType = ColorType.TruecolorWithAlpha
});
}
}
Код для .NET (WPF, ASP.NET)
/// Loading PNG image
var image = new Image();
using (var pngStream = new FileStream(pngFile, FileMode.Open, FileAccess.Read))
await image.LoadPngAsync(pngStream);
/// Modifying
int x = 1;
int y = 1;
uint colorARGB = image.GetPixel(x,y); // Get color of the specified point.
colorARGB = colorARGB / 2; // Modifying color value.
image.SetPixel(x, y, colorARGB); // Set color for specified pixel.
/// Saving PNG image
using (var pngSteam = new FileStream(pngFile, FileMode.Create, FileAccess.Write)) {
await image.SavePngAsync(pngSteam, new PngSaveOptions() {
BitDepth = 8,
ColorType = ColorType.TruecolorWithAlpha
});
}
Как можно легко заметить, все отличие сводится к различному коду создания потоков для чтения и сохранения изображения.
А теперь рассмотрим классы библиотеки подробнее.
Класс Image
Класс Image предоставляет основные операции с изображениями: загрузка, модификация и сохранение.
Конструкторы
- Image() – конструктор по умолчанию.
- Image(int width, int height) – конструктор, создающий изображение указанного размера.
Свойства
- uint BackgroundColor { get; set; } – свойство, позволяющее получить или установить фоновый цвет.
- int Width { get; } – ширина изображения.
- int Height { get; } – высота изображения.
Методы
- void SetPixel(int x, int y, uint colorARGB) – присваивает заданному пикселю (x,y) указанный цвет colorARGB.
- uint GetPixel(int x, int y) – возвращает цвет заданного пикселя (x,y).
- Task LoadPngAsync(Stream source) – асинхронно загружает изображение из PNG файла.
- Task SavePngAsync(Stream target, PngSaveOptions options) – асинхронно сохраняет изображение в PNG файл.
Класс PngSaveOptions
Класс PngSaveOptions содержит параметры для сохранения изображения в PNG формат.
- byte BitDepth { get; set; } – глубина изображения в битах на каждый цвет. В текущей версии поддерживается только 8 бит на канал (32-bit ARGB или 24-bit RGB изображения).
- ColorType ColorType { get; set; } – тип изображения:
- Greyscale (в данный момент не поддерживается);
- Truecolor;
- IndexedColor (в данный момент сохранение не поддерживается);
- GreyscaleWithAlpha (в данный момент не поддерживается);
- TruecolorWithAlpha;
Обратная связь
Вопросы, советы, предложения принимаются по почте или на сайте проекта.