Изменить размер изображения любого размера в 400Wx264H, используя C# для веб-приложения asp.net

Я проектирую веб-сайт и мне нужно изменить размер большого изображения до 400Wx264H без потери соотношения сторон.

Я работал над другой версией кода, но все возвращаются с той или иной проблемой.

Прямо сейчас я изменяю размеры больших изображений до 400 Вт, сохраняя соотношение сторон, и затем я разрешаю пользователю выбрать часть изображения с помощью jCrop, область выбора - 350 Вт × 230 Н.

Проблема в том, что иногда он добавляет к изображению черную часть, если высота или ширина изображения были меньше 400 Вт или 264 Н пикселей.

Я был бы признателен, если бы кто-нибудь указал мне на нечто подобное, что я должен сделать.

Код для загрузки и изменения размера изображения ниже

public void ResizeImageFreeSize(string OriginalFile, string NewFile, int NewWidth, int MaxHeight, bool OnlyResizeIfWider, string fileExtension)
    {
        System.Drawing.Image FullsizeImage = System.Drawing.Image.FromFile(OriginalFile);
        // Prevent using images internal thumbnail
        //FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
        //FullsizeImage.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipNone);
        //if (OnlyResizeIfWider)
        //{
        //    if (FullsizeImage.Width <= NewWidth)
        //    {
        //        NewWidth = FullsizeImage.Width;
        //    }
        //}
        //int NewHeight = FullsizeImage.Height * NewWidth / FullsizeImage.Width;
        //if (NewHeight > MaxHeight)
        //{
        //    // Resize with height instead
        //    NewWidth = FullsizeImage.Width * MaxHeight / FullsizeImage.Height;
        //    NewHeight = MaxHeight;
        //}
        System.Drawing.Image NewImage = FullsizeImage.GetThumbnailImage(NewWidth, MaxHeight, null, IntPtr.Zero);
        // Clear handle to original file so that we can overwrite it if necessary
        FullsizeImage.Dispose();
        // Save resized picture

        if (fileExtension.ToLower() == ".jpg" || fileExtension.ToLower() == ".jpeg")
        {
            //NewImage.Save(NewFile, System.Drawing.Imaging.ImageFormat.Jpeg);

            Encoder quality = Encoder.Quality;
            var ratio = new EncoderParameter(quality, 100L);
            var codecParams = new EncoderParameters(1);
            codecParams.Param[0] = ratio;
            NewImage.Save(NewFile, GetEncoder(ImageFormat.Jpeg), codecParams);
        }

        if (fileExtension.ToLower() == ".png")
        {
            NewImage.Save(NewFile, System.Drawing.Imaging.ImageFormat.Png);
        }

        if (fileExtension.ToLower() == ".gif")
        {
            NewImage.Save(NewFile, System.Drawing.Imaging.ImageFormat.Gif);
        }
    }

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

После загрузки изображения с измененным размером я разрешаю пользователю выбрать область из этого изображения с помощью jCrop, можно выбрать 350x230 пикселей.

Это работает без проблем, но изображения растягиваются

protected void btnCrop_Command(object sender, CommandEventArgs e)
{
    cropImage();
    // pnlImageDetails.Visible = true;
}

protected void cropImage()
{
    var x = int.Parse(_xField.Value);
    var y = int.Parse(_yField.Value);
    var width = int.Parse(_widthField.Value);
    var height = int.Parse(_heightField.Value);
    string _CropImagePath = Session["_CropImagePath"].ToString();
    using (var photo = System.Drawing.Image.FromFile(_CropImagePath))
    using (var result =
          new Bitmap(width, height, photo.PixelFormat))
    {
        result.SetResolution(photo.HorizontalResolution, photo.VerticalResolution);
        using (var g = Graphics.FromImage(result))
        {
            // g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.DrawImage(photo, new Rectangle(0, 0, width, height),
                               new Rectangle(x, y, width, height),
                                             GraphicsUnit.Pixel);
            photo.Dispose();
            result.Save(_CropImagePath);
            string filePath = _CropImagePath.ToString();
            System.IO.FileInfo f = new System.IO.FileInfo(filePath);
            string fileExtension = f.Extension;
            string fileName = f.Name;
            string[] fNameArray = fileName.Split('.');
            string fileNewName = fNameArray[0] + "TN" + f.Extension;
            Session["ArticleThumbnailImage"] = fileNewName;
            string fileNewPath = Server.MapPath("../ImagesArticles/") + fileNewName;
            ResizeImageFreeSize(filePath, fileNewPath, 170, 112, true, fileExtension);
        }

    }
}

