2015-09-10 84 views
1

我想壓縮PNG圖像,以減小其大小,但質量應保持不變。我試圖壓縮JPEG圖片。壓縮大約90%的圖片和質量保持不變,但是當我用它壓縮PNG圖像時。沒有結果,沒有壓縮。相同的尺寸。我必須壓縮PNG文件圖像,而不會丟失質量

這是我的代碼。

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) 
      { 
      } 
     } 

對於PNG壓縮,我更改了以下行。

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

請問有人幫我一把。如果有新的方法,我很歡迎。如果這可能會改變,那會好很多。

+2

PNG已經是很好的壓縮,不太可能改進..你不能壓縮在JPG不失一些質量。 – TaW

+0

圖像本身不是PNG或JPEG。 PNG和JPEG是_file formats_,代表存儲某些圖像的方式。兩者都已壓縮。 JPEG是「有損」的,但其設計方式是優先丟失大多數(即使不是所有人類都不會僅僅通過查看圖像就看不到的數據)。 PNG是無損的;這必然會阻止PNG格式壓縮給定的圖像,就像JPEG一樣。 PNG確實具有大量的壓縮選項,並且可能其他PNG編碼器的壓縮比.NET壓縮更好,但是您將永遠無法從JPEG中看到壓縮的程度。 –

+0

@Taw,由於評分較低,我無法評論。我在某種程度上可以接受這種損失。如果我有一個方法,它可以問我,這樣大的圖像質量損失,這將是規模,所以我會做一個交易。 –

回答

0

PNG壓縮的一個主要變量是壓縮速度和輸出大小之間的折衷。 PNG壓縮實際上可能非常慢,因爲它涉及在數據緩衝區中搜索匹配的模式。您可以通過限制編碼器搜索的緩衝區的數量來加速壓縮。

您的編碼器應該有一個設置,允許您指定搜索匹配的方式。

IF您的輸入PNG圖像未使用編碼器搜索整個緩衝區進行壓縮,您可以通過在應用程序中搜索完整緩衝區來獲得一些改進的壓縮。但是,你不可能獲得重大改善。

+0

由於Photoshop通過一些質量交易減少了圖像的大小。同樣我想在.net的幫助下做到這一點。 –

+1

PNG沒有尺寸/質量折衷。 PNG可以實現壓縮時間/大小折衷。 – user3344003

6

PNG圖像默認爲32位。您可以將它們轉換爲8位:生成的文件將比原始文件小5倍。對於大多數圖像來說,質量損失幾乎看不見。

這是在線PNG壓縮機做的。

您可以通過使用nQuant自己做:http://nquant.codeplex.com/(可上的NuGet)

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

方法的全面解釋可以在這個博客帖子http://www.hurryupandwait.io/blog/convert-32-bit-pngs-to-high-quality-8-bit-pngs-with-c

+1

感謝您提供nQuant。我只是試了一下。在.NET創建一個具有alpha透明度的800kb PNG的情況下,nQuant能夠在240kb的時間創建相同的PNG圖像,而不會出現明顯的質量損失。請記住它通過將顏色數減少到256來做到這一點,但它非常巧妙。 –

相關問題