Создать миниатюру в .NET C #, определив ширину - PullRequest
4 голосов
/ 11 января 2011

Я использую следующий код на своем веб-сайте для создания миниатюр:

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; }

Я хотел бы изменить этот код и иметь возможность создавать ТОЛЬКО миниатюру, определяющую ширину.На самом деле я имею в виду что-то вроде обрезки / изменения размера изображения, использования статической ширины, сохранения его соотношения.Это возможно;

Ответы [ 4 ]

15 голосов
/ 11 января 2011

Вы упоминаете изменение размера и обрезку.Если вы хотите, чтобы высота миниатюр варьировалась в зависимости от фиксированной ширины, приведенные ответы уже будут работать для вас.

Упоминание обрезки заставляет меня думать, что вам может потребоваться фиксированный размер миниатюр с заполненной шириной и любымпереполненная вертикальная часть обрезана.Если это так, вам нужно сделать немного больше работы.Недавно мне понадобилось что-то похожее, и это то, что я придумал.

Это создаст миниатюру оригинала, размер которой будет обрезан и обрезан таким образом, что исходное изображение полностью заполняет целевой эскиз, обрезая любыепереполнение.Внутри миниатюры не будет границ, даже если исходное соотношение и пропорции миниатюр отличаются.

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;
}

Чтобы использовать с вашим кодом, вы можете заменить свой вызов на OriginalImage.GetThumbnailImage следующим:

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

Обратите внимание, что для портретных изображений этот код фактически сместит область просмотра миниатюры немного выше исходного изображения.Это было сделано для того, чтобы при создании эскизов портретные снимки людей не приводили к безголовым торсам.Если вам не нужна эта логика, просто удалите блок if после комментария «портретный режим».

7 голосов
/ 11 января 2011

давайте получим originalWidth = ширину исходного изображения и ширину thumbWidth.Вы можете просто выбрать thumbWidth для желаемого значения и вычислить thumbHeigth=originalHeigth*thumbWidth/originalWidth

1 голос
/ 28 января 2014

Мне надоело это делать и я создал библиотеку, которая делает это легко: Ссылка на документацию и загрузка

0 голосов
/ 11 января 2011

Базовый пример без округления с шириной миниатюры 140, ниже «файла» - HttpPostedFile, загруженный из элемента управления ASP.Net FileUpload, HttpPostedFile предоставляет поток.

// Save images to disk.
using (System.Drawing.Image image = System.Drawing.Image.FromStream(file.InputStream))
using (System.Drawing.Image thumbnailImage = image.GetThumbnailImage(140, Convert.ToInt32((image.Height / (image.Width / 140))), null, IntPtr.Zero))
{
    if (image != null)
    {
        image.Save(imageFilePath);
        thumbnailImage.Save(thumbnailImagePath); 
    }
    else
        throw new ArgumentNullException("Image stream is null");
}
...