#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2012
    Posts
    33
    Rep Power
    3

    Javascript Save Button for Canvas Image


    Hi
    I've been battling to add a save button the whole weekend and yesterday.
    I just don't know enough about javascript to make it happen

    I've found a nice tool to convert images larger than 4meg on client side to save data and upload time for client and myself.
    Below is the script, All credits go to WebReflection. This is the complete working html page.
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>AJAX Image Resizing</title>
    
    </head>
    <title>JavaScript Image Resample :: WebReflection</title>
     </head>
     <body>
      <input id="width" type="hidden" value="656" />
      <input id="height" type="hidden" />
      Select File<input id="file" type="file" />
      <br /><span id="message"></span><br />
      <div id="img"></div>
    </body>
     
    <script>
    // JavaScript Document
    
    var Resample = (function (canvas) {
    
     // (C) WebReflection Mit Style License
    
     // Resample function, accepts an image
     // as url, base64 string, or Image/HTMLImgElement
     // optional width or height, and a callback
     // to invoke on operation complete
     function Resample(img, width, height, onresample) {
      var
       // check the image type
       load = typeof img == "string",
       // Image pointer
       i = load || img
      ;
      // if string, a new Image is needed
      if (load) {
       i = new Image;
       // with propers callbacks
       i.onload = onload;
       i.onerror = onerror;
      }
      // easy/cheap way to store info
      i._onresample = onresample;
      i._width = width;
      i._height = height;
      // if string, we trust the onload event
      // otherwise we call onload directly
      // with the image as callback context
      load ? (i.src = img) : onload.call(img);
    
    
     }
     
     // just in case something goes wrong
     function onerror() {
      throw ("not found: " + this.src);
     }
     
     // called when the Image is ready
     function onload() {
      var
       // minifier friendly
       img = this,
       // the desired width, if any
       width = img._width,
       // the desired height, if any
       height = img._height,
       // the callback
       onresample = img._onresample
      ;
      // if width and height are both specified
      // the resample uses these pixels
      // if width is specified but not the height
      // the resample respects proportions
      // accordingly with orginal size
      // same is if there is a height, but no width
      width == null && (width = round(img.width * height / img.height));
      height == null && (height = round(img.height * width / img.width));
      // remove (hopefully) stored info
      delete img._onresample;
      delete img._width;
      delete img._height;
      // when we reassign a canvas size
      // this clears automatically
      // the size should be exactly the same
      // of the final image
      // so that toDataURL ctx method
      // will return the whole canvas as png
      // without empty spaces or lines
      canvas.width = width;
      canvas.height = height;
      // drawImage has different overloads
      // in this case we need the following one ...
      context.drawImage(
       // original image
       img,
       // starting x point
       0,
       // starting y point
       0,
       // image width
       img.width,
       // image height
       img.height,
       // destination x point
       0,
       // destination y point
       0,
       // destination width
       width,
       // destination height
       height
      );
      // retrieve the canvas content as
      // base4 encoded PNG image
      // and pass the result to the callback
      onresample(canvas.toDataURL("image/png"));
     }
     
     var
      // point one, use every time ...
      context = canvas.getContext("2d"),
      // local scope shortcut
      round = Math.round
     ;
     
     return Resample;
     }(
     // lucky us we don't even need to append
     // and render anything on the screen
     // let's keep this DOM node in RAM
     // for all resizes we want
     this.document.createElement("canvas"))
    );
     
     
      
     
     
     
     ////  resampling script ///
     (function (global, $width, $height, $file, $message, $img) {
      
      // (C) WebReflection Mit Style License
      
      // simple FileReader detection
      if (!global.FileReader)
       // no way to do what we are trying to do ...
       return $message.innerHTML = "FileReader API not supported"
      ;
      
      // async callback, received the
      // base 64 encoded resampled image
      function resampled(data) {
       $message.innerHTML = "done";
       ($img.lastChild || $img.appendChild(new Image)
       ).src = data;
     
    
     }
      // async callback, fired when the image
      // file has been loaded
      function load(e) {
       $message.innerHTML = "resampling ...";
       // see resample.js
       Resample(
         this.result,
         this._width || null,
         this._height || null,
         resampled
       );
       
      }
      
      // async callback, fired if the operation
      // is aborted ( for whatever reason )
      function abort(e) {
       $message.innerHTML = "operation aborted";
      }
      
      // async callback, fired
      // if an error occur (i.e. security)
      function error(e) {
       $message.innerHTML = "Error: " + (this.result || e);
      }
      
      // listener for the input@file onchange
      $file.addEventListener("change", function change() {
       var
        // retrieve the width in pixel
        width = parseInt($width.value, 10),
        // retrieve the height in pixels
        height = parseInt($height.value, 10),
        // temporary variable, different purposes
        file
       ;
       // no width and height specified
       // or both are NaN
       if (!width && !height) {
        // reset the input simply swapping it
        $file.parentNode.replaceChild(
         file = $file.cloneNode(false),
         $file
        );
        // remove the listener to avoid leaks, if any
        $file.removeEventListener("change", change, false);
        // reassign the $file DOM pointer
        // with the new input text and
        // add the change listener
        ($file = file).addEventListener("change", change, false);
        // notify user there was something wrong
        $message.innerHTML = "please specify width or height";
       } else if(
        // there is a files property
        // and this has a length greater than 0
        ($file.files || []).length &&
        // the first file in this list 
        // has an image type, hopefully
        // compatible with canvas and drawImage
        // not strictly filtered in this example
        /^image\//.test((file = $file.files[0]).type)
       ) {
        // reading action notification
        $message.innerHTML = "reading ...";
        // create a new object
        file = new FileReader;
        // assign directly events
        // as example, Chrome does not
        // inherit EventTarget yet
        // so addEventListener won't
        // work as expected
        file.onload = load;
        file.onabort = abort;
        file.onerror = error;
        // cheap and easy place to store
        // desired width and/or height
        file._width = width;
        file._height = height;
        // time to read as base 64 encoded
        // data te selected image
        file.readAsDataURL($file.files[0]);
        // it will notify onload when finished
        // An onprogress listener could be added
        // as well, not in this demo tho (I am lazy)
       } else if (file) {
        // if file variable has been created
        // during precedent checks, there is a file
        // but the type is not the expected one
        // wrong file type notification
        $message.innerHTML = "please chose an image";
       } else {
        // no file selected ... or no files at all
        // there is really nothing to do here ...
        $message.innerHTML = "nothing to do";
       }
      }, false);
     }(
      // the global object
      this,
      // all required fields ...
      document.getElementById("width"),
      document.getElementById("height"),
      document.getElementById("file"),
      document.getElementById("message"),
      document.getElementById("img")
     ));
     
    
     </script>
    </html>
    But what I would like to do is to insert a save button below the converted image. This would be an alternative to right click and "Save Image As" option.
    I can read an understand the code but dont know enough to put things in the right place with javascript. I'm much better with php
    Any input would greatly be appreciated.
  2. #2
  3. No Profile Picture
    Lost in code
    Devshed Supreme Being (6500+ posts)

    Join Date
    Dec 2004
    Posts
    8,316
    Rep Power
    7171
    I don't believe there is any file writing or saving API as part of HTML 5. You could transmit the file to the server when they click save and then send it back to them as a standard file download. It might be possible to trigger a save dialog by redirecting them to a URL containing the image data, however I'm not sure if all or even if any browsers would allow this.
    PHP FAQ

    Originally Posted by Spad
    Ah USB, the only rectangular connector where you have to make 3 attempts before you get it the right way around
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2012
    Posts
    33
    Rep Power
    3
    Hi thanks for reply

    Can i not include more javascript

    Code:
                 window.onload = function () {
                    var button = document.getElementById('saveImage');
                    button.onclick = function () {
                        window.location.href = img.replace('image/png', 'image/octet-stream');
                    };
                };
    underneath
    Code:
      load ? (i.src = img) : onload.call(img); document.URL
    then it looks like this
    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>AJAX Image Resizing</title>
    
    </head>
    
      <title>JavaScript Image Resample :: WebReflection</title>
     </head>
     <body>
    
    
      Width<input id="width" type="text" value="320" />
      Height<input id="height" type="text" />
      Select File<input id="file" type="file" />
      <br /><span id="message"></span><br />
      <div id="img"></div>
    
    
    <script>
                 window.onload = function () {
                    var button = document.getElementById('saveImage');
                    button.onclick = function () {
                        window.location.href = img.replace('image/png', 'image/octet-stream');
                    };
                };
    </script>
    
      <input id="saveImage" type="button" value="save image" />
    
     </body>
     
     
    
    
    
     <script>
     
     
     
     
     // JavaScript Document
    
    
    var Resample = (function (canvas) {
    
     // (C) WebReflection Mit Style License
    
     // Resample function, accepts an image
     // as url, base64 string, or Image/HTMLImgElement
     // optional width or height, and a callback
     // to invoke on operation complete
     function Resample(img, width, height, onresample) {
      var
       // check the image type
       load = typeof img == "string",
       // Image pointer
       i = load || img
      ;
      // if string, a new Image is needed
      if (load) {
       i = new Image;
       // with propers callbacks
       i.onload = onload;
       i.onerror = onerror;
      }
      // easy/cheap way to store info
      i._onresample = onresample;
      i._width = width;
      i._height = height;
      // if string, we trust the onload event
      // otherwise we call onload directly
      // with the image as callback context
      load ? (i.src = img) : onload.call(img); document.URL
    // document.write("" + img);
     //document.write("" + img);
    
                 window.onload = function () {
                    var button = document.getElementById('saveImage');
                    button.onclick = function () {
                        window.location.href = img.replace('image/png', 'image/octet-stream');
                    };
                };
    
    
    }
    
     // just in case something goes wrong
     function onerror() {
      throw ("not found: " + this.src);
     }
     
     // called when the Image is ready
     function onload() {
      var
       // minifier friendly
       img = this,
       // the desired width, if any
       width = img._width,
       // the desired height, if any
       height = img._height,
       // the callback
       onresample = img._onresample
      ;
      // if width and height are both specified
      // the resample uses these pixels
      // if width is specified but not the height
      // the resample respects proportions
      // accordingly with orginal size
      // same is if there is a height, but no width
      width == null && (width = round(img.width * height / img.height));
      height == null && (height = round(img.height * width / img.width));
      // remove (hopefully) stored info
      delete img._onresample;
      delete img._width;
      delete img._height;
      // when we reassign a canvas size
      // this clears automatically
      // the size should be exactly the same
      // of the final image
      // so that toDataURL ctx method
      // will return the whole canvas as png
      // without empty spaces or lines
      canvas.width = width;
      canvas.height = height;
      // drawImage has different overloads
      // in this case we need the following one ...
      context.drawImage(
       // original image
       img,
       // starting x point
       0,
       // starting y point
       0,
       // image width
       img.width,
       // image height
       img.height,
       // destination x point
       0,
       // destination y point
       0,
       // destination width
       width,
       // destination height
       height
      );
      // retrieve the canvas content as
      // base4 encoded PNG image
      // and pass the result to the callback
      onresample(canvas.toDataURL("image/png"));
     }
     
     var
      // point one, use every time ...
      context = canvas.getContext("2d"),
      // local scope shortcut
      round = Math.round
     ;
     
     return Resample;
     
    }(
     // lucky us we don't even need to append
     // and render anything on the screen
     // let's keep this DOM node in RAM
     // for all resizes we want
     this.document.createElement("canvas"))
    );
     
     
     
     
     
      
     
     (function (global, $width, $height, $file, $message, $img) {
      
      // (C) WebReflection Mit Style License
      
      // simple FileReader detection
      if (!global.FileReader)
       // no way to do what we are trying to do ...
       return $message.innerHTML = "FileReader API not supported"
      ;
      
      // async callback, received the
      // base 64 encoded resampled image
      function resampled(data) {
       $message.innerHTML = "done";
       ($img.lastChild || $img.appendChild(new Image)
       ).src = data;
      }
      
      // async callback, fired when the image
      // file has been loaded
      function load(e) {
       $message.innerHTML = "resampling ...";
       // see resample.js
       Resample(
         this.result,
         this._width || null,
         this._height || null,
         resampled
       );
       
      }
      
      // async callback, fired if the operation
      // is aborted ( for whatever reason )
      function abort(e) {
       $message.innerHTML = "operation aborted";
      }
      
      // async callback, fired
      // if an error occur (i.e. security)
      function error(e) {
       $message.innerHTML = "Error: " + (this.result || e);
      }
      
      // listener for the input@file onchange
      $file.addEventListener("change", function change() {
       var
        // retrieve the width in pixel
        width = parseInt($width.value, 10),
        // retrieve the height in pixels
        height = parseInt($height.value, 10),
        // temporary variable, different purposes
        file
       ;
       // no width and height specified
       // or both are NaN
       if (!width && !height) {
        // reset the input simply swapping it
        $file.parentNode.replaceChild(
         file = $file.cloneNode(false),
         $file
        );
        // remove the listener to avoid leaks, if any
        $file.removeEventListener("change", change, false);
        // reassign the $file DOM pointer
        // with the new input text and
        // add the change listener
        ($file = file).addEventListener("change", change, false);
        // notify user there was something wrong
        $message.innerHTML = "please specify width or height";
       } else if(
        // there is a files property
        // and this has a length greater than 0
        ($file.files || []).length &&
        // the first file in this list 
        // has an image type, hopefully
        // compatible with canvas and drawImage
        // not strictly filtered in this example
        /^image\//.test((file = $file.files[0]).type)
       ) {
        // reading action notification
        $message.innerHTML = "reading ...";
        // create a new object
        file = new FileReader;
        // assign directly events
        // as example, Chrome does not
        // inherit EventTarget yet
        // so addEventListener won't
        // work as expected
        file.onload = load;
        file.onabort = abort;
        file.onerror = error;
        // cheap and easy place to store
        // desired width and/or height
        file._width = width;
        file._height = height;
        // time to read as base 64 encoded
        // data te selected image
        file.readAsDataURL($file.files[0]);
        // it will notify onload when finished
        // An onprogress listener could be added
        // as well, not in this demo tho (I am lazy)
       } else if (file) {
        // if file variable has been created
        // during precedent checks, there is a file
        // but the type is not the expected one
        // wrong file type notification
        $message.innerHTML = "please chose an image";
       } else {
        // no file selected ... or no files at all
        // there is really nothing to do here ...
        $message.innerHTML = "nothing to do";
       }
      }, false);
     }(
      // the global object
      this,
      // all required fields ...
      document.getElementById("width"),
      document.getElementById("height"),
      document.getElementById("file"),
      document.getElementById("message"),
      document.getElementById("img")
     ));
     
     
     
     </script>
     
    
    </html>
    also when you unhash the
    Code:
    document.write("" + img);
    You send the URIdata to the screen.
    If there is absolutely no way.
    How would I get the uri data from javascript to php or how would i get the url from browser to php and then send back to client as savable image

IMN logo majestic logo threadwatch logo seochat tools logo