I want to show images of different sizes in a ListView. The image is displayed in a standard size. However, I do not want the images to be skewed or expanded while displaying.How can I do this?

The most common approach is to use Image.GetThumbnailImage(). This will work if all images have the same width / height ratio. But if width / height ratio is different, then the images will appear skewed.

A more suitable approach is to crop the image so that width / height ratio of all images is same as desired width / height ratio of desired display. Here is some sample code:


public void ProcessRequest(HttpContext context)
{
    // This is the dimensions you want to display in the web page
    int displayWidth = 400;
    int displayHeight = 300;
    float displayAspect = (float)displayWidth / displayHeight;

    // Get the filename and initialize the image to draw
    string file = context.Request.QueryString["name"];
    Image image = Image.FromFile(context.Server.MapPath("~/" + file + ".jpg"));

    // Get the aspect of image in the file
    // Crop the image to the same ratio as the display desired
    float aspect = (float)image.Width / image.Height;
    
    int newWidth = image.Width;
    int newHeight = image.Height;

    if (aspect > displayAspect)
    {
        newWidth = (int)(image.Height * displayAspect);
    }
    if (aspect < displayAspect)
    {
        newHeight = (int)(image.Width / displayAspect);
    }

    // SrcRect = Cropped rectangle from the file
    Rectangle srcRect = new Rectangle((image.Width - newWidth) / 2, (image.Height - newHeight) / 2, newWidth, newHeight);
    
    // Bitmap to copy to
    Bitmap bmp = new Bitmap(newWidth, newHeight);
    Rectangle destRect = new Rectangle(0, 0, newWidth, newHeight);
    Graphics graphics = Graphics.FromImage(bmp);

    // Copy to new image using Graphics object
    graphics.DrawImage(image, destRect, srcRect, GraphicsUnit.Pixel);
    
    // Get the bytestream of the cropped bitmap
    MemoryStream ms = new MemoryStream();
    bmp.Save(ms, ImageFormat.Jpeg);
    context.Response.BinaryWrite(ms.GetBuffer());
}

Here is a sample markup using the above handler.

<form id="form1" runat="server"><div><img src="Viewer.ashx?name=Kp1" width="400" height="300" /><img src="Viewer.ashx?name=Kp2" width="400" height="300" /><img src="Viewer.ashx?name=Kp3" width="400" height="300" /></div></form>