MyBot ImageLoader

MyBot Pixel Place Image Loader

สคริปต์นี้ไม่ควรถูกติดตั้งโดยตรง มันเป็นคลังสำหรับสคริปต์อื่น ๆ เพื่อบรรจุด้วยคำสั่งเมทา // @require https://update.greasyfork.org/scripts/479129/1275794/MyBot%20ImageLoader.js

// ==UserScript==
// @name         MyBot ImageLoader
// @description  MyBot Pixel Place Image Loader
// @version      1.6.2
// @author       SamaelWired
// @namespace    https://greasyfork.org/tr/users/976572
// @match        https://pixelplace.io/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=pixelplace.io
// @license      MIT
// @grant        none
// @run-at       document-start
// ==/UserScript==
(() => {
    const MyBot = window.MyBot || { modules: {} };
    window.MyBot = MyBot;
    if ('ImageLoader' in MyBot.modules) return;

    const progressManager = func => {
        const callbacks = {};
        const root = new Proxy({}, {
            get(target, key) {
                if (!target[key]) target[key] = callback => (callbacks[key] = callback, root);
                return target[key];
            }
        });
        root.start = (...args) => func(callbacks)(...args);
        return root;
    };

    const worker = progressManager(({ progress = () => 0, finish = () => 0 }) =>
        (data, func) => {
            const worker = new Worker(URL.createObjectURL(new Blob([`
            const progress = value => self.postMessage({ progress: true, value });
            const finish = value => self.postMessage({ finish: true, value });
            onmessage = async ({ data }) => {
                await (${func.toString()})(data);
                close();
            };
        `], { type: "text/javascript" })));
            worker.addEventListener('message', ({ data }) => data.progress && progress(data.value));
            worker.addEventListener('message', ({ data }) => data.finish && finish(data.value));
            worker.postMessage(data);
        });

    const module = {};
    module.args = {};
    module.config = ({ colors, exclude, zero }) =>
        Object.assign(module.args, { colors, exclude, zero });

    module.imageToPixels = progressManager(({ progress = () => 0, finish = () => 0, silent = true }) =>
        (img, w, h) => {
            let { width, height } = img;
            if (w != null) width = w;
            if (h != null) height = h;

            const canvas = document.createElement('canvas');
            canvas.width = width;
            canvas.height = height;
            const ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0, width, height);
            const rgba = ctx.getImageData(0, 0, width, height).data;

            worker.progress(progress).finish(finish).start(
                { rgba, width, height, silent, ...module.args },
                async ({ rgba, width, height, silent, colors, exclude, zero }) => {
                    const palette = [...colors.map(p => exclude.includes(p) ? zero : p)]
                        .filter(p => p != zero)
                        .map(clr => [(clr >> 16) & 0xFF, (clr >> 8) & 0xFF, clr & 0xFF]);

                    const toPixel = (r, g, b) => colors.indexOf(
                        palette
                            .map(([r2, g2, b2]) => ((r2 - r) ** 2 + (g2 - g) ** 2 + (b2 - b) ** 2) * 0x1000000 + (r2 << 16) + (g2 << 8) + b2)
                            .sort((a, b) => a - b)[0] & 0xFFFFFF
                    );

                    const pixels = new Uint8Array(rgba.length >> 2);
                    for (let i = 0; i < rgba.length; i += 4) {
                        silent || progress(i / rgba.length);
                        pixels[i >> 2] = rgba[i + 3] >= 0xAA ? toPixel(rgba[i], rgba[i + 1], rgba[i + 2]) : -1;
                    }

                    finish([pixels, width, height]);
                });
        });

    module.loadImage = progressManager(({ progress = () => 0, finish = () => 0, silent = true }) =>
        (w, h) => {
            const dropArea = document.createElement('div');
            top.document.body.appendChild(dropArea);
            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;";
            dropArea.textContent = "Drop Image";
            dropArea.onclick = e => dropArea.remove();

            ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eName =>
                dropArea.addEventListener(eName, e => {
                    e.preventDefault();
                    e.stopPropagation();
                }, false)
            );

            dropArea.addEventListener('drop', e => {
                const reader = new FileReader();
                reader.readAsDataURL(e.dataTransfer.files[0]);
                reader.onload = e => {
                    const img = new Image;
                    img.src = reader.result;
                    img.onload = e => module.imageToPixels.silent(silent).progress(progress).finish(finish).start(img, w, h);
                };
                dropArea.remove();
            }, false);
        });

    MyBot.modules.ImageLoader = module;
})();