dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.36k stars 4.74k forks source link

[API Proposal]: `System.Drawing.Imaging.ImageFormat.Heif` and `Webp`. #70422

Closed teo-tsirpanis closed 2 years ago

teo-tsirpanis commented 2 years ago

Background and motivation

GDI+ seems to support the newer HEIF and WebP image formats since Windows 10 1809 [^1]. We should expose this functionality to System.Drawing.Common.

API Proposal

namespace System.Drawing.Imaging;

public class ImageFormat {
    [SupportedOSPlatform("windows10.0.17763.0")]
    public static ImageFormat Heif { get; }
    [SupportedOSPlatform("windows10.0.17763.0")]
    public static ImageFormat Webp { get; }
}

API Usage

// Fancy the value
Bitmap bmp = new Bitmap(184, 475);
// ...
bmp.Save("myimage.heif", ImageFormat.Heif);
bmp.Save("myimage.webp", ImageFormap.Webp);

Alternative Designs

Users can use these formats by creating an ImageFormat object with the format's GUID but it is not easily found in the documentation.

Risks

No response

[^1]: Source: I bisected Windows 10 SDK versions and checked the contents of gdiplusimaging.h.

ghost commented 2 years ago

Tagging subscribers to this area: @dotnet/area-system-drawing See info in area-owners.md if you want to be subscribed.

Issue Details
### Background and motivation GDI+ [seems to support the newer HEIF and WebP image formats](https://docs.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-constant-image-file-format-constants). We should expose this functionality to `System.Drawing.Common`. ### API Proposal ```csharp namespace System.Drawing.Common; public class ImageFormat { // I need to find in which version of Windows they were introduced. [SupportedOSPlatform("winTBD")] public static ImageFormat Heif { get; } [SupportedOSPlatform("winTBD")] public static ImageFormat Webp { get; } } ``` ### API Usage ```csharp // Fancy the value Bitmap bmp = new Bitmap(184, 475); // ... bmp.Save("myimage.heif", ImageFormat.Heif); bmp.Save("myimage.webp", ImageFormap.Webp); ``` ### Alternative Designs Users can use these formats by creating an `ImageFormat` object with the format's GUID but it is not easily found in the documentation. ### Risks _No response_
Author: teo-tsirpanis
Assignees: -
Labels: `api-suggestion`, `area-System.Drawing`
Milestone: -
danmoseley commented 2 years ago

Aside from these two, we match the GDI+ list. Although we're generally adding not features to this library, its goal is to expose GDI+, we do want to enable these new formats, and in this case it's simply a matter of passing through different constants.

saucecontrol commented 2 years ago

It's more than a matter of missing constants. System.Drawing currently throws OutOfMemoryException when attempting to load either WebP or HEIC images. AFAIK, GDI+ should be using the WIC codecs underneath, but even with these codecs present and working from WIC code, they don't work from System.Drawing.

Also, WIC has both decoder and encoder for HEIC/HEIF (although they don't work without the HEVC Video Extensions installed from Microsoft Store), but it only has a decoder for WebP. The above example to save as WebP wouldn't work even if everything were wired up correctly.

saucecontrol commented 2 years ago

Just tested Image.Save with the added GUIDs. It appears to work (no exception thrown), but the output in both cases is actually PNG.

static void TestFormats()
{
    Guid ImageFormatHEIF = new(0xb96b3cb6, 0x0728, 0x11d3, 0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e);
    Guid ImageFormatWEBP = new(0xb96b3cb7, 0x0728, 0x11d3, 0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e);

    using var img = new Bitmap(256, 256);
    img.Save("test.webp", new ImageFormat(ImageFormatWEBP));
    img.Save("test.heif", new ImageFormat(ImageFormatHEIF));
}
terrajobst commented 2 years ago

Video

namespace System.Drawing.Imaging;

public class ImageFormat
{
    [SupportedOSPlatform("windows10.0.17763.0")]
    public static ImageFormat Heif { get; }
    [SupportedOSPlatform("windows10.0.17763.0")]
    public static ImageFormat Webp { get; }
}