OK, as the error pointed out, you needed to provide an img for the drawImage function.
So, in order to do that I've created a dynamic image, created an onload handler and then passed the loaded img to your routine. I don't know if the result is "correct", but the code now works.
function getAverageRGB(imgEl) {
var blockSize = 5, // only visit every 5 pixels
defaultRGB = {
r: 0,
g: 0,
b: 0
}, // for non-supporting envs
canvas = document.createElement('canvas'),
context = canvas.getContext && canvas.getContext('2d'),
data, width, height,
i = -4,
length,
rgb = {
r: 0,
g: 0,
b: 0
},
count = 0;
if (!context) {
return defaultRGB;
}
height = canvas.height = imgEl.naturalHeight || imgEl.offsetHeight || imgEl.height;
width = canvas.width = imgEl.naturalWidth || imgEl.offsetWidth || imgEl.width;
context.drawImage(imgEl, 0, 0);
try {
data = context.getImageData(0, 0, width, height);
} catch (e) {
/* security error, img on diff domain */
alert('x');
return defaultRGB;
}
length = data.data.length;
while ((i += blockSize * 4) < length) {
++count;
rgb.r += data.data[i];
rgb.g += data.data[i + 1];
rgb.b += data.data[i + 2];
}
// ~~ used to floor values
rgb.r = ~~(rgb.r / count);
rgb.g = ~~(rgb.g / count);
rgb.b = ~~(rgb.b / count);
return rgb;
}
(async function() {
let blob = await fetch("https://images.unsplash.com/photo-1537017469405-7faf1912af7c?ixid=MnwzMDUwMHwwfDF8cmFuZG9tfHx8fHx8fHx8MTY1Mzk5ODA1OQ&ixlib=rb-1.2.1").then(r => r.blob());
let dataUrl = await new Promise(resolve =>
{
let reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.readAsDataURL(blob);
});
// In order to use the data url, we need to create an img and wait for it to load
let img = document.createElement('img');
document.body.appendChild(img);
img.onload = function(e) {
var rgb = getAverageRGB(img);
let rgbText = 'rgb(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ')';
document.body.style.backgroundColor = rgbText;
document.querySelector("#rgb").innerText = rgbText;
}
img.src = dataUrl;
})();
#text, #rgb {
color: white;
}
img {
width: 600px;
}
<div id="text">Setting the BODY's background to the average color in the following image:</div>
<div id="rgb"></div>