首页 文章

Azure blob:图像优化

提问于
浏览
0

需要优化上传到azure blob存储的图像 . 我正在编写一个天蓝色的功能应用程序(blob触发器),它将获取上传的图像并使用图像压缩器库对其进行压缩,然后将生成的图像保存到另一个blob中 .

我已经创建了一个自定义库来通过引用ImageOptimizerWebJob库来压缩图像 . 压缩逻辑运行适当的图像压缩器exe文件( pingo.exe, cjpeg.exe, jpegtran.exe or 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;
    }

我的azure函数使用这个库来完成这项工作 . 但这里的挑战是,输入和输出文件位置是azure blobs而不是本地桌面路径 .

输入和输出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

    您将需要使用某些描述的文件系统,或者如果exe提供StdIn / Out,您可以在 MemoryStream 中执行此操作并保存(使用它)您喜欢的方式

    以下是支持StdIn / Out的 jpegoptim.exe 的示例

    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}");      
       }
    }
    

相关问题