【发布时间】:2015-12-06 15:46:40
【问题描述】:
我想压缩 PNG 图像,以减小其大小,但质量应保持不变。我试图压缩JPEG图片。图片压缩了大约 90%,质量保持不变,但是当我用它压缩 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);
请有人帮助我。如果有新的方法,我欢迎。如果可以改变这一点,那就更好了。
【问题讨论】:
-
PNG 已经被很好地压缩了,不太可能被改进。你不能在 JPG 中压缩而不损失一些质量。
-
图像本身不是 PNG 或 JPEG。 PNG 和 JPEG 是 文件格式,代表存储某些图像的方式。两者都已经压缩了。 JPEG 是“有损”的,但其设计方式是优先丢失大多数人(如果不是所有人)仅通过查看图像就不会注意到的数据。 PNG是无损的;这必然会阻止 PNG 格式像 JPEG 那样压缩给定的图像。 PNG 确实有大量的压缩选项,而且其他 PNG 编码器可能会比 .NET 压缩得更好,但你永远不会看到 JPEG 的压缩程度。
-
@Taw,由于评分低,我无法在那里发表评论。在某种程度上,我可以接受损失。如果我有一种方法,它可能会问我,对于图像质量的损失,这将是尺寸,所以我会做出交易。
-
@Peter Duniho JPEG 可以压缩。图像质量明显下降,但在某种程度上是可以接受的。有什么办法可以在一定程度上压缩PNG,在一定程度上损失质量。
-
“有什么办法可以在一定程度上压缩PNG,在一定程度上降低质量”——不,不是。 PNG根据定义是“无损的”。正如我所提到的,格式本身支持各种可用于优化结果的参数,这可能会稍微影响最终的压缩大小(但与您要求的不同),但 .NET 编码器不提供访问这些参数。你需要一个第三方编码器。当然,您始终可以减小图像尺寸;这必然会丢弃信息并且也会减小文件大小。
标签: c# image compression png