title: Image.Save() on MemoryBmp to TIFF with EncoderParams - How?
body: <p>I have an application that allows a user to define a region of an image and save that region to file.  I have run up against a snag that I can't sort out.  The Bitmap that I create to paint the selected region onto is stuck with an ImageFormat of "MemoryBmp", it appears that this is the ImageFormat that is set for any non-file loaded bitmaps.  The problem is my Bitmap is created in memory and I want to save it as a CCITT4 bitonal TIFF but I'm getting a "A generic error occurred in GDI+" Exception.  I'm pretty confident this is due to the fact the Image.RawFormat property is that dreaded MemoryBmp.</p>
  
  <p>Image.Save() has an overload that takes an ImageFormat parameter and when I use that passing ImageFormat.Tiff it saves fine, but I don't get the opportunity to specify my encoder parameters.</p>
  
  <p>The only possible workaround I can think of is to save to disk using Image.Save(Image, ImageFormat) then reload it (RawFormat will now correctly be set to ImageFormat.Tif) and THEN save again passing the encoder settings.  That is just stupid though, there must be a better way.</p>
  
  <p>Here is a snipped of code (this is just testing stuff) that should give you an idea of what I'm doing in case my earlier description wasn't clear enough:</p>
  
  <pre><code>SizeF dpiScale = GetScreenToImageDPIRatio(loadedImage);
  using (Bitmap image = new Bitmap(loadedImage,
      (int)(_cropBox.Width * dpiScale.Width),
      (int)(_cropBox.Height * dpiScale.Height)))
  {
      image.SetResolution(loadedImage.HorizontalResolution, 
          loadedImage.VerticalResolution);
  
      using (Graphics g = Graphics.FromImage(image))
      {
          g.DrawImage(loadedImage, 0, 0, new Rectangle(
              (int)(_cropBox.Location.X * dpiScale.Width),
              (int)(_cropBox.Location.Y * dpiScale.Height),
              (int)(_cropBox.Width * dpiScale.Width),
              (int)(_cropBox.Height * dpiScale.Height)),
              GraphicsUnit.Pixel);
      }
  
      //  It's stuck as a MemoryBmp so none of these checks will work
      if (true || image.RawFormat.Equals(ImageFormat.Tiff))
      {
          ImageCodecInfo tiffCodecInfo = ImageUtils.GetEncoderInfo("image/tiff");
          EncoderParameters myEncoderParameters = new EncoderParameters(2);
  
          myEncoderParameters.Param[0] = new
              EncoderParameter(System.Drawing.Imaging.Encoder.Compression,
                  (long)EncoderValue.CompressionCCITT4);
          myEncoderParameters.Param[1] = new
              EncoderParameter(System.Drawing.Imaging.Encoder.ColorDepth, 1L);
  
          image.Save(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".tif"),
              tiffCodecInfo, myEncoderParameters);
  
          //  The file is a "MemoryBmp" and it's screwing things up
          //image.Save(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".tif"),
          //    ImageFormat.Tiff);
      }
      else
      {
          //  other format saving support, blah blah blah
      }
  }
  </code></pre>
  
  <p>Oh, I should mention that "loadedIimage" is indeed a tiff image, I passed the reference to loadedImage to the Bitmap.ctor() to see if that would clue it in to what it's dealing with but it made no difference.</p>