ЧАСТЬ HTML КОДА

 <div id="ImageEditorFrame" style="width:800px; height:350px; float:left; ">

    <div style="width:404px; height:268px; margin-left:160px; margin-top:10px; padding-top:1px;  background-image:url('images/Scale.png'); background-repeat:no-repeat;">
        <div style="width:400px; height:264px; margin-left:3px; margin-top:2px; padding-top:1px; background-color:#f5f5f5;">
            <asp:Image runat="server" ID="_imageEditor" ImageUrl="" Visible="true" />   

        </div>
        <div style="margin-top:10px;"> 
         <asp:Button ID="btnCrop" runat="server" style="float:left;"  Text=" Crop Image " Visible="False" oncommand="btnCrop_Command"  />
        <input id="w" type="text" name="w" size="4" disabled="disabled">
        <input id="h" type="text" name="h" size="4" disabled="disabled">(350x230)<br /><br />
        <asp:Label ID="lblUplodedImgInfo" runat="server" Text=""></asp:Label>
        </div>
    </div>


    <input type="hidden" runat="server" id="_xField" />
    <input type="hidden" runat="server" id="_yField" />
    <input type="hidden" runat="server" id="_widthField" />
    <input type="hidden" runat="server" id="_heightField" />



</div>

var editorID = '<%= _imageEditor.ClientID %>';
jQuery(function () {
    jQuery('#' + editorID).Jcrop({
        onChange: showCoords,
        onSelect: showCoords,
        setSelect: [0, 0, 350, 230],
        allowResize: false
    });
});

function showCoords(c) {

    var xField = document.getElementById('<%= _xField.ClientID %>');
    var yField = document.getElementById('<%= _yField.ClientID %>');
    var widthField = document.getElementById('<%= _widthField.ClientID %>');
    var heightField = document.getElementById('<%= _heightField.ClientID %>');

    xField.value = c.x;
    yField.value = c.y;
    widthField.value = 350;
    heightField.value = 230;
    $('#w').val(c.w);
    $('#h').val(c.h);
}

Снимок экрана для идеиСнимок экрана для идеи

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

Я был бы признателен, если бы кто-то мог помочь мне с этим кодом, укажем на полный рабочий пример.

С уважением

3 ответа

Решение

Если я правильно понимаю, ваша конечная цель - получить миниатюрное изображение размером 350x230 пикселей, но вы хотите, чтобы пользователь мог выбирать кадрирование на основе предварительного просмотра размером 400x264 пикселей. К сожалению, вы заставляете соотношение сторон при предварительном просмотре, поэтому вы получаете искажение. Если вместо этого вы обрабатываете размер 400x264px как минимум, вы можете создавать миниатюры на основе тех минут, которые не будут искажены.

public static void ResizeImageFreeSize(string OriginalFile, string NewFile, int MinWidth, int MinHeight, string FileExtension)
{
    var NewHeight = MinHeight;
    var NewWidth = MinWidth;        
    var OriginalImage = Image.FromFile(OriginalFile);

    if (OriginalImage.Width < MinWidth || OriginalImage.Height < MinHeight)
        throw new Exception(String.Format("Invalid Image Dimensions, please upload an image with minmum dimensions of {0}x{1}px", MinWidth.ToString(), MinHeight.ToString()));

    // If the image dimensions are the same then make the new dimensions the largest of the two mins.
    if (OriginalImage.Height == OriginalImage.Width)
        NewWidth = NewHeight = (MinWidth > MinHeight) ? MinWidth : MinHeight;
    else
    {
        if (MinWidth > MinHeight)
            NewHeight = (int)(OriginalImage.Height * ((float)MinWidth / (float)OriginalImage.Width));
        else
            NewWidth  = (int)(OriginalImage.Width * ((float)MinHeight / (float)OriginalImage.Height));
    }

    // Just resample the Original Image into a new Bitmap
    var ResizedBitmap = new System.Drawing.Bitmap(OriginalImage, NewWidth, NewHeight);

    // Saves the new bitmap in the same format as it's source image
    FileExtension = FileExtension.ToLower().Replace(".","");

    ImageFormat Format = null;
    switch (FileExtension)
    {
        case "jpg":
            Format = ImageFormat.Jpeg;
            break;
        case "gif":
            Format = ImageFormat.Gif;
            break;
        case "png":
            Format = ImageFormat.Png;
            break;
        default:
            Format = ImageFormat.Png;
            break;
    }

    ResizedBitmap.Save(NewFile, Format);


    // Clear handle to original file so that we can overwrite it if necessary
    OriginalImage.Dispose();
    ResizedBitmap.Dispose();
}

