2

パレットを「カラー タイプ」として使用する PNG のレンダリングに問題があります。問題を再現するための簡単なコードを次に示します。

private async System.Threading.Tasks.Task Fetch()
{
    HttpClient httpClient = new HttpClient();
    Uri uri = new Uri("http://static.splashnology.com/articles/How-to-Optimize-PNG-and-JPEG-without-Quality-Loss/PNG-Palette.png");
    HttpResponseMessage response = await httpClient.GetAsync(uri);
    if (response.StatusCode == HttpStatusCode.Ok)
    {
        try
        {
            var content = await response.Content.ReadAsBufferAsync();
            WriteableBitmap image = await BitmapFactory.New(1, 1).FromStream(content.AsStream());
            Rect destination = new Rect(0, 0, image.PixelWidth, image.PixelHeight);
            Rect source = new Rect(0, 0, image.PixelWidth, image.PixelHeight);
            WriteableBitmap canvas = new WriteableBitmap(image.PixelWidth, image.PixelHeight);
            canvas.Blit(destination, image, source);
            RadarImage.Source = canvas;
        }
        catch (Exception e)
        {
            System.Diagnostics.Debug.WriteLine(e.Message);
            System.Diagnostics.Debug.WriteLine(e.StackTrace);
        }
    }
}

Windows Phone 8.1 を使用してそのコードを実行すると、画像が間違った色で表示されます。「カラー タイプ」として RGB を使用している PNG を使用して同じテストを行うと、すべて正常に動作します。

Codeplex フォーラムを見てきましたが、それに関連する投稿は見たことがありません。レンダリング方法に関連している可能性がありますが、問題として報告しました。間違ったレンダリングを引き起こす可能性のある WriteableBitmap の使用方法に間違いはありますか?


アップデート

このディスカッション https://writeablebitmapex.codeplex.com/discussions/274445によると 、問題はバイトの予期しない順序に関連しています。これらのコメントは1年半前のものなので、どこかに適切な修正があるはずだと思います...

正しくレンダリングされていない画像は、上記のコードにあります。

これは、同じコードを使用して正しくレンダリングされます。 http://www.queness.com/resources/images/png/apple_ex.png

これら 2 つの画像の唯一の違いは、「色の種類」プロパティです。失敗したものは「パレット」に設定され、正しくレンダリングされたものは「RGB アルファ」に設定されます。

ありがとう!カルロス。

4

1 に答える 1

1

問題は、パレットの png を RGBA に変換するように見える FromStream 拡張機能にあるようです。お気づきのように、WriteableBitmap は BGRA を必要としています。FromStream はパレット以外の png のピクセルをスウィズルせずに渡すと思われます。これにより、リンゴは BGRA として開始および終了し、サルは最終的に RGBA になり、赤と青を逆にして描画します。

FromStream をスキップして BitmapDecoder を使用することで、この問題を回避できます。これにより、デコード先の形式を指定できます。

// Read the retrieved image's bytes and write them into an IRandomAccessStream
IBuffer buffer = await response.Content.ReadAsBufferAsync();
var randomAccessStream = new InMemoryRandomAccessStream();
await randomAccessStream.WriteAsync(buffer);

// Decode the downloaded image as Bgra8 with premultiplied alpha
// GetPixelDataAsync lets us pass in the desired format and it'll do the magic to translate as it decodes
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(randomAccessStream);
var pixelData = await decoder.GetPixelDataAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied, new BitmapTransform(), ExifOrientationMode.IgnoreExifOrientation, ColorManagementMode.DoNotColorManage);

// Get the decoded bytes
byte[] imageData = pixelData.DetachPixelData();

// And stick them in a WriteableBitmap
WriteableBitmap image = new WriteableBitmap((int)decoder.PixelWidth,(int) decoder.PixelHeight);
Stream pixelStream = image.PixelBuffer.AsStream();

pixelStream.Seek(0, SeekOrigin.Begin);
pixelStream.Write(imageData, 0, imageData.Length);

// And stick it in an Image so we can see it.
RadarImage.Source = image;
于 2014-10-25T02:39:11.753 に答える