locked
Canvas content into image element RRS feed

  • Question

  • User1510859543 posted

    I have the code below working fine for using input file to save as an image file on a server folder. However, now I also want to put the resized image picture into an existing image element to show the user. Note that I plan to reuse the canvas element for multiple file upload controls (4-5 more) so it must be a snapshot of the image. So the element id of "thecanvas" will be reused for the 2nd, etc. photo uploads.

    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Upload Photos Test</title>
        <script src="Scripts/jquery-3.1.1.min.js"></script>
        <script type="text/javascript">
        window.uploadPhotos = function(url){
            // Read in file
            var file = event.target.files[0];
    
            // Ensure it's an image
            if(file.type.match(/image.*/)) {
                //alert('An image file=' + file.name + ' has been loaded');
    
                // Load the image
                var reader = new FileReader();
                reader.onload = function (readerEvent) {
                    var image = new Image();
                    image.onload = function (imageEvent) {
    
                        // Resize the image
                        var canvas = document.getElementById('thecanvas'),
                            max_size = 544,     // TODO : pull max size from a site config
                            width = image.width,
                            height = image.height;
                        if (width > height) {
                            if (width > max_size) {
                                height *= max_size / width;
                                width = max_size;
                            }
                        } else {
                            if (height > max_size) {
                                width *= max_size / height;
                                height = max_size;
                            }
                        }
                        canvas.width = width;
                        canvas.height = height;
                        canvas.getContext('2d').drawImage(image, 0, 0, width, height);
                        var dataUrl = canvas.toDataURL('image/jpeg').replace("image/jpeg", "image/octet-stream");
                        
                        var resizedImage = dataURLToBlob(dataUrl);
                        $.event.trigger({
                            type: "imageResized",
                            blob: resizedImage,
                            url: dataUrl,
                            fileName: file.name
                        });
                    }
                    image.src = readerEvent.target.result;
                }
                reader.readAsDataURL(file);
            }
        };
    
    
        /* Utility function to convert a canvas to a BLOB */
        var dataURLToBlob = function (dataURL) {
            var BASE64_MARKER = ';base64,';
            if (dataURL.indexOf(BASE64_MARKER) == -1) {
                var parts = dataURL.split(',');
                var contentType = parts[0].split(':')[1];
                var raw = parts[1];
    
                return new Blob([raw], {type: contentType});
            }
    
            var parts = dataURL.split(BASE64_MARKER);
            var contentType = parts[0].split(':')[1];
            var raw = window.atob(parts[1]);
            var rawLength = raw.length;
    
            var uInt8Array = new Uint8Array(rawLength);
    
            for (var i = 0; i < rawLength; ++i) {
                uInt8Array[i] = raw.charCodeAt(i);
            }
    
            return new Blob([uInt8Array], {type: contentType});
        }
        /* End Utility function to convert a canvas to a BLOB      */
    
    
        /* Handle image resized events */
        $(document).on("imageResized", function (event) {
            var data = new FormData($("form[id*='uploadImageForm']")[0]);
            if (event.blob && event.url) {
                data.append('image_data', event.blob);
                //alert('event.savePath=' + event.savePath);
                $.ajax({
                    url: 'uploadPhoto.aspx/uploadPhoto',
                    data: JSON.stringify({
                        "imageData": event.url,        // this is image data
                        "fileName": event.fileName
                    }),
                    dataType: "json",
                    contentType: "application/json; charset=utf-8",
                    type: 'POST',
                    success: function(data){
                        alert('upload success');
                    },
                    error: function (req, status, error) {
                        alert('upload failed')
                        //alert(req.responseText); 
                        var lbl = document.getElementById('LblError');
                        lbl.innerHTML = req.responseText;
    
                    }
                });
            }
        });
        </script>
    </head>
    
    <body>
        <form id="uploadImageForm" enctype="multipart/form-data">
            <input name="imagefile[]" type="file" id="takePictureField" accept="image/*" onchange="uploadPhotos()" />
            <canvas width="200" height="200" id="thecanvas" hidden="hidden"></canvas>
            <p>
            <asp:Image ID="Image1" runat="server" ImageUrl="/Images/Auto/001.png" 
                AlternateText="VIN Label Example" onmouseover="imageBig(this);" onmouseout="imageSmall(this);" />
            </p>
            <p>
                <asp:Label ID="LblError" runat="server" Text="" Font-Size="Medium"></asp:Label>
            </p>
        </form>
    </body>
    </html>

    Sunday, March 7, 2021 8:27 PM

