Потеря качества изображения в C# с использованием класса Image (уменьшает количество цветов)
У меня есть программа 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 ответа
System.Drawing плохо поддерживает 8-битные изображения. При конвертации из 24 или 32-битных изображений в 8-битные; он всегда будет использовать фиксированную цветовую палитру по умолчанию. Эта цветовая палитра по умолчанию содержит только 16 оттенков серого, остальные записи имеют различные цвета.
Есть ли у вас такая же проблема при сохранении как ".bmp"? Если да, то преобразование в 8-битный формат уже произошло ранее, вам придется выяснить, где ваша программа делает это, и устранить проблему там. Если преобразование в 8-битный код выполняется только в tiff-кодировщик, сначала вам придется выполнить 8-битное преобразование в отдельном шаге. Создайте 8-битное изображение, заполните Image.Palette
с палитрой оттенков серого, а затем скопируйте растровые данные поверх.
Но System.Drawing плохо поддерживает 8-битные изображения и несколько методов (например, SetPixel
) просто скину InvalidOperationException
когда имеем дело с такими изображениями. Возможно, вам придется использовать небезопасный код (с LockBits
и т. д.) для копирования растровых данных. На вашем месте я бы посмотрел, есть ли альтернативные графические библиотеки, которые вы могли бы использовать.
Image.Save
по умолчанию используется настройка качества 75%. Вы можете попробовать использовать одну из других перегрузок метода, которая позволяет вам указать параметры настройки качества. Смотрите этот вопрос.
Только одно предложение на самом деле.... при загрузке изображения вы используете new Bitmap(fileName)
... Вместо использования растрового изображения вы рассматривали возможность использования
Image tiffImage = Image.FromFile(tiffFileName, true);
Истина говорит ему использовать "встроенное управление цветом", а использование изображения вместо растрового изображения позволяет избежать любого приведения изображения, которое может происходить за кулисами.
У меня были проблемы с использованием библиотек.NET для нахождения хорошего баланса качества и размера изображения. Я бросил свою собственную и попробовал несколько библиотек изображений. Я обнаружил, что http://imageresizing.net/ дает неизменно хорошие результаты, гораздо лучше, чем я смог сделать.
Просто добавьте это как план Б на тот случай, если ваш собственный метод не будет работать на постоянной основе для вас.