Skip to content

Not waiting on images to load (maybe?) in node when using loadFromJSON (Error: Image given has not completed loading) #3889

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
RyanF13 opened this issue Apr 26, 2017 · 1 comment

Comments

@RyanF13
Copy link

RyanF13 commented Apr 26, 2017

UPDATE

There may be an issue with the image itself causing this issue, will update if I figure anything out. The SVG background isn't rendering on the canvas possibly creating other stemmed issues, however I do think a try/catch or more informative error in that function would help many people as it seems the error is returned for reasons unrelated to its message. Major props to the developers though, everything else works great and fabric is nothing short of amazing! Thanks kangax and anyone else involved! If I don't update this then I haven't found the true issue here so if someone comes across this issue and has time to check it out, it'd be appreciated (not sure if it's something my fault or not as everything works in the browser and is exported directly from the browser)

Versions

Node: v6.10.2
Canvas: [email protected]
Fabric: [email protected]

The error appears in all versions of node, canvas, and fabric that I've tested.

Steps to reproduce

  1. Load a image in nodejs with loadFromJSON
    Note: It appears to only do this on some images, the images affected are in the JSON below.
    Example JSON:
    {"objects":[{"type":"image","originX":"left","originY":"top","left":3,"top":27,"width":1920,"height":1080,"fill":"rgb(0,0,0)","stroke":null,"strokeWidth":0,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":0.24,"scaleY":0.24,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-atop","transformMatrix":null,"skewX":0,"skewY":0,"src":"https://f13works-platform.s3.amazonaws.com/custom_designs/REV2_753842258149324088819389411891493240887692461369.PNG","filters":[],"resizeFilters":[],"crossOrigin":"","alignX":"none","alignY":"none","meetOrSlice":"meet"}],"background":"","backgroundImage":{"type":"image","originX":"left","originY":"top","left":0,"top":0,"width":459,"height":328,"fill":"rgb(0,0,0)","stroke":null,"strokeWidth":0,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"src":"https://f13works-platform.s3.amazonaws.com/custom_designs/REV2_1421060042149248797934522256514924879791899021292.SVG","filters":[],"resizeFilters":[],"crossOrigin":"","alignX":"none","alignY":"none","meetOrSlice":"meet"}}

Expected Behavior

Image loads and is added to canvas.

Actual Behavior

The following error appears and kills the node server:

Error: Image given has not completed loading
at Error (native)
at klass._render (/node/node_modules/fabric/dist/fabric.js:18956:32)
at klass.drawObject (/node/node_modules/fabric/dist/fabric.js:12650:12)
at klass.render (/node/node_modules/fabric/dist/fabric.js:12632:14)
at klass._renderBackgroundOrOverlay (/node/node_modules/fabric/dist/fabric.js:6874:16)
at klass._renderBackground (/node/node_modules/fabric/dist/fabric.js:6884:12)
at klass.renderCanvas (/node/node_modules/fabric/dist/fabric.js:6819:12)
at klass.renderAll (/node/node_modules/fabric/dist/fabric.js:8747:12)
at cbIfLoaded (/node/node_modules/fabric/dist/fabric.js:11327:15)
at /node/node_modules/fabric/dist/fabric.js:11358:21

Temporary Solution

Edit /node_modules/fabric/dist @ 18956 (line number may differ between versions)

Original Code (_render function)

elementToDraw && ctx.drawImage(elementToDraw,
                                          x + imageMargins.marginX,
                                          y + imageMargins.marginY,
                                          imageMargins.width,
                                          imageMargins.height
                                         );

this._stroke(ctx);
this._renderStroke(ctx);

Replace with:

var try_rendering = function(){
        try{
          elementToDraw && ctx.drawImage(elementToDraw,
                                          x + imageMargins.marginX,
                                          y + imageMargins.marginY,
                                          imageMargins.width,
                                          imageMargins.height
                                         );
          
          this._stroke(ctx);
          this._renderStroke(ctx);
        }catch(e){
          setTimeout(function(){
            try_rendering();
          },100);
        }
      };
      try_rendering();

Node Server Code

Mainly the code for the example server with some slight modifications

var fabric = require('fabric').fabric,
    http = require('http'),
    url = require('url'),
    qs = require('querystring'),
    request = require('request')
    PORT = 8124;


var server = http.createServer(function(request, response){
	console.log('Client Connected to Port');
  var params = url.parse(request.url, true);

  // Make sure we're using POST.
  if(request.method == 'POST'){
        // Get the POST data.
        var body = '';
        request.on('data', function (data) {
            body += data;
        });
        request.on('end', function () {
            var post = qs.parse(body);

            // DEBUG
            console.log('JSON DATA:');
            console.log(post.json_data);

            // Load the canvas object.
            response.writeHead(200, { 'Content-Type': 'image/png' });
            var canvas = fabric.createCanvasForNode(500, 500);

            // Try / catch load (so server doesn't die)
            try{
              canvas.loadFromJSON(post.json_data, function(){
                  canvas.renderAll();
                  console.log(canvas._objects);
                  var stream = canvas.createPNGStream();
                  stream.on('data', function(chunk) {
                    response.write(chunk);
                    console.log(chunk);
                    console.log('writing chunk...');
                  });
                  stream.on('end', function(){
                    response.end();
                    console.log('response sent.');
                  });
              });
            }catch(e){
              console.log('Error exception caught.');
              console.log(e);
              response.end();
            }
        });
    }else{
      response.write('Please only use POST.');
      response.end();
    }
});

server.listen(PORT);

Related

Please note that the resolved links below were different issues, but I'm referencing them just in case anyone comes across this with a different issue (or someone has the same issue, they may wind up here)
Automattic/node-canvas#486
#765
#2057
Automattic/node-canvas#289
https://groups.google.com/forum/#!topic/fabricjs/LcbJ8YI4jiI
http://stackoverflow.com/questions/20660036/node-js-canvas-image-given-has-not-completed-loading
http://stackoverflow.com/questions/13859389/using-fabric-js-to-render-and-manipulate-server-side-canvas-in-node-js
#1894

@asturur
Copy link
Member

asturur commented Apr 30, 2017

Automattic/node-canvas#811

related to this. node canvas cannot load svg for now. not fabric bug.

@asturur asturur closed this as completed Apr 30, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants