使用Image类在c#中丢失图像质量(减少颜色数量)

我有一个ac#程序打开一个.tif图像,后来提供了保存它的选项。 但是,保存图像时质量始终会下降。

(编辑:我保存图像时传递了一些参数,使质量达到100%并且没有压缩,但实际独特颜色的数量从254到16,即使图像属性显示为8bpp)

(EDIT2:所讨论的图像是每像素8位的灰度图像 – 256种颜色/灰度阴影 – 我测试的每像素24位彩色图像不会发生这种情况,所有颜色都保留在这里。我正在开始认为图像类可能只支持16种灰度

我该如何避免这种情况?

这是打开图像的代码:

public Image imageImport() { Stream myStream = null; OpenFileDialog openTifDialog = new OpenFileDialog(); openTifDialog.Title = "Open Desired Image"; openTifDialog.InitialDirectory = @"c:\"; openTifDialog.Filter = "Tiff only (*.tif)|*.tif"; openTifDialog.FilterIndex = 1; openTifDialog.RestoreDirectory = true; if (openTifDialog.ShowDialog() == DialogResult.OK) { try { if ((myStream = openTifDialog.OpenFile()) != null) { using (myStream) { String tifFileName= openTifDialog.FileName; imgLocation = tifFileName; Bitmap tifFile = new Bitmap(tifFileName); return tifFile; } } } catch (Exception ex) { MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message); } } return null; } 

这是我保存图像的方式:

 private void saveImage(Image img) { SaveFileDialog sf = new SaveFileDialog(); sf.Title = "Select File Location"; sf.Filter = " bmp (*.bmp)|*.bmp|jpeg (*.jpg)|*.jpg|tiff (*.tif)|*.tif"; sf.FilterIndex = 4; sf.RestoreDirectory = true; sf.ShowDialog(); // If the file name is not an empty string open it for saving. if (sf.FileName != "") { // Saves the Image via a FileStream created by the OpenFile method. System.IO.FileStream fs = (System.IO.FileStream)sf.OpenFile(); // Saves the Image in the appropriate ImageFormat based upon the // File type selected in the dialog box. // NOTE that the FilterIndex property is one-based. switch (sf.FilterIndex) { case 1: img.Save(fs, System.Drawing.Imaging.ImageFormat.Bmp); break; case 2: img.Save(fs, System.Drawing.Imaging.ImageFormat.Jpeg); break; case 3://EDITED -STILL DOES NOT RESOLVE THE ISSUE ImageCodecInfo codecInfo = ImageClass.GetEncoderInfo(ImageFormat.Tiff); EncoderParameters parameters = new EncoderParameters(2); parameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality,100L); parameters.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionNone); img.Save(fs,codecInfo, parameters); break; } fs.Close(); } } 

即使我没有以任何方式调整图像大小或改变图像,我也会遇到质量损失。 任何建议?

System.Drawing对8位图像的支持很差。 从24位或32位图像转换为8位图像时; 它总是使用固定的默认调色板。 该默认调色板仅包含16种灰度,其他条目为各种颜色。

保存为“.bmp”时是否有同样的问题? 如果是,那么转换为8位格式已经发生在早期,你必须弄清楚你的程序在哪里做并解决问题。 如果只有tiff编码器转换为8位,则必须先在单独的步骤中进行8位转换。 创建一个8位图像,用灰度调色板填充Image.Palette ,然后复制位图数据。

但是System.Drawing对8位图像的支持很差,并且在处理这些图像时,几种方法(例如SetPixel )只会抛出InvalidOperationException 。 您可能必须使用不安全的代码(使用LockBits等)来复制位图数据。 如果我是你,我会看看你是否有可以使用的替代图形库。

我在使用.NET库找到图像质量和大小的良好平衡时遇到了问题。 我放弃了自己的尝试并尝试了一些成像库。 我发现http://imageresizing.net/能够产生始终如一的好结果,比我能做得更好。

只是将它作为一个计划B扔出去,以防你自己的方法不能在一致的基础上为你工作。

Image.Save默认使用75%的质量设置。 您可以尝试使用允许您指定质量设置参数的方法的其他重载之一。 看到这个问题。

真的只有一个建议….加载图像时你使用new Bitmap(fileName) …而不是使用Bitmap你考虑使用

 Image tiffImage = Image.FromFile(tiffFileName, true); 

真实告诉它使用“嵌入式颜色管理”,使用Image而不是Bitmap可以避免任何可能在幕后发生的图像投射。

Interesting Posts