Почему размер файла не всегда меняется при настройке уровня качества JpegBitmapEncoder?

#c# #visual-studio #jpeg

#c# #visual-studio #jpeg

Вопрос:

Я пытаюсь сохранить файл BITMAP для записи и убедиться, что результирующий файл меньше определенного размера. Мой код выглядит следующим образом

 //Fetch Image from file
BitmapImage bitmap = new BitmapImage(new Uri("YourImage.jpg", UriKind.Relative));
WriteableBitmap writableBitmapImage = new WriteableBitmap(bitmap);

//initialize variables and values
MemoryStream stream;
JpegBitmapEncoder encoder;
byte[] resu<
int quality = 100;

//loop through save process, checking file size and changing quality
while (selected.maxFileSize < result.Length amp;amp; quality > 1)
{
    encoder = new JpegBitmapEncoder();
    stream = new MemoryStream();
    encoder.QualityLevel = quality;
    encoder.Frames.Add(BitmapFrame.Create(
        ReplaceTransparency(writableBitmapImage, Colors.White))
    );
    encoder.Save(stream);
    result = stream.GetBuffer();
    if (quality > 5) quality  = -5;
    else quality--;
}
  

Когда я запускаю этот код, я не вижу никаких изменений размера файла от начальной точки QualityLevel = 100; до QualityLevel = 10; .

На QualityLevel = 5; я вижу значительное изменение размера файла.

Есть ли какой-либо способ контролировать размер файла более детально?

Комментарии:

1. Хм, ты же на самом деле не пишешь белый прямоугольник, не так ли?

2. Почему вы создаете и настраиваете encoder только для того, чтобы выбросить это? Вы никогда не пишете на QualityLevel == 100 в своем примере кода. Кроме того, что находится в writableBitmapImage ?

3. @TaW Вы правы, я не пишу белый прямоугольник. Записываемый BitmapImage — это существующее записываемое BITMAP-изображение. Я не был уверен, как представить это в вопросе.

4. @NetMage Я настраиваю кодировщик, только для удаления, чтобы я мог установить encoder.QualityLevel перед входом в цикл while. Записываемый BitmapImage содержит существующее изображение, обычно снимок головы или портрет. Я не был уверен, что лучший способ показать это в коде. Мне пришлось сконструировать приведенный выше код из гораздо более крупной программы.

5. @NetMage Я отредактировал код для наглядности

Ответ №1:

Прочитайте документацию для MemoryStream.GetBuffer() :

Обратите внимание, что буфер содержит выделенные байты, которые могут быть неиспользуемыми. Например, если строка «test» записывается в объект MemoryStream, длина буфера, возвращаемого из GetBuffer, равна 256, а не 4, при этом 252 байта не используются. Чтобы получить только данные в буфере, используйте метод toArray; однако toArray создает копию данных в памяти.

Тогда используйте .ToArray() вместо этого.

Комментарии:

1. Или просто используйте MemoryStream.Length для определения фактической длины.