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

Я должен написать программу, которая получает некоторые изображения PNG от пользователя, выполняет некоторые простые изменения, такие как вращение, и сохраняет их в JAR файле, чтобы он мог использовать изображения в качестве ресурсов. Проблема в том, что когда я открываю, скажу 80-килобайтное изображение, а затем сохраняю его с помощью С#, я получаю изображение с тем же качеством, но для пространства 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 [] - это только строковый массив, в котором есть некоторые имена файлов, с которыми должны сохраняться изображения.

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

Ответы

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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