Подтвердить что ты не робот

Высококачественное сжатие JPEG с помощью С#

Я использую С# и хочу сохранять изображения в формате JPEG. Однако .NET снижает качество изображений и сохраняет их с недостаточным сжатием.

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

Bitmap bm = (Bitmap)Image.FromFile(FilePath); 
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); 
ImageCodecInfo ici = null; 

foreach (ImageCodecInfo codec in codecs)
{ 
    if (codec.MimeType == "image/jpeg") 
    ici = codec; 
} 

EncoderParameters ep = new EncoderParameters(); 
ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)100); 
bm.Save("C:\\quality" + x.ToString() + ".jpg", ici, ep);

Я архивирую фотографии студии, качество и сжатие очень важны. Спасибо.

4b9b3361

Ответ 1

Похоже, вы устанавливаете качество на 100%. Это означает, что сжатие не будет.

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

ОБНОВЛЕНИЕ. Как отметил комментатор, качество 100% по-прежнему не означает сжатие без потерь при использовании JPEG. Загрузка изображения, что-то с ним, а затем сохранение его снова приведет к деградации изображения. Если вам нужно изменить и сохранить изображение без потери каких-либо данных, вам необходимо использовать формат без потерь, например TIFF, PNG или BMP. Я бы пошел со сжатым TIFF (так как он все еще без потерь, хотя и сжат) или PNG.

Ответ 2

Встроенный в библиотеку .Net-кодировщик (по крайней мере, библиотека Windows по умолчанию, предоставленная Microsoft) довольно плохая:

http://b9dev.blogspot.com/2013/06/nets-built-in-jpeg-encoder-convenient.html

Частичное обновление

Теперь я использую подход, описанный здесь, который использует ImageMagick для изменения размера, а затем jpegoptim для окончательного сжатия, с гораздо лучшими результатами. Я понимаю, что частичный ответ, но я буду расширять этот раз, когда позволяет время.

Старый ответ

ImageMagick - лучший выбор, который я нашел до сих пор. Он выполняет относительно твердое сжатие jpeg.

http://magick.codeplex.com/

У него есть пара недостатков:

  • Это лучше, но не идеально. В частности, его подвыборка Chroma установлена ​​на высокую детализацию при 90% или выше, затем переходит на более низкий уровень детализации - тот, который может ввести много артефактов. Если вы хотите игнорировать подвыборку, это на самом деле довольно удобно. Но если вы хотите, чтобы подвыборка с высокой детализацией, скажем, на 50%, у вас впереди большая задача. Он также по-прежнему не будет поражать уровни качества/сжатия Photoshop или Google PageSpeed.

  • На сервере есть особая нагрузка на развертывание, которую очень легко пропустить. Он требует установки Visual Studio 2008 SDK lib. Эта библиотека доступна на любом dev-машине с Visual Studio, но затем вы попадаете на сервер в первый раз, и он взрывается с неясной ошибкой. Это одна из тех скрытых ошибок, что большинство людей не будут иметь сценарий/автоматизацию, и вы будете путешествовать по ней во время какой-либо будущей миграции сервера.

Самый старый ответ

Я вырыл вокруг и наткнулся на проект, чтобы реализовать кодировщик С# JPEG, переведя проект на C:

http://www.codeproject.com/Articles/83225/A-Simple-JPEG-Encoder-in-C

который я упростил немного:

https://github.com/b9chris/ArpanJpegEncoder

Он создает гораздо более качественные JPEG файлы, чем встроенный .Net, но все же не так хорош, как Gimp или Photoshop. Размер файлов также больше.

реализация BitMiracle практически идентична встроенным тем же проблемам качества .Net.

Вероятно, что просто завершение существующей реализации с открытым исходным кодом, например Google jpeg_optimizer в Инструментах PageSpeed ​​ - казалось бы libjpeg ниже, будет наиболее эффективным вариантом.

Update

ArpanJpegEncoder, похоже, имеет проблемы после его развертывания - возможно, мне нужно увеличить уровень доверия кода или, возможно, что-то еще происходит. Локально он прекрасно пишет изображения, но после его развертывания я получаю от него пустое черное изображение. Я уточню, если я определяю причину. Просто предупреждение другим, рассматривающим это.

Ответ 3

Сжатие и качество всегда являются компромиссом.

JPEG всегда будут потерять.

Возможно, вам захочется использовать PNG и минимизировать файлы с помощью PNGCrush или PNGauntlet

Ответ 4

Что касается настройки уровня сжатия в .NET, проверьте эту ссылку (все включено): http://msdn.microsoft.com/en-us/library/bb882583.aspx

Реинжиниринг вашего вопроса: Обычно вы сохраняете загруженное изображение от пользователей в виде PNG, тогда вы используете этот PNG в качестве базы для генерации ваших JPG разных размеров (и вы помещаете водяной знак ТОЛЬКО на JPG, никогда не на оригинальном PNG!) Преимущество этого заключается в следующем: если вы впоследствии измените размеры ваших изображений на своей платформе, у вас будет сохранен исходный PNG, и на основе этого вы сможете повторно вычислить любые новые размеры изображений.

Ответ 5

Он должен сохранять файл как его качество и размер.

Это не имеет большого смысла. Когда вы используете сжатие с потерей, вы потеряете некоторую информацию по определению. Цель сжатия изображения - уменьшить размер файла. Если вам нужно высокое качество, и jpeg не делает этого для вас, вам, возможно, придется пойти с каким-либо сжатием без потерь, но ваши размеры файлов не будут значительно уменьшены. Вы всегда можете попробовать использовать стандартную библиотеку для сжатия в jpeg (libjpeg) и посмотреть, дает ли это разные результаты (я сомневаюсь, но я не знаю, что .NET использует под капотом.)

Ответ 6

Сжатие формата jpeg по самой своей природе снижает качество. Возможно, вам стоит изучить сжатие файлов, например # ziplib. Вы можете получить разумное сжатие по группе файлов.