MyBot ImageLoader

MyBot Pixel Place Image Loader

Dette script bør ikke installeres direkte. Det er et bibliotek, som andre scripts kan inkludere med metadirektivet // @require https://update.greasyfork.org/scripts/479129/1275794/MyBot%20ImageLoader.js

  1. // ==UserScript==
  2. // @name MyBot ImageLoader
  3. // @description MyBot Pixel Place Image Loader
  4. // @version 1.6.2
  5. // @author SamaelWired
  6. // @namespace https://greasyfork.org/tr/users/976572
  7. // @match https://pixelplace.io/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=pixelplace.io
  9. // @license MIT
  10. // @grant none
  11. // @run-at document-start
  12. // ==/UserScript==
  13. (() => {
  14. const MyBot = window.MyBot || { modules: {} };
  15. window.MyBot = MyBot;
  16. if ('ImageLoader' in MyBot.modules) return;
  17.  
  18. const progressManager = func => {
  19. const callbacks = {};
  20. const root = new Proxy({}, {
  21. get(target, key) {
  22. if (!target[key]) target[key] = callback => (callbacks[key] = callback, root);
  23. return target[key];
  24. }
  25. });
  26. root.start = (...args) => func(callbacks)(...args);
  27. return root;
  28. };
  29.  
  30. const worker = progressManager(({ progress = () => 0, finish = () => 0 }) =>
  31. (data, func) => {
  32. const worker = new Worker(URL.createObjectURL(new Blob([`
  33. const progress = value => self.postMessage({ progress: true, value });
  34. const finish = value => self.postMessage({ finish: true, value });
  35. onmessage = async ({ data }) => {
  36. await (${func.toString()})(data);
  37. close();
  38. };
  39. `], { type: "text/javascript" })));
  40. worker.addEventListener('message', ({ data }) => data.progress && progress(data.value));
  41. worker.addEventListener('message', ({ data }) => data.finish && finish(data.value));
  42. worker.postMessage(data);
  43. });
  44.  
  45. const module = {};
  46. module.args = {};
  47. module.config = ({ colors, exclude, zero }) =>
  48. Object.assign(module.args, { colors, exclude, zero });
  49.  
  50. module.imageToPixels = progressManager(({ progress = () => 0, finish = () => 0, silent = true }) =>
  51. (img, w, h) => {
  52. let { width, height } = img;
  53. if (w != null) width = w;
  54. if (h != null) height = h;
  55.  
  56. const canvas = document.createElement('canvas');
  57. canvas.width = width;
  58. canvas.height = height;
  59. const ctx = canvas.getContext('2d');
  60. ctx.drawImage(img, 0, 0, width, height);
  61. const rgba = ctx.getImageData(0, 0, width, height).data;
  62.  
  63. worker.progress(progress).finish(finish).start(
  64. { rgba, width, height, silent, ...module.args },
  65. async ({ rgba, width, height, silent, colors, exclude, zero }) => {
  66. const palette = [...colors.map(p => exclude.includes(p) ? zero : p)]
  67. .filter(p => p != zero)
  68. .map(clr => [(clr >> 16) & 0xFF, (clr >> 8) & 0xFF, clr & 0xFF]);
  69.  
  70. const toPixel = (r, g, b) => colors.indexOf(
  71. palette
  72. .map(([r2, g2, b2]) => ((r2 - r) ** 2 + (g2 - g) ** 2 + (b2 - b) ** 2) * 0x1000000 + (r2 << 16) + (g2 << 8) + b2)
  73. .sort((a, b) => a - b)[0] & 0xFFFFFF
  74. );
  75.  
  76. const pixels = new Uint8Array(rgba.length >> 2);
  77. for (let i = 0; i < rgba.length; i += 4) {
  78. silent || progress(i / rgba.length);
  79. pixels[i >> 2] = rgba[i + 3] >= 0xAA ? toPixel(rgba[i], rgba[i + 1], rgba[i + 2]) : -1;
  80. }
  81.  
  82. finish([pixels, width, height]);
  83. });
  84. });
  85.  
  86. module.loadImage = progressManager(({ progress = () => 0, finish = () => 0, silent = true }) =>
  87. (w, h) => {
  88. const dropArea = document.createElement('div');
  89. top.document.body.appendChild(dropArea);
  90. dropArea.style = "width: calc(100% - 2em);height: calc(100% - 2em);position: fixed;left: 0px;top: 0px;background-color: rgba(0, 0, 0, 0.533);z-index: 9999;display: flex;color: white;font-size: 48pt;justify-content: center;align-items: center;border: 3px white dashed;border-radius: 18px;margin: 1em;";
  91. dropArea.textContent = "Drop Image";
  92. dropArea.onclick = e => dropArea.remove();
  93.  
  94. ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eName =>
  95. dropArea.addEventListener(eName, e => {
  96. e.preventDefault();
  97. e.stopPropagation();
  98. }, false)
  99. );
  100.  
  101. dropArea.addEventListener('drop', e => {
  102. const reader = new FileReader();
  103. reader.readAsDataURL(e.dataTransfer.files[0]);
  104. reader.onload = e => {
  105. const img = new Image;
  106. img.src = reader.result;
  107. img.onload = e => module.imageToPixels.silent(silent).progress(progress).finish(finish).start(img, w, h);
  108. };
  109. dropArea.remove();
  110. }, false);
  111. });
  112.  
  113. MyBot.modules.ImageLoader = module;
  114. })();