Nokia недавно выпустила бета-версию Nokia Imaging SDK, позволяющего создавать приложения Windows Phone 8 с расширенными возможностями в работе с изображениями для смартфонов Nokia Lumia.
Nokia Imaging SDK включает библиотеку для манипуляций над изображениями, захваченными и сохраненными на устройствах Windows Phone, и содержит средства для кодирования и декодирования JPEG-изображений, применения фильтров и эффектов, кадрирования, поворота и масштабирования. Nokia Imaging SDK предоставляет более 50 готовых фильтров и эффектов. Вы можете применять не только эффекты вроде сепии, мультипликации, абриса (sketch) и т. д., но и автоматическое улучшение изображения, контроль яркости, контрастности, насыщенности и многое другое. SDK специально разработан для обработки изображений на мобильных устройствах с расчетом на максимальную производительность и эффективное использование памяти.
В этой статье я продемонстрирую применение эффекта абриса на примере приложения Paper Photo. Эффект абриса применяется в реальном времени к потоку данных, поступающих от видоискателя; это приложение также дает возможность пользователям захватывать изображения и сохранять их в каталоге с фотографиями, снятыми камерой смартфона (phone’s camera roll). Я разработал это приложение, используя Visual Studio 2012, Nokia Imaging SDK и Windows Phone 8 SDK. Приложение тестировалось на смартфоне Nokia Lumia 920.
Основы Nokia Imaging SDK
Nokia Imaging SDK создан в Nokia для того, чтобы предоставить вам полный доступ к мощной библиотеке средств манипуляций над изображениями, которая помогает легко и быстро создавать впечатляющие приложения для работы с изображениями. Как упоминалось, этот SDK спроектирован с расчетом на высокую производительность и использование небольшого объема памяти, что крайне важно, поскольку Microsoft и Nokia работают над созданием устройств следующего поколения, таких как Nokia Lumia 1020. Данный SDK уже используется в приложении Nokia для работы с изображениями — Creative Studio. SDK и библиотека доступны бесплатно (лицензионное соглашение см. по ссылке bit.ly/130tVHJ), и в настоящее время SDK поддерживает только приложения Windows Phone 8.
Nokia Imaging SDK предлагает следующие средства.
- Простой в использовании API, доступный как из управляемого кода, так и из неуправляемого. Это означает, что SDK предоставляется как библиотека Windows Phone Runtime, и вы можете вызывать методы библиотеки из C#, Visual Basic или C++. API включает набор классов и методов для различных операций над изображениями.
- Технология RAJPEG для доступа к данным изображения без декодирования всего JPEG-изображения, что обеспечивает невероятно быстрый предварительный просмотр, применение эффектов, кадрирование и поворачивание изображений высокого разрешения.
- Более 50 фильтров, эффектов и расширений. Некоторые из расширений позволяют программным способом регулировать RGB-уровни, контраст, яркость и насыщенность. Кроме того, при необходимости можно создавать собственные эффекты и фильтры. В дополнение к этим фильтрам и эффектам SDK также обеспечивает кадрирование, поворачивание и масштабирование с неограниченной функциональностью отмены любых операций.
- Несколько полнофункциональных приложений-примеров позволяют исследовать исходный код и изучить возможности SDK. Эти примеры охватывают многие возможности вроде манипуляций в реальном времени над свойствами фильтров и применением к фотоснимкам нескольких уровней фильтров.
- Обширная документация с краткими руководствами, проекты примеров, справочное руководство по API и несколько документов, где дается обзор некоторых основных концепций, понимание которых необходимо для создания приложений, работающих с изображениями.
Приступаем
Для своего приложения-примера я использовал на верхнем уровне следующие API из Nokia Imaging SDK:
- Nokia.Graphics;
- Nokia.Graphics.Imaging;
- Nokia.InteropServices.WindowsRuntime.
Nokia.Graphics.Imaging API содержит базовую функциональность Nokia Imaging SDK, в том числе все фильтры, эффекты и кодеки JPEG. Библиотека Nokia.InteropServices.WindowsRuntime используется на внутреннем уровне и является обязательной библиотекой, на которую нужно ссылаться в вашем проекте. Она содержит класс BufferFactory, используемый для создания экземпляра IBuffer. Этот SDK можно установить через диспетчер NuGet-пакетов в Visual Studio. Найти этот пакет можно поиском по NokiaImagingSDK.
Объектный граф этого приложения в основном состоит из трех ключевых классов, показанных на рис. 1. MainPage — это типичная страница приложения, реализованная в XAML-файле и парном ему файле исходного кода на C#. Класс MainPage реализует UI приложения, который включает MediaElement, отображающий видоискатель камеры с эффектом абриса (sketch effect). Класс MainPage также владеет экземплярами двух других ключевых классов: CameraStreamSource и NokiaSketchEffect. Первый из них наследует от MediaStreamSource и предоставляет данные от камеры, а NokiaSketchEffect реализует эффект абриса. Класс CameraStreamSource реализован Nokia вне Nokia Imaging SDK и предлагается разработчикам через приложения-примеры, созданные компанией.
Рис. 1. Схема классов для проекта Paper Photo
Объектный граф преобразуется в структуру кода, показанную на рис. 2.
Рис. 2. Структура решения в Visual Studio
Определение UI
UI этого приложения довольно прост (рис. 3). Основная страница отображает изображение с видоискателя камеры и содержит панель приложения с единственной кнопкой для захвата снимка с эффектом абриса.
Рис. 3. UI приложения Paper Photo
На рис. 4 показана XAML-разметка основной страницы. В ней используется элемент Grid для определения контейнера, задействованного для вывода изображения с видоискателя с примененным эффектом абриса.
Nokia Imaging SDK создан в Nokia для того, чтобы предоставить полный доступ к мощной библиотеке средств манипуляций над изображениями, которая помогает легко и быстро создавать впечатляющие приложения для работы с изображениями.
Рис. 4. XAML-разметка основной страницы
<Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid Grid.Row="1" Margin="8"> <Grid x:Name="MediaElementContainer" Margin="0"></Grid> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock Text="{Binding Path=LocalizedResources.ApplicationTitle, Source={StaticResource LocalizedStrings}}" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/> </StackPanel> </Grid> </Grid>
Панель приложения создается с помощью разметки, представленной на рис. 5. Как видите, она определяет кнопку захвата и элемент меню About. Кнопка захвата связана с обработчиком событий щелчка.
Рис. 5. Разметка панели приложения
<phone:PhoneApplicationPage.ApplicationBar> <shell:ApplicationBar Opacity="0.4"> <shell:ApplicationBarIconButton x:Name="CaptureButton" Text="Capture" IconUri="Assets/capture-button-icon.png" Click="CaptureButton_Click" IsEnabled="True" /> <shell:ApplicationBar.MenuItems> <shell:ApplicationBarMenuItem Click="OnAboutPageButtonClicked" Text="about" /> </shell:ApplicationBar.MenuItems> </shell:ApplicationBar> </phone:PhoneApplicationPage.ApplicationBar>
Windows Phone использует модель защиты на основе доступа к возможностям (capabilities-driven security model). Эта модель позволяет разрешать пользователям активацию определенной функциональности. В моем демонстрационном приложении нужно разрешить следующие возможности для пользователей.
- ID_CAP_ISV_CAMERA Обеспечивает доступ к камере на обратной стороне смартфона (основной) или на лицевой стороне.
- ID_CAP_MEDIALIB_PHOTO Обеспечивает доступ только для чтения к фотоснимкам в медийной библиотеке. Кроме того, дает возможность приложению сохранять снимки в каталоге фотографий, отснятых камерой (camera roll). Я продемонстрирую эту возможность позже, когда буду сохранять снимок в этом каталоге после применения эффекта абриса.
Приложение требует должного функционирования камеры на обратной стороне. Параметр ID_REQ_REARCAMERA выбирается для того, чтобы предотвратить установку приложения на смартфон без камеры на обратной стороне.
Применение эффекта абриса в реальном времени к изображению от видоискателя камеры
За применение этого эффекта в реальном времени к изображению от видоискателя камеры отвечает класс NokiaSketchEffect. Заметьте, что для получения нужного эффекта в моем приложении используется SketchMode.Gray. Функция GetSampleAsync класса CameraStreamSource отвечает за обработку буфера камеры с применением эффекта абриса, и с буфером предоставляется media-элемент. Метод GetSampleAsync вызывает метод NokiaSketchEffect.GetNewFrameAndApplyEffect, чтобы получить модифицированный буфер камеры. Код на рис. 6 показывает, как это делается.
Рис. 6. Получение модифицированного буфера камеры
public async Task GetNewFrameAndApplyEffect(IBuffer processedBuffer) { if (captureDevice == null) { return; } captureDevice.GetPreviewBufferArgb(cameraBitmap.Pixels); Bitmap outputBtm = new Bitmap( outputBufferSize, ColorMode.Bgra8888, (uint)outputBufferSize.Width * 4, processedBuffer); EditingSession session = new EditingSession(cameraBitmap.AsBitmap()); session.AddFilter(FilterFactory.CreateSketchFilter(SketchMode.Gray)); await session.RenderToBitmapAsync(outputBtm); }
Закрытая переменная captureDevice в функции принадлежит классу PhotoCaptureDevice, который находится в Windows.Phone.Media.Capture. Функция RenderToBitmapAsync предоставляется Nokia Imaging SDK для поддержки асинхронного рендеринга EditingSession в битовую карту. EditingSession — важный класс из Nokia Imaging SDK, представляющий сеанс редактирования обрабатываемого изображения. Объект EditingSession является сердцевиной SDK. В типичном рабочем процессе EditingSession создается на основе изображения, в этот сеанс добавляются фильтры или эффекты, а затем выполняется рендеринг EditingSession в битовую карту или в буфер памяти; после этого EditingSession закрывается. Код на рис. 6 показывает, как создается новая битовая карта, сопоставленная с аргументом processedBuffer, потом к ней применяется эффект абриса, а далее выполняется рендеринг в новый буфер. Наконец, метод CreateSketchFilter создает облик оконтуренного изображения. Эта функция принимает перечисление SketchMode в качестве аргумента, который передается фильтру абриса и определяет конкретный режим оконтуривания. Доступно два режима: абрис в оттенках серого и цветовой абрис. Как видите, в коде на рис. 6 я использовал SketchMode.Gray. Это позволяет приложению Paper Photo создавать изображения в оттенках серого.
Захват и сохранение картинки как JPEG-изображения в каталоге фотоснимков камеры
Пока что я показал, как применять эффект абриса в реальном времени к видоискателю. Теперь я расскажу о захвате картинки с видоискателя и последующем ее сохранении в каталоге фотоснимков, сделанных камерой устройства. Функция захвата сначала инициирует автофокусировку, а затем захватывает снимок. Вы можете обрабатывать не только функциональность захвата с панели приложения, но и захват, инициируемый аппаратным триггером.
Код на рис. 7 обеспечивает захват через кнопку камеры. Точнее, функция захвата включает или отключает аппаратную функцию спуска затвора. Класс CameraButtons предоставляет события, которые инициируются аппаратными кнопками затвора. Одно из таких событий — ShutterKeyHalfPressed, генерируемое при неполном нажатии аппаратной кнопки затвора и ее удержании в таком положении в течение примерно 800 мс. Другое событие — ShutterKeyPressed. Оно происходит, когда аппаратная кнопка затвора нажимается полностью. Функция SetCameraButtonsEnabled также обеспечивает удаление обработчиков этих событий, помогая освобождать память, связанную с камерой.
Рис. 7. Захват, инициируемый кнопкой камеры
private void SetCameraButtonsEnabled(bool enabled) { if (enabled) { Microsoft.Devices.CameraButtons.ShutterKeyHalfPressed += ShutterKeyHalfPressed; Microsoft.Devices.CameraButtons.ShutterKeyPressed += ShutterKeyPressed; } else { Microsoft.Devices.CameraButtons.ShutterKeyHalfPressed -= ShutterKeyHalfPressed; Microsoft.Devices.CameraButtons.ShutterKeyPressed -= ShutterKeyPressed; } }
Теперь я подробно объясню процесс захвата. В коде на рис. 8 объект camera представляет устройство захвата снимков, await-функция camera.FocusAsync инициирует автофокусировку, а метод StartCaptureAsync захватывает кадр. Но перед тем как вы сможете захватить кадр, вы должны подготовить последовательность захвата (capture sequence). Для этого вызовите PrepareCaptureSequenceAsync. Вы также создаете объект последовательности захвата с одним кадром, как видно из camera.CreateCaptureSequence(1). Значение 1 указывает количество кадров, которые будут захвачены сразу после того, как вы инициируете захват. Наконец, вы указываете свойства камеры и параметры снимка, используя метод KnownCameraPhotoProperties. LockedAutoFocusParameters устанавливается в None, сообщая, что фокус, выдержка и баланс белого будут настроены автоматически перед захватом.
Рис. 8. Процесс захвата
private async System.Threading.Tasks.Task Capture() { try { await camera.FocusAsync(); MemoryStream imageStream = new MemoryStream(); imageStream.Seek(0, SeekOrigin.Begin); CameraCaptureSequence sequence = camera.CreateCaptureSequence(1); sequence.Frames[0].CaptureStream = imageStream.AsOutputStream(); await camera.PrepareCaptureSequenceAsync(sequence); await sequence.StartCaptureAsync(); camera.SetProperty( KnownCameraPhotoProperties.LockedAutoFocusParameters, AutoFocusParameters.None); ... }
Следующий код показывает, как сохранить захваченный снимок в каталог фотоснимков камеры:
MediaLibrary library = new MediaLibrary(); EditingSession session = new EditingSession(imageStream.GetWindowsRuntimeBuffer()); using (session) { session.AddFilter(FilterFactory.CreateSketchFilter(SketchMode.Gray)); IBuffer data = await session.RenderToJpegAsync(); library.SavePictureToCameraRoll(FileNamePrefix + DateTime.Now.ToString() + ".jpg", data.AsStream()); }
Класс MediaLibrary предоставляется Microsoft.XNA.Framework.Media API и используется для сохранения снимков в медиа-библиотеке смартфона. Пространство имен Microsoft.XNA.Framework.Media содержит классы для перечисления, воспроизведения и просмотра песен, альбомов, списков проигрывания и картинок. Далее вы можете задействовать класс EditingSession из Nokia Imaging SDK, чтобы создать сеанс на основе буфера сжатого изображения и применить фильтр эффекта абриса перед сохранением картинки в каталоге фотоснимков камеры с помощью функции SavePictureToCameraRoll.
Интеграция с интерактивной линзой
В Windows Phone 8 можно создать интерактивную линзу (media lens), которая открывается из встроенного приложения камеры и запускает ваше приложение прямо в среде видоискателя. Для интеграции с интерактивной линзой приложение нужно зарегистрировать на расширение Camera_Capture_App. Это расширение объявляет ОС, что приложение Paper Photo может отображать видоискатель при запуске из приложения камеры. Расширения задаются в файле WMAppManifest.xml. Вы должны открыть этот файл в текстовом редакторе: щелкните файл правой кнопкой мыши и выберите Open With… | Text Editor. Расширение линзы указывается следующим элементом Extension (сразу после элемента Tokens внутри элемента Extensions):
<Extension ExtensionName="Camera_Capture_App" ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5631}" TaskID="_default" />
Теперь ваше приложение интегрировано с линзой и может сохранять картинки прямо в каталоге фотоснимков камеры на устройстве. Изображение на рис. 9 было снято встроенным приложением камеры, а изображение на рис. 10 — приложением Paper Photo с применением эффекта абриса.
Рис. 9. Обычное изображение, снятое встроенным приложением камеры
Рис. 10. Изображение, снятое приложением Paper Photo с применением эффекта абриса
Заключение
В этой статье я исследовал API-средства захвата фотоснимков, разработанные Microsoft и содержащиеся в новом Nokia Imaging SDK, для создания богатой функциональности обработки изображений. Я применял эффект абриса к картинке с видоискателя в реальном времени, а затем захватывал снимок и сохранял его в каталоге фотоснимков камеры на устройстве. Как видите, теперь вам доступна уйма средств, которыми можно пользоваться благодаря Nokia Imaging SDK, который упрощает создание приложений, подобных моему. Для краткости я опустил несколько мелких деталей, но вы можете увидеть их в сопутствующем исходном коде (github.com/Srikar-Doddi/PaperPhoto). Это лишь один пример использования Nokia Imaging SDK, но есть масса других средств, которые вы можете добавлять, и в совокупности их возможности безграничны. Надеюсь, что вы используете этот код в качестве отправной точки и добавите больше средств в свое приложение.