// ==UserScript==
// @name PPIL
// @description Pixel Place Image Loader
// @version 1.1
// @author 0vC4
// @namespace https://greasyfork.org/users/670183
// @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 PPIU = (() => {
if (window.PPIU) return window.PPIU;
const worker = function(func) {
const worker = new Worker(URL.createObjectURL(new Blob(["onmessage=async({data})=>self.postMessage(await(" + func.toString() + ")(data))"], { type: "text/javascript" })));
const root = {};
const post = data => (worker.postMessage(data), root);
const then = callback => (worker.onmessage=({data})=>callback(data), root);
return Object.assign(root, {post, then});
};
const PPIU = {};
PPIU.loadImage = (w, h) => callback => {
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 => {
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(async ({rgba, width, height}) => {
const zero = 0xCCCCCC;
const palette = new Uint32Array([
0xFFFFFF,
0xC4C4C4,
0x888888,
0x555555,
0x222222,
0x000000,
0x006600,
0x22B14C,
0x02BE01,
0x51E119,
0x94E044,
0xFBFF5B,
0xE5D900,
0xE6BE0C,
0xE59500,
0xA06A42,
0x99530D,
0x633C1F,
0x6B0000,
0x9F0000,
0xE50000,
0xFF3904,
0xBB4F00,
0xFF755F,
0xFFC49F,
0xFFDFCC,
0xFFA7D1,
0xCF6EE4,
0xEC08EC,
0x820080,
0x5100FF,
0x020763,
0x0000EA,
0x044BFF,
0x6583CF,
0x36BAFF,
0x0083C7,
0x00D3DD,
0x45FFC8
]);
const exclude = new Uint32Array([
0x51E119,
0xFF3904,
0x5100FF,
0x45FFC8
]);
const filtered = [...palette.map(p => exclude.includes(p) ? zero : p)].filter(p => p != zero).map(clr => [(clr>>16)&0xFF, (clr>>8)&0xFF, clr&0xFF]);
const toPixel = (r2, g2, b2) => palette.indexOf(
filtered
.map(([r, g, b]) => [
(r2 - r)^2 +
(g2 - g)^2 +
(b2 - b)^2,
(r<<16) + (g<<8) + b
])
.sort((a,b) => a[0]-b[0])[0][1]
);
const pixels = new Uint8Array(rgba.length>>2);
for (let i = 0; i < rgba.length; i += 4)
pixels[i>>2] = toPixel(rgba[i], rgba[i+1], rgba[i+2]);
return [pixels, width, height];
})
.then(callback)
.post({rgba,width,height});
};
};
dropArea.remove();
},false);
};
window.PPIU = PPIU;
return PPIU;
})();
// 0vC4#7152