0

Here's my situation: I have a console application that creates screenshots of webpages in a bitmap format and then saves it to a database as a byte array.

Then I have a Generic Handler that basically gets the byte array and then returns the image (it is set as the html image source). Here is the code:

public void ProcessRequest(HttpContext context)
{
    int id = Convert.ToInt32(context.Request.QueryString["Id"]);

    context.Response.ContentType = "image/jpeg";
    MemoryStream strm = new MemoryStream(getByteArray(id));
    byte[] buffer = new byte[4096];
    int byteSeq = strm.Read(buffer, 0, 4096);
    while (byteSeq > 0)
    {
        context.Response.OutputStream.Write(buffer, 0, byteSeq);
        byteSeq = strm.Read(buffer, 0, 4096);
    }
}

public Byte[] getByteArray(int id)
{
    EmailEntities e = new EmailEntities();

    return e.Email.Find(id).Thumbnail;
}

(I did not write that code myself)

The Image although is of course still returned as a bitmap and is far too big in size. Which is why I wanted to return it as a compressed jpg or png, as long as it is small.

So my question to you: What possibilities are there to do this without having to save the image to the filesystem directly?

Thanks in advance for your responses.

Some Developer
  • 229
  • 6
  • 19
  • Propably there is an answer for u: http://stackoverflow.com/questions/18609757/how-to-compress-image-byte-array-to-jpeg-png-and-return-imagesource-object – sdrzymala Jun 13 '14 at 09:14
  • hmm, it might technically be a solution. But as far as I know you cannot just 'return' something in a generic handler. Or I just don't know how. – Some Developer Jun 13 '14 at 09:19
  • The code you have now can only work correctly with the `image/jpeg` MIME type if the blob in the dbase was already compressed into the JPEG file format. So you can't get ahead by encoding the image, that was already done. Only reducing the quality or storing a smaller image is an option. – Hans Passant Jun 13 '14 at 11:45
  • ok. Well reducing the quality would be fine, but how do you do that from a byte array? – Some Developer Jun 13 '14 at 11:46

1 Answers1

1

The following snippet should get you closer to your goal.

This assumes the byte array retrieved from the database can be interpreted by .net as a valid image (e.g. a simple bitmap image).

public class ImageHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        int id = Convert.ToInt32(context.Request.QueryString["Id"]);
        var imageBytes = getByteArray(id);
        using (var stream = new MemoryStream(imageBytes))
        using (var image = Image.FromStream(stream))
        {
            var data = GetEncodedImageBytes(image, ImageFormat.Jpeg);

            context.Response.ContentType = "image/jpeg";
            context.Response.BinaryWrite(data);
            context.Response.Flush();
        }
    }

    public Byte[] getByteArray(int id)
    {
        EmailEntities e = new EmailEntities();

        return e.Email.Find(id).Thumbnail;
    }

    public byte[] GetEncodedImageBytes(Image image, ImageFormat format)
    {
        using (var stream = new MemoryStream())
        {
            image.Save(stream, format);
            return stream.ToArray();
        }
    }

    public bool IsReusable
    {
        get { return false; }
    }
}

And in web.config:

  <system.webServer>
    <handlers>
      <add name="ImageHandler" path="/ImageHandler" verb="GET" type="ImageHandler" preCondition="integratedMode" />
    </handlers>
  </system.webServer>

If you need to control compression / quality, you will need to start looking at things like this: https://stackoverflow.com/a/1484769/146999

Or you can go for PNG, which is lossless – and will likely compress better if most of the imagery is graphics/UI/text. If so, don’t forget to set both ImageFormat for encoding and ContentType for http response.

Hope this helps...

Community
  • 1
  • 1
tranquil tarn
  • 1,606
  • 1
  • 13
  • 11