Мы с другом провели большую часть прошлой ночи, чуть не вырвав себе волосы, пытаясь работать с некоторыми изображениями в приложении метро. Мы добавили изображения в приложение с помощью чудо-кнопки «Поделиться», а затем мне захотелось поработать с ними, обрезать изображения и сохранить их обратно в папку appdata. Это оказалось крайне неприятно.
Мой вопрос в конце всего этого будет звучать так: «Как правильно это сделать, не чувствуя, что я склеиваю воедино кучу несоответствующих кусочков головоломки?»
При совместном использовании нескольких изображений с приложением они появляются в виде списка Windows.Storage.StorageFile
s. Вот некоторый код, используемый для обработки этого.
var storageItems = await _shareOperation.Data.GetStorageItemsAsync();
foreach (StorageFile item in storageItems)
{
var stream = await item.OpenReadAsync();
var properties = await item.Properties.GetImagePropertiesAsync();
var image = new WriteableBitmap((Int32)properties.Width, (Int32)properties.Height);
image.SetSource(stream);
images.Add(image);
}
Поиск в Интернете показал, что в настоящее время Windows.UI.Xaml.Media.Imaging.WriteableBitmap
— это единственная вещь, которая позволяет вам получить доступ к пиксельным данным изображения. Этот вопроссодержит полезный ответ, полный методов расширения для сохранения изображений в файл, поэтому мы использовали их.
Наши проблемы были еще хуже, когда я снова попытался открыть файлы позже. Я сделал что-то похожее на то, что было раньше:
var files = await ApplicationData.Current.LocalFolder.GetFilesAsync();
foreach (var file in files)
{
var fileStream = await file.OpenReadAsync();
var properties = await file.Properties.GetImagePropertiesAsync();
var bitmap = new WriteableBitmap((Int32)properties.Width, (Int32)properties.Height);
bitmap.SetSource(fileStream);
System.IO.Stream stream = bitmap.PixelBuffer.AsStream();
Возникла проблема. Какова длина этого потока, если я хочу получить из него байты?
// CRASH! Length isn't supported on an IRandomAccessStream.
var pixels = new byte[fileStream.Length];
Хорошо, попробуйте еще раз.
var pixels = new byte[stream.Length];
Это работает, за исключением...если изображение сжато, поток короче, чем вы ожидаете, поэтому в конечном итоге вы получите исключение за пределами границ. А пока представьте, что это несжатое растровое изображение.
await _stream.ReadAsync(pixels, 0, pixels.Length);
Угадайте, что. Несмотря на то, что я сказал bitmap.SetSource(fileStream);
для чтения данных, мой массив байтов по-прежнему полон нулей. Понятия не имею почему. Если я передам это же растровое изображение в свой пользовательский интерфейс через группу образцов данных, изображение будет отображаться нормально. Таким образом, он явно где-то получил данные о пикселях в этом растровом изображении, но я не могу прочитать их из растрового изображения
. PixelBuffer
? Почему нет?
Наконец, вот что в итоге заработало.
var decoder = await BitmapDecoder.CreateAsync(BitmapDecoder.PngDecoderId, fileStream);
var data = await decoder.GetPixelDataAsync();
var bytes = data.DetachPixelData();
/* process my data, finally */
} // end of that foreach I started a while ago
Итак, теперь у меня есть данные изображения, но у меня все еще есть большая проблема. Чтобы что-то с ним делать, я должен делать предположения о его формате. Я понятия не имею, будь то rgba, rgb, abgr, bgra, какими бы они ни были. Если я ошибаюсь, моя обработка просто терпит неудачу. У меня были десятки тестовых запусков, выдающих нулевой байт и поврежденные изображения, перевернутые изображения (???), неправильные цвета и т. д. Я ожидал найти некоторую информацию в свойствах
, которые Я получил вызов await file.Properties.GetImagePropertiesAsync();
, но не повезло. Это содержит только ширину и высоту изображения, а также некоторые другие бесполезные вещи. Минимум документацииздесь.
Итак, почему этот процесс такой болезненный? Является ли это просто отражением незрелости библиотек прямо сейчас, и могу ли я ожидать, что она станет лучше? Или уже есть какой-то стандартный способ сделать это? Хотелось бы, чтобы это было так же просто, как в System.Drawing
.Это дало вам все данные, которые вам когда-либо были нужны, и с радостью правильно загрузило любой тип изображения, не заставляя вас самостоятельно иметь дело с потоками.