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

Losing image quality in c# using Image class (reduces amount of colors)(使用 Image 类在 c# 中丢失图像质量(减少颜色数量))
本文介绍了使用 Image 类在 c# 中丢失图像质量(减少颜色数量)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a c# program that opens a .tif image and later offers the option to save it. However, there is always a drop in quality when saving the image.

(我在保存图像时传递了一些参数,以便质量为 100% 并且没有压缩,但实际唯一颜色的数量从 254 变为 16,即使图像属性显示 8bpp)

(有问题的图像是每像素 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;
}

这是我保存图像的方式:

This is the way I save the image:

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();
    }
}

即使我不以任何方式调整图像大小或更改图像,我的质量也会有所下降.有什么建议吗?

Even if I don't resize or change the image in any ways, I experience a loss in quality. any advice?

推荐答案

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

System.Drawing has poor support for 8-bit images. When converting from 24 or 32-bit images to 8-bit; it'll always use a fixed default color palette. That default color palette only contains 16 shades of grey, the other entries are various colors.

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

Do you have the same problem when saving as '.bmp'? If yes, then the conversion to the 8-bit format already happened earlier, you'll have to figure out where your program does that and fix the issue there. If it's only the tiff encoder that converts to 8-bit, you'll have to do the 8-bit conversion in a separate step first. Create an 8-bit image, fill Image.Palette with a gray-scale palette, and then copy the bitmap data over.

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

But System.Drawing has poor support for 8-bit images, and several methods (e.g. SetPixel) will just throw InvalidOperationException when dealing with such images. You will probably have to use unsafe code (with LockBits etc.) to copy the bitmap data. If I were you, I'd look if there are alternative graphics libraries you could use.

这篇关于使用 Image 类在 c# 中丢失图像质量(减少颜色数量)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)