Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebP with alpha image is broken #1436

Open
neelabo opened this issue Jul 29, 2019 · 12 comments
Open

WebP with alpha image is broken #1436

neelabo opened this issue Jul 29, 2019 · 12 comments
Labels
Bug Product bug (most likely)
Milestone

Comments

@neelabo
Copy link

neelabo commented Jul 29, 2019

  • .NET Core Version: 3.0 Preview7
  • Windows version: Windows 10 version 1903
  • Does the bug reproduce also in WPF for .NET Framework 4.8?: Yes

Problem description:

WebP can now be displayed on Windows 10, but when trying to display transparent WebP with WPF, the transparent part becomes broken display.

sample

However, BitmapImage using DecodePixelWidth different from the source is displayed correctly.

I submitted a similar report as an issue with the .NET Framework.

Minimal repro:

  • The test WebP image is here.
  • <Image Source="1_webp_a.webp"/> only.
@grubioe grubioe added the Bug Product bug (most likely) label Jul 29, 2019
@grubioe grubioe added this to the Future milestone Jul 29, 2019
@jairbubbles
Copy link

Indeed, same behavior on .NET Framework, the .webp version is broken while the .png version displays correctly.

This code:

<UniformGrid Rows="1">
     <Image Source="https://www.gstatic.com/webp/gallery3/1_webp_ll.webp"></Image>
     <Image Source="https://www.gstatic.com/webp/gallery3/1_webp_ll.png"></Image>
</UniformGrid>

Will produce:

image

(Windows version 1903 too)

@h82258652
Copy link

https://github.com/dotnet/wpf/blob/ac9d1b7a6b0ee7c44fd2875a1174b820b3940619/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Imaging/BitmapDecoder.cs
There is no webp decoder. So wpf use the UnknownBitmapDecoder and it can not handle the alpha in webp format.

@weltkante
Copy link

weltkante commented Dec 5, 2019

There is no webp decoder. So wpf use the UnknownBitmapDecoder

Thats a contradiction, I think you mean that there's no explicit C#/.NET class for it but (I assume) it just falls back to WIC and lets Windows resolve the decoder. All decoders are native implementations just some have explicit wrappers in .NET - but if you look at their implementation they all do the same as the UnknownBitmapDecoder and forward to base class

So the fact that there is no named class for it doesn't really mean anything.

@weltkante
Copy link

weltkante commented Dec 5, 2019

@grubioe /cc @vatsan-madhavan can we get that reevaluated? If this is a bug in WIC or (external to WPF) WEBP decoder it would be really annoying if its not forwarded to the right Windows team just because the WPF team planned it for "future"

[edit] its a bug in WPF but it'd still be nice to reevaluate and fix in 5.0 timeframe instead of leaving it on "future"

@jairbubbles
Copy link

The thumbnail appears correctly on Windows explorer. I don't know if it ends up using the same decoder though.

@weltkante
Copy link

weltkante commented Dec 5, 2019

Unless someone beats me to it I'll test with native WIC when I get home to determine if this is a WPF bug or WIC bug, for some reason my Windows 10 / 1909 installation at work doesn't have the webp decoder (I get an exception when referencing the image in WPF) and Windows doesn't offer it as optional feature either. I'm pretty sure I've seen it yesterday on my home machine when I happened to scroll through optional features.

[edit] apparently its not an optional feature, you can find it under "apps and features" as installed application but it isn't uninstallable. Still no idea how to install webp support on my work machine, would have assumed it gets installed automatically with the 1903 or 1909 update.

[edit] apparently you can install it from the store

@weltkante
Copy link

weltkante commented Dec 5, 2019

The bug is in WPF, probably in native code which hasn't been open sourced yet. WIC can load the image just fine, test code to load the image via WIC attached.

In fact I also figured out what happens, if you call new BitmapImage(new Uri(...)).Format on the webp image it reports Bgr32 which is wrong. WPF simply ignores the alpha channel even though WIC reports that the image has an alpha channel. The webp image has color artifacts in transparent places so it looks weird when they aren't transparent. (Its probably an optimization of the webp encoding because color in transparent regions is irrelevant so it doesn't bother to encode it and just leaves it at whatever is convenient.)

