Reputation: 638
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
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
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
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