Search code examples
c#.netimagedrawingwebp

Save a webp file with System.Drawing.Imaging generates a big file size or encoder doesn't exists


So I'm working with .NET 7 since System.Drawing.Imaging can (or seems to be) save a file as webp file with the following code:

            pictureBox1.Image = image; //image is a Bitmap
           image.Save(folderpath, ImageFormat.Webp); 

Pretty forward, but the image saved occupies 716kb but its size is 640x480

How can I reduce the file size?

I found a lot of answers about reduce the image size, but is not my case, already reduced, and I'm wonder why a webp file will be so big, because the quality also is very poor (webcam image).
Using the PNG format ocuppies the same space on disk.

UPDATE:

So I could reduce "the quality" of PNG with the following code from MSDN:

if (capture.IsOpened())
            {
                capture.Read(frame);
                image = BitmapConverter.ToBitmap(frame);
                if (pictureBox1.Image != null)
                {
                    pictureBox1.Image.Dispose();
                }
                pictureBox1.Image = image;



                ImageCodecInfo myImageCodecInfo;
                System.Drawing.Imaging.Encoder myEncoder;
                EncoderParameter myEncoderParameter;
                EncoderParameters myEncoderParameters;

                myImageCodecInfo = GetEncoder("image/webp");

                myEncoderParameters = new EncoderParameters(1);
                myEncoder = System.Drawing.Imaging.Encoder.Quality;
                // Save the bitmap as a JPEG file with quality level 25.
                myEncoderParameter = new EncoderParameter(myEncoder, 25L);
                myEncoderParameters.Param[0] = myEncoderParameter;
                // and now save it to the file

                image.Save(filename, myImageCodecInfo, myEncoderParameters); 

            }

that uses this method:

   public static ImageCodecInfo GetEncoder(string mimetype)
    {
        return ImageCodecInfo.GetImageEncoders().FirstOrDefault(e => e.MimeType == mimetype);
    }

but I can't understand why if Save() allows me to save as webp file, there is no encoder to mimetype webp in ImageCodecInfo.GetImageEncoders()


Solution

  • The reason why it takes the same space as PNG is simple: it's probably producing a PNG. In the source code for the save() function you can see that if it can't find an encoder for the requested format, it silently defaults to PNG.

    I believe despite the library having the ImageFormat.Webp constant, Windows doesn't provide a WebP encoder. The documentation for GDI+ doesn't list WebP, and when I list encoders on my Windows 10 system it matches that list as well. So if you want to save to WebP you're going to need to use a third party library.

    For example, you could use the SkiaSharp.Views.Desktop.Common package like this:

    using var skImage = image.ToSKImage();
    using var skData = skImage.Encode(SkiaSharp.SKEncodedImageFormat.Webp, 90);
    using var file = File.OpenWrite(filename);
    skData.SaveTo(file);