سؤال

I am designing a website and need to re size large image into a dimension of 400Wx264H without loosing aspect ration.

I have worked on different version of code but all come back with the one or the other problem.

Right now i am resizing large images into with of 400W while maintaining the aspect ratio and then i allow user to select part of image using jCrop are selectable area is 350Wx230H.

Problem with this is sometime it adds black portion to the image if the image re sized height or width was smaller than 400W or 264H pixels.

I would appreciate if some can point me to the some thing similar that i have to do.

CODE FOR Upload and re-sizing image is BELOW

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

ABOVE code upload the large image and re size it to fixed size of 400x264 pixels. but this approach stretches the image as i have comments the code which maintains the aspect ration.

After the Re-sized image is Uploaded i allow user to select the area from this image using jCrop are selectable is 350x230 pixels.

This works without any problem but images are stretched

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

    }
}

PART OF HTML CODE

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

Screen Shot for idea Screen Shot for idea

I would love to get it right where i can give user a functionality to select and area of an image and create a resized image from that. right now code is not giving a perfect result.

I would appreciate if someone can help me with this code of point me to a complete working example.

Regards

هل كانت مفيدة؟

المحلول

If I understand correctly, your ultimate goal is to end up with a 350x230px thumbnail image but you want the user to be able to choose the crop based on a 400x264px preview. Unfortunately you're forcing an aspect ratio on your preview which is why you're getting the distortion. If you instead treat the 400x264px dimension as minimums then you can generate thumbnails based on those mins that will not be distorted.

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

نصائح أخرى

You can either maintain aspect ratio or hard limit on dimensions of image i.e. 400x264 If you want to maintain aspect ratio your resized image should be reduced by factor of min(finalWidth/orignalWidth, finalHeight/orignalHeight)

See

@MyItchyChin I am using his logic with some changes so i will mark his answer as correct also**

I edited this code to add two thing one i was getting error due to the locking so i used MemoryStream to get around the locking issue. Another issue with code was that it was generating low res images for JPG's for that i added bit of code. Rest of the logic is same which i have not change

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;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top