title: In .Net is System.Drawing.Image.Save deterministic?
body: <p>I'm trying to compare two Images via their byte content. However, they do not match.</p>
  
  <p>Both images were generated from the same source image, using the same method with the same parameters. I am guessing that something in the image generation or the way I convert to a byte array is not deterministic. Does anyone know where the non-deterministic behavior is occurring and whether or not I can readily force deterministic behavior for my unit testing?</p>
  
  <p>This method within my test class converts the image to a byte array - is <code>image.Save</code> deterministic? Is <code>memStream.ToArray()</code> deterministic?</p>
  
  
  
  <pre class="lang-cs prettyprint-override"><code>private static byte[] ImageToByteArray(Image image)
  {
      byte[] actualBytes;
      using (MemoryStream memStream = new MemoryStream())
      {
          image.Save(memStream, ImageFormat.Bmp);
          actualBytes = memStream.ToArray();
      }
      return actualBytes;
  }
  </code></pre>
  
  <p>Here is the unit test, which is failing - <code>TestImageLandscapeDesertResized_300_300</code> was generated from <code>TestImageLandscapeDesert</code> using the <code>ImageHelper.ResizeImage(testImageLandscape, 300, 300)</code> and then saving to a file before loading into the project's resource file. If all calls within my code were deterministic based upon my input parameters, this test should pass.</p>
  
  <pre class="lang-cs prettyprint-override"><code>public void ResizeImage_Landscape_SmallerLandscape()
  {
      Image testImageLandscape = Resources.TestImageLandscapeDesert;
      Image expectedImage = Resources.TestImageLandscapeDesertResized_300_300;
      byte[] expectedBytes = ImageToByteArray(expectedImage);
      byte[] actualBytes;
      using (Image resizedImage = ImageHelper.ResizeImage(testImageLandscape, 300, 300))
      {
          actualBytes = ImageToByteArray(resizedImage);
      }
      Assert.IsTrue(expectedBytes.SequenceEqual(actualBytes));
  }
  </code></pre>
  
  <p>The method under test - this method will shrink the input image so its height and width are less than <code>maxHeight</code> and <code>maxWidth</code>, retaining the existing aspect ratio. Some of the graphics calls may be non-deterministic, I cannot tell from Microsoft's limited documentation.</p>
  
  <pre class="lang-cs prettyprint-override"><code>public static Image ResizeImage(Image image, int maxWidth, int maxHeight)
  {
      decimal width = image.Width;
      decimal height = image.Height;
      decimal newWidth;
      decimal newHeight;
  
      //Calculate new width and height
      if (width &gt; maxWidth || height &gt; maxHeight)
      {
          // need to preserve the original aspect ratio
          decimal originalAspectRatio = width / height;
  
          decimal widthReductionFactor = maxWidth / width;
          decimal heightReductionFactor = maxHeight / height;
  
          if (widthReductionFactor &lt; heightReductionFactor)
          {
              newWidth = maxWidth;
              newHeight = newWidth / originalAspectRatio;
          }
          else
          {
              newHeight = maxHeight;
              newWidth = newHeight * originalAspectRatio;
          }
      }
  
      else
          //Return a copy of the image if smaller than allowed width and height
          return new Bitmap(image);
  
      //Resize image
      Bitmap bitmap = new Bitmap((int)newWidth, (int)newHeight, PixelFormat.Format48bppRgb);
      Graphics graphic = Graphics.FromImage(bitmap);
      graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
      graphic.DrawImage(image, 0, 0, (int)newWidth, (int)newHeight);
      graphic.Dispose();
  
      return bitmap;
  }
  </code></pre>