Crop an image and convert to PNG

1.4k views Asked by At

Guys I am trying to crop an image and save it as PNG.

I can crop it fine, but the image doesn't get saved as PNG properly -- it gets saved as JPEG or whatever the original format was. Only when user decides not to crop the image.

Here is what I mean, even though I set ImageFormat.Png the image gets saved as JPEG.

enter image description here

Here is the code I am using:

private byte[] ResizeImage2(string resizeInfo)
{
    string[] picInfo = resizeInfo.Split('|');

    int width = int.Parse(picInfo[0]);
    int height = int.Parse(picInfo[1]);
    int targetWidth = int.Parse(picInfo[2]);
    int targetHeight = int.Parse(picInfo[3]);
    int x = int.Parse(picInfo[4]);
    int y = int.Parse(picInfo[5]);

    using (var fileStore = new EPMLiveFileStore(Web))
    {
        using (var sourceImage = new Bitmap(fileStore.GetStream(FileNameField.Value)))
        {
            using (var bitmap = new Bitmap(width, height))
            {
                using (var graphics = Graphics.FromImage(bitmap))
                {
                    graphics.CompositingQuality = CompositingQuality.HighQuality;
                    graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    graphics.SmoothingMode = SmoothingMode.HighQuality;

                    graphics.DrawImage(sourceImage, new Rectangle(0, 0, width, height));

                    using (var memoryStream = new MemoryStream())
                    {
                        bitmap.Save(memoryStream, ImageFormat.Png);

                        using (var bmp = new Bitmap(bitmap))
                        {
                            using (var pic = bmp.Clone(new Rectangle(x, y, targetWidth, targetHeight), bitmap.PixelFormat))
                            {
                                using (var stream = new MemoryStream())
                                {
                                    pic.Save(stream, ImageFormat.Png);
                                    return stream.ToArray();
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
2

There are 2 answers

2
Jigsore On

I made some changes to your code. The method returns the entire PNG file expressed as a byte array (not sure if this is what you're trying to achieve):

private byte[] ResizeImage2(string resizeInfo)
{
    string[] picInfo = resizeInfo.Split('|');

    int width = int.Parse(picInfo[0]);
    int height = int.Parse(picInfo[1]);
    int targetWidth = int.Parse(picInfo[2]);
    int targetHeight = int.Parse(picInfo[3]);
    int x = int.Parse(picInfo[4]);
    int y = int.Parse(picInfo[5]);
    byte[] rslt;

    Bitmap sourceImage;

    using (var fileStore = new EPMLiveFileStore(Web))
    {
        sourceImage = new Bitmap(fileStore.GetStream(FileNameField.Value));
    }

    using (var bitmap = new Bitmap(targetWidth, targetHeight))
    {
        bitmap.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);

        using (var graphics = Graphics.FromImage(bitmap))
        {
            graphics.CompositingQuality = CompositingQuality.HighQuality;
            graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            graphics.SmoothingMode = SmoothingMode.HighQuality;

            graphics.DrawImage(sourceImage, new Rectangle(0, 0, targetWidth, targetHeight), new Rectangle(x, y, targetWidth, targetHeight), GraphicsUnit.Pixel);

            using (var memoryStream = new MemoryStream())
            {
                bitmap.Save(memoryStream, ImageFormat.Png);
                rslt = memoryStream.ToArray();
            }
        }
    }
    return rslt;
}

Since you're only cropping (no resampling is performed), the following lines could be unnecessary:

graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.SmoothingMode = SmoothingMode.HighQuality;
0
drew_w On

Taking what Jigstore and simplifying I think you can just use the following:

private byte[] ResizeImage2(string resizeInfo)
{
  string[] picInfo = resizeInfo.Split('|');
  int width = int.Parse(picInfo[0]);
  int height = int.Parse(picInfo[1]);
  int targetWidth = int.Parse(picInfo[2]);
  int targetHeight = int.Parse(picInfo[3]);
  int x = int.Parse(picInfo[4]);
  int y = int.Parse(picInfo[5]);

  using (var fileStore = new EPMLiveFileStore(Web))
  {
    using (Bitmap sourceImage = new Bitmap(fileStore.GetStream(FileNameField.Value)))
    {
      using (var bitmap = new Bitmap(width, height))
      {
        bitmap.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);

        using (var graphics = Graphics.FromImage(bitmap))
        {
          graphics.DrawImageUnscaled(sourceImage, Point.Empty);

          using (var memoryStream = new MemoryStream())
          {
              bitmap.Save(memoryStream, ImageFormat.Png);
              return (byte[]) memoryStream.ToArray();
          }
        }
      }
    }
  }
}

By the way, you are going to loose any metadata that you had on the original file. This would be EXIF information, and the thumbnail from the JPEG just to name a few. If you want to keep this information I would recommend using a tool like the following via command line (http://www.hugsan.com/exifutils/).