BLOB-объекты Azure: оптимизация изображений - PullRequest
0 голосов
/ 11 сентября 2018

Требуется оптимизировать изображения, загружаемые в хранилище BLOB-объектов Azure.Я пишу приложение-функцию Azure (триггер BLOB-объекта), которое берет загруженное изображение и сжимает его с помощью библиотеки компрессора изображений, а затем сохраняет полученное изображение в другой BLOB-объект.

Я создал пользовательскую библиотеку длясжатие изображений с помощью ссылки на библиотеку ImageOptimizerWebJob .Логика сжатия запускает соответствующий exe-файл программы сжатия изображений ( pingo.exe, cjpeg.exe, jpegtran.exe или gifsicle.exe ) для сжатия указанного изображения.

public CompressionResult CompressFile(string fileName, bool lossy)
    {
        string targetFile = Path.ChangeExtension(Path.GetTempFileName(), Path.GetExtension(fileName));

        ProcessStartInfo start = new ProcessStartInfo("cmd")
        {
            WindowStyle = ProcessWindowStyle.Hidden,
            WorkingDirectory = _cwd,
            Arguments = GetArguments(fileName, targetFile, lossy),
            UseShellExecute = false,
            CreateNoWindow = true,
        };

        var stopwatch = Stopwatch.StartNew();

        using (var process = Process.Start(start))
        {
            process.WaitForExit();
        }

        stopwatch.Stop();

        return new CompressionResult(fileName, targetFile, stopwatch.Elapsed);
    }


 private static string GetArguments(string sourceFile, string targetFile, bool lossy)
    {
        if (!Uri.IsWellFormedUriString(sourceFile, UriKind.RelativeOrAbsolute) && !File.Exists(sourceFile))
            return null;

        string ext;

        try
        {
            ext = Path.GetExtension(sourceFile).ToLowerInvariant();
        }
        catch (ArgumentException ex)
        {
            Console.WriteLine(ex);
            return null;
        }

        switch (ext)
        {
            case ".png":
                File.Copy(sourceFile, targetFile);

                if (lossy)
                    return string.Format(CultureInfo.CurrentCulture, "/c pingo -s8 -q -palette=79 \"{0}\"", targetFile);
                else
                    return string.Format(CultureInfo.CurrentCulture, "/c pingo -s8 -q \"{0}\"", targetFile);

            case ".jpg":
            case ".jpeg":
                if (lossy)
                {
                    return string.Format(CultureInfo.CurrentCulture, "/c cjpeg -quality 80,60 -dct float -smooth 5 -outfile \"{1}\" \"{0}\"", sourceFile, targetFile);
                }

                return string.Format(CultureInfo.CurrentCulture, "/c jpegtran -copy none -optimize -progressive -outfile \"{1}\" \"{0}\"", sourceFile, targetFile);

            case ".gif":
                return string.Format(CultureInfo.CurrentCulture, "/c gifsicle -O3 --batch --colors=256 \"{0}\" --output=\"{1}\"", sourceFile, targetFile);
        }

        return null;
    }

Моя функция лазурииспользует эту библиотеку, чтобы сделать работу.Но проблема здесь в том, что расположение файла ввода и вывода - это лазурные объекты, а не локальные пути к рабочему столу.

Входные и выходные данные BLOB-объектов поступают из метода Run ()

public static void Run([BlobTrigger("test/{name}", Connection = "")]Stream myBlob,
        [Blob("test-output/{name}", FileAccess.ReadWrite)]CloudBlockBlob output,
        string name,
        TraceWriter log)

Но я не могу напрямую использовать пути ввода и вывода BLOB-объектов для компрессора изображений.Я не мог найти способ получить выходное изображение в виде потока памяти (для загрузки в выходной BLOB-объект)

Оцените ваши предложения, чтобы решить эту проблему.

1 Ответ

0 голосов
/ 11 сентября 2018

Вам потребуется либо использовать файловую систему некоторого описания, либо, если exe предоставляет StdIn / Out , вы можете сделать все это в MemoryStream и сохранить ее (воспроизвести с ним) как вам нравится

Вот пример для jpegoptim.exe, который поддерживает StdIn / Out

var startInfo = new ProcessStartInfo
   {
      WindowStyle = ProcessWindowStyle.Hidden,
      FileName = @"jpegoptim.exe",
      Arguments = @"-s --stdin --stdout",
      RedirectStandardOutput = true,
      RedirectStandardError = true,
      RedirectStandardInput = true,
      UseShellExecute = false,
      CreateNoWindow = true
   };

using (var process = Process.Start(startInfo))
{

   inputStream.CopyTo(process.StandardInput.BaseStream);
   process.StandardInput.Close();

   using (var file = new FileStream(dest, FileMode.Create, FileAccess.Write))
   {
      process.StandardOutput.BaseStream.CopyTo(file);
   }

   if (process.ExitCode != 0)
   {
      var message = process.StandardError.ReadToEnd();
      throw new InvalidOperationException($"Failed to optimise image : {message}");      
   }
}
...