代码之家  ›  专栏  ›  技术社区  ›  Auxiliary

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

  •  13
  • Auxiliary  · 技术社区  · 16 年前

    我应该编写一个程序,从用户那里获取一些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);
    

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

    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[]只是一个字符串数组,它包含一些必须保存图像的文件名。

    如有任何想法,请提前表示感谢。

    2 回复  |  直到 14 年前
        1
  •  11
  •   Jacob G    16 年前

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

    此外,我已经采取了2.6mbpng,打开它在photoshop和保存两个副本,一个隔行扫描(减少到2.06mb),一个非隔行扫描(减少到1.7mb)然后我采取了每一个,运行你的代码和保存它们。两者的大小都恢复到原来的2.6MB。

    所以,我的猜测是,原始图像是用一个软件(如photoshop)创建的,而且这个软件有一个优化的压缩算法,它是用于png规范的,而.net不采用这种压缩算法。

    我对encoderParameter的压缩做了一些修改,但它似乎没有任何影响。

        2
  •  12
  •   kostix    14 年前

    很抱歉提出了一个旧问题,但我今天正在解决同一问题,在MSDN上找到了此页: "Listing Parameters and Values for All Encoders" . 我希望在那里参考一下可能有用。

    本文包含一个示例程序,它输出 EncoderParameter s支持的股票gdi+图像编码器,而png编码器不支持根据它的参数。

    我不确定人们是否可以想当然,或者在未来的某个版本中 gdiplus.dll png编码器可能会增加更多的支持,因此应该在运行时检查编码器的功能。

    无论如何,在源图像上应用一些显式转换似乎是一种更有成效的方法;不过,我还没有对此进行探索。

    推荐文章