简体   繁体   English

我必须压缩PNG文件图像,而不会降低质量

[英]I have to compress the PNG file image, without losing the quality

I want to compress a PNG image, to reduce its size but the quality should remain the same.我想压缩 PNG 图像,以减小其大小,但质量应保持不变。 I have tried to compress JPEG picture.我试图压缩 JPEG 图片。 Picture compressed about 90% and quality remain the same but when i compress a PNG image with it.图片压缩了大约 90%,质量保持不变,但是当我用它压缩 PNG 图像时。 No result, no compression.没有结果,没有压缩。 Same size.一样的大小。

Here is my code.这是我的代码。

public const string _StatusLog = "StatusLog.csv";
        static void Main(string[] args)
        {
            Console.WriteLine("                 ###   WELCOME   ###");
            Console.Write("\n\nPlease enter image folder path :");
            string imagePath = Console.ReadLine();
            Program p = new Program();
            p.VaryQualityLevel(imagePath);
            Console.ReadLine();
        }
        private void VaryQualityLevel(string pathOfImage)
        {
            try
            {
                //Console.Write("Target Directory Path :");
                string targetDirectory = pathOfImage;//Console.ReadLine();

                if (targetDirectory != null)
                {
                    string[] allDirectoryInTargetDirectory = Directory.GetDirectories(targetDirectory);
                    //PRODUCT DIRECOTY OPEN
                    Console.Write("Total Folders found = " + allDirectoryInTargetDirectory.Count());
                    Console.Read();
                    if (allDirectoryInTargetDirectory.Any())
                    {
                        foreach (var directory in allDirectoryInTargetDirectory)
                        {
                            string[] subDirectory = Directory.GetDirectories(directory); // ATTRIBUTE DIRECTORY OPEN
                            if (subDirectory.Any())
                            {
                                foreach (var filesInSubDir in subDirectory)
                                {
                                    string[] allFilesInSubDir = Directory.GetFiles(filesInSubDir);
                                    //FILES IN SUB DIR OPEN
                                    if (allFilesInSubDir.Any())
                                    {
                                        foreach (var imageFile in allFilesInSubDir)
                                        {
                                            try
                                            {
                                                Bitmap bmp1 = new Bitmap(imageFile);//pathOfImage);
                                                ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg);

                                                // Create an Encoder object based on the GUID 
                                                // for the Quality parameter category.
                                                System.Drawing.Imaging.Encoder myEncoder =
                                                    System.Drawing.Imaging.Encoder.Quality;

                                                // Create an EncoderParameters object. 
                                                // An EncoderParameters object has an array of EncoderParameter 
                                                // objects. In this case, there is only one 
                                                // EncoderParameter object in the array.



                                                #region SAVING THE COMPRESS IMAGE FILE
                                                EncoderParameters myEncoderParameters = new EncoderParameters(1);

                                                EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L);
                                                myEncoderParameters.Param[0] = myEncoderParameter;

                                                bmp1.Save(filesInSubDir + "\\" + "Zip" + GettingImageNameForOptimizedImage(imageFile), jpgEncoder, myEncoderParameters);//pathOfImage
                                                Console.WriteLine(filesInSubDir + GettingImageNameForOptimizedImage(imageFile) + "  CREATED");//pathOfImage 
                                                #endregion

                                                #region DELETING THE ORIGNAL FILE
                                                bmp1.Dispose();
                                                System.IO.File.Delete(filesInSubDir + "\\" + GettingImageNameForOptimizedImage(imageFile));//pathOfImage
                                                Console.WriteLine(imageFile.Replace("jpg", "png") + "  DELETED");//pathOfImage 
                                                #endregion
                                                //myEncoderParameter = new EncoderParameter(myEncoder, 100L);
                                                //myEncoderParameters.Param[0] = myEncoderParameter;
                                                //bmp1.Save("D:\\" + RemovingImageFormat[0] + "100L" + ".jpg", jpgEncoder, myEncoderParameters);

                                                #region BACK RENAMING FILE TO ORIGNAL NAME
                                                System.IO.File.Move(filesInSubDir + "\\" + "Zip" + GettingImageNameForOptimizedImage(imageFile), filesInSubDir + "\\" + GettingImageNameForOptimizedImage(imageFile)); 
                                                #endregion
                                            }
                                            catch (Exception ex)
                                            {
                                                Console.Write("\n" + ex.Message + " Press enter to continue :");
                                                Console.ReadLine();

                                                Console.Write("\nWould you like to retry ? [Y/N] :");
                                                string resp = Console.ReadLine();
                                                if (resp == "Y" || resp == "y")
                                                {
                                                    Console.WriteLine("                 -------------------\n\n");
                                                    Main(null);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.Write(ex);
                Console.Read();
            }

            Console.Write("Press any key to exit...");
            Console.Read();
            // Get a bitmap. ###################################################################


        }
        private ImageCodecInfo GetEncoder(ImageFormat format)
        {

            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();

            foreach (ImageCodecInfo codec in codecs)
            {
                if (codec.FormatID == format.Guid)
                {
                    return codec;
                }
            }
            return null;
        }
        public string GettingImageNameForOptimizedImage(string pathOfImage)
        {
            try
            {
                string[] splitingPathOfImage = pathOfImage.Split('\\');
                string[] RemovingImageFormat = splitingPathOfImage[splitingPathOfImage.Count() - 1].ToString().Split('.');
                return RemovingImageFormat[0] + ".jpg";
            }
            catch (Exception)
            {
                return null;
            }
            return null;
        }
        public static void LoggingOperations(string ImageName, string Status, bool UpdateRequired)
        {
            try
            {
                if (!File.Exists(_StatusLog))
                {
                    using (File.Create(_StatusLog)) { }
                    DirectorySecurity sec = Directory.GetAccessControl(_StatusLog);
                    SecurityIdentifier everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
                    sec.AddAccessRule(new FileSystemAccessRule(everyone, FileSystemRights.Modify | FileSystemRights.Synchronize, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));
                    Directory.SetAccessControl(_StatusLog, sec);
                }
                if (UpdateRequired == true)
                {
                    string UpdateStatusText = File.ReadAllText(_StatusLog);
                    UpdateStatusText = UpdateStatusText.Replace(ImageName, ImageName + "," + Status);
                    File.WriteAllText(_StatusLog, UpdateStatusText);
                    UpdateStatusText = "";
                }
                else
                {
                    File.AppendAllText(_StatusLog, Environment.NewLine);
                    File.AppendAllText(_StatusLog, Status);
                }
            }
            catch (Exception)
            {
            }
        }

For PNG compression i changed the following line.对于 PNG 压缩,我更改了以下行。

Bitmap bmp1 = new Bitmap(imageFile);//pathOfImage);
ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Png);

Kindly some one help me out.请有人帮助我。 If there is a new method, I welcome it.如果有新的方法,我欢迎。 If this could be altered, it would a lot better.如果可以改变这一点,那就更好了。

PNG Images are 32 bits by default. PNG图像默认为32位。 You can convert them to 8 bits : resulting file will be about 5 times smaller than the original one. 您可以将它们转换为8位:结果文件将比原始文件小5倍。 With most images, the loss of quality is almost invisible. 对于大多数图像,质量损失几乎是不可见的。

This is what online png compressors do. 这就是在线png压缩机的作用。

You can do this yourself by using nQuant : http://nquant.codeplex.com/ (available on Nuget) 您可以使用nQuant自己完成此操作: http ://nquant.codeplex.com/(Nuget上提供)

var quantizer = new WuQuantizer();         
using(var quantized = quantizer.QuantizeImage(bmp1))
{
    quantized.Save(targetPath, ImageFormat.Png);
}

Full explanation of the method is available on this blog post http://www.hurryupandwait.io/blog/convert-32-bit-pngs-to-high-quality-8-bit-pngs-with-c 有关该方法的完整说明,请参见此博客文章http://www.hurryupandwait.io/blog/convert-32-bit-pngs-to-high-quality-8-bit-pngs-with-c

I also suggest looking at ImageSharp which also works with .NET Core 我还建议看一下也适用于.NET Core的ImageSharp

            using (var image = Image.Load(fileData)) // fileData could be file path or byte array etc.
            {
                var h = image.Size().Height / 2;
                var w = image.Size().Width / 2;
                var options = new ResizeOptions
                {
                    Mode = ResizeMode.Stretch,
                    Size = new Size(w, h)
                };
                image.Mutate(_ => _.Resize(options));
                using (var destStream = new MemoryStream())
                {
                    var encoder = new JpegEncoder();
                    image.Save(destStream, encoder);
                    // Do something with output stream
                }     
            }

The one major variable in PNG compression is the tradeoff between compression speed and output size. PNG压缩中的一个主要变量是压缩速度和输出大小之间的权衡。 PNG compression can actually be quite slow because it involves searching a data buffer for matching patterns. PNG压缩实际上可能非常慢,因为它涉及搜索数据缓冲区以匹配模式。 You can speed up the compression by limiting how much of the buffer the encoder searches. 您可以通过限制编码器搜索的缓冲区数来加速压缩。

Your encoder should have a setting that allows you to specify how searching for matches it will do. 您的编码器应该有一个设置,允许您指定搜索匹配项的方式。

IF your input PNG image was not compressed with the encoder searching the entire buffer, you may get some improved compression by searching the full buffer in your application. 如果您的输入PNG图像未通过编码器搜索整个缓冲区进行压缩,则可以通过在应用程序中搜索完整缓冲区来获得一些改进的压缩。 However, you are unlikely to get a major improvement. 但是,您不太可能获得重大改进。

PNG should be losless given pixel size and color depth are consistent. PNG 应该是无损的,因为像素大小和颜色深度是一致的。 If looking for something to baseline output size against.如果正在寻找一些可以作为基准输出大小的东西。

https://pnggauntlet.com/ https://pnggauntlet.com/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM