base64 resize image

HTML

<div>
  Old Image:
  <img id='old'...

JavaScript

// maxDeviation is the difference that is allowed default: 50kb 
// Example: targetFileSizeKb = 500 then result will be between 450kb and 500kb 
// increase the deviation to reduce the amount of iterations.
async function resizeImage(dataUrl, targetFileSizeKb,maxDeviation = 1)
  {
    let originalFile = await urltoFile(dataUrl,'test.png','image/png');
    if(originalFile.size / 1000 < targetFileSizeKb)
      return dataUrl; // File is already smaller

    let low = 0.0;
    let middle = 0.5;
    let high = 1.0;
    
    let result = dataUrl;

    let file = originalFile;

    while(Math.abs(file.size / 1000 - targetFileSizeKb) > maxDeviation)
    {
      const canvas = document.createElement("canvas");
      const context = canvas.getContext("2d");
      const img = document.createElement('img');

      const promise = new Promise((resolve, reject) =>
      {
        img.onload = () => resolve();
        img.onerror = reject;
      });

      img.src = dataUrl;

      await promise;

      canvas.width = Math.round(img.width * middle);
      canvas.height = Math.round(img.height * middle);
      context.scale(canvas.width / img.width, canvas.height / img.height);
      context.drawImage(img, 0, 0);
      file = await urltoFile(canvas.toDataURL(),'test.png','image/png');

      if(file.size/1000 < (targetFileSizeKb - maxDeviation))
      {
          low = middle;
      }
      else if(file.size/1000 > targetFileSizeKb)
      {
          high = middle;
      }

      middle = (low+high)/2;
      result = canvas.toDataURL();
    }
    
    return result;
  }

  function urltoFile(url, filename, mimeType){
    return (fetch(url)
            .then(function(res){return res.arrayBuffer();})
            .then(function(buf){return new File([buf], filename,{type:mimeType});})
    );
  }
//example usage:
resizeImage(document.getElementById('old').src,10,1).then((res)=>{
	document.getElementById('new').src = res;
});