title: JS OffscreenCanvas.toDataURL
body: <p><code>HTMLCanvasElement</code> has <code>toDataURL()</code>, but <code>OffscreenCanvas</code> does not have. What a surprise.</p>
  
  <p>Ok, so how can i get this <code>toDataURL()</code> to work with <code>Worker</code>-s? I have a ready canvas (fully drawn), and can send it to a <code>Worker</code>. But then what can i do from there?</p>
  
  <p>The only solution i have, is to manually do all operations to create an <code>image/png</code>. So i found <a href="https://www.xarg.org/2010/03/generate-client-side-png-files-using-javascript/" rel="nofollow noreferrer">this page</a> from 2010. (I am not sure if that is what i need though.) And further it provides <a href="https://www.xarg.org/download/pnglib.js" rel="nofollow noreferrer">this code</a>, from where it generates a PNG and makes it to base64.</p>
  
  <p>And my final question:</p>
  
  <p>1 - Is there some reasonable way to get <code>toDataURL()</code> from <code>Worker</code>, OR</p>
  
  <p>2 - Is there any library or something designed to for this job, OR</p>
  
  <p>3 - Using all functionalities of <code>HTMLCanvasElement</code> and <code>OffscreenCanvas</code>, how should the following code be adapted to replace <code>toDataURL()</code>?</p>
  
  <p>Here are the two functions from the code im linking to. (They are really complicated for me, and i understand almost nothing from <code>getDump()</code>)</p>
  
  <pre><code>    // output a PNG string
      this.getDump = function() {
  
          // compute adler32 of output pixels + row filter bytes
          var BASE = 65521; /* largest prime smaller than 65536 */
          var NMAX = 5552;  /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) &lt;= 2^32-1 */
          var s1 = 1;
          var s2 = 0;
          var n = NMAX;
  
          for (var y = 0; y &lt; this.height; y++) {
              for (var x = -1; x &lt; this.width; x++) {
                  s1+= this.buffer[this.index(x, y)].charCodeAt(0);
                  s2+= s1;
                  if ((n-= 1) == 0) {
                      s1%= BASE;
                      s2%= BASE;
                      n = NMAX;
                  }
              }
          }
          s1%= BASE;
          s2%= BASE;
          write(this.buffer, this.idat_offs + this.idat_size - 8, byte4((s2 &lt;&lt; 16) | s1));
  
          // compute crc32 of the PNG chunks
          function crc32(png, offs, size) {
              var crc = -1;
              for (var i = 4; i &lt; size-4; i += 1) {
                  crc = _crc32[(crc ^ png[offs+i].charCodeAt(0)) &amp; 0xff] ^ ((crc &gt;&gt; 8) &amp; 0x00ffffff);
              }
              write(png, offs+size-4, byte4(crc ^ -1));
          }
  
          crc32(this.buffer, this.ihdr_offs, this.ihdr_size);
          crc32(this.buffer, this.plte_offs, this.plte_size);
          crc32(this.buffer, this.trns_offs, this.trns_size);
          crc32(this.buffer, this.idat_offs, this.idat_size);
          crc32(this.buffer, this.iend_offs, this.iend_size);
  
          // convert PNG to string
          return "\211PNG\r\n\032\n"+this.buffer.join('');
      }
  </code></pre>
  
  <p>Here it is quite clear what is going on:</p>
  
  <pre><code>    // output a PNG string, Base64 encoded
      this.getBase64 = function() {
  
          var s = this.getDump();
  
          // If the current browser supports the Base64 encoding
          // function, then offload the that to the browser as it
          // will be done in native code.
          if ((typeof window.btoa !== 'undefined') &amp;&amp; (window.btoa !== null)) {
              return window.btoa(s);
          }
  
          var ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
          var c1, c2, c3, e1, e2, e3, e4;
          var l = s.length;
          var i = 0;
          var r = "";
  
          do {
              c1 = s.charCodeAt(i);
              e1 = c1 &gt;&gt; 2;
              c2 = s.charCodeAt(i+1);
              e2 = ((c1 &amp; 3) &lt;&lt; 4) | (c2 &gt;&gt; 4);
              c3 = s.charCodeAt(i+2);
              if (l &lt; i+2) { e3 = 64; } else { e3 = ((c2 &amp; 0xf) &lt;&lt; 2) | (c3 &gt;&gt; 6); }
              if (l &lt; i+3) { e4 = 64; } else { e4 = c3 &amp; 0x3f; }
              r+= ch.charAt(e1) + ch.charAt(e2) + ch.charAt(e3) + ch.charAt(e4);
          } while ((i+= 3) &lt; l);
          return r;
      }
  </code></pre>
  
  <p>Thanks</p>