title: Rendering smallest possible image size with MVC3 vs Webforms Library
body: <p>I am in the process of moving a webforms app to MVC3.  Ironically enough, everything is cool beans except one thing - images are served from a handler, specifically the <a href="http://aspnet.codeplex.com/releases/view/16449" rel="nofollow">Microsoft Generated Image Handler</a>.  It works really well - on average a 450kb photo gets output at roughly 20kb.</p>
  
  <p>The actual <a href="http://test.sk8loc8.com/content/test.jpg" rel="nofollow">photo on disk</a> weighs in at 417kb, so i am getting a great reduction. </p>
  
  <p>Moving over to MVC3 i would like to drop the handler and use a controller action.  However i seem to be unable to achieve the same kind of file size reduction when rendering the image. I walked through the source and took an exact copy of their <a href="http://aspnet.codeplex.com/SourceControl/changeset/view/68345#257229" rel="nofollow">image transform code</a> yet i am only achieving 230~kb, which is still a lot bigger than what the ms handler is outputting - 16kb.</p>
  
  <p>You can <a href="http://test.sk8loc8.com" rel="nofollow">see an example of both the controller and the handler here</a></p>
  
  <p>I have walked through the handler source code and cannot see anything that is compressing the image further.  If you examine both images you can see a difference - the handler rendered image is less clear, more grainy looking, but still what i would consider satisfactory for my needs.</p>
  
  <p>Can anyone give me any pointers here? is output compression somehow being used? or am i overlooking something very obvious?</p>
  
  <p>The code below is used in my home controller to render the image, and is an exact copy of the FitImage method in the <a href="http://aspnet.codeplex.com/SourceControl/changeset/view/68345#257229" rel="nofollow">Image Transform class</a> that the handler uses ...</p>
  
  <pre><code>public ActionResult MvcImage()
      {
          var file = Server.MapPath("~/Content/test.jpg");
          var img = System.Drawing.Image.FromFile(file);
          var sizedImg = MsScale(img);
  
          var newFile = Server.MapPath("~/App_Data/test.jpg");
          if (System.IO.File.Exists(newFile))
          {
              System.IO.File.Delete(newFile);
          }
          sizedImg.Save(newFile);
          return File(newFile, "image/jpeg");
      }
  
  private Image MsScale(Image img)
      {
          var scaled_height = 267;
          var scaled_width = 400;
          int resizeWidth = 400;
          int resizeHeight = 267;
          if (img.Height == 0)
          {
              resizeWidth = img.Width;
              resizeHeight = scaled_height;
          }
          else if (img.Width == 0)
          {
              resizeWidth = scaled_width;
              resizeHeight = img.Height;
          }
          else
          {
              if (((float)img.Width / (float)img.Width &lt; img.Height / (float)img.Height))
              {
                  resizeWidth = img.Width;
                  resizeHeight = scaled_height;
              }
              else
              {
                  resizeWidth = scaled_width;
                  resizeHeight = img.Height;
              }
          }
  
          Bitmap newimage = new Bitmap(resizeWidth, resizeHeight);
          Graphics gra = Graphics.FromImage(newimage);
          SetupGraphics(gra);
          gra.DrawImage(img, 0, 0, resizeWidth, resizeHeight);
          return newimage;
      }
  
      private void SetupGraphics(Graphics graphics)
      {
          graphics.CompositingMode = CompositingMode.SourceCopy;
          graphics.CompositingQuality = CompositingQuality.HighSpeed;
          graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
          graphics.SmoothingMode = SmoothingMode.HighSpeed;
      }
  </code></pre>