C# как сжать.png без потери прозрачного фона?

Я использую следующие коды для сжатия файла изображения в JPG:

// _rawBitmap = a Bitmap object

ImageCodecInfo encoder = GetEncoder(ImageFormat.Jpeg);
System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;
EncoderParameters myEncoderParameters = new EncoderParameters(1);
EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L);
myEncoderParameters.Param[0] = myEncoderParameter;

ImageConverter imageConverter = new ImageConverter();
byte[] b = (byte[])imageConverter.ConvertTo(_rawBitmap, typeof(byte[]));

using (MemoryStream ms = new MemoryStream())
{
    ms.Write(b, 0, b.Length);
    ms.Seek(0, SeekOrigin.Begin);
    rawBitmap.Save(ms, encoder, myEncoderParameters);
    bmp = ToBitmap(ms.ToArray());
    return (Bitmap)bmp.Clone();
}

но когда я пытаюсь сжать файл PNG таким же образом, но только изменить:

ImageCodecInfo encoder = GetEncoder(ImageFormat.Jpeg);

в

ImageCodecInfo encoder = GetEncoder(ImageFormat.Png);

мой файл png потерял прозрачные данные.

так как правильно сжать файл PNG?

1 ответ

Решение

Здесь есть пара проблем. Во-первых, вам не нужно устанавливать эти EncoderParams за качество для PNG.

Во-вторых, вам не нужно ImageConverter

В-третьих, вы записываете все, что ImageConverter производит в ваш поток памяти, перематываете и затем записываете кодированный PNG поверх него - вполне вероятно, что в результате у вас будет файл PNG с кучей мусора в конце.,

Упрощенный подход должен быть:

using (MemoryStream ms = new MemoryStream())
{
    rawBitmap.Save(ms, ImageFormat.Png);    
}

Если вы хотите загрузить свое растровое изображение обратно, откройте его из потока, но не закрывайте поток (поток будет удален после удаления вашего возвращенного растрового изображения):

var ms = new MemoryStream();    
rawBitmap.Save(ms, ImageFormat.Png);    
ms.Seek(0, SeekOrigin.Begin);
return Bitmap.FromStream(ms);

Вы можете использовать nQuant ( https://www.nuget.org/packages/nQuant/)

С его помощью вы конвертируете 32-битные PNG в высококачественные 8-битные PNG

    private static int alphaTransparency = 10;
private static int alphaFader = 70;
var quantizer = new WuQuantizer();
using(var bitmap = new Bitmap(sourcePath))
{

    using(var quantized = quantizer.QuantizeImage(bitmap, alphaTransparency, alphaFader))
    {
        quantized.Save(targetPath, ImageFormat.Png);
    }

}
Другие вопросы по тегам