Я пытаюсь записать метод для сокращения размера любого изображения 50%, которыми называют каждый раз, но я нашел проблему. Иногда, я заканчиваю с большим размером файла, в то время как изображение является действительно всего половиной того, каково это было. Я забочусь о DPI и PixelFormat. Что еще я пропускаю?
Спасибо за Ваше время.
public Bitmap ResizeBitmap(Bitmap origBitmap, int nWidth, int nHeight)
{
Bitmap newBitmap = new Bitmap(nWidth, nHeight, origBitmap.PixelFormat);
newBitmap.SetResolution(
origBitmap.HorizontalResolution,
origBitmap.VerticalResolution);
using (Graphics g = Graphics.FromImage((Image)newBitmap))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(origBitmap, 0, 0, nWidth, nHeight);
}
return newBitmap;
}
Править: Вот недостающий код:
int width = (int)(bitmap.Width * 0.5f);
int height = (int)(bitmap.Height * 0.5f);
Bitmap resizedBitmap = ResizeBitmap(bitmap, width, height);
resizedBitmap.Save(newFilename);
Редактирование 2: На основе Ваших комментариев это - решение, которое я нашел:
private void saveAsJPEG(string savingPath, Bitmap bitmap, long quality)
{
EncoderParameter parameter = new EncoderParameter(Encoder.Compression, quality);
ImageCodecInfo encoder = getEncoder(ImageFormat.Jpeg);
if (encoder != null)
{
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = parameter;
bitmap.Save(savingPath, encoder, encoderParams);
}
}
private ImageCodecInfo getEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo codec in codecs)
if (codec.FormatID == format.Guid)
return codec;
return null;
}
Скорее всего, вы сохраняете изображение в формате jpeg с низкой степенью сжатия (высокое качество).
Я бы сказал, что вы сохраняете его как высококачественный jpeg (меньше сжатия == больше места)
Проблема не в опубликованном вами коде, а в том, где вы сохраняете JPEG. Какую степень сжатия вы используете?
Кажется, что ваши растровые изображения фактически сохраняются в формате jpeg, и зная, как C # любит делать что-то за вас, вероятно, выполняется сохранение с уровнем сжатия по умолчанию, который довольно низкий. Исходный jpeg должен иметь приличный уровень сжатия. Даже если это был тот же уровень сжатия, то, как работает формат jpeg, может означать, что вы нашли случайное изображение, которое дает раздувание при более низком разрешении.
Битовая карта - это точный размер, если он десять пикселей в ширину и десять в высоту, это 100 пикселей, скажем, в 16-битном (2-байтовом) цвете, который составляет 200 байтов, плюс бит заголовка.
уменьшите разрешение до 5 на 5, у вас будет 50 байт плюс бит заголовка, хотя размер заголовка должен быть таким же.
Похоже, оригинал - это снимок с цифровой камеры.Я думаю, что производители камер используют собственные супероптимизированные алгоритмы сжатия, тогда как обычная библиотека может иметь менее эффективную реализацию. (И, конечно, вы, вероятно, не используете тот же уровень сжатия, что и камера.)
Вдобавок камера использует в качестве входных необработанные данные (возможно, сначала выполняя некоторую «магическую» предварительную обработку) от своих датчиков. Когда вы повторно сжимаете его, входные данные содержат артефакты сжатия и масштабирования, которые могут снизить эффективность сжатия.
На самом деле, я думаю, что если вы сожмете изображение несколько раз с помощью того же jpg алгоритма на том же уровне , оно может вырасти в размере, потому что артефакты от предыдущих сжатий добавляют "деталей" "который сложнее сжать (и он становится еще уродливее).
(Алгоритм сжатия камеры также может быть оптимизирован с учетом того факта, что на входе всегда фотография, в то время как алгоритм общего назначения может делать некоторые менее эффективные вещи, чтобы работать достаточно хорошо как для фотографий, так и для ] штриховая графика смешанные изображения, содержащие как фотографии, так и созданные графические элементы.)
Повторного сжатия изображения JPEG следует избегать. Но настоящая проблема здесь - InterpolationMode, высококачественный режим дает много тонко затененных пикселей, что затрудняет сжатие изображения. Использование InterpolationMode.NearestNeighbor должно избежать этого, но за счет получения изображения более низкого качества.
Попробуйте этот код, чтобы сохранить имеющийся у вас JPEG. Это позволит вам установить качество сжатия. Поэкспериментируйте и посмотрите, поможет ли это решить вашу проблему с размером:
private void saveJpeg(string path, Bitmap img, long quality)
{
EncoderParameter parameter = new EncoderParameter(Encoder.Quality, quality);
ImageCodecInfo encoder = this.getEncoderInfo("image/jpeg");
if (encoder != null)
{
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = parameter;
img.Save(path, encoder, encoderParams);
}
}
private ImageCodecInfo getEncoderInfo(string mimeType)
{
ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders();
for (int i = 0; i < imageEncoders.Length; i++)
{
if (imageEncoders[i].MimeType == mimeType)
{
return imageEncoders[i];
}
}
return null;
}