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

C# 使用image类在c中丢失图像质量(减少颜色数量),c#,image,save,bpp,C#,Image,Save,Bpp,我有一个c程序,可以打开一个.tif图像,然后提供保存该图像的选项。但是,保存图像时,质量总是会下降 编辑:我在保存图像时传递了一些参数,使图像质量达到100%,没有压缩,但实际唯一颜色的数量从254变为16,即使图像属性显示为8bpp EDIT2:所讨论的图像是每像素8位的灰度图像-256色/灰度-我测试的每像素24位的彩色图像在保留所有颜色的情况下不会出现这种情况。我开始认为image类可能只支持16种灰度 我如何避免这种情况 以下是打开图像的代码: public Image imageIm

我有一个c程序,可以打开一个.tif图像,然后提供保存该图像的选项。但是,保存图像时,质量总是会下降

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

EDIT2:所讨论的图像是每像素8位的灰度图像-256色/灰度-我测试的每像素24位的彩色图像在保留所有颜色的情况下不会出现这种情况。我开始认为image类可能只支持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();
    }
}

即使我没有以任何方式调整或更改图像大小,我也会体验到质量下降。有什么建议吗?

我在使用.NET库寻找图像质量和大小的良好平衡方面遇到了问题。我放弃了自己的,尝试了一些图像库。我发现自己的成绩始终如一,比我能做到的要好得多


把它作为B计划扔掉,以防roll your own方法在一致的基础上不能很好地工作

Image.Save默认使用75%的质量设置。您可以尝试使用该方法的其他重载之一来指定质量设置参数。请参见

只有一个建议…加载图像时,请使用新的位图文件名。。。您是否考虑过使用位图而不是位图

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

true告诉它使用嵌入式颜色管理,使用图像而不是位图可以避免任何可能发生在幕后的图像转换。

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

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


但是System.Drawing对8位图像的支持较差,一些方法(例如SetPixel)在处理此类图像时只会抛出InvalidoOperationException。您可能必须使用带有锁位等的不安全代码来复制位图数据。如果我是你,我会看看是否有其他图形库可供使用。

更新:查看irfanview上保存的图像的信息并将其与原始图像进行比较,我注意到两件事:一件是原始图像的压缩表示“无”,而保存的图像表示“LZW”。我注意到的另一件事是,虽然两幅256色图像中的颜色保持为每像素8位,但保存图像中的唯一颜色计数为16,而原始图像中的唯一颜色计数为251update:我更改了代码,将其保存为100%质量,并消除了压缩,然而,在保存的图像中,唯一颜色的比例仍然是16,我仍然可以看到两幅图像在质量上的差异。也许问题出在构造器打开图像时?我尝试过传递参数,消除lzw压缩,并将质量设置为100,但保存的图像中的颜色数保持在16,但我已经考虑过这个问题,并修改了我的代码-仍然是同样的问题,结果是16种颜色而不是250Im所有的想法,现在,我将环顾四周,看看还能发现什么:-谢谢!这帮了大忙。我正在考虑切换到WPF,因为最终我还需要支持16位灰度图像。尽管就获取像素值而言,这可能会带来问题。