7

I have a canvas with webGL-drawings, created by Blend4Web framework.

I tried to save image using toDataURL():

image= $('canvas')[0].toDataURL();

All platforms works perfect, except iOS (iphone & ipad)

I know about webGL aspects: Canvas toDataURL() returns blank image only in Firefox, preserveDrawingBuffer is enabled.

Also, I know about limitations in iOS: iOS HTML5 Canvas toDataURL, but canvas is small, even 100×500px images are blank (it is 0,05MP, limit is 3MP).

I use toDataURL() to send graphic information on server.

Crantisz
  • 227
  • 3
  • 13
  • Not fixing your issue but using `toBlob` would be (one third) more efficient in terms of required memory and bandwidth etc. – LJᛃ Oct 30 '17 at 11:00
  • Can you include logic of saving image? – Observer Nov 02 '17 at 15:59
  • 1
    Instead of using `preserveDrawingBuffer` that iOS may ignore, did you tried the more efficient way of checking inside your rendering loop if a call to export has been made and do this call from there before the thread ends? – Kaiido Nov 05 '17 at 02:26

2 Answers2

2

The following is a polyfill of toDataURL. In order to get toBlob to work on iOS, you need an additional polyfill, I recommend the following polyfill: https://github.com/blueimp/JavaScript-Canvas-to-Blob. Basically just download the canvas-to-blob.min.js. I would have recommended a direct toDataURL polyfill by someone else, but I could not find one.

if (typeof HTMLCanvasElement.prototype.toDataURL !== "function") {
  HTMLCanvasElement.prototype.toDataURL = function() {
    this.toBlob(function (blob) {
      var fileReader = new FileReaderSync();
      return fileReader.readAsDataURL(blob);
    });
  };
}
Greenbeard
  • 508
  • 5
  • 14
  • I know, older post, but work this also with a videojs. I need a function to create videojs screenshots from livestream. – TheAlphaGhost Jan 26 '23 at 16:51
0

1) Try get image after some tiomeout

window.setTimeout(function(){var result = $('canvas')[0].toDataURL();
},100);

2)Before get image url, you can check canvas for transparent pixels

var canvas = $('canvas')[0];
var ctx = canvas .getContext("2d")
var data = ctx.getImageData(0,0,canvas .width,canvas .height);
console.dir(data);//empty pixel it is each [0,0,0,0] array (rgba(0,0,0,0))

3) Try to write your canvas on other canvas

var canvas = $('canvas')[0];
var tmpCanvas = document.createElement("canvas");
tmpCanvas.width = canvas.width;
tmpCanvas.height = canvas.height;
tmpCanvas.getContext("2d").drawImage(canvas,0,0,tmpCanvas.width,tmpCanvas.height,0,0,tmpCanvas.width,tmpCanvas.height);
var result = tmpCanvas.toDataURL(); 

4) Try to send blobs to server instead of base64, it is more memory friendly: https://stackoverflow.com/a/34924715/5138198

5) or maybe better just read this post: https://stackoverflow.com/a/45223017/5138198

Alex Nikulin
  • 8,194
  • 4
  • 35
  • 37
  • @ Kaiido yes it is, but you still can take 2d render from it. According to the question, @Crantisz tries to take 2d render from webgl canvas. You use the same canvas but different contexts. – Alex Nikulin Nov 08 '17 at 05:20
  • @Kaiido i am not tried, but i am read https://stackoverflow.com/a/45223017/5138198 )) I don't know anything about webgl context, but I am very experienced at 2d canvas (image processing, resizing, parsing by js of different image formats jpg, tiff, heif etc..) – Alex Nikulin Nov 08 '17 at 05:34