Profile Pic: Make Cropping VERY Simple

16 posts, 0 answers
  1. James
    James avatar
    55 posts
    Member since:
    Oct 2011

    Posted 06 Mar 2012 Link to this post

    Hi,

    I'm not sure if the RadImageEditor is the right tool for my requirements, but I thought I would ask our community for their opinion.  Also, I'm sure many of us have needed to deal with Profile pictures, and I would love to avoid reinventing the wheel.

    High level, I need to allow my users to (1) select a picture as a profile picture, (2) crop it, (3) lock the aspect ratio, and (4) return it to the DB.  It is critical that this is as simple as Facebook, for example.

    More specifically, here are my requirements:

    1. User navigates to a page with an "upload button," maybe using RadUpload.
    2. After selecting the file, it must upload to the page, hopefully to the editor. 
    3. (I would like to avoid the users needing to click the select button, then to click another button to upload, as with the default configuration of the RadUpload module.  As soon as they select, it needs to be displayed.)
    4. When displayed in the editor, it needs to immediately go into "crop" mode.
    5. I do not want the "crop" dialoge displayed, with will protect form them changes the aspect ratio.
    6. I do not mind them changing the "size" of the crop area, as long as the aspect ratio does not change.
    7. I do want them to be able to move the crop area around the picture.
    8. After they are satisfied, I want them to hit a button, which returns the picture to the database, and then displays it.  Maybe in a RadBinary image.  (Thus, I don't want it to appear "stuck" in the RadEditor.

    Any suggestions to handle these requirements would be really appreciated.  

    Thanks,

    Jim
  2. Pero
    Admin
    Pero avatar
    1156 posts

    Posted 09 Mar 2012 Link to this post

    Hi Jim,

         For your convenience I have implemented a sample web-application that I think will satisfy your requirements. It is based on the following AsyncUpload example: http://demos.telerik.com/aspnet-ajax/upload/examples/async/ajaxprocessing/defaultcs.aspx?product=asyncupload.

         I have added RadImageEditor that will handle image editing. Once the user selects an image to upload, the image is uploaded and stored into the Server.Cache, and loaded into the ImageEditor for editing. What the user sees after upload is the image into the ImageEditor, and the crop dialog opened. The dialog is opened with JavaScript, immediately after the editor is loaded in the client load event.
    The image editor dialogs can be loaded from external location, which allows easy customization. That's what I did, I moved the Crop tool dialog to external location, and modified it to lock the aspect ratio for end users.This is what's modified:
    • The Aspect Ratio ComboBox is hidden
    • The "Constrain Proportions" and "Switch Dimensions" buttons are disabled
    • In the initialize method of the Crop JavaScript class (the JS is in the same Crop.ascx file, just below the HTML), I am setting the ratio to the desired value.

    After the user is satisfied with the modifications, he can save the image, and he will be taken to his profile pic.

       Please note that this example is for demonstration purposes, and might have bugs. It works OK, but has not been tested extensively. :)
    I hope it gives you idea on how to start your implementation!

    Greetings,
    Pero
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. James
    James avatar
    55 posts
    Member since:
    Oct 2011

    Posted 09 Mar 2012 Link to this post

    This is a really gorgeous demo.  Thank you.

    Everything is perfect in this demo for my requirements, except that i need the user to be able to crop the picture.  For example, they may want to focus on their face.  Here is an example that demonstrates this functionality exactly as desired:

    http://samples.cemsisman.com/webcropimage/Ratiosample.aspx

    However, the problem with this example is that it is not a Telerik control.  I prefer to use your controls when I can because I find them to be reliable, robust, and consistent within my applications.  That is why I thought I might be able to use the rad editor for the cropping.

    Any ideas on how to take your demo to the next step.

    Jim
  5. Pero
    Admin
    Pero avatar
    1156 posts

    Posted 12 Mar 2012 Link to this post

    Hello Jim,

    I just wanted to make sure, you need to use RadEditor or RadImageEditor for the cropping? In the demo I am using the ImageEditor, and the cropping functionality is opened immediately after uploading the image. Here is a screen capture of the process: http://screencast.com/t/XouJnap2ce.

    All the best,
    Pero
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
  6. James
    James avatar
    55 posts
    Member since:
    Oct 2011

    Posted 12 Mar 2012 Link to this post

    I just configured your sample slightly incorrectly.  All working good now.

    In the editor, is there a way to:  Lock the aspect ratio on the cropping, so the user cannot modify?

    Really awesome example/work!  Thank you so much!

    Jim
  7. Pero
    Admin
    Pero avatar
    1156 posts

    Posted 13 Mar 2012 Link to this post

    Hello Jim,

    I am glad the sample helped!

    In the project there is folder named "ImageEditorDialogs". In this folder you will find the markup for the Crop dialog (Crop.ascx). You can modify the markup, so the aspect ratio stays locked. What I have done in the sample is I have disabled the buttons for locking/unlocking the ratio, so the user cannot modify it. Also I have hidden the drop-down list so the user is not allowed to choose a new ratio.

    To set a custom aspect ratio, in the initialize JavaScript method you should change the following code (again in the same Crop.ascx file):
    initialize: function ()
    {
        .....................
        .....................
        this.get_imageEditor().get_formDecorator().decorate($get(this.get_parentId() + "Table"));
     
     
        //This code sets the initial dimensions of the CropBox and the aspect ratio
        this._widthTxt.value = 75;
        this._heightTxt.value = 50;
        var ratio = 75 / 50;
        this._setCropBoxRatio(ratio);
        this._sizeRatio = ratio;
        this._updateCropBoxFromControls();
    },

    For demonstration purposes I have also hidden the two buttons and changed the ratio to 1/1. Find the new Crop.ascx attached to the thread.

    Note that you have to use the latest version of the ImageEditor control, to be able to load external dialogs.

    Regards,
    Pero
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
  8. Rob
    Rob avatar
    2 posts
    Member since:
    Sep 2012

    Posted 18 Oct 2012 Link to this post

    Very cool, I need one modification.

    I've downloaded the code and it does exactly what I need, except that I want it to save to the files system instead of the database. Any chance it could be easily modified to do so?
  9. Sauge
    Sauge avatar
    24 posts
    Member since:
    Feb 2013

    Posted 12 Feb 2013 Link to this post

    Hi there
    I tried implementing the attached "profilepic.zip" example (it was just what I had been looking for), and got it working perfectly in a "stand alone" page (without master page).  Trouble is, it doesn't work if the page has a master page. 

    Within a master page, the panel with the ImageEditor doesn't appear once the image has uploaded to the temporary folder.  I also have a problem if I try to set the initial ImageURL of the Thumbnail (binaryimage) by checking if file exists and get a "Object reference not set to an object" error. 

    I don't have any of these problems in a stand alone page and all works perfectly.  Please could you tell me what I am doing wrong and how to fix it

    My code
    <asp:Content ID="Content2" ContentPlaceHolderID="cphContent" runat="Server">
    <telerik:RadScriptManager ID="RadScriptManager1" runat="server">
            <Scripts>
                <asp:ScriptReference Assembly="Telerik.Web.UI"
                    Name="Telerik.Web.UI.Common.Core.js"></asp:ScriptReference>
                <asp:ScriptReference Assembly="Telerik.Web.UI"
                    Name="Telerik.Web.UI.Common.jQuery.js"></asp:ScriptReference>
                <asp:ScriptReference Assembly="Telerik.Web.UI"
                    Name="Telerik.Web.UI.Common.jQueryInclude.js"></asp:ScriptReference>
            </Scripts>
        </telerik:RadScriptManager>
        <telerik:RadFormDecorator ID="RadFormDecoratorMenu" runat="server" Skin="Windows7" />
        <telerik:RadToolTipManager runat="server" ID="ToolTipManager" AutoTooltipify="true"
            Position="TopRight" Skin="Web20">
        </telerik:RadToolTipManager>
        <telerik:RadStyleSheetManager ID="RadStyleSheetManager1" runat="server">
        </telerik:RadStyleSheetManager>
     
        <script type="text/javascript">
            function fileUploaded(sender, args) {
     
                $find("RadAjaxPanel1").ajaxRequest();
     
                $telerik.$(".invalid").html("");
                setTimeout(function () {
                    sender.deleteFileInputAt(0);
                }, 10);
            }
     
            function validationFailed(sender, args) {
                $telerik.$(".invalid")
                    .html("Invalid extension, please choose an image file");
                sender.deleteFileInputAt(0);
            }
     
            function ImageEditorLoad(imgEditor, args) {
                //open the Crop tool dialog with a little timeout
                setTimeout(function () {
                    imgEditor.fire("Crop");
                }, 0);
            }
        </script>
               
        <telerik:RadAjaxPanel ID="RadAjaxPanel1" runat="server">
            <div class="upload-panel">
                <asp:Panel ID="ShowImagePanel" runat="server" Visible="true">
                    <telerik:RadBinaryImage runat="server" Width="150px" Height="200px" ResizeMode="Fit" ID="Thumbnail" ImageUrl=""
                        AlternateText="Thumbnail" CssClass="binary-image" CropPosition="Center" />
                    <span class="invalid"></span>
                </asp:Panel>
                <asp:Panel ID="EditImagePanel" runat="server" Visible="false">
                    <telerik:RadImageEditor ID="RadImageEditor1" runat="server" OnImageLoading="RadImageEditor1_ImageLoading"
                        OnImageSaving="RadImageEditor1_ImageSaving" ExternalDialogsPath="~/ImageEditorDialogs/" Width="720px"
                        Height="430px" OnClientLoad="ImageEditorLoad" CanvasMode="No">
                        <Tools>
                            <telerik:ImageEditorToolGroup>
                                <telerik:ImageEditorTool CommandName="Undo" />
                                <telerik:ImageEditorTool CommandName="Redo" />
                                <telerik:ImageEditorToolSeparator />
                                <telerik:ImageEditorTool CommandName="Crop" IsToggleButton="true" />
                                <telerik:ImageEditorTool CommandName="Zoom" IsToggleButton="true" />
                                <telerik:ImageEditorTool Text="ZoomIn" CommandName="ZoomIn" />
                                <telerik:ImageEditorTool Text="ZoomOut" CommandName="ZoomOut" />
                                <telerik:ImageEditorTool Text="Rotate" CommandName="Rotate" IsToggleButton="true" />
                                <telerik:ImageEditorTool Text="RotateRight" CommandName="RotateRight" />
                                <telerik:ImageEditorTool Text="Rotate Left" CommandName="RotateLeft" />
                                <telerik:ImageEditorTool Text="Flip" CommandName="Flip" IsToggleButton="true" />
                                <telerik:ImageEditorTool Text="FlipVertical" CommandName="FlipVertical" />
                                <telerik:ImageEditorTool Text="FlipHorizontal" CommandName="FlipHorizontal" />
                            </telerik:ImageEditorToolGroup>
                        </Tools>
                    </telerik:RadImageEditor>
                    <br />
                    <telerik:RadButton ID="RadButton1" runat="server" Text="Save Changes" OnClick="RadButton1_Click">
                        <Icon PrimaryIconCssClass="rbSave" />
                    </telerik:RadButton>
                    <telerik:RadButton ID="RadButton2" runat="server" Text="Cancel" OnClick="RadButton2_Click">
                        <Icon PrimaryIconCssClass="rbSave" />
                    </telerik:RadButton>
                    <br />
                    <br />
                </asp:Panel>
                <telerik:RadAsyncUpload runat="server" ID="AsyncUpload1" MaxFileInputsCount="1" OnClientFileUploaded="fileUploaded"
                    OnFileUploaded="AsyncUpload1_FileUploaded" AllowedFileExtensions="jpeg,jpg,gif,png,bmp" OnClientValidationFailed="validationFailed">
                    <Localization Select="Choose Profile Image" />
                </telerik:RadAsyncUpload>
            </div>
        </telerik:RadAjaxPanel>
    </asp:Content>
    And my code behind:

    Protected Sub Page_Load(sender As Object, e As EventArgs)
            TogglePanels()
            Dim UserId As String
            Dim strSavePath As String
            UserId = Membership.GetUser().ProviderUserKey.ToString()
            Dim myFilePath As String = Server.MapPath("~/images/users/" + UserId + "/" + "profile.jpg")
            Dim Thumbnail As RadBinaryImage = DirectCast(FindControl("Thumbnail"), RadBinaryImage)
            strSavePath = Server.MapPath("~/images/users/" + UserId)
     
     
     
            If (Not Directory.Exists(strSavePath)) Then
                Directory.CreateDirectory(strSavePath)
            End If
     
            If File.Exists(myFilePath) Then
                Thumbnail.ImageUrl = "~/images/users/" + UserId + "/" + "profile.jpg"
            Else
                Thumbnail.ImageUrl = "~/images/users/blank.jpg"
            End If
        End Sub
     
        Protected Sub RadImageEditor1_ImageSaving(sender As Object, args As ImageEditorSavingEventArgs)
            Dim UserId As String
            UserId = Membership.GetUser().ProviderUserKey.ToString()
     
            args.Image.Image.Save(MapPath("~/images/users/" + UserId + "/" + "profile.jpg"))
            args.Cancel = True
     
            Using ms As New MemoryStream()
                args.Image.Image.Save(ms, args.Image.RawFormat)
                Context.Cache.Insert(Session.SessionID + "UploadedFile", ms, Nothing, DateTime.Now.AddMinutes(20), TimeSpan.Zero)
            End Using
     
            Dim imageData = DirectCast(Context.Cache.[Get](Session.SessionID + "UploadedFile"), MemoryStream)
            If imageData IsNot Nothing Then
                Thumbnail.DataValue = imageData.ToArray()
            End If
     
            args.Cancel = True
        End Sub
     
        Protected Sub RadButton1_Click(sender As Object, e As EventArgs)
            TogglePanels(True)
            RadImageEditor1.SaveEditableImage("profile.jpg", True)
        End Sub
     
        Private Sub TogglePanels(Optional hideEditImagePanel As Boolean = False)
            If hideEditImagePanel Then
                EditImagePanel.Visible = False
                ShowImagePanel.Visible = True
                Return
            End If
     
            Dim imageData = Context.Cache.[Get](Session.SessionID + "UploadedFile")
            If imageData IsNot Nothing Then
                EditImagePanel.Visible = True
                ShowImagePanel.Visible = False
            Else
                EditImagePanel.Visible = False
                ShowImagePanel.Visible = True
            End If
        End Sub
     
        Protected Sub AsyncUpload1_FileUploaded(sender As Object, e As FileUploadedEventArgs)
            'Clear changes and remove uploaded image from Cache
            RadImageEditor1.ResetChanges()
            Context.Cache.Remove(Session.SessionID + "UploadedFile")
            Using stream As Stream = e.File.InputStream
                Dim imgData As Byte() = New Byte(stream.Length - 1) {}
                stream.Read(imgData, 0, imgData.Length)
                Dim ms As New MemoryStream()
                ms.Write(imgData, 0, imgData.Length)
     
                Context.Cache.Insert(Session.SessionID + "UploadedFile", ms, Nothing, DateTime.Now.AddMinutes(20), TimeSpan.Zero)
            End Using
            TogglePanels()
        End Sub
     
        Protected Sub RadImageEditor1_ImageLoading(sender As Object, args As ImageEditorLoadingEventArgs)
            'Handle Uploaded images
            If Not [Object].Equals(Context.Cache.[Get](Session.SessionID + "UploadedFile"), Nothing) Then
                Using image As New EditableImage(DirectCast(Context.Cache.[Get](Session.SessionID + "UploadedFile"), MemoryStream))
                    args.Image = image.Clone()
                    args.Cancel = True
                End Using
            End If
        End Sub
     
        Protected Sub RadButton2_Click(sender As Object, e As EventArgs) Handles RadButton2.Click
            TogglePanels(True)
        End Sub
    End Class


    The object reference not set to an object error is caused by this bit of code

    If File.Exists(myFilePath) Then
                Thumbnail.ImageUrl = "~/images/users/" + UserId + "/" + "profile.jpg"
            Else
                Thumbnail.ImageUrl = "~/images/users/blank.jpg"
            End If

    I must point out, that if I comment out the above snippet of code then I don't get an error, but no imageeditor appears when I click the "choose avatar/ choose profile image button"  I just see the file upload indicator and a cancel button

    Please help

    Thank you in advance :-)
  10. Vessy
    Admin
    Vessy avatar
    1380 posts

    Posted 14 Feb 2013 Link to this post

    Hi James,

    In general, when you are using a control in the content of a master page, the master page changes the control's client ID. This is why you have to modify the references in the above provided code to use the ClientID of the controls::
    <telerik:RadCodeBlock runat="server">
        <script type="text/javascript">
            function fileUploaded(sender, args) {
     
                $find("<%=RadAjaxPanel1.ClientID %>").ajaxRequest();
     
                $telerik.$(".invalid").html("");
                setTimeout(function () {
                    sender.deleteFileInputAt(0);
                }, 10);
            }
     
            function validationFailed(sender, args) {
                $telerik.$(".invalid")
                .html("Invalid extension, please choose an image file");
                sender.deleteFileInputAt(0);
            }
     
            function ImageEditorLoad(imgEditor, args) {
                //open the Crop tool dialog with a little timeout
                setTimeout(function () {
                    imgEditor.fire("Crop");
                }, 0);
            }
        </script>
    </telerik:RadCodeBlock>

    Regards,
    Vesi
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
  11. Sauge
    Sauge avatar
    24 posts
    Member since:
    Feb 2013

    Posted 14 Feb 2013 Link to this post

    Thank you for your help Vesi

    But unfortunately that didn't work at all :-(  and I am having the exact same problems.
    Could you please take another look at perhaps come up with another solution and perhaps work out why I am getting the error
    object reference not set to an object
    When I use this code block
    If File.Exists(myFilePath) Then
                Thumbnail.ImageUrl = "~/images/users/" + UserId + "/" + "profile.jpg"
            Else
                Thumbnail.ImageUrl = "~/images/users/blank.jpg"
            End If

    Cause I also only get this error when using a master page

    Thanks in advance :-)
  12. Vessy
    Admin
    Vessy avatar
    1380 posts

    Posted 19 Feb 2013 Link to this post

    Hi Sauge,

    I am afraid that the provided information is not enough to find the reason of the problem. Could you please provide either working sample code or a live url where we can examine the problem? Once we receive that and we have a better understanding on what is actually happening we will do our best to help.

    For the time being, could you ensure that the blank.jpg image actually exist in this location:
    Thumbnail.ImageUrl = "~/images/users/blank.jpg"

    Kind regards,
    Vesi
    the Telerik team
    If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.
  13. Sauge
    Sauge avatar
    24 posts
    Member since:
    Feb 2013

    Posted 24 Feb 2013 Link to this post

    Hi Vesi

    I checked that the image was there (which it was), but I have since decided to change how the image editor is implemented.  I now want to be able to open the image editor (with the new uploaded image in it) in a window (radwindow if possible).  To clarify:

    • User clicks "upload new image" button on page A
    • Once the image has uploaded to temp directory, the image would be automatically loaded into the image editor which will be in window or popup (instead of a panel) - page/window B
    • User would then edit the image, and on save, the window will close and the image preview on page A would somehow be refreshed to reflect the new image  (something like the way that the grid is refreshed on this demo: http://demos.telerik.com/aspnet-ajax/controls/examples/integration/gridandwindow/defaultvb.aspx?product=window )

    Have you any idea how to implement this?

    I have been trying out various demos and code all day to no avail.  (I am a bit of a newbie girl I'm afraid)

    I would be extremely grateful for any help at all with this

    Thank you :-)
  14. Sauge
    Sauge avatar
    24 posts
    Member since:
    Feb 2013

    Posted 25 Feb 2013 Link to this post

    Not to worry, I figured out another plan

    Thank you for all your help :-)
  15. sairam
    sairam avatar
    2 posts
    Member since:
    May 2011

    Posted 10 Sep 2013 Link to this post

    hi,

        your example is working fine without master page,
    if we use master page then gets the javascript error like
    JavaScript runtime error: Sys.ArgumentOutOfRangeException: Value must be an integer.

    Parameter name: x

    Actual value was 14.000030517578125.


    please help me to resolve this.

    Thank you in advance.
  16. Ali
    Ali avatar
    2 posts
    Member since:
    Mar 2016

    Posted 04 Mar in reply to Pero Link to this post

    Thank you i was searching for crop.ascx file for two days !!! and i found it here

    its worked like a charm

  17. Vessy
    Admin
    Vessy avatar
    1380 posts

    Posted 08 Mar Link to this post

    Hi guys,

    @sairam:
    Can you attach a sample project in which the problem can be reproduced? Please, make sure that you are using server tags for the references of all controls on the page, as the Master page is a namng container which is changing the Client IDs of the controls.

    @Ali:
    All dialogs of RadImageEditor are available in the installation of the controls under the folder named ImageEditorDialogs. I would advise that you take the Crop.ascx dialog from the mentioned folder from your Telerik installation so the version of the dialog will match the version of the controls.

    Regards,
    Vessy
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Back to Top
UI for ASP.NET Ajax is Ready for VS 2017