C # - Как изменить качество PNG или глубину цвета

Я должен написать программу, которая получает изображения в формате PNG от пользователя, делает некоторые простые изменения, такие как вращение, и сохраняет их в файле JAR, чтобы он мог использовать изображения в качестве ресурсов. Проблема в том, что когда я открываю, скажем, изображение размером 80 КБ, а затем сохраняю его с помощью C #, я получаю изображение с тем же качеством, но на 130 КБ. И поскольку он должен находиться внутри jar-файла J2ME, мне действительно нужны меньшие размеры, по крайней мере, исходный размер. Я попробовал код ниже, но позже узнал, что он работает только для изображений Jpeg.

ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
                int j = 0;
                for (j = 0; j < codecs.Length; j++)
                {
                    if (codecs[j].MimeType == "image/png") break;
                }
                EncoderParameter ratio = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 10L);
                EncoderParameters CodecParams = new EncoderParameters(1);
                CodecParams.Param[0] = ratio;

                Image im;
                im = pictureBox1.Image;
                im.Save(address , codecs[j], CodecParams);

Здесь изображение загружается в окно изображения:

private void pictureBox1_DoubleClick(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                string address = openFileDialog1.FileName;
                address.Replace("\\", "\\\\");
                Image im = Image.FromFile(address);
                pictureBox1.Image = im;
            }
        }

И вот где он сохраняется обратно без правок:

private void generateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {

                ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
                int j = 0;
                for (j = 0; j < codecs.Length; j++)
                {
                    if (codecs[j].MimeType == "image/png") break;
                }
                EncoderParameter ratio = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 10L);
                EncoderParameters CodecParams = new EncoderParameters(1);
                CodecParams.Param[0] = ratio;

                string address = folderBrowserDialog1.SelectedPath;
                address = address + "\\";
                address.Replace("\\", "\\\\");

                Image im;
                im = pictureBox1.Image;               
                im.Save(address + imageFileNames[1], codecs[j], CodecParams);

Примечание: imageFileNames[] — это просто массив строк, содержащий некоторые имена файлов, в которых должны быть сохранены изображения.

Любые идеи будут оценены и спасибо заранее.


person Auxiliary    schedule 10.03.2010    source источник
comment
Получаете ли вы изменения размера файла при повторном сохранении изображения без редактирования?   -  person Jacob G    schedule 10.03.2010
comment
Можем ли мы увидеть код, в котором вы загружаете изображение, и код, в котором вы сохраняете изображение? Я не вижу подобного поведения в своем (простом) тесте.   -  person Jacob G    schedule 10.03.2010
comment
Да, я обновил сообщение и добавил полные коды. Спасибо за внимание.   -  person Auxiliary    schedule 10.03.2010


Ответы (2)


Я взял 4 разных PNG размером от 2 КБ до 2,6 МБ. Используя ваш код, я загружаю их и сохраняю. Я не изменяю изображение, поворачивая или переворачивая. Все 4 PNG при повторном сохранении имеют одинаковый размер.

Кроме того, я взял PNG размером 2,6 МБ, открыл его в Photoshop и сохранил две его копии: одну с чересстрочной разверткой (уменьшенную до 2,06 МБ), одну без чересстрочной развертки (уменьшившую до 1,7 МБ). их через ваш код и сохранил их. Результирующие размеры обоих вернулись к исходным 2,6 МБ.

Итак, я предполагаю, что исходные изображения были созданы с помощью программного обеспечения (например, Photoshop), и это программное обеспечение имеет оптимизированный алгоритм сжатия, который он использует для спецификации PNG, который не использует .NET.

Я возился с параметром EncoderParameter для сжатия, но, похоже, это не имеет никакого значения.

person Jacob G    schedule 10.03.2010
comment
Ага, ваше право. Изображения были экспортированы программой экспорта 3dsMax jsr. Но знаете ли вы способ сжать PNG или понизить его качество, чтобы я мог получить результат, аналогичный экспортеру? - person Auxiliary; 10.03.2010
comment
Это выглядит многообещающе: benhollis.net/software/pnggauntlet ... Он содержит PNGOUT с этой страницы. : advsys.net/ken/utils.htm - person Jacob G; 10.03.2010
comment
Спасибо за ваше время, я думаю, вы дали мне мои ответы. - person Auxiliary; 10.03.2010
comment
Итак, в основном ответ таков: это не C# увеличивает размер, а другие приложения, которые, кажется, имеют приемы оптимизации для его уменьшения? Было бы удобно иметь это и в .Net... - person Nyerguds; 17.08.2016

Извините, что поднял старый вопрос, но сегодня я решал ту же проблему и нашел эту страницу в MSDN: "Список параметров и значений для всех кодировщиков". Я надеюсь, что будет полезно сослаться на него там.

В статье содержится пример программы, которая выводит EncoderParameters, поддерживаемые стандартными кодировщиками изображений GDI+, а кодировщик PNG не поддерживает никаких параметров в соответствии с ней.

Я не уверен, что можно считать это само собой разумеющимся, или в какой-то будущей версии gdiplus.dll кодировщик PNG может получить больше поддержки, и поэтому предполагается проверять возможности кодировщика во время выполнения.

В любом случае применение некоторого явного преобразования к исходному изображению кажется более плодотворным подходом; Я еще не исследовал его, хотя.

person kostix    schedule 20.12.2011
comment
Почему в GDI+ нет настройки качества для PNG? Думаю, тогда мне придется использовать Jpeg. :-/ - person Nick Gotch; 20.07.2013
comment
@NickGotch, поскольку PNG - это формат без потерь, у него не может быть настроек качества - в некотором смысле его качество всегда составляет 100%. Чего, по-видимому, не хватает кодировщику GDI+, так это ручки, управляющей компромиссом между скоростью кодирования и коэффициентом сжатия. - person kostix; 21.07.2013
comment
@kostix Однако запись image / tiff в этом списке имеет сжатие. ›edit‹ Да ладно, это перечисление методов сжатия. - person Nyerguds; 17.08.2016