Uncategorized

Exporting A Html Canvas Data To Image

As Part of a bigger project I am doing right now, I wanted to be able to store data from a HTML Canvas as a byte[] and save it in Azure blog storage. I thought that this by iteself may make an interesting post. I have not posted up any code this time, but all you should need will be available as snippets here

So the first thing I did was start a new ASP MVC project, which gave me all that I needed to start

Next I added a changed Index.Html page to look like the following

@{
    ViewBag.Title = "Home Page";
}


@section Scripts {
    <script src="~/Scripts/Index.js"></script>
}

<br/>
<p>This small example saves the canvas to blob storage</p>
<div style="border:  1px solid black; margin: 10px;">
    <canvas id="canv" width="600" height="600"></canvas>
</div>
<br/>

<div id="savedImageDiv" style="display:none">
    <img id="savedImage" width="100" height="100"/>
</div>
<button type="button" id="saveCanvas" >Save Canvas TO Blob</button>

See how there is a Canvas element, and a initially hidden Div, where the Div contains an image. This Div will get shown and the image will get filled in with a valid Azure blog storage Url when the Canvas is saved to blob storage.

So how does this happen. There are not that many moving parts there is basically the following 4 things needed

  • An Azure storage account (you set this in the Web.Config), though if you want to try this out, you can just use the Azure storage emulator, and a reference to the Azure Storage dlls, which you can grab via Nuget
  • A page with a Canvas on it (shown above)
  • Some Javascript to post the canvas data over to a MVC controller
  • A controller
  • Lets have a look at each of these in turn

    The Web.Config

    You will need something like this in your app

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
    
      <appSettings>
    
        .....
        .....
        .....
    
        <!-- TODO : This would need to change to live azure value when deployed -->
        <add key="azureStorageConnectionString" value="UseDevelopmentStorage=true;" />
    
    
    
      </appSettings>
    
    
    .....
    .....
    .....
    </configuration>
    

    And you would need to install the following Nuget package “WindowsAzure Storage”

    Javascript

    With the pages html in place, we need some JavaScript to post the Canvas data to the server side controller action. This client side javascript is shown below

    $(document).ready(function () {
        
        fillCanvas();
    
        $("#saveCanvas").on("click", function () {
    
            saveCanvas();
    
        });
    });
    
    
    
    function saveCanvas() {
    
        var canvas = document.getElementById('canv');
        var imageData = canvas.toDataURL('image/jpeg', 1);
    
        $.ajax({
            type: "POST",
            url: "/Home/StoreImage",
            dataType: "json",
            data: { ImageData: imageData, ImageType: "jpeg" },
            success: function (data) {
    
                if (data.StoredOk) {
    
                    $('#savedImageDiv').show();
                    $('#savedImage').attr("src", data.Uri);
                    alert("success :-)");
                } else {
                    alert("fail :-(");
                }
    
                
            },
            error: function () {
                alert("fail :-(");
            }
        });
    }
    
    
    //Draws random stuff on the canvas
    function fillCanvas() {
        var canvas = document.getElementById('canv');
        var context = canvas.getContext('2d');
    
    
        context.fillStyle = "rgb(255,255,255)";
        context.fillRect(0, 0, 600, 600);
    
    
        context.fillStyle = "rgb(150,29,28)";
        context.fillRect(10, 10, 80, 80);
    
        context.fillStyle = "rgb(100,55,28)";
        context.fillRect(200, 200, 20, 80);
    }
    

    All that is then left to do is the server side (MVC Controller Action), which is shown below

    Server side code

    p>The server side controller action to save the canvas byte[] into blob storage is shown below. It will also return a JSON object which includes the Blob Uri is stored successfully. Then the javascript will examine this JSOn response, and decide whether to unhide the Div containing the image, and set the image Uri to the stored canvas data. Which is now stored in a Azure blob as an image.

    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.IO;
    using System.Linq;
    using System.Web;
    using System.Web.Helpers;
    using System.Web.Mvc;
    
    using CanvasToBlob.Models;
    
    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Blob;
    
    namespace CanvasToBlob.Controllers
    {
        public class HomeController : Controller
        {
    
            private readonly string azureStorageConnectionString;
            private readonly CloudStorageAccount storageAccount;
    
            public HomeController()
            {
                azureStorageConnectionString = 
    		ConfigurationManager.AppSettings["azureStorageConnectionString"];
    
                storageAccount = 
    		CloudStorageAccount.Parse(azureStorageConnectionString);
            }
    
    
            public ActionResult Index()
            {
                return View();
            }
    
    
            [HttpPost]
            public JsonResult StoreImage(ImageToStore imageToStore)
            {
                try
                {
    
                     CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
     
                    // Retrieve a reference to a container. 
                    CloudBlobContainer container = blobClient.GetContainerReference("images");
                    container.CreateIfNotExists();
                    container.SetPermissions(
                       new BlobContainerPermissions
                       {
                           PublicAccess = BlobContainerPublicAccessType.Blob
                       });
    
                    CloudBlockBlob blockBlob = container.GetBlockBlobReference(
    			string.Format("{0}.{1}", Guid.NewGuid().ToString(), imageToStore.ImageType));
                    string marker = string.Format("data:image/{0};base64,", imageToStore.ImageType);
                    string dataWithoutJpegMarker = imageToStore.ImageData.Replace(marker, String.Empty);
                    byte[] filebytes = Convert.FromBase64String(dataWithoutJpegMarker);
    
                    blockBlob.UploadFromByteArray(filebytes, 0, filebytes.Length);
    
    
                    JsonImageResult result = new JsonImageResult(true, blockBlob.Uri.ToString());
                    return this.Json(result);
                }
                catch (Exception e)
                {
                    JsonImageResult result = new JsonImageResult(false, "");
                    return this.Json("");
                }
            }
        }
    }
    

    Anyway that is all there is too it, I hope you can use this somehow. Enjoy

Leave a comment