Kevin Fisher
Kevin Fisher

Reputation: 638

Return Re-sized Image from Database Through .ashx

I've found some similar questions on SO and elsewhere, but nothing that quite does what I'm looking for (or, maybe I'm just too boneheaded to connect the dots!)

I'm looking to return a thumbnail image from a full size image stored as varbinary(max) in the database. I'll be using the thumbnails in a gallery-style view, so small size / efficient loading is crucial. I've been using an .ashx to return the full size image into a bound asp.net Image control, with the following code:

Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest

    Dim conn As New SqlConnection()
    conn.ConnectionString = *connectionstring*

    Dim cmd As New SqlCommand()
    cmd.Connection = conn
    cmd.CommandType = CommandType.StoredProcedure
    cmd.CommandText = "GetEmplHeadShot"

    Dim emplID As New SqlParameter("@emplID", context.Request.QueryString("emplid"))
    cmd.Parameters.Add(emplID)

    conn.Open()

    Dim myReader As SqlDataReader = cmd.ExecuteReader
    If myReader.Read Then

        context.Response.BinaryWrite(myReader("HeadShot"))
        context.Response.ContentType = "image/jpeg"

    End If
    myReader.Close()
    conn.Close()

End Sub

I realize it's probably best to address the re-size at the upload, and stored the smaller image as a discrete column. But in the meantime, is it possible to program the handler to re-size the image on the fly? Ideally, I'd be able to pass an additional query string parameter, something like isResized from the image binding, allowing the same handler to be used for both full size and re-sized images.

Any advice / assistance would be greatly appreciated. Ideas on alternative approaches (i.e. "you're going about this all wrong") would also be very welcome.

Upvotes: 3

Views: 2288

Answers (3)

Neil N
Neil N

Reputation: 25258

Yes, instead of returning the var binary directly back to the response, put it into a Bitmap object (via a memory stream created from the varbinary)

Resize the BMP, then save it back to the memory stream via the save method, then output the memory stream back to a byte array to the response.

Keep in mind though that instantiating a Bitmap on the server can be very memory intesive. If you have multiple requests simultaneously, you could run into "out of memory exceptions". It's probably a good idea to save the thumbnails to db or disk when created, so that you don't have to keep re-creating them on every request.

Upvotes: 1

Nathan Ratcliff
Nathan Ratcliff

Reputation: 1502

Sorry, not a VB guy, but here's an example if you can read C#. You'll want to add some handling for missing parameters and such, but this could outline your basic approach.

        public void ProcessRequest( HttpContext context )
        {
            int height = Convert.ToInt32(context.Request["height"]);
            int width = Convert.ToInt32(context.Request["width"]);


            //Get image from database here, put into a stream
            var stream = new MemoryStream(); //this would represent the stream from your database image

            using( var original = Image.FromStream( stream ) )
            {
                using( var resized = new Bitmap(width, height, PixelFormat.Format24bppRgb) )
                {
                    using( var g = Graphics.FromImage( resized ) )
                    {
                        g.SmoothingMode = SmoothingMode.AntiAlias;
                        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        g.PixelOffsetMode = PixelOffsetMode.HighQuality;

                        g.DrawImage( original, new Rectangle( new Point( 0, 0 ), new Size(width, height) ) );

                        var resizedStream = new MemoryStream();
                        resized.Save(resizedStream, ImageFormat.Jpeg);

                        context.Response.ContentType = "image/jpeg";
                        context.Response.BinaryWrite(resizedStream.GetBuffer());
                        context.Response.End();
                    }
                }               
            }

        }

Upvotes: 3

Jakob Gade
Jakob Gade

Reputation: 12419

Yes, it's certainly possible to do the resizing on the fly. I would suggest you just let the HttpHandler create the thumbnail on the first request, storing it in the database or as an image on the server.

For your scenario I would probably consider a solution where the handler takes in height/width parameters, resizes the image, and stores it for reuse.

Upvotes: 1

Related Questions