Answers

  • User1535942433 posted

    Hi dlchase,

    According to your description,as far as I think,you could return image's path and name in ajax.

    Just like this:

    <script src="Scripts/jquery-1.10.2.min.js"></script>
        <script type="text/javascript">
    
        window.uploadPhotos = function(url){
            // Read in file
            var file = event.target.files[0];
    
            // Ensure it's an image
            if(file.type.match(/image.*/)) {
                //alert('An image file=' + file.name + ' has been loaded');
    
                // Load the image
                var reader = new FileReader();
                reader.onload = function (readerEvent) {
                    var image = new Image();
                    image.onload = function (imageEvent) {
    
                        // Resize the image
                        var canvas = document.getElementById('thecanvas'),
                            max_size = 544,     // TODO : pull max size from a site config
                            width = image.width,
                            height = image.height;
                        if (width > height) {
                            if (width > max_size) {
                                height *= max_size / width;
                                width = max_size;
                            }
                        } else {
                            if (height > max_size) {
                                width *= max_size / height;
                                height = max_size;
                            }
                        }
                        canvas.width = width;
                        canvas.height = height;
                        canvas.getContext('2d').drawImage(image, 0, 0, width, height);
                        var dataUrl = canvas.toDataURL('image/jpeg').replace("image/jpeg", "image/octet-stream");
                        
                        var resizedImage = dataURLToBlob(dataUrl);
                        $.event.trigger({
                            type: "imageResized",
                            blob: resizedImage,
                            url: dataUrl,
                            fileName: file.name
                        });
                    }
                    image.src = readerEvent.target.result;
       
                }
                reader.readAsDataURL(file);
            }
        };
    
    
        /* Utility function to convert a canvas to a BLOB */
        var dataURLToBlob = function (dataURL) {
            var BASE64_MARKER = ';base64,';
            if (dataURL.indexOf(BASE64_MARKER) == -1) {
                var parts = dataURL.split(',');
                var contentType = parts[0].split(':')[1];
                var raw = parts[1];
    
                return new Blob([raw], {type: contentType});
            }
    
            var parts = dataURL.split(BASE64_MARKER);
            var contentType = parts[0].split(':')[1];
            var raw = window.atob(parts[1]);
            var rawLength = raw.length;
    
            var uInt8Array = new Uint8Array(rawLength);
    
            for (var i = 0; i < rawLength; ++i) {
                uInt8Array[i] = raw.charCodeAt(i);
            }
    
            return new Blob([uInt8Array], {type: contentType});
        }
        /* End Utility function to convert a canvas to a BLOB      */
    
    
        /* Handle image resized events */
        $(document).on("imageResized", function (event) {
            var data = new FormData($("form[id*='uploadImageForm']")[0]);
            if (event.blob && event.url) {
                data.append('image_data', event.blob);
                //alert('event.savePath=' + event.savePath);
                $.ajax({
                    url: '2174931.aspx/uploadPhoto',
                    data: JSON.stringify({
                        "imageData": event.url,        // this is image data
                        "fileName": event.fileName
                    }),
                    dataType: "json",
                    contentType: "application/json; charset=utf-8",
                    type: 'POST',
                    success: function(data){
                        //alert('upload success');
                        var data = $.parseJSON(data.d);
                        var x = data.Path + "/" + data.fileName;
                        $("#Image1").attr("src", '/'+ x.match(/image\/.*$/i)[0]);
                    },
                    error: function (req, status, error) {
                        alert('upload failed')
                        //alert(req.responseText); 
                        var lbl = document.getElementById('LblError');
                        lbl.innerHTML = req.responseText;
    
                    }
                });
            }
        });
        </script>
    
    
      <form id="uploadImageForm" enctype="multipart/form-data">
            <input name="imagefile[]" type="file" id="takePictureField" accept="image/*" onchange="uploadPhotos()" />
            <canvas width="200" height="200" id="thecanvas"></canvas>
            <p>
            <asp:Image ID="Image1" runat="server" ImageUrl="/image/tree.png" 
                AlternateText="VIN Label Example" />
            </p>
            <p>
                <asp:Label ID="LblError" runat="server" Text="" Font-Size="Medium"></asp:Label>
            </p>
        </form>

    Code-behind:

      <WebMethod>
        Public Shared Function uploadPhoto(ByVal imageData As String, ByVal fileName As String) As String
            Dim serverPath As String = HttpContext.Current.Server.MapPath("~/image")
            imageData = imageData.Replace("data:image/octet-stream;base64,", "")
    
            Try
                File.WriteAllBytes(serverPath & fileName, Convert.FromBase64String(imageData))
    
            Catch ex As Exception
                Console.WriteLine(ex.StackTrace)
                Return "Failed"
    
            End Try
            Dim chk = New check With {
                            .Path = serverPath,
                            .fileName = fileName
                        }
    
            Return JsonConvert.SerializeObject(chk)
        End Function
        Public Class check
            Public Property Path As String
            Public Property fileName As String
        End Class

    Best regards,

    Yijing Sun

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, March 8, 2021 8:03 AM

