0

I have write this code to do crop and resize the image on the fly. I send the processed image to the browser like <img src="imagehandler.aspx?img=1.jpg">:

imagehandler.aspx:

<%@ Page Language="C#"%>
<%@ import Namespace="System.Drawing" %>
<%@ import Namespace="System.IO" %>
<script runat="server">
    System.Drawing.Image oldImage, newImage,cloned,tempImage;
    void Page_Load(Object sender, EventArgs e) {
    string strFileName = Convert.ToString(Request.QueryString["img"]);
    oldImage = System.Drawing.Image.FromFile(Server.MapPath(strFileName));
    rect= new Rectangle(0,50,100,100);  
    cloned = new Bitmap(oldImage ).Clone(rect, tempImage.PixelFormat);
    newImage = new Bitmap(cloned);
    cloned.Dispose();   

    Response.ContentType = "image/jpeg";
    newImage.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
    oldImage.Dispose();
    newImage.Dispose();
    oldImage = null;
    newImage = null;
    }
</script>

Now I want to add quality control to the output image and I found this Q/A This answer suggests a method which saves the image to the disk. I have tried to fit it to my purpose. Currently I can only save it on the disk and the method is void. I don't know how to pass the output to my own codes before streaming the result to the browser:

private void VaryQualityLevel(bmp1)
{
    ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);
    System.Drawing.Imaging.Encoder myEncoder= System.Drawing.Imaging.Encoder.Quality;
    EncoderParameters myEncoderParameters = new EncoderParameters(1);
    EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L);
    myEncoderParameters.Param[0] = myEncoderParameter;
    bmp1.Save(@"c:\TestPhotoQualityFifty.jpg", jgpEncoder,myEncoderParameters);
}

private ImageCodecInfo GetEncoder(ImageFormat format)
{
    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
    foreach (ImageCodecInfo codec in codecs)
    {
        if (codec.FormatID == format.Guid)
        {
            return codec;
        }
    }
    return null;
}
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Ali Sheikhpour
  • 10,475
  • 5
  • 41
  • 82

1 Answers1

0

You can save your bitmap directly to MemoryStream and do whatever you want with it. Your encoder will be applied to image inside this stream. Instead of passing file path as first parameter of Save method just pass instance of MemoryStream. If I remember correctly there's also a way to pass this stream directly as a response to browser.

using(var ms = new MemoryStream()) 
{
    bmp1.Save(ms, jgpEncoder, myEncoderParameters);
    var bmp2 = new BitMap(ms);
    //do whatever you want with this image
}

Keep in mind to use using statment or dispose method for sfream to avoid memory leak.

More details here: https://learn.microsoft.com/en-us/dotnet/api/system.drawing.bitmap?view=netframework-4.7.2

Wokuo
  • 206
  • 1
  • 8
  • Thanks . But I did the same in my own codes. The main problem is to pass the output of second method to the first method not to the stream. In fact I think I have to return a bitmap and get it in the first? – Ali Sheikhpour Oct 03 '18 at 16:06
  • No. From `VaryQualityLevel` to my own code in first block of question. – Ali Sheikhpour Oct 03 '18 at 16:16
  • Ok. Based on my experience bitmap/image in C# doesn't allow resize/change quality on existing objects, it generally ends with creating new object. From stream you can easily create new bitmap and return it. I've updated my answer above. – Wokuo Oct 03 '18 at 16:22