Вы можете сохранить соотношение сторон или жесткое ограничение размеров изображения, например, 400x264. Если вы хотите сохранить соотношение сторон, ваше уменьшенное изображение должно быть уменьшено с коэффициентом min(finalWidth/orignalWidth, finalHeight/orignalHeight)

Увидеть

@MyItchyChin Я использую его логику с некоторыми изменениями, поэтому я также отмечу его ответ как правильный **

Я отредактировал этот код, чтобы добавить две вещи, которые я получал из-за блокировки, поэтому я использовал MemoryStream, чтобы обойти проблему блокировки. Другая проблема с кодом заключалась в том, что он генерировал изображения низкого разрешения для JPG, для этого я добавил немного кода. Остальная логика та же самая, которую я не изменил

public static void ResizeImageFreeSize(string OriginalFile, string NewFile, int MinWidth, int MinHeight, string FileExtension)
{
    var NewHeight = MinHeight;
    var NewWidth = MinWidth;
    // var OriginalImage = System.Drawing.Image.FromFile(OriginalFile); // THis statlement alon with generate error as file is locked so -->//GDI+ keeps a lock on files from which an image was contructed.  To avoid the lock, construct the image from a MemorySteam:

    MemoryStream ms = new MemoryStream(File.ReadAllBytes(OriginalFile));
    var OriginalImage = System.Drawing.Image.FromStream(ms);

    if (OriginalImage.Width < MinWidth || OriginalImage.Height < MinHeight)
        throw new Exception(String.Format("Invalid Image Dimensions, please upload an image with minmum dimensions of {0}x{1}px", MinWidth.ToString(), MinHeight.ToString()));

    // If the image dimensions are the same then make the new dimensions the largest of the two mins.
    if (OriginalImage.Height == OriginalImage.Width)
        NewWidth = NewHeight = (MinWidth > MinHeight) ? MinWidth : MinHeight;
    else
    {
        if (MinWidth > MinHeight)
            NewHeight = (int)(OriginalImage.Height * ((float)MinWidth / (float)OriginalImage.Width));
        else
            NewWidth = (int)(OriginalImage.Width * ((float)MinHeight / (float)OriginalImage.Height));
    }

    // Just resample the Original Image into a new Bitmap
    var ResizedBitmap = new System.Drawing.Bitmap(OriginalImage, NewWidth, NewHeight);

    // Saves the new bitmap in the same format as it's source image
    FileExtension = FileExtension.ToLower().Replace(".", "");

    ImageFormat Format = null;
    switch (FileExtension)
    {
        case "jpg":
            Format = ImageFormat.Jpeg;

            Encoder quality = Encoder.Quality;
            var ratio = new EncoderParameter(quality, 100L);
            var codecParams = new EncoderParameters(1);
            codecParams.Param[0] = ratio;
            // NewImage.Save(NewFile, GetEncoder(ImageFormat.Jpeg), codecParams);
            ResizedBitmap.Save(NewFile, GetEncoder(ImageFormat.Jpeg), codecParams);
            break;
        case "gif":
            Format = ImageFormat.Gif;
            ResizedBitmap.Save(NewFile, Format);
            break;
        case "png":
            Format = ImageFormat.Png;
            ResizedBitmap.Save(NewFile, Format);
            break;
        default:
            Format = ImageFormat.Png;
            ResizedBitmap.Save(NewFile, Format);
            break;
    }

    //  ResizedBitmap.Save(NewFile, Format);


    // Clear handle to original file so that we can overwrite it if necessary
    OriginalImage.Dispose();
    ResizedBitmap.Dispose();
}

private static ImageCodecInfo GetEncoder(ImageFormat format)
{
    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
    foreach (ImageCodecInfo codec in codecs)
        if (codec.FormatID == format.Guid)
            return codec;
    return null;
}
Другие вопросы по тегам