pixely.cf tools

Allows you to draw images by uploading and then clicking. MAKE SURE YOUR IMAGES ARE LESS THAN 100x100px

当前为 2020-04-25 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name pixely.cf tools
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.2
  5. // @description Allows you to draw images by uploading and then clicking. MAKE SURE YOUR IMAGES ARE LESS THAN 100x100px
  6. // @author theusaf
  7. // @match http://pixely.cf/
  8. // @match http://qwertyquerty.cf/
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. var drawScale = 10;
  13. window.finalInfo = [];
  14. window.sketchint = 0;
  15. window.isPlacingImage = false;
  16. var di = document.createElement('div'); //div
  17. di.style.background = 'white';
  18. di.style.display = 'none';
  19. di.style.top = "0px";
  20. di.style.position = "fixed";
  21. var im = new Image(); //image
  22. im.crossOrigin = "Anonymous";
  23. var ca = document.createElement('canvas'); //canvas
  24. ca.style.display = 'none';
  25. var fi = document.createElement('input'); //file input
  26. fi.type = 'file';
  27. di.style.float = 'left';
  28. var ct = ca.getContext('2d'); //context
  29.  
  30. document.body.addEventListener('keydown',toggleFile);
  31.  
  32. function toggleFile(evt){
  33. if(evt.keyCode == 16){
  34. evt.preventDefault();
  35. di.style.display = di.style.display == "block" ? "none" : "block";
  36. }
  37. }
  38.  
  39. fi.onchange = function(e){
  40. if(!e){
  41. return;
  42. }
  43. var reader = new FileReader();
  44. reader.onload = function(e){
  45. im.src = e.target.result;
  46. }
  47. reader.readAsDataURL(e.target.files[0]);
  48. }
  49.  
  50. const int = document.createElement("input");
  51. int.type = "number";
  52. int.placeholder = "Max size";
  53. int.min = 1;
  54. int.max = 100;
  55. int.step = 1;
  56. int.value = 100;
  57.  
  58. im.onload = function(){
  59. const max = Math.round(Number(int.value));
  60. if(!max){
  61. max = 100;
  62. }
  63. console.log('loaded');
  64. if(im.src.length > 0){
  65. //change canvas width and height.
  66. ca.width = im.width;
  67. ca.height = im.height;
  68. if(im.width <= max && im.height <= max){
  69. ct.drawImage(im,0,0);
  70. }else{
  71. if(im.width > im.height){
  72. const scalar = im.height / im.width;
  73. ca.width = max;
  74. ca.height = Math.round(max * scalar);
  75. ct.drawImage(im,0,0,max,Math.round(max*scalar));
  76. }else{
  77. const scalar = im.width / im.height;
  78. ca.width = Math.round(max * scalar);
  79. ca.height = max;
  80. ct.drawImage(im,0,0,Math.round(max*scalar),max);
  81. }
  82. }
  83. let data = ct.getImageData(0,0,ca.width,ca.height).data;
  84. let bestColor = 0;
  85. let bestPercent = 0;
  86. finalInfo = [];
  87. let x = 0;
  88. let y = 0;
  89. let maxX = ca.width;
  90. console.log(data.length);
  91. for(let i = 0; i < data.length; i+=4){
  92. //loop through colors
  93. /*global colors*/
  94. if(x >= maxX){
  95. console.log("x has hit max: " + maxX);
  96. y++;
  97. x = 0;
  98. }
  99. for(let j in colors){
  100. if(hslcd([data[i],data[Number(i)+1],data[Number(i)+2]],htr(colors[j])) > bestPercent){
  101. bestPercent = hslcd([data[i],data[Number(i)+1],data[Number(i)+2]],htr(colors[j]));
  102. bestColor = j;
  103. }
  104. }
  105. //if alpha is less than 40, dont push.
  106. if(data[Number(i)+3] <= 40){
  107. x++;
  108. bestPercent = 0;
  109. bestColor = 0;
  110. continue;
  111. }
  112. //now that best color has been set, add to a thingy.
  113. finalInfo.push({
  114. x: x,
  115. y: y,
  116. c: Number(bestColor)
  117. });
  118. x++;
  119. bestPercent = 0;
  120. bestColor = 0;
  121. }
  122. isPlacingImage = true;
  123. sketchint = 0;
  124. drawScale = SCALE;
  125. console.log(finalInfo);
  126. }
  127. }
  128.  
  129. /*global canvas*/
  130. /*global getMousePos*/
  131. /*global isPlacingImage*/
  132. /*global finalInfo*/
  133. /*global si*/
  134. canvas.addEventListener('click',function(e){
  135. console.log('click!')
  136. let x = Math.floor(getMousePos(canvas,e).x);
  137. let y = Math.floor(getMousePos(canvas,e).y);
  138. if(isPlacingImage){
  139. console.log('placing image');
  140. isPlacingImage = false;
  141. di.style.display = "none";
  142. //start interval
  143. /*global io*/
  144. /*global SCALE*/
  145. var sketch = setInterval(function(){
  146. if(finalInfo.length == 0){
  147. clearInterval(sketch);
  148. return;
  149. }
  150. if(sketchint >= finalInfo.length){
  151. clearInterval(sketch);
  152. console.log("done");
  153. return;
  154. }
  155. if(finalInfo[sketchint].x + (x/drawScale) >= 640 || finalInfo[sketchint].y + (y/drawScale) >= 640){
  156. sketchint++;
  157. console.log('hit canvas limit');
  158. return;
  159. }
  160. console.log('drawing');
  161. //adding listener to skip over useless stuff..
  162. /*global pixels*/
  163. let ok = false;
  164. while(!ok){
  165. if(pixels[finalInfo[sketchint].y + Math.floor(y/drawScale)][finalInfo[sketchint].x + Math.floor(x/drawScale)] == finalInfo[sketchint].c){
  166. sketchint++;
  167. continue;
  168. }
  169. ok = true;
  170. }
  171. io.emit('set',{x:finalInfo[sketchint].x + Math.floor(x/drawScale),y:finalInfo[sketchint].y + Math.floor(y/drawScale),c:finalInfo[sketchint].c});
  172. sketchint++;
  173. },300);
  174. }
  175. });
  176.  
  177. // no longer using hcd to compare. (works like a computer, but not like a human)
  178. function hcd(hex1, hex2) {
  179. hex1 = hex1.split("#").length == 1 ? hex1 : hex1.split("#")[1];
  180. hex2 = hex2.split("#").length == 1 ? hex2 : hex2.split("#")[1];
  181. // get red/green/blue int values of hex1
  182. var r1 = parseInt(hex1.substring(0, 2), 16);
  183. var g1 = parseInt(hex1.substring(2, 4), 16);
  184. var b1 = parseInt(hex1.substring(4, 6), 16);
  185. // get red/green/blue int values of hex2
  186. var r2 = parseInt(hex2.substring(0, 2), 16);
  187. var g2 = parseInt(hex2.substring(2, 4), 16);
  188. var b2 = parseInt(hex2.substring(4, 6), 16);
  189. // calculate differences between reds, greens and blues
  190. var r = 255 - Math.abs(r1 - r2);
  191. var g = 255 - Math.abs(g1 - g2);
  192. var b = 255 - Math.abs(b1 - b2);
  193. // limit differences between 0 and 1
  194. r /= 255;
  195. g /= 255;
  196. b /= 255;
  197. // 0 means opposit colors, 1 means same colors
  198. return (r + g + b) / 3;
  199. } //compare hex values
  200.  
  201. function rth(r, g, b) {
  202. return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
  203. } //rbg to hex
  204.  
  205. function htr(hex) {
  206. var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  207. return result ? [
  208. parseInt(result[1], 16),
  209. parseInt(result[2], 16),
  210. parseInt(result[3], 16)
  211. ] : null;
  212. } // hex to rgb
  213.  
  214. function componentToHex(c) {
  215. var hex = c.toString(16);
  216. return hex.length == 1 ? "0" + hex : hex;
  217. }
  218.  
  219. // from stackoverflow lol
  220. // https://stackoverflow.com/questions/13586999/color-difference-similarity-between-two-values-with-js
  221. function deltaE(rgbA, rgbB) {
  222. let labA = rgb2lab(rgbA);
  223. let labB = rgb2lab(rgbB);
  224. let deltaL = labA[0] - labB[0];
  225. let deltaA = labA[1] - labB[1];
  226. let deltaB = labA[2] - labB[2];
  227. let c1 = Math.sqrt(labA[1] * labA[1] + labA[2] * labA[2]);
  228. let c2 = Math.sqrt(labB[1] * labB[1] + labB[2] * labB[2]);
  229. let deltaC = c1 - c2;
  230. let deltaH = deltaA * deltaA + deltaB * deltaB - deltaC * deltaC;
  231. deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH);
  232. let sc = 1.0 + 0.045 * c1;
  233. let sh = 1.0 + 0.015 * c1;
  234. let deltaLKlsl = deltaL / (1.0);
  235. let deltaCkcsc = deltaC / (sc);
  236. let deltaHkhsh = deltaH / (sh);
  237. let i = deltaLKlsl * deltaLKlsl + deltaCkcsc * deltaCkcsc + deltaHkhsh * deltaHkhsh;
  238. return 100 - (i < 0 ? 0 : Math.sqrt(i));
  239. }
  240.  
  241. function rgb2lab(rgb){
  242. let r = rgb[0] / 255, g = rgb[1] / 255, b = rgb[2] / 255, x, y, z;
  243. r = (r > 0.04045) ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
  244. g = (g > 0.04045) ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
  245. b = (b > 0.04045) ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
  246. x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047;
  247. y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.00000;
  248. z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883;
  249. x = (x > 0.008856) ? Math.pow(x, 1/3) : (7.787 * x) + 16/116;
  250. y = (y > 0.008856) ? Math.pow(y, 1/3) : (7.787 * y) + 16/116;
  251. z = (z > 0.008856) ? Math.pow(z, 1/3) : (7.787 * z) + 16/116;
  252. return [(116 * y) - 16, 500 * (x - y), 200 * (y - z)]
  253. }
  254.  
  255. // turns out the deltaE algorithm didn't help much. trying hsl.
  256. function rgbToHsl(r, g, b){
  257. r /= 255, g /= 255, b /= 255;
  258. var max = Math.max(r, g, b), min = Math.min(r, g, b);
  259. var h, s, l = (max + min) / 2;
  260.  
  261. if(max == min){
  262. h = s = 0; // achromatic
  263. }else{
  264. var d = max - min;
  265. s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
  266. switch(max){
  267. case r: h = (g - b) / d + (g < b ? 6 : 0); break;
  268. case g: h = (b - r) / d + 2; break;
  269. case b: h = (r - g) / d + 4; break;
  270. }
  271. h /= 6;
  272. }
  273.  
  274. return [h, s, l];
  275. }
  276.  
  277. function hslcd(rgb1,rgb2){
  278. const hsl1 = rgbToHsl(...rgb1);
  279. const hsl2 = rgbToHsl(...rgb2);
  280. const hpa = Math.abs(hsl1[0] - hsl2[0]) * 3.0;
  281. const hpb = Math.abs(hsl1[1] - hsl2[1]) * 0.9;
  282. const hpc = Math.abs(hsl1[2] - hsl2[2]) * 1.1;
  283. return 1 - ((hpa + hpb + hpc)/3);
  284. }
  285.  
  286. di.append(fi,int);
  287. di.append(ca);
  288. document.body.append(di);
  289.  
  290. //add slider for zoom
  291. let sli = document.createElement('input'); //slider input. changes scale.
  292. sli.type = 'range';
  293. sli.min = 1;
  294. sli.max = 20;
  295. sli.value = 10;
  296. sli.step = 1;
  297. let fdiv = document.getElementById('colorpicker'); //a div that has the colors
  298. fdiv.append(sli);
  299. /*global draw*/
  300. sli.oninput = function(){
  301. let DIMS = [pixels[0].length, pixels.length];
  302. SCALE = sli.value;
  303. canvas.width = SCALE * DIMS[0];
  304. canvas.height = SCALE * DIMS[1];
  305. draw(pixels);
  306. if(isPlacingImage){
  307. drawScale = SCALE;
  308. }
  309. }
  310.  
  311. //hide color picker and slider
  312. document.body.addEventListener('keydown',togglePicker);
  313.  
  314. function togglePicker(e){
  315. fdiv.style.display = e.keyCode == 16 ? fdiv.style.display == "none" ? "block" : "none" : fdiv.style.display;
  316. }