title: Azure blobs: Image optimization
body: <p>There is a requirement to optimize images uploaded to a azure blob storage. I'm writing an azure function app (blob trigger) which will take the uploaded image and compress it using a image compressor library and then save the resulting image into another blob.</p>
  <p>I've created a custom library to compress images by referencing the <a href="https://github.com/madskristensen/ImageOptimizerWebJob" rel="nofollow noreferrer">ImageOptimizerWebJob</a> library. The compression logic runs appropriate image compressor exe file (<strong>pingo.exe, cjpeg.exe, jpegtran.exe or gifsicle.exe</strong>) to compress the given image.</p>
  <pre><code>public CompressionResult CompressFile(string fileName, bool lossy)
      {
          string targetFile = Path.ChangeExtension(Path.GetTempFileName(), Path.GetExtension(fileName));
  
          ProcessStartInfo start = new ProcessStartInfo(&quot;cmd&quot;)
          {
              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) &amp;&amp; !File.Exists(sourceFile))
              return null;
  
          string ext;
  
          try
          {
              ext = Path.GetExtension(sourceFile).ToLowerInvariant();
          }
          catch (ArgumentException ex)
          {
              Console.WriteLine(ex);
              return null;
          }
  
          switch (ext)
          {
              case &quot;.png&quot;:
                  File.Copy(sourceFile, targetFile);
  
                  if (lossy)
                      return string.Format(CultureInfo.CurrentCulture, &quot;/c pingo -s8 -q -palette=79 \&quot;{0}\&quot;&quot;, targetFile);
                  else
                      return string.Format(CultureInfo.CurrentCulture, &quot;/c pingo -s8 -q \&quot;{0}\&quot;&quot;, targetFile);
  
              case &quot;.jpg&quot;:
              case &quot;.jpeg&quot;:
                  if (lossy)
                  {
                      return string.Format(CultureInfo.CurrentCulture, &quot;/c cjpeg -quality 80,60 -dct float -smooth 5 -outfile \&quot;{1}\&quot; \&quot;{0}\&quot;&quot;, sourceFile, targetFile);
                  }
  
                  return string.Format(CultureInfo.CurrentCulture, &quot;/c jpegtran -copy none -optimize -progressive -outfile \&quot;{1}\&quot; \&quot;{0}\&quot;&quot;, sourceFile, targetFile);
  
              case &quot;.gif&quot;:
                  return string.Format(CultureInfo.CurrentCulture, &quot;/c gifsicle -O3 --batch --colors=256 \&quot;{0}\&quot; --output=\&quot;{1}\&quot;&quot;, sourceFile, targetFile);
          }
  
          return null;
      }
  </code></pre>
  <p>My azure function uses this library to do the job. But the challenge here is, the input and output file location are azure blobs not local desktop paths.</p>
  <p>The input and output blob data are coming from the Run() method</p>
  <pre><code>public static void Run([BlobTrigger(&quot;test/{name}&quot;, Connection = &quot;&quot;)]Stream myBlob,
          [Blob(&quot;test-output/{name}&quot;, FileAccess.ReadWrite)]CloudBlockBlob output,
          string name,
          TraceWriter log)
  </code></pre>
  <p>But I cannot directly use the input and output blob paths for the image compressor. I could not figure out a way to get the output image as a memory stream (to upload to output blob)</p>
  <p>Appreciate your suggestions to resolve this.</p>