LoadPixels() on SVG with P5.js

Hello, I’m working with [OMSD](https://opensheetmusicdisplay.github.io/) and the music score is rendered on a div element.
How Can I get the image’s pixels. I only need this for counting the black ones.

Some example code

In the index.html head you need to add
<script src="https://cdn.jsdelivr.net/npm/opensheetmusicdisplay@1.3.1/build/opensheetmusicdisplay.min.js"></script>

And this on the body

<div id="osmdCanvas" style="width: 100%"/>
<canvas id="canvas" width="800" height="400"></canvas>
<div id="png-container"></div>

And in the sketch.js is

let blacks, canv;

function setup() {
  canv = createCanvas(100, 100);
  var url = "helloworld.xml";
  var osmd = new opensheetmusicdisplay.OpenSheetMusicDisplay("osmdCanvas");
  osmd
    .load(url)
    .then((value) => {
      //console.log(value);
      //console.log(value);
      osmd.setOptions({
        drawTitle: false,
        drawSubtitle: false,
        drawCredits: false,
        drawComposer: false,
        drawMeasureNumbers: false,
        autoBeam: false,
        autoResize: false,
        drawHiddenNotes: false,
        drawFromMeasureNumber: 1,
        drawUpToMeasureNumber: 1,
        drawPartNames: false,
      });
      osmd.zoom = 0.75;
      osmd.render();
      //print('hola');
      setTimeout(convert(), 1000);
    })
    .catch((err) => {
      console.error(err);
    });
}

function draw() {
  //background(50);
  noLoop();
}

function convert() {
  let x,y;
  
  var svgString = document.getElementById("osmdSvgPage1"); //osmdCanvas
  //print(svgString);
  
  x = svgString.getBBox().width;
  y = svgString.getBBox().height;

  //var canvas = document.getElementById("canvas");
  var ctx = canv.elt.getContext("2d");
  //ctx = canvas.drawingContext; // option 2
  
  
var DOMURL = self.URL || self.webkitURL || self;
var img = new Image();
var svg = new Blob([svgString], {type: "image/svg+xml;charset=utf-8"});
  
var url = DOMURL.createObjectURL(svg);
img.onload = function() {
    ctx.drawImage(img, 0, 0);
    var png = canvas.toDataURL("image/png");
    document.querySelector('#png-container').innerHTML = '<img src="'+png+'"/>';
    DOMURL.revokeObjectURL(png);
};
img.src = url;
  
  loadPixels();
  //document.getElementById('osmdCanvas').style.display = 'none';
  setTimeout(raster(x,y),1000);
  
}

function raster(x,y) {
  let count,
    blackPixels = 0;
  count = ceil(x) * ceil(y) * 4;
  //MEASURES
  for (var a = 0; a < count; a += 4) {
    //print(count)
    if (pixels[a + 3] != 0) {
      blackPixels++;
    }
  }
  //print(count, blackPixels, abs(blackPixels - count));
  blacks = blackPixels / count;
  print(blacks);
}

Lastly, the helloworld.xml has

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE score-partwise PUBLIC
    "-//Recordare//DTD MusicXML 4.0 Partwise//EN"
    "http://www.musicxml.org/dtds/partwise.dtd">
<score-partwise version="4.0">
  <part-list>
    <score-part id="P1">
      <part-name>Music</part-name>
    </score-part>
  </part-list>
  <part id="P1">
    <measure number="1">
      <attributes>
        <divisions>1</divisions>
        <key>
          <fifths>0</fifths>
        </key>
        <time>
          <beats>4</beats>
          <beat-type>4</beat-type>
        </time>
        <clef>
          <sign>G</sign>
          <line>2</line>
        </clef>
      </attributes>
      <note>
        <pitch>
          <step>C</step>
          <octave>4</octave>
        </pitch>
        <duration>4</duration>
        <type>whole</type>
      </note>
    </measure>
  </part>
</score-partwise>

But it does not work

Well, that was a debugging adventure:

Your usage of setTimeout has issues: setTimeout(someFunc(), 1000) is incorrect unless someFunc() returns the function that you want to invoke in one second. If you want to run someFunc you need to use one of the following:

// No parens uses someFunc as a function pointer
setTimeout(someFunc, 1000);

// Arrow function expression creates an anonymous function
// (useful if someFunc uses "this" or if it takes some arguments
// you want to set)
setTimeout(() => someFunc(), 1000);

The <svg> element that was generated did not have an xmlns which made the Image object fail to load.

Using getContext("2d"), and drawImage was all unnecessary complexity.

You were not accounting for pixelDensity.

Here’s a simplified working version.

@KumuPaul incredible. Sorry for the mess, and thank you for the response, works great. I will get into setTimeout() and promises, these are very useful for sequencing music.

Best