zendriver-stealth 0.4.1

Anti-detection patches and profiles for zendriver
Documentation
(function (seed) {
  const rng = __zdRng(seed);
  function farble(data) {
    for (let i = 0; i < data.length; i += 4) {
      // +/-1 LSB perturbation on RGB, deterministic per seed.
      data[i]     = Math.max(0, Math.min(255, data[i]     + (rng() < 0.5 ? -1 : 1)));
      data[i + 1] = Math.max(0, Math.min(255, data[i + 1] + (rng() < 0.5 ? -1 : 1)));
      data[i + 2] = Math.max(0, Math.min(255, data[i + 2] + (rng() < 0.5 ? -1 : 1)));
    }
    return data;
  }
  const origGetImageData = CanvasRenderingContext2D.prototype.getImageData;
  __zdReplace(CanvasRenderingContext2D.prototype, 'getImageData', (orig) => function (...args) {
    const img = orig.apply(this, args);
    farble(img.data);
    return img;
  });
  __zdReplace(HTMLCanvasElement.prototype, 'toDataURL', (orig) => function (...args) {
    const ctx = this.getContext('2d');
    if (ctx && this.width > 0 && this.height > 0) {
      const imgData = origGetImageData.call(ctx, 0, 0, this.width, this.height);
      const copy = new ImageData(new Uint8ClampedArray(imgData.data), this.width, this.height);
      farble(copy.data);
      ctx.putImageData(copy, 0, 0);
      const url = orig.apply(this, args);
      ctx.putImageData(imgData, 0, 0);
      return url;
    }
    return orig.apply(this, args);
  });
})(SEED);