Оптимизация вывода PNG из System.Drawing в.NET

У меня есть подпрограмма, которая читает изображение, изменяет его размер и помещает его на новый фон (новый растровый рисунок, только размер установлен).

Это все работает абсолютно идеально, но теперь я хотел бы уменьшить размер выводимых файлов PNG - если я выводю файлы JPEG, я получаю ожидаемый размер файла ~4 Кбайт, но мои PNG-файлы имеют размер более 30 Кбайт.,

Я знаю, что я никогда не достигну уровней JPEG с PNG, но я думаю, что могу сделать немного лучше.

Когда я загружаю выведенные PNG-файлы в Fireworks, я замечаю, что фон и измененное изображение все еще являются отдельными слоями. Сглаживание PNG в Fireworks уменьшает размер файла на 5-10K.

Итак, во-первых, есть ли способ программно сгладить PNG на выходе?

Во-вторых, может ли кто-нибудь еще порекомендовать уменьшить размер PNG?

Я использую файлы PNG, потому что хочу сохранить фон прозрачным.

Код:

private static void ResizeImage(String ImageInPath, int MaxWidth, int MaxHeight, String ImageOutPath, Boolean PadImage, Color MyColour)
{
    Bitmap MyImage = new Bitmap(ImageInPath);
    Bitmap MyResizedImage = null;

    int XPosition = 0;
    int YPosition = 0;
    float Ratio = MyImage.Width / (float)MyImage.Height;

    int MyImageHeight = MyImage.Height;
    int MyImageWidth = MyImage.Width;

    if (MyImage.Width > MyImage.Height)
    {
        if (MyImage.Width > MaxWidth)
            MyResizedImage = new Bitmap(MyImage, new Size(MaxWidth, (int)Math.Round(MaxWidth /
            Ratio, 0)));
        YPosition = (MaxHeight / 2) - (MyResizedImage.Height / 2);
    }
    else if (MyImage.Height > MyImage.Width)
    {
        if (MyImage.Height > MaxHeight)
            MyResizedImage = new Bitmap(MyImage, new Size((int)Math.Round(MaxWidth * Ratio,
            0), MaxHeight));
        XPosition = (MaxWidth / 2) - (MyResizedImage.Width / 2);
    }


    if (PadImage)
    {
        Bitmap MyUnderlay = new Bitmap(MaxWidth, MaxHeight);
        var Canvas = Graphics.FromImage(MyUnderlay);
        Canvas.Clear(MyColour);
        Canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
        Canvas.DrawImage(MyResizedImage, XPosition, YPosition);
        Canvas.Save();
        if (MyColour == Color.Transparent)
        {
            MyUnderlay.Save(ImageOutPath + ".png", ImageFormat.Png);
        }
        else
        {
            MyUnderlay.Save(ImageOutPath, ImageFormat.Jpeg);
        }

        Canvas.Dispose();
        MyUnderlay.Dispose();
    }
    else
    {
        MyResizedImage.Save(ImageOutPath, ImageFormat.Jpeg);
    }

    MyResizedImage.Dispose();
    MyImage.Dispose();
}

1 ответ

Решение

Ответ Супер-пользователя " Как читать многослойные файлы Fireworks PNG без Fireworks" объясняет, что Fireworks имеет расширения PNG для хранения нескольких слоев в файле PNG. Уплощение удаляет лишние слои. Учитывая, что файлы не были созданы в Fireworks, теоретически "выравнивание" не должно на них влиять. Я подозреваю, что уменьшение размера происходит из-за сохранения и оптимизации файла PNG в Firework.

Инструменты, которые я использую для оптимизации PNG:

  1. Конвертировать в PNG8: если цветов мало (скажем, скриншотов), я использую pngnq или индексированный цветовой режим GIMP для квантования до 256 цветов. PNG8 может быть меньше PNG24 или PNG32. Подробнее см. PNG8 - "Чистый победитель".
  2. Optipng, быстрый общий оптимизатор PNG. C# PNG Optimization Tutorial содержит подробную информацию о том, как запустить optipng из C#.
  3. Наконец, pngout медленный, но часто (в 80-90% случаев) удается сжать PNG дальше, чем optipng. Сначала запустите optipng, так как optipng автоматически выполнит другие оптимизации, которые pngout не пытается выполнить.

Если вы заинтересованы в оптимизации файлов PNG, спецификация PNG удивительно проста, и стоит взглянуть на наименьший возможный прозрачный PNG. Как и в спецификации, реализации также удивительно просты, например, один файл, чистая реализация Python png.py (pypng).

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