Использование jpegtran, jpegoptim или другой оптимизации / сжатия jpeg в C#

У меня есть 100-е (может быть, 1000-е) продуктов с 10-30 изображениями каждого продукта, поступающего в интернет-магазин, который я собрал. Мне нужно максимально оптимизировать размеры файлов изображений без потери качества изображения.

Я не использовал jpegtran, jpegoptim или любой другой оптимизатор jpeg напрямую, но заметил, что punypng сокращает размеры файлов примерно на 4-6% на больших изображениях jpeg без потерь.

Метаданные уже извлекаются из изображений во время загрузки (через Jumpoader), так что это больше не является проблемой / проблемой.

Есть ли способ заставить один из оптимизаторов jpeg работать из кода C#?

Примечание: я использую общий хостинг Godaddy с IIS7 и.Net 3.5

5 ответов

Это может быть на 7 лет позже, но я столкнулся с этим вопросом, пытаясь решить эту проблему. В конце концов мне удалось сделать это, и это решение. Для PNG сначала необходимо установить nQuant с помощью NuGet.

включают:

using System.Web.Hosting;
using System.IO;
using System.Diagnostics;
using nQuant;
using System.Drawing;
using System.Drawing.Imaging;

Методы:

    public void optimizeImages()
    {
        string folder = 
            Path.Combine(HostingEnvironment.ApplicationPhysicalPath, @"assets\temp");
        var files = Directory.EnumerateFiles(folder);

        foreach (var file in files)
        {
            switch (Path.GetExtension(file).ToLower())
            {
                case ".jpg":
                case ".jpeg":
                    optimizeJPEG(file);
                    break;
                case ".png":
                    optimizePNG(file);
                    break;
            }

        }

    }

    private void optimizeJPEG(string file)
    {
        string pathToExe = HostingEnvironment.MapPath("~\\adminassets\\exe\\") + "jpegtran.exe";

        var proc = new Process
        {
            StartInfo =
            {
                Arguments = "-optimize \"" + file + "\" \"" + file + "\"",
                FileName = pathToExe,
                UseShellExecute = false,
                CreateNoWindow = false,
                WindowStyle = ProcessWindowStyle.Hidden,
                RedirectStandardError = true,
                RedirectStandardOutput = true
            }
        };

        Process jpegTranProcess = proc;

        jpegTranProcess.Start();
        jpegTranProcess.WaitForExit();
    }

    private void optimizePNG(string file)
    {
        string tempFile = Path.GetDirectoryName(file) + @"\temp-" + Path.GetFileName(file);
        int alphaTransparency = 10;
        int alphaFader = 70;
        var quantizer = new WuQuantizer();
        using (var bitmap = new Bitmap(file))
        {
            using (var quantized = quantizer.QuantizeImage(bitmap, alphaTransparency, alphaFader))
            {
                quantized.Save(tempFile, ImageFormat.Png);

            }

        }
        System.IO.File.Delete(file);
        System.IO.File.Move(tempFile, file);
    }

Он возьмет все файлы из папки /assets/temp и оптимизирует JPEG и PNG. Я следил за этим вопросом для PNG. Часть JPEG, которую я соскоблил из нескольких источников. Включая PicJam и Оптимизатор изображения. Я использую его путем загрузки всех файлов от пользователя во временную папку, запуска этого метода, загрузки файлов в хранилище BLOB-объектов Azure и удаления локальных файлов. Я скачал jpegtran здесь.

Если вам не нравится возиться с временными файлами, я бы посоветовал использовать C++/CLI.

Создайте C++/CLI dll проект в visual studio. Создайте один статический управляемый класс и определите функции так, как вы хотите их использовать из C#:

public ref class JpegTools
{
public:
     static array<byte>^ Optimize(array<byte>^ input)
};

Эти функции, которые вы определяете, могут быть напрямую вызваны из C#, и вы можете реализовать их со всем, что предлагает C++.

массив ^ соответствует байтовому массиву C#. Вам нужно будет использовать pin_ptr<> для закрепления байтового массива в памяти, чтобы вы могли передавать данные неуправляемой вспомогательной функции Jpeg по вашему выбору. C++/CLI имеет достаточную поддержку для преобразования управляемых типов в собственные типы. Вы также можете выделить новый массив с помощью gc_new, чтобы возвращать CLI-совместимые типы. Если вам необходимо выполнить маршаллинг строк из C# в C++ как часть этого упражнения, используйте тип CString Mfc/Atl.

Вы можете статически связать весь код jpeg в dll. DLL C++ может быть смешан с чистым нативным кодом и кодом C++/CLI. В наших проектах C++ / CLI обычно только исходные файлы интерфейса знают о типах CLI, все остальные работают с типами C++.

Для этого нужно проделать определенную работу, но положительным моментом является то, что ваш код проверяется по типу во время компиляции, а все операции с неуправляемым кодом и памятью выполняются на стороне C++. На самом деле это работает настолько хорошо, что я использовал C++ / CLI для тестирования модулей собственного кода C++ почти напрямую с NUnit.

Удачи!

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

Я уверен, что опоздал ответить на этот вопрос, но недавно я столкнулся с проблемой оптимизации без потерь в формате jpeg и не нашел подходящей реализации C# утилиты jpegtran. Итак, я решил самостоятельно реализовать процедуры для уменьшения размера jpeg без потерь на основе оболочки C модифицированного jpegtran, которую вы можете найти здесь. Получается, что подобная реализация с использованием чистого.Net LibJpeg.NET намного медленнее, чем завернутое в C решение, поэтому я не включил его в репозиторий. Использование обертки довольно просто,

if (JpegTools.Transform(jpeg, out byte[] optimized, copy: false, optimize: true))
{
  //do smth useful 
}
else
{
  //report on error or use original jpeg
}

Надеюсь, кто-то найдет это полезным.

Почему бы не вызвать punypng.com с Process.Start ()? Нет причин, по которым ваш код.net не может запускать внешние программы при условии, что обработка выполняется во время загрузки (а не при обработке изображений)

Например

  • загрузить в папку "загрузить",
  • есть службы windows, которые следят за новыми файлами в папке "upload"
  • когда вы получите новый файл, запустите punypng.com для его обработки и поместите вывод в правильную папку с изображениями.
Другие вопросы по тегам