By locknies


2016-11-17 07:21:18 8 Comments

I'am using jcrop plugin in our project and i came across an issue. The issue is that iam cropping the image from the preview image and when i try to crop that portion from original image from controller, then the image is not cropped from the exact position i selected.

When user click browse and select a photo i upload that image to server and open a view with link to that image from server. Using the plugin it is cropping correctly and previewing it in the view.

Suppose if the image is 1000px width and 500px height and i load it into an img src with width 700px and height 350px (in jcrop there is an option to give fixed width/height called boxwidth and boxheight). however even if we give some exact size then also the plugin varies the width and height by pixels +- 50px etc...

i get the crop area width, crop area height, crop x co-ordinate, crop y co-ordinate in the POST method.

Iam cropping the image in the POST method. In there i divide the original image width by preview image width and the original image height by preview image height to get the image scale difference then i multiply it with the x/y co-ordinate value and width/height crop area to crop it correctly from the original image.

Iam cropping the image from byte[] (code from internet). I think my problem lies in this line to extract the crop area using 'new rectangle(int x, int y, int width, int height)'.

Since i couldn't use the float values in rectangle iam using int values and i think that why the variation occurs. Is there a way to use flat values in 'new Rectangle(' as parameter.

Iam trying my best to explain my situation, please let me know if you need any more explanations. thanks you.

Please see the below image also for understanding my situtaion better,

enter image description here

Here is the coding part that i have done so far,

View Page

@using (Html.BeginForm("PhotoChange", "Profile", FormMethod.Post, new { enctype = "multipart/form-data", id = "changeProfilePhotoForm" }))
{
    @Html.HiddenFor(x => x.IsCropped, new { id = "IsCropped", Value = @Model.IsCropped })
    @Html.HiddenFor(x => x.PersonID)
    @Html.HiddenFor(x => x.PersonDetailID)
    @Html.HiddenFor(x => x.Photo)
    @Html.HiddenFor(x => x.ImageURL, new { id = "ImageURL", Value = @Model.ImageURL })
    @Html.HiddenFor(x => x.CropPointX, new { id = "CropPointX" })
    @Html.HiddenFor(x => x.CropPointY, new { id = "CropPointY" })
    @Html.HiddenFor(x => x.CropPortionWidth, new { id = "CropPortionWidth" })
    @Html.HiddenFor(x => x.CropPortionHeight, new { id = "CropPortionHeight" })
    @Html.HiddenFor(x => x.PreviewImageWidth, new { id = "PreviewImageWidth" })
    @Html.HiddenFor(x => x.PreviewImageHeight, new { id = "PreviewImageHeight" })

    <div class="form-horizontal image-preview-page">

        <div class="row">
            <div class="form-group">
                <div class="col-sm-12">
                    <div id="profile-image-preview-pane">
                        <div class="profile-image-preview-container">
                            <img src="@Model.ImageURL" class="profile-image-preview-image" alt="Preview" />
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div class="row">
            <div class="form-group">
                <div class="col-sm-12">
                    <div class="profile-image-source-wrap">
                        <img id="profile-image-source" accept="image" name="photo" id="Photo" src="@Model.ImageURL" />
                    </div>
                </div>
            </div>
        </div>

        <div class="row">
            <div class="form-group">
                <div class="col-sm-12 text-center">
                    <input type="button" value="Upload" onclick="cropImage()" />
                </div>
            </div>
        </div>

    </div>
}


    <script type="text/javascript">

        var imageCropWidth,
            imageCropHeight,
            cropPointX,
            cropPointY,
            jcrop_api,
            boundx,
            boundy

        parent.$('.modal-content').css('height', '510px');
        parent.$('.bootstrap-modal-body').css('height', '500px');

        parent.$('.modal-content').css('width', '680px');
        parent.$('.bootstrap-modal-body').css('width', '690px');

        // Grab some information about the preview pane
        $preview = $('#profile-image-preview-pane'),
        $pcnt = $('#profile-image-preview-pane .profile-image-preview-container'),
        $pimg = $('#profile-image-preview-pane .profile-image-preview-container img'),

        xsize = $pcnt.width(),
        ysize = $pcnt.height();

        $('#profile-image-source').Jcrop({
            boxWidth: 450, //Maximum width you want for your bigger images
            boxHeight: 400, //Maximum Height for your bigger images
            minSize: [25, 25],
            onChange: updatePreview,
            onSelect: updatePreview,
            aspectRatio: 1,
            bgFade: true, // use fade effect
            bgOpacity: .6, // fade opacity
        }, function () {

            // Use the API to get the real image size
            var bounds = this.getBounds();
            boundx = bounds[0];
            boundy = bounds[1];

            // Store the API in the jcrop_api variable
            jcrop_api = this;

            // Move the preview into the jcrop container for css positioning
            $preview.appendTo(jcrop_api.ui.holder);
        });

        function updatePreview(c) {

            if (parseInt(c.w) > 0) {
                var rx = xsize / c.w;
                var ry = ysize / c.h;

                $pimg.css({
                    width: Math.round(rx * boundx) + 'px',
                    height: Math.round(ry * boundy) + 'px',
                    marginLeft: '-' + Math.round(rx * c.x) + 'px',
                    marginTop: '-' + Math.round(ry * c.y) + 'px'
                });


                cropPointX = Math.round(c.x);
                cropPointY = Math.round(c.y);

                imageCropWidth = Math.round(c.w);
                imageCropHeight = Math.round(c.h);

                $('#CropPointX').val(cropPointX);
                $('#CropPointY').val(cropPointY);
                $('#CropPortionWidth').val(imageCropWidth);
                $('#CropPortionHeight').val(imageCropHeight);

                $('#PreviewImageWidth').val($('.jcrop-holder img').width());
                $('#PreviewImageHeight').val($('.jcrop-holder img').height());
            }
        };

        function cropImage() {

            if (imageCropWidth == 0 && imageCropHeight == 0) {
                alert("Please select crop area.");
                return;
            }

            $('#IsCropped').val(true);

            $.ajax({
                url: "@Url.Action("PhotoChange", "Profile")",
                type: 'POST',
                data: $("#changeProfilePhotoForm").serialize(),
                async: false,
                success: function (data) {
                    parent.ChangeImageAfterSave('@ViewData["CroppedImage"]')
                },
                error: function (data) { }
            });


            }
    </script>

Controller Page

[HttpPost]
        public ActionResult PhotoChange(ProfilePicVM profilePic, HttpPostedFileBase photo)
        {
            bool isUpdated = false;
            string fileName = string.Empty;
            byte[] imageBytes = null;
            byte[] croppedImage = null;
            int scaleValueX = 0;
            int scaleValueY = 0;

            try
            {
                    imageBytes = System.IO.File.ReadAllBytes(Server.MapPath(profilePic.ImageURL));
                    System.Drawing.Image image = System.Drawing.Image.FromStream(new System.IO.MemoryStream(imageBytes));

                    if (image.Width >= profilePic.PreviewImageWidth || image.Height >= profilePic.PreviewImageHeight)
                    {
                        scaleValueX = image.Width / profilePic.PreviewImageWidth;
                        scaleValueY = image.Height / profilePic.PreviewImageHeight;
                    }

                    croppedImage = ProfileController.CropImage(imageBytes, scaleValueX * profilePic.CropPointX, scaleValueY * profilePic.CropPointY, scaleValueX * profilePic.CropPortionWidth, scaleValueY * profilePic.CropPortionHeight);

                    string tempFolderName = Server.MapPath("~/uploads/PersonProfile/");

                    string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(profilePic.ImageURL);
                    fileName = Path.GetFileName(profilePic.ImageURL).Replace(fileNameWithoutExtension, fileNameWithoutExtension + "_cropped");

                    profilePic.ImageCroppedURL = string.Concat(tempFolderName, fileName);
                    FileHelper.SaveFile(croppedImage, Path.Combine(tempFolderName, fileName));

                    isUpdated = (new PersonDetailService(this.GdbObject)).UpdateProfilePhoto(profilePic.PersonDetailID, fileName);
                    if (isUpdated)
                    {
                        this.ViewData["CroppedImage"] = fileName;
                    }
            }
            catch (Exception ex)
            {                
            }

            return this.View(profilePic);
        }



        public static byte[] CropImage(byte[] content, int x, int y, int width, int height)
        {
            using (MemoryStream stream = new MemoryStream(content))
            {
                return CropImage(stream, x, y, width, height);
            }
        }


        public static byte[] CropImage(Stream content, int x, int y, int width, int height)
        {
            //// Parsing stream to bitmap
            using (Bitmap sourceBitmap = new Bitmap(content))
            {
                //// Get new dimensions
                double sourceWidth = Convert.ToDouble(sourceBitmap.Size.Width);
                double sourceHeight = Convert.ToDouble(sourceBitmap.Size.Height);
                Rectangle cropRect = new Rectangle (x, y, width, height);

                //// Creating new bitmap with valid dimensions
                using (Bitmap newBitMap = new Bitmap(cropRect.Width, cropRect.Height))
                {
                    using (Graphics g = Graphics.FromImage(newBitMap))
                    {
                        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        g.SmoothingMode = SmoothingMode.HighQuality;
                        g.PixelOffsetMode = PixelOffsetMode.HighQuality;
                        g.CompositingQuality = CompositingQuality.HighQuality;

                        g.DrawImage(sourceBitmap, new Rectangle(0, 0, newBitMap.Width, newBitMap.Height), cropRect, GraphicsUnit.Pixel);

                        return GetBitmapBytes(newBitMap);
                    }
                }
            }
        }



        public static byte[] GetBitmapBytes(Bitmap source)
        {
            ////Settings to increase quality of the image
            ImageCodecInfo codec = ImageCodecInfo.GetImageEncoders()[4];
            EncoderParameters parameters = new EncoderParameters(1);
            parameters.Param[0] = new EncoderParameter(Encoder.Quality, 100L);

            ////Temporary stream to save the bitmap
            using (MemoryStream tmpStream = new MemoryStream())
            {
                source.Save(tmpStream, codec, parameters);

                ////Get image bytes from temporary stream
                byte[] result = new byte[tmpStream.Length];
                tmpStream.Seek(0, SeekOrigin.Begin);
                tmpStream.Read(result, 0, (int)tmpStream.Length);

                return result;
            }
        }

1 comments

@Yanga 2016-11-17 07:32:34

An other solution which i use to crop image with jcrop :

    public void photocrop(int x, int y, int w, int h)
    {

            string filePath = Path.Combine(Server.MapPath("/images/users/temp"), "MyImage.jpg");
            System.Drawing.Image orgImg = System.Drawing.Image.FromFile(filePath);
            Rectangle CropArea = new Rectangle(
                Convert.ToInt32(x),
                Convert.ToInt32(y),
                Convert.ToInt32(w),
                Convert.ToInt32(h));
            Bitmap bitMap = new Bitmap(CropArea.Width, CropArea.Height);
            using (Graphics g = Graphics.FromImage(bitMap))
            {
                g.DrawImage(orgImg, new Rectangle(0, 0, bitMap.Width, bitMap.Height), CropArea, GraphicsUnit.Pixel);
            }
            cropFilePath = Path.Combine(Server.MapPath("~/images/users"), fileNameOk);
            bitMap.Save(cropFilePath);

   }

@locknies 2016-11-17 07:44:13

I will check out this code. Meanwhile i have edited the image and added an image for better understanding the situation.

@Vixed 2016-11-17 10:07:52

@Yanga can you please check it? stackoverflow.com/questions/40636439

Related Questions

Sponsored Content

1 Answered Questions

[SOLVED] Reading Datastream sharpDX Error all values are 0

  • 2017-07-04 14:43:58
  • user7970127
  • 308 View
  • 1 Score
  • 1 Answer
  • Tags:   c# sharpdx

1 Answered Questions

[SOLVED] Cropping an image with a preview using jcrop

1 Answered Questions

[SOLVED] Crop and save images as circle JCrop

  • 2015-06-04 05:48:15
  • Sonia
  • 532 View
  • 0 Score
  • 1 Answer
  • Tags:   c# jquery jcrop

1 Answered Questions

[SOLVED] JCrop in Firefox attaches original image height/width

  • 2013-08-29 01:36:32
  • Anshuman Biswas
  • 696 View
  • 5 Score
  • 1 Answer
  • Tags:   jquery css jcrop

2 Answered Questions

[SOLVED] Extjs Jcrop - Crop image with preview

2 Answered Questions

[SOLVED] Using Jcrop ,could not refresh preview pane correctly when changing image

  • 2012-12-22 16:51:29
  • Ryan Hu
  • 3251 View
  • 0 Score
  • 2 Answer
  • Tags:   jcrop

1 Answered Questions

[SOLVED] Jcrop with resizing preview

Sponsored Content