15

画像にフィルターを適用する Windows 8 Metro アプリに取り組んでいます。アプリの Web バージョンがあり、それを移植したいと考えていました。しかし、誰もが知っているように、WinRT には .NET が提供するすべての優れた機能が備わっているわけではありません:/

現在、バイト配列にフィルターを適用していますが、超高速なので、そのままにしておきたいです! そのため、過去数日間、StorageFile を byte[] に変換し、次に byte[] を BitmapImage に変換する方法を探していました。

これまでのところ、最初のもの(StorageFileから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 の使用を提案していますが、それは私にはあまり役に立ちません。また、動作するはずのコードをいくつか見つけましたが、動作しません。

私が試した解決策の 1 つは、次のように 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;
        }

そして、最初のコードと同じ例外を取得します。

通常の Stream を使用してから IRandomAccessStream に変換するなど、他のいくつかの方法も試しましたが、どちらも機能しませんでした。

上記のコードはすべて私には問題ないようです。したがって、現時点での私の推測では、問題はbyte[]. 内部の pixelData の形式が有効ではないと推測しているので、RGBA に変更しようとしましたが、それも役に立ちませんでした。BitmapImage の PixelHeight と PixelWidth も 0 です。

4

2 に答える 2

13

これは私のために働いています、

    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;
    }
于 2013-08-09T15:33:23.223 に答える
1

これが私の最初の答えです。

私はまったく同じ問題を抱えていて、これを理解するのに6時間以上かかりました. これが私が思いついたものです:あなたの言ったことは正しかったです。画像を byteArray に変換する方法は 2 つあります。

最初のアプローチ(あなたのもの)

        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;
    }

ピクセルを使用せずに 2 番目のアプローチを使用して画像をデコードする場合、このコンバーターは機能します。

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();
    }

最初のアプローチでは、あなたが言ったように WriteableBitmap を使用する必要があります。

于 2014-11-28T21:34:46.190 に答える