2010-01-15 2 views
4

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

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

Я знаю, что я никогда не смогу добраться до уровней 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(); 
} 

ответ

7

Супер ответ пользователь, How to read Fireworks PNG multilayer files without Fireworks, объясняет, что фейерверк имеет расширение PNG для хранения нескольких слоев в файле PNG. Сглаживание удаляет лишние слои. Учитывая, что файлы не были созданы в Fireworks в первую очередь, теоретически «сглаживание» не должно оказывать на них никакого влияния. Я подозреваю, что уменьшение размера связано с тем, что FireWare сохраняет оптимизацию PNG-файла.

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

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

Если вы заинтересованы в оптимизации PNG файлов, то PNG specification удивительно прост, и это стоит взглянуть на Smallest possible transparent PNG. Подобно спецификации, реализации также удивительно просты, например, один файл, чистый Python реализация png.py (pypng).

+0

Что касается Fireworks и его расширений - png был создан инфраструктурой .NET с использованием нового растрового изображения и jpeg, но при загрузке в фейерверк я все еще могу манипулировать как отдельными объектами, пока я не сплющил все на экспорт из Fireworks, поэтому либо больше, чем расширения Fireworks или .Net поддерживает их ... – Moo

+0

Moo, может ли быть отправлен код, расчесывающий растровые изображения и jpg? Я бы подумал, что после рисования как jpg, так и растрового изображения в другое растровое изображение, что любая информация о «слое» уже давно исчезнет, ​​а полученный png будет комбинацией двух. Разве это не так? –

+0

Jonathan, я добавил код :) – Moo

Смежные вопросы