Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create thumbnail in .NET C# by defining width

I am using the following code in my website, for thumbnail creation:

string furl = "~/images/thumbs/" + matchString;
lBlogThumb.ImageUrl = GetThumbnailView(furl, 200, 200);


private string GetThumbnailView(string originalImagePath, int height, int width)
        {
            //Consider Image is stored at path like "ProductImage\\Product1.jpg"

            //Now we have created one another folder ProductThumbnail to store thumbnail image of product.
            //So let name of image be same, just change the FolderName while storing image.
            string thumbnailImagePath = originalImagePath.Replace("thumbs", "thumbs2");
            //If thumbnail Image is not available, generate it.
            if (!System.IO.File.Exists(Server.MapPath(thumbnailImagePath)))
            {
                System.Drawing.Image imThumbnailImage;
                System.Drawing.Image OriginalImage = System.Drawing.Image.FromFile(Server.MapPath(originalImagePath));
                imThumbnailImage = OriginalImage.GetThumbnailImage(width, height,
                             new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);

                imThumbnailImage.Save(Server.MapPath(thumbnailImagePath), System.Drawing.Imaging.ImageFormat.Jpeg);

                imThumbnailImage.Dispose();
                OriginalImage.Dispose();
            }
            return thumbnailImagePath;
        }

public bool ThumbnailCallback() { return false; }

I would like to change this code, and be able to create a thumbnail defining width ONLY. What I have in mind is actually something like cropping/resizing image, using a static width, maintaining it's ratio. Is that possible;

like image 882
zekia Avatar asked Nov 29 '22 18:11

zekia


1 Answers

You mention resizing and cropping. If you want the thumbnail heights to vary with a fixed width, the answers provided already will work for you.

The mention of cropping makes me think that you may want a fixed thumbnail size, with the width filled and any overflowing vertical portion cropped off. If that is the case, you'll need to do a bit more work. I needed something similar recently, and this is what I came up with.

This will create a thumbnail of the original that is sized and cropped in such a way that the source image completely fills the target thumbnail, cropping any overflow. There will be no borders within the thumbnail, even if the original and thumbnail aspect ratios are different.

public System.Drawing.Image CreateThumbnail(System.Drawing.Image image, Size thumbnailSize)
{
    float scalingRatio = CalculateScalingRatio(image.Size, thumbnailSize);

    int scaledWidth = (int)Math.Round((float)image.Size.Width * scalingRatio);
    int scaledHeight = (int)Math.Round((float)image.Size.Height * scalingRatio);
    int scaledLeft = (thumbnailSize.Width - scaledWidth) / 2;
    int scaledTop = (thumbnailSize.Height - scaledHeight) / 2;

    // For portrait mode, adjust the vertical top of the crop area so that we get more of the top area
    if (scaledWidth < scaledHeight && scaledHeight > thumbnailSize.Height)
    {
        scaledTop = (thumbnailSize.Height - scaledHeight) / 4;
    }

    Rectangle cropArea = new Rectangle(scaledLeft, scaledTop, scaledWidth, scaledHeight);

    System.Drawing.Image thumbnail = new Bitmap(thumbnailSize.Width, thumbnailSize.Height);
    using (Graphics thumbnailGraphics = Graphics.FromImage(thumbnail))
    {
        thumbnailGraphics.CompositingQuality = CompositingQuality.HighQuality;
        thumbnailGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
        thumbnailGraphics.SmoothingMode = SmoothingMode.HighQuality;
        thumbnailGraphics.DrawImage(image, cropArea);
    }
    return thumbnail;
}

private float CalculateScalingRatio(Size originalSize, Size targetSize)
{
    float originalAspectRatio = (float)originalSize.Width / (float)originalSize.Height;
    float targetAspectRatio = (float)targetSize.Width / (float)targetSize.Height;

    float scalingRatio = 0;

    if (targetAspectRatio >= originalAspectRatio)
    {
        scalingRatio = (float)targetSize.Width / (float)originalSize.Width;
    }
    else
    {
        scalingRatio = (float)targetSize.Height / (float)originalSize.Height;
    }

    return scalingRatio;
}

To use with your code, you could replace your call to OriginalImage.GetThumbnailImage with this:

imThumbnailImage = CreateThumbnail(OriginalImage, new Size(width, height));

Note that for portrait images, this code will actually shift the thumbnail's viewport slightly higher on the original image. This was done so that portrait shots of people wouldn't result in headless torsos when the thumbnails were created. If you don't want that logic, simply remove the if block following the "portrait mode" comment.

like image 104
Jeromy Irvine Avatar answered Dec 10 '22 12:12

Jeromy Irvine