Иногда, уменьшение масштаб битового массива генерирует больший файл. Почему?

Я пытаюсь записать метод для сокращения размера любого изображения 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;
}

http://imgur.com/lY9BN.png

http://imgur.com/KSka0.png

Править: Вот недостающий код:

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;
}
5
задан Matías 24 March 2010 в 21:24
поделиться

7 ответов

Скорее всего, вы сохраняете изображение в формате jpeg с низкой степенью сжатия (высокое качество).

6
ответ дан 18 December 2019 в 10:43
поделиться

Я бы сказал, что вы сохраняете его как высококачественный jpeg (меньше сжатия == больше места)

1
ответ дан 18 December 2019 в 10:43
поделиться

Проблема не в опубликованном вами коде, а в том, где вы сохраняете JPEG. Какую степень сжатия вы используете?

2
ответ дан 18 December 2019 в 10:43
поделиться

Кажется, что ваши растровые изображения фактически сохраняются в формате jpeg, и зная, как C # любит делать что-то за вас, вероятно, выполняется сохранение с уровнем сжатия по умолчанию, который довольно низкий. Исходный jpeg должен иметь приличный уровень сжатия. Даже если это был тот же уровень сжатия, то, как работает формат jpeg, может означать, что вы нашли случайное изображение, которое дает раздувание при более низком разрешении.

Битовая карта - это точный размер, если он десять пикселей в ширину и десять в высоту, это 100 пикселей, скажем, в 16-битном (2-байтовом) цвете, который составляет 200 байтов, плюс бит заголовка.

уменьшите разрешение до 5 на 5, у вас будет 50 байт плюс бит заголовка, хотя размер заголовка должен быть таким же.

1
ответ дан 18 December 2019 в 10:43
поделиться

Похоже, оригинал - это снимок с цифровой камеры.Я думаю, что производители камер используют собственные супероптимизированные алгоритмы сжатия, тогда как обычная библиотека может иметь менее эффективную реализацию. (И, конечно, вы, вероятно, не используете тот же уровень сжатия, что и камера.)

Вдобавок камера использует в качестве входных необработанные данные (возможно, сначала выполняя некоторую «магическую» предварительную обработку) от своих датчиков. Когда вы повторно сжимаете его, входные данные содержат артефакты сжатия и масштабирования, которые могут снизить эффективность сжатия.

На самом деле, я думаю, что если вы сожмете изображение несколько раз с помощью того же jpg алгоритма на том же уровне , оно может вырасти в размере, потому что артефакты от предыдущих сжатий добавляют "деталей" "который сложнее сжать (и он становится еще уродливее).

(Алгоритм сжатия камеры также может быть оптимизирован с учетом того факта, что на входе всегда фотография, в то время как алгоритм общего назначения может делать некоторые менее эффективные вещи, чтобы работать достаточно хорошо как для фотографий, так и для ] штриховая графика смешанные изображения, содержащие как фотографии, так и созданные графические элементы.)

1
ответ дан 18 December 2019 в 10:43
поделиться

Повторного сжатия изображения JPEG следует избегать. Но настоящая проблема здесь - InterpolationMode, высококачественный режим дает много тонко затененных пикселей, что затрудняет сжатие изображения. Использование InterpolationMode.NearestNeighbor должно избежать этого, но за счет получения изображения более низкого качества.

4
ответ дан 18 December 2019 в 10:43
поделиться

Попробуйте этот код, чтобы сохранить имеющийся у вас 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;
}
1
ответ дан 18 December 2019 в 10:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: