Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Export resized image in canvas to new JSZip package

I can load an image into a canvas element and resize it, but I'm having trouble grabbing the resized image:

var logo = $(".logo"),
    loader = $(".load"),
    canvas = $(".holder"),
    ctx = canvas[0].getContext("2d");

function displayPreview(file) {
  var reader = new FileReader();

  reader.onload = function(e) {
    var img = new Image();
    img.src = e.target.result;
    img.onload = function() {
      // x, y, width, height
      ctx.drawImage(img, 0, 0, 128, 128);

      var dataURL = canvas[0].toDataURL("image/png");

      var logo = $(".logo");
      var imgUrl = dataURL;
      var imgz = $("<img>");
      imgz.attr("src", imgUrl);
      logo.html("");
      logo.append(imgz);
    };
  };
  reader.readAsDataURL(file);
}

into the download package function for jszip.

// Download Zip
$(".download").on("click", function(imgUrl) {
  var zip = new JSZip();
  zip.file("logo.png", imgUrl);
  var content = zip.generate({type:"blob"});
  // see FileSaver.js
  saveAs(content, "test.zip");
});

Snippet:

var logo = $(".logo"),
    loader = $(".load"),
    canvas = $(".holder"),
    ctx = canvas[0].getContext("2d");

function displayPreview(file) {
  var reader = new FileReader();

  reader.onload = function(e) {
    var img = new Image();
    img.src = e.target.result;
    img.onload = function() {
      // x, y, width, height
      ctx.drawImage(img, 0, 0, 128, 128);

      var dataURL = canvas[0].toDataURL("image/png");

      var logo = $(".logo");
      var imgUrl = dataURL;
      var imgz = $("<img>");
      imgz.attr("src", imgUrl);
      logo.html("");
      logo.append(imgz);
    };
  };
  reader.readAsDataURL(file);
}


$(document).ready(function() {
  loader.on("change", function(evt) {
    var file = evt.target.files[0];
    displayPreview(file);

    var reader = new FileReader();

    reader.onload = function(e) {
      // Download Zip
      $(".download").on("click", function(imgUrl) {
        var zip = new JSZip();
        zip.file("logo.png", imgUrl);
        var content = zip.generate({type:"blob"});
        // see FileSaver.js
        saveAs(content, "test.zip");
      });
      return false;
    };
    reader.readAsArrayBuffer(file);
  });

  // Trigger Load Image
  $(".trigload").click(function() {
    $("input").trigger("click");
  });
});
@import url("http://necolas.github.io/normalize.css/3.0.1/normalize.css");

.hide {
  display: none;
}

.logo {
  text-align: center;
}

.fill {
  width: 100%;
}

.fr {
  float: right;
}
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript" src="http://stuk.github.io/jszip/dist/jszip.min.js"></script>
<script type="text/javascript" src="http://stuk.github.io/jszip-utils/dist/jszip-utils.js"></script>
<script type="text/javascript" src="http://stuk.github.io/jszip/vendor/FileSaver.js"></script>

<input type="file" class="hide load">
<a class="trigload" href="javascript:void(0)">Load Image</a>
<a class="download fr" href="javascript:void(0)">Download</a>
<div class="logo"></div>
<div class="fill" align="center">
  <canvas class="holder" width="128" height="128"></canvas>
</div>
like image 531
Michael Schwartz Avatar asked Dec 24 '22 17:12

Michael Schwartz


1 Answers

In order to get JSZip to correctly save your dataURL to valid png file, it seems you need to add an object containing {base64: true}as third argument of the zip.file() method, and to remove the data:image/png;base64, from the dataURL.

Also, you were assigning the click event to the imgUrl variable. You may want to store it in a global variable, or check the $('.logo>img')[0].src or call once again canvas[0].toDataURL().

var logo = $(".logo"),
    loader = $(".load"),
    canvas = $(".holder"),
    ctx = canvas[0].getContext("2d");

function displayPreview(file) {
  var reader = new FileReader();

  reader.onload = function(e) {
    var img = new Image();
    img.src = e.target.result;
    img.onload = function() {
      // x, y, width, height
      ctx.drawImage(img, 0, 0, 128, 128);

      var dataURL = canvas[0].toDataURL("image/png");

      var logo = $(".logo");
      var imgUrl = dataURL;
      var imgz = $("<img>");
      imgz.attr("src", imgUrl);
      logo.html("");
      logo.append(imgz);
    };
  };
  reader.readAsDataURL(file);
}


$(document).ready(function() {
  loader.on("change", function(evt) {
    var file = evt.target.files[0];
    displayPreview(file);

    var reader = new FileReader();

    reader.onload = function(e) {
      // Download Zip
      $(".download").on("click", function() {
        var imgUrl = canvas[0].toDataURL();
        var zip = new JSZip();
        zip.file("logo.png", imgUrl.split('base64,')[1],{base64: true});
        var content = zip.generate({type:"blob"});
        // see FileSaver.js
        saveAs(content, "test.zip");   
      });
      return false;
    };
    reader.readAsArrayBuffer(file);
  });

  // Trigger Load Image
  $(".trigload").click(function() {
    $("input").trigger("click");
  });
});
@import url("http://necolas.github.io/normalize.css/3.0.1/normalize.css");

.hide {
  display: none;
}

.logo {
  text-align: center;
}

.fill {
  width: 100%;
}

.fr {
  float: right;
}
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript" src="http://stuk.github.io/jszip/dist/jszip.min.js"></script>
<script type="text/javascript" src="http://stuk.github.io/jszip-utils/dist/jszip-utils.js"></script>
<script type="text/javascript" src="http://stuk.github.io/jszip/vendor/FileSaver.js"></script>

<input type="file" class="hide load">
<a class="trigload" href="javascript:void(0)">Load Image</a>
<a class="download fr" href="javascript:void(0)">Download</a>
<div class="logo"></div>
<div class="fill" align="center">
  <canvas class="holder" width="128" height="128"></canvas>
</div>

2022 Edit

JSZip now accepts Blobs as input directly, so it's better to convert your canvas to a Blob and pass this directly to JSZip. (As a fiddle because StackSnippets don't allow-downloads).

like image 181
Kaiido Avatar answered Jan 05 '23 01:01

Kaiido