example code to load image via WIC
private void LoadImage()
{
    // Referencing SharpDX.Direct2D1 nuget package
    using (var factory = new SharpDX.WIC.ImagingFactory2())
    using (var decoder = new SharpDX.WIC.BitmapDecoder(factory, "1_webp_a.webp", SharpDX.WIC.DecodeOptions.CacheOnLoad))
    {
        Debug.Assert(decoder.FrameCount == 1);
        using (var frame = decoder.GetFrame(0))
        {
            Debug.Assert(frame.PixelFormat == SharpDX.WIC.PixelFormat.Format32bppRGBA);
            var size = frame.Size;
            var stride = size.Width * 4;
            var pixels = new byte[stride * size.Height];
            frame.CopyPixels(pixels, stride);

            for (int iy = 0; iy < size.Height; iy++)
            {
                for (int ix = 0; ix < size.Width; ix++)
                {
                    // convert from RGBA to BGRA
                    Swap(ref pixels[iy * stride + ix * 4 + 0], ref pixels[iy * stride + ix * 4 + 2]);

                    // uncomment to reproduce the bug, WPF seems to ignore the alpha channel
                    // which you can simulate by setting alpha to 255 (opaque)
                    //pixels[iy * stride + ix * 4 + 3] = 255;
                }
            }

            var bitmap = new WriteableBitmap(size.Width, size.Height, 96, 96, PixelFormats.Bgra32, null);
            bitmap.Lock();
            try { bitmap.WritePixels(new Int32Rect(0, 0, size.Width, size.Height), pixels, stride, 0); }
            finally { bitmap.Unlock(); }
            ImageControl.Source = bitmap;
        }
    }
}

private static void Swap(ref byte lhs, ref byte rhs)
{
    var tmp = lhs;
    lhs = rhs;
    rhs = tmp;
}

@vatsan-madhavan vatsan-madhavan removed this from the Future milestone Dec 6, 2019
@vatsan-madhavan vatsan-madhavan removed the Bug Product bug (most likely) label Dec 6, 2019
@vatsan-madhavan
Copy link
Member

@arpitmathur can we bring this one up in our bug triage again for discussion ?

More than just WebP, I’d like us to think about how we are going to support emerging media formats for which native WIC support is lacking. We may want to find out how Office does this today, for e.g. to see if their approach is reusable for us.

{It could be that we wait till Jan to dig into this.}

@jairbubbles
Copy link

Would be nice to have native support for .gif. I usually use https://github.com/XamlAnimatedGif/WpfAnimatedGif for this.

@arpitmathur arpitmathur added the Bug Product bug (most likely) label Dec 10, 2019
@arpitmathur arpitmathur added this to the Future milestone Dec 10, 2019
@icetech233
Copy link

我也发现了 这个 bug ,怎么处理
!??

@miloush
Copy link
Contributor

miloush commented Nov 25, 2022

@icetech233 See #1436 (comment) for a workaround. Basically you need to convert the image into a known pixel format. You can let WIC do it:

var decoder = BitmapDecoder.Create(new Uri("1_webp_a.webp", UriKind.Relative), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None);
var converted = new FormatConvertedBitmap(decoder.Frames[0], PixelFormats.Bgra32, null, 0);

Content = new Image { Source = converted };

The WebP decoder returns GUID_WICPixelFormat32bppRGBA which is not supported by WPF so it fallbacks to Default. I suggested extending the supported pixel formats in #4570

But I also agree with @vatsan-madhavan we need an easy way to plug in managed only/non-WIC image decoders and encoders.

@oktagon2
Copy link

oktagon2 commented Jan 29, 2023

Based on the example in learn.microsoft I coded the following xaml:

<Window x:Class="WpfApplicationForStackOverflow1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplicationForStackOverflow1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        Background="Aquamarine">
    <StackPanel>
        <Image Name="Image1" Width="400">
            <Image.Source>
                <BitmapImage DecodePixelWidth="997"
                             UriSource="https://www.gstatic.com/webp/gallery3/1_webp_ll.webp" />
            </Image.Source> 
        </Image>
    </StackPanel>
</Window>

It works. The background is transparent. The DecodePixelWidth seems to have a healthy effect. Unfortunately not for every value. I prefer prime numbers like 997.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Product bug (most likely)
Projects
None yet
Development

No branches or pull requests

10 participants