All replies

  • User1535942433 posted

    Hi dlchase,

    According to your description,as far as I think,you could return image's path and name in ajax.

    Just like this:

    <script src="Scripts/jquery-1.10.2.min.js"></script>
        <script type="text/javascript">
    
        window.uploadPhotos = function(url){
            // Read in file
            var file = event.target.files[0];
    
            // Ensure it's an image
            if(file.type.match(/image.*/)) {
                //alert('An image file=' + file.name + ' has been loaded');
    
                // Load the image
                var reader = new FileReader();
                reader.onload = function (readerEvent) {
                    var image = new Image();
                    image.onload = function (imageEvent) {
    
                        // Resize the image
                        var canvas = document.getElementById('thecanvas'),
                            max_size = 544,     // TODO : pull max size from a site config
                            width = image.width,
                            height = image.height;
                        if (width > height) {
                            if (width > max_size) {
                                height *= max_size / width;
                                width = max_size;
                            }
                        } else {
                            if (height > max_size) {
                                width *= max_size / height;
                                height = max_size;
                            }
                        }
                        canvas.width = width;
                        canvas.height = height;
                        canvas.getContext('2d').drawImage(image, 0, 0, width, height);
                        var dataUrl = canvas.toDataURL('image/jpeg').replace("image/jpeg", "image/octet-stream");
                        
                        var resizedImage = dataURLToBlob(dataUrl);
                        $.event.trigger({
                            type: "imageResized",
                            blob: resizedImage,
                            url: dataUrl,
                            fileName: file.name
                        });
                    }
                    image.src = readerEvent.target.result;
       
                }
                reader.readAsDataURL(file);
            }
        };
    
    
        /* Utility function to convert a canvas to a BLOB */
        var dataURLToBlob = function (dataURL) {
            var BASE64_MARKER = ';base64,';
            if (dataURL.indexOf(BASE64_MARKER) == -1) {
                var parts = dataURL.split(',');
                var contentType = parts[0].split(':')[1];
                var raw = parts[1];
    
                return new Blob([raw], {type: contentType});
            }
    
            var parts = dataURL.split(BASE64_MARKER);
            var contentType = parts[0].split(':')[1];
            var raw = window.atob(parts[1]);
            var rawLength = raw.length;
    
            var uInt8Array = new Uint8Array(rawLength);
    
            for (var i = 0; i < rawLength; ++i) {
                uInt8Array[i] = raw.charCodeAt(i);
            }
    
            return new Blob([uInt8Array], {type: contentType});
        }
        /* End Utility function to convert a canvas to a BLOB      */
    
    
        /* Handle image resized events */
        $(document).on("imageResized", function (event) {
            var data = new FormData($("form[id*='uploadImageForm']")[0]);
            if (event.blob && event.url) {
                data.append('image_data', event.blob);
                //alert('event.savePath=' + event.savePath);
                $.ajax({
                    url: '2174931.aspx/uploadPhoto',
                    data: JSON.stringify({
                        "imageData": event.url,        // this is image data
                        "fileName": event.fileName
                    }),
                    dataType: "json",
                    contentType: "application/json; charset=utf-8",
                    type: 'POST',
                    success: function(data){
                        //alert('upload success');
                        var data = $.parseJSON(data.d);
                        var x = data.Path + "/" + data.fileName;
                        $("#Image1").attr("src", '/'+ x.match(/image\/.*$/i)[0]);
                    },
                    error: function (req, status, error) {
                        alert('upload failed')
                        //alert(req.responseText); 
                        var lbl = document.getElementById('LblError');
                        lbl.innerHTML = req.responseText;
    
                    }
                });
            }
        });
        </script>
    
    
      <form id="uploadImageForm" enctype="multipart/form-data">
            <input name="imagefile[]" type="file" id="takePictureField" accept="image/*" onchange="uploadPhotos()" />
            <canvas width="200" height="200" id="thecanvas"></canvas>
            <p>
            <asp:Image ID="Image1" runat="server" ImageUrl="/image/tree.png" 
                AlternateText="VIN Label Example" />
            </p>
            <p>
                <asp:Label ID="LblError" runat="server" Text="" Font-Size="Medium"></asp:Label>
            </p>
        </form>

    Code-behind:

      <WebMethod>
        Public Shared Function uploadPhoto(ByVal imageData As String, ByVal fileName As String) As String
            Dim serverPath As String = HttpContext.Current.Server.MapPath("~/image")
            imageData = imageData.Replace("data:image/octet-stream;base64,", "")
    
            Try
                File.WriteAllBytes(serverPath & fileName, Convert.FromBase64String(imageData))
    
            Catch ex As Exception
                Console.WriteLine(ex.StackTrace)
                Return "Failed"
    
            End Try
            Dim chk = New check With {
                            .Path = serverPath,
                            .fileName = fileName
                        }
    
            Return JsonConvert.SerializeObject(chk)
        End Function
        Public Class check
            Public Property Path As String
            Public Property fileName As String
        End Class

    Best regards,

    Yijing Sun

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, March 8, 2021 8:03 AM
  • User1510859543 posted

    Made changes below but when I ran it I got the error below in the Web Method on the line below

            Return JsonConvert.SerializeObject(chk)

    Below are the latest code changes as you suggested.

            $(document).on("imageResized", function (event) {
            var data = new FormData($("form[id*='uploadImageForm']")[0]);
            if (event.blob && event.url) {
                data.append('image_data', event.blob);
                $.ajax({
                    url: 'uploadPhoto.aspx/uploadPhoto',
                    data: JSON.stringify({
                        "imageData": event.url,        // this is image data
                        "fileName": event.fileName
                    }),
                    dataType: "json",
                    contentType: "application/json; charset=utf-8",
                    type: 'POST',
                    success: function (data) {
                        addFileName(event.fileName);
                        var data = $.parseJSON(data.d);
                        var x = data.Path + "/" + data.fileName;
                        $("#Image1").attr("src", '/'+ x.match(/image\/.*$/i)[0]);
    
                        alert('upload success');
                    },
                    error: function (req, status, error) {
                        alert('upload failed');
                        //alert(req.responseText); 
                        var lbl = document.getElementById('LblError');
                        lbl.innerHTML = req.responseText;
    
                    }
                });
            }
            });
            function addFileName(sname) {
                var lbl = document.getElementById('LblFileNames');
                lbl.innerHTML += sname + '~';
            }
    
        <WebMethod>
        Public Shared Function uploadPhoto(ByVal imageData As String, ByVal fileName As String) As String
    
            Dim serverPath As String = HttpContext.Current.Server.MapPath("~/uploads/")
            imageData = imageData.Replace("data:image/octet-stream;base64,", "")
    
            Try
                File.WriteAllBytes(serverPath & fileName, Convert.FromBase64String(imageData))
    
            Catch ex As Exception
                File.WriteAllText(serverPath & "error.txt", ex.StackTrace)
                'Console.WriteLine(ex.StackTrace)
                Return "Failed"
    
            End Try
            Dim chk As check = New check With {.Path = serverPath, .fileName = fileName}
    
            Return JsonConvert.SerializeObject(chk)
    
            'Return "OK"
        End Function
        Public Class check
            Public Path As String
            Public fileName As String
        End Class

    Below is the error returned

    {"Message":"Object variable or With block variable not set.","StackTrace":" at Microsoft.VisualBasic.CompilerServices.Symbols.Container..ctor(Object Instance)\r\n at Microsoft.VisualBasic.CompilerServices.NewLateBinding.LateGet(Object Instance, Type Type, String MemberName, Object[] Arguments, String[] ArgumentNames, Type[] TypeArguments, Boolean[] CopyBack)\r\n at uploadPhoto.uploadPhoto(String imageData, String fileName)","ExceptionType":"System.NullReferenceException"}

    Tuesday, March 9, 2021 3:03 PM
  • User1535942433 posted

    Hi dlchase,

    I copied your current codes and have a test.It works.

    I suggest you could debug and break point at these codes to check which variables are null. Or do you have other codes?

    Best regards,

    Yijing Sun

    Wednesday, March 10, 2021 8:49 AM
  • User1510859543 posted

    Still no luck.  I have not done debug using ajax so I don't know where to start.  Also, can you explain the line below?  I have no idea what .parseJSON(data.d); is referring to. What is data.d ?

    var data = $.parseJSON(data.d);

    Thursday, March 11, 2021 4:00 PM
  • User1535942433 posted

    Hi dlchase,

    About how to debug,you could do like this:

    1.Press F12 when you run the project.

    2.The page will show a panel.Click "Source" and then break point at some lines.Just like this:

    3.Trigger the ajax and press F11 to continue. 

    4.You could check if the data have value.

    What's $.parseJSON(data.d):

    In the code behind,you have got an object and convert it to JSON string using SerializeObject function from JsonConvert class.

    And $.parseJSON will parse a string (written in JSON format) and return a JavaScript object. Data is the JSON object returned from the endpoint and d is one of the properties of it.

    You could learn more about serialization and deserialization.

    https://docs.microsoft.com/zh-tw/dotnet/framework/wcf/feature-details/how-to-serialize-and-deserialize-json-data

    https://api.jquery.com/serialize/

    Best regards,

    Yijing Sun

    Friday, March 12, 2021 7:35 AM
  • User1510859543 posted

    I tried your suggestion and (apparently) never hit the breakpoints. One item to note is that it DID upload and create the image file.

    In Console it shows below.
    POST https://www.fixit.com/uploadPhoto.aspx/uploadPhoto 500 (Internal Server Error)  jquery-3.1.1.min.js:4

    When I click on the jquery-3.1.1.min.js:4 link it highlights a ton of stuff in the .js file starting with text below.
    try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}}

    Below is the uploadPhoto.aspx.vb code I am using

    Imports System.Collections.Generic
    Imports System.IO
    Imports System.Web.Services
    
    Partial Class uploadPhoto
        Inherits System.Web.UI.Page
    
        Public Shared JsonConvert As Object
    
        <WebMethod> _
        Public Shared Function uploadPhoto(ByVal imageData As String, ByVal fileName As String) As String
    
            Dim serverPath As String = HttpContext.Current.Server.MapPath("~/uploads/")
            imageData = imageData.Replace("data:image/octet-stream;base64,", "")
    
            Try
                File.WriteAllBytes(serverPath & fileName, Convert.FromBase64String(imageData))
    
            Catch ex As Exception
                File.WriteAllText(serverPath & "error.txt", ex.StackTrace)
                'Console.WriteLine(ex.StackTrace)
                Return "Failed"
    
            End Try
    
            Dim chk As check = New check With {.Path = serverPath, .fileName = fileName}
    
            Return JsonConvert.SerializeObject(chk)
    
            'Return "OK"
        End Function
        Public Class check
            Public Path As String
            Public fileName As String
        End Class
    
    End Class

    Friday, March 12, 2021 3:20 PM
  • User1535942433 posted

    Hi dlchase,

    According to your description, as far as I think,your problem is client. I suggest you could check if ajax post data is null. You could press F11 to check which data is null.

    Best refards,

    Yijing Sun

    Monday, March 15, 2021 9:36 AM
  • User1510859543 posted

    The only values being posted are path and filename but the file IS being saved so neither can be null.

    Monday, March 15, 2021 11:37 AM
  • User1510859543 posted

    That worked but now I am noticing that the FileUpload1 button is showing up when I use Edge but hides fine in Chrome.  Below is my css for Hide and Show. 

    .Show {
        visibility: visible;
    }
    
    .Hide {
        visibility: hidden;
    }

    Monday, March 15, 2021 1:59 PM
  • User1510859543 posted

    Ignore this. I made the css local and renamed them to showel and hideel and now it works on all browsers.

    Monday, March 15, 2021 2:42 PM
  • User1535942433 posted

    Hi dlchase,

    So do you have solved your problems?If you still have problems,you could post your current codes to us.If you have solved,you could mark these answers which help you.

    Best regards,

    Yijing Sun

    Tuesday, March 16, 2021 7:10 AM
  • User1510859543 posted

    No. Still failing.

    Tuesday, March 16, 2021 11:30 AM
  • User1510859543 posted

    When I do an F12 to view the elements after trying an upload (which the upload works) I see the error below in the Console section. Line 161 is this in the $.ajax section

    var data = $.parseJSON(data.d);

    Uncaught SyntaxError: Unexpected token O in JSON at position 0
        at Function.parse [as parseJSON] (<anonymous>)
        at Object.success (CustEstimate.aspx:161)
        at i (jquery-3.1.1.min.js:2)
        at Object.fireWith [as resolveWith] (jquery-3.1.1.min.js:2)
        at A (jquery-3.1.1.min.js:4)
        at XMLHttpRequest.<anonymous> (jquery-3.1.1.min.js:4)

    Tuesday, March 16, 2021 1:35 PM
  • User1535942433 posted

    Hi dlchase,

    According to your errors,I'm guessing that in your code, it is most likely not a JSON string anymore, but already a JavaScript object. This means, no more parsing is necessary. 

    Your codes is like this:

    var data = data.d;

    Best regards,

    Yijing Sun

    Wednesday, March 17, 2021 8:41 AM
  • User1510859543 posted

    I tried this and added alert(data.Path); after that line and it popped up "undefined"

    I even tried adding alert(data.d) and it still gave "undefined"

    Wednesday, March 17, 2021 1:40 PM
  • User1510859543 posted

    Got it to work with code below.

                    success: function (data) {
                        addFileName(event.fileName);
                        //change source of image to new one uploaded
                        var x = 'uploads/' + event.fileName;
                        $("#Image1").attr("src", x);
    

    Wednesday, March 17, 2021 2:29 PM