This is a migrated thread and some comments may be shown as answers.

Profile Pic: Make Cropping VERY Simple

15 Answers 566 Views
ImageEditor
This is a migrated thread and some comments may be shown as answers.
James
Top achievements
Rank 1
James asked on 06 Mar 2012, 04:54 PM
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

15 Answers, 1 is accepted

Sort by
0
Pero
Telerik team
answered on 09 Mar 2012, 06:29 PM
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.
0
James
Top achievements
Rank 1
answered on 09 Mar 2012, 06:54 PM
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
0
Pero
Telerik team
answered on 12 Mar 2012, 10:20 AM
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.
0
James
Top achievements
Rank 1
answered on 12 Mar 2012, 01:02 PM
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
0
Pero
Telerik team
answered on 13 Mar 2012, 12:53 PM
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.
0
Rob
Top achievements
Rank 1
answered on 18 Oct 2012, 05:17 AM
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?
0
Sauge
Top achievements
Rank 1
answered on 12 Feb 2013, 11:40 AM
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 :-)
0
Vessy
Telerik team
answered on 14 Feb 2013, 02:57 PM
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.
0
Sauge
Top achievements
Rank 1
answered on 14 Feb 2013, 09:40 PM
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 :-)
0
Vessy
Telerik team
answered on 19 Feb 2013, 01:46 PM
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.
0
Sauge
Top achievements
Rank 1
answered on 24 Feb 2013, 08:45 PM
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 :-)
0
Sauge
Top achievements
Rank 1
answered on 25 Feb 2013, 09:24 PM
Not to worry, I figured out another plan

Thank you for all your help :-)
0
sairam
Top achievements
Rank 1
answered on 10 Sep 2013, 07:12 AM
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.
0
Ali
Top achievements
Rank 1
answered on 04 Mar 2016, 10:06 AM

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

its worked like a charm

0
Vessy
Telerik team
answered on 08 Mar 2016, 12:23 PM
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
Tags
ImageEditor
Asked by
James
Top achievements
Rank 1
Answers by
Pero
Telerik team
James
Top achievements
Rank 1
Rob
Top achievements
Rank 1
Sauge
Top achievements
Rank 1
Vessy
Telerik team
sairam
Top achievements
Rank 1
Ali
Top achievements
Rank 1
Share this question
or