docs: function _bfs(canvas, queue, eventMap, blacklist) {
      var ctx = canvas.getContext('2d'),
          imgSize = {
              w: canvas.width,
              h: canvas.height
          },
          imgCols = ctx.getImageData(0, 0, imgSize.w, imgSize.h).data,
          visited = {},
          stopMainLoop = false,
          skipNeighbords = false;
  
      if (blacklist !== undefined) {
          blacklist.forEach(function(coord) {
              visited[coord.x + '-' + coord.y] = true;
          });
      }
  
      function visitPx(coord) {
          visited[coord.x + '-' + coord.y] = true;
          if (eventMap !== undefined && eventMap.onvisit !== undefined) {
              eventMap.onvisit({
                  pixel: {
                      coord: coord,
                      color: _getColorByXY(coord, imgSize, imgCols)
                  },
                  stop: function() { stopMainLoop = true; },
                  skip: function() { skipNeighbords = true; }
              });
          }
      }
  
      visitPx(queue[0]);
  
  mainLoop:
      while (queue.length > 0) {
          if (stopMainLoop) { break mainLoop; }
  
          var coord = queue.shift(),
              colPos = _getColorPositionByXY(coord, imgSize),
              col = [imgCols[colPos], imgCols[colPos+1], imgCols[colPos+2], imgCols[colPos+3]],
              px = { coord: coord, color: col },
              nPxs = _getNeighborPixels(coord, imgSize, imgCols);
  
          for (var i = 0; i < nPxs.length; i++) {
              var nPx = nPxs[i];
              if (visited[nPx.coord.x + '-' + nPx.coord.y] !== true) {
                  visitPx(nPx.coord);
                  if (stopMainLoop) { break mainLoop; }
                  if (!skipNeighbords) {
                      queue.push(nPx.coord);
                  }
                  skipNeighbords = false;
              }
          }
      }
  }