С# Windows 8 Store (Metro, WinRT) Байт-массив для BitmapImage
Я работаю над приложением Windows 8 Metro, которое применяет фильтры к изображениям. У меня есть веб-версия приложения и вы хотите его портировать. Но, как мы все знаем, у WinRT нет всех хороших вещей, которые .NET предоставляет в противном случае:/
В настоящее время я применяю фильтры для байтового массива, и я хочу сохранить его таким образом, потому что он очень быстрый! Поэтому в течение последних нескольких дней я искал способы конвертировать StorageFile в байт [], а затем байт [] в BitmapImage.
До сих пор мне удалось сделать первый (StorageFile to byte []). Вот как я это делаю:
public async Task<Byte[]> ImageFileToByteArray(StorageFile file)
{
IRandomAccessStream stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
PixelDataProvider pixelData = await decoder.GetPixelDataAsync();
return pixelData.DetachPixelData();
}
Этот фрагмент кода возвращает byte[]
, который содержит данные пикселя в виде BGRA.
И здесь идет сложная часть. Я не могу успешно преобразовать массив байтов в BitmapImage. Я искал по всем местам, и многие люди предлагают использовать WriteableBitmap, но это не очень хорошо для меня. Я также нашел некоторые фрагменты кода, которые должны работать... но они этого не делают.
Одно из решений, которые я пробовал, использует InMemoryRandomAccessStream следующим образом:
public async Task<BitmapImage> ByteArrayToBitmapImage(Byte[] pixels)
{
var stream = new InMemoryRandomAccessStream();
await stream.WriteAsync(pixels.AsBuffer());
stream.Seek(0);
var image = new BitmapImage();
await image.SetSourceAsync(stream);
return image;
}
Это вызывает следующее исключение:
Исключение типа "System.Exception" произошло в mscorlib.dll, но не было обработано в коде пользователя
Дополнительная информация: Компонент не найден. (Исключение из HRESULT: 0x88982F50)
Я попытался использовать эту строку вместо:
PixelDataProvider pixelData = await decoder.GetPixelDataAsync(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
new BitmapTransform(),
ExifOrientationMode.IgnoreExifOrientation,
ColorManagementMode.DoNotColorManage);
Но мне это не помогло, так как я продолжаю получать это исключение.
Я также пробовал это:
var bitmapImage = new BitmapImage();
var pixels = await ImageFileToByteArray(file);
ImageSource imgSource;
using (InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream())
{
using (DataWriter writer = new DataWriter(ms.GetOutputStreamAt(0)))
{
writer.WriteBytes(pixels);
await writer.StoreAsync();
}
await bitmapImage.SetSourceAsync(ms);
imgSource = bitmapImage;
}
И получите то же исключение, что и первая часть кода.
Я также пробовал несколько других способов, которые включают использование обычного потока, а затем преобразование в IRandomAccessStream, но они также не работали.
Все приведенные выше коды кажутся мне прекрасными. Поэтому я предполагаю, что проблема заключается в byte[]
. Я предполагаю, что формат pixelData внутри недействителен, поэтому я попытался изменить его на RGBA, но это тоже не помогло. Также PixelHeight и PixelWidth BitmapImage равны 0.
Ответы
Ответ 1
Это работает для меня,
private async Task<BitmapImage> ByteArrayToBitmapImage(byte[] byteArray)
{
var bitmapImage = new BitmapImage();
var stream = new InMemoryRandomAccessStream();
await stream.WriteAsync(byteArray.AsBuffer());
stream.Seek(0);
bitmapImage.SetSource(stream);
return bitmapImage;
}
Ответ 2
Это мой первый ответ. Надеюсь, это поможет.
У меня была такая же проблема, и я тренировался более 6 часов, пытаясь разобраться в этом.
вот что я придумал:
что вы сказали, было правильно. есть 2 способа конвертировать изображение в byteArray:
Первый aproach (ваш)
public async Task<byte[]> ImageFileToByteArrayAsync(StorageFile file)
{
IRandomAccessStream stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
PixelDataProvider pixelData = await decoder.GetPixelDataAsync();
return pixelData.DetachPixelData();
}
Второй аспект
public async Task<byte[]> ImageFileToByteArrayAsync(StorageFile file)
{
var inputStream = await file.OpenSequentialReadAsync();
var readStream = inputStream.AsStreamForRead();
var buffer = new byte[readStream.Length];
await readStream.ReadAsync(buffer, 0, buffer.Length);
return buffer;
}
если вы используете второй aproach для декодирования картинки без пикселя, этот конвертер будет работать:
public class ByteArrayToImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value == null || !(value is byte[]))
return null;
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
using (DataWriter writer = new DataWriter(stream.GetOutputStreamAt(0)))
{
writer.WriteBytes((byte[])value);
writer.StoreAsync().GetResults();
}
BitmapImage image = new BitmapImage();
image.SetSource(stream);
return image;
}
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
для первого aproach вам нужно будет работать с WriteableBitmap, как вы сказали.