Loss of image quality in C # using an image class (reduces the number of colors)

I have a C # program that opens a .tif image and then offers a save option. However, when you save an image, quality always decreases.

(EDIT: I passed some parameters when saving the image so that the quality is 100% and there is no compression, but the number of real unique colors goes from 254 to 16, although the image properties show 8bpp)

(EDIT2: the image in question is a grayscale image of 8 bits per pixel - 256 colors / shades of gray). This does not happen with the 24-bit color image I tested, where all the colors are saved. I'm starting to think that an image class can only support 16 shades of gray)

How can I avoid this?

Here is the code to open the image:

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

So 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 do not resize or resize the image in any way, I experience a loss of quality. any advice?

+4
source share
4 answers

System.Drawing poorly supports 8-bit images. When converting from 24 or 32-bit images to 8-bit; it will always use a fixed default color palette. This default color palette contains only 16 shades of gray, while others contain different colors.

Do you have the same problem saving as ".bmp"? If so, the conversion to 8-bit format has already happened before, you need to find out where your program does this and fix the problem. If it is only a tiff encoder that converts to 8-bit, you first need to perform 8-bit conversion in a separate step. Create an 8-bit image, fill Image.Palette gray palette, and then copy the bitmap data.

But System.Drawing has poor support for 8-bit images, and several methods (like SetPixel ) will just throw an InvalidOperationException when working with such images. You may have to use unsafe code (with LockBits , etc.) to copy raster data. If I were you, I would see if there are alternative graphic libraries that you could use.

+1
source

I am having problems using .NET libraries to find good balances in image quality and size. I threw my own and tried several image libraries. I found http://imageresizing.net/ to provide consistently good results, much better than I could do.

Just throw it away as plan B in case your own method doesn't complete the work on an ongoing basis for you.

0
source

Image.Save defaults to 75% quality setting. You can try using one of the other method overloads, which allows you to specify quality settings. See this question.

0
source

Only one sentence is valid ... when loading an image, you use new Bitmap(fileName) ... Instead of using a bitmap, you thought you were using

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

Truth says that it uses “built-in color management,” and using the image instead of Bitmap avoids any casting of the image that might happen behind the scenes.

0
source

Source: https://habr.com/ru/post/1443650/


All Articles