C# - 如何更改PNG质量或颜色深度

Aux*_*ary 13 c# png image-manipulation image save

我应该编写一个程序,从用户那里获取一些PNG图像,进行一些简单的编辑,如旋转,并将它们保存在JAR文件中,以便它可以将图像用作资源.问题是当我打开,说一个80kb的图像,然后用C#保存它,我得到一个质量相同但130kb空间的图像.因为它必须进入J2ME jar文件,我真的需要更小的尺寸,至少是原始尺寸.我尝试了下面的代码,但后来发现它只适用于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);
Run Code Online (Sandbox Code Playgroud)

这是将图像加载到图片框的位置:

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;
            }
        }
Run Code Online (Sandbox Code Playgroud)

这就是它被保存回来的地方,没有编辑:

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);
Run Code Online (Sandbox Code Playgroud)

注意:imageFileNames []只是一个字符串数组,其中包含一些必须保存图像的文件名.

任何想法将得到赞赏,并提前感谢.

kos*_*tix 12

很抱歉提出一个旧问题,但我今天解决了同样的问题并在MSDN上找到了这个页面:"列出所有编码器的参数和值".我希望在那里引用它可能是有用的.

本文包含一个示例程序,它输出EncoderParameter由库存GDI +图像编码器支持的s,而PNG编码器根据它不支持任何参数.

我不确定是否可以将此视为理所当然,或者在将来某个版本gdiplus.dll的PNG编码器中可能会获得更多支持,因此应该在运行时检查编码器的功能.

在任何情况下,对源图像应用一些显式转换似乎是更有成效的方法; 我没有探索它.

  • @NickGotch,因为`PNG`是无损格式,它不能具有"质量设置" - 从某种意义上说,它的质量始终是100%.GDI +编码器似乎缺少的是控制编码速度/压缩比折衷的旋钮. (6认同)

Jac*_*b G 11

我已经采用了4种不同的PNG,大小从2KB到2.6MB不等.使用您的代码,我将它们加载并保存.我不会通过旋转或翻转来修改图像.重新保存时,所有4个PNG的大小完全相同.

另外,我已经拿了2.6MB的PNG,在Photoshop中打开并保存了两份,一次隔行扫描(减少到2.06MB),一次非隔行扫描(减少到1.7MB).然后我拿了每一个,跑了他们通过你的代码并保存.由此产生的尺寸都恢复到原来的2.6MB.

因此,我的猜测是原始图像是使用一个软件(如photoshop)创建的,并且该软件具有优化的压缩算法,它用于.NET不使用的PNG规范.

我已经搞乱了EncoderParameter for Compression,但似乎没有任何影响.