4

我有一个 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();
    }
}

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

4

4 回答 4

1

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

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

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

于 2012-11-02T21:05:06.563 回答
0

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

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

于 2012-11-02T13:10:58.550 回答
0

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

于 2012-11-02T13:31:47.963 回答
0

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

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

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

于 2012-11-02T18:56:16.397 回答