Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name Web Terminal
- // @namespace http://thepotato.net/
- // @version 1.2
- // @description Fallout aesthetic
- // @author Steve5451
- // @include *
- // @downloadURL http://pastebin.com/raw/U0rpZQLb
- // @updateURL http://pastebin.com/raw/U0rpZQLb
- // @run-at document-start
- // @grant GM_xmlhttpRequest
- // @connect *
- // ==/UserScript==
- var color = rgb(0,255,0);
- // rgb color. (red, green, blue) from 0-255. red = (255,0,0), eye rape pink = (255,0,255), white = (255,255,255)
- // Too confusing? http://www.w3schools.com/colors/colors_picker.asp
- // pick a color and copy the numbers
- // ---------------------------------------------------------------------------------------------------------------- //
- // Although this is super niche and no one is going to use it for more than five minutes I will comment every line
- // So that a seperate stylesheet isn't required I'm just going to poll the page as soon as it begins loading until the body is created. That's when it'll be placed at the bottom of the <head>
- // This is undesirable but not terrible. I'm doing this so the page doesn't go from normal to *~POP GREEN~* when the page has finished loading.
- var checkInterval = setInterval(function() { // Create an interval
- if(document.body) { // If the body exists that means the head is done.
- var terminalStyle = document.createElement("style"); // Create our style element
- terminalStyle.innerHTML = styleSheet; // Set style
- document.head.appendChild(terminalStyle); // Place style in head
- document.body.appendChild(effectCanvas); // Place our canvas
- clearInterval(checkInterval); // We don't need this interval anymore. Get rid of it.
- }
- }, 1); // 1ms?? why not use while(true) steve???? because the 1ms gives our page time to process stuff.
- // Style has been placed. On to the important bits...
- var canvas = document.createElement("canvas"),
- ctx = canvas.getContext("2d"),
- effectCanvas = document.createElement("canvas"), // Create a canvas. This will be used for the scrolling line effects.
- effect = effectCanvas.getContext("2d"),
- lineOffset = 0, // offset of the line things
- images; // This will contain our pages images
- effectCanvas.width = window.innerWidth; // Set its size to match the browser
- effectCanvas.height = window.innerHeight;
- effectCanvas.style.position = "fixed"; // fix it to the top
- effectCanvas.style.left = "0px";
- effectCanvas.style.top = "0px";
- effectCanvas.style.zIndex = "100"; // Make sure it's the topmost layer
- effectCanvas.setAttribute("id","effectCanvas");
- window.onresize = function() { // When we resize the window we want the canvas to resize too.
- effectCanvas.width = window.innerWidth;
- effectCanvas.height = window.innerHeight;
- };
- window.addEventListener("load", function() {
- images = document.getElementsByTagName("img"); // Get every image on the page
- for(var i = 0; i < images.length; i++) { // For every image...
- GM_xmlhttpRequest({
- ///////////// So this is a hack. The cross origin policy doesn't allow me to modify images from another site (eg. imgur) so this is what I've done:
- // (?) GM_xmlhttpRequest is a userscript method that functions the same way as an xmlHttpRequest(), however it ignores the cross-origin policy.
- // Get image url
- // Open a new request in plain text
- // Place every byte into a unit8array
- // Create a blob from the data array
- // Use a file reader to create a base64 string from the data
- // Create a new image and set the image source to the base64 string
- // We now have an image loaded from another origin. (all that to load an image????)
- method: "GET",
- url: images[i].src + "#imgnum" + i,
- overrideMimeType: "text/plain; charset=x-user-defined", // couldn't figure out a way to load the image without plaintext -> base64
- onload: function(response) { // once loaded...
- var img = images[parseInt(response.finalUrl.split("#imgnum")[1])];
- var data = new Uint8Array(response.responseText.length); // Creat the unit8array
- for(var a = 0; a < response.responseText.length; a++) { // For each byte in the loaded image
- data[a] = response.responseText.charCodeAt(a); // Place in the unit8array
- }
- var contentType = img.src.split("."); // We'll just get the content type (aka imag extension) from the beginning of the image
- contentType = "image/" + contentType[contentType.length - 1].replace("jpg","jpeg"); // jpg = jpeg
- var blob = new Blob([data], {type: contentType}); // Create a blob
- var fr = new FileReader(); // Create a file reader
- fr.orig = img; // to read: our image data
- fr.onload = function() { // Once loaded...
- var newImage = new Image(); // Create an image
- newImage.orig = fr.orig; // doing this to pass along data
- newImage.src = fr.result; // Set the source to a base64 of the requested image
- newImage.onload = function() { // Once it has finished loading
- canvas.width = newImage.naturalWidth; // set canvas to size of image
- canvas.height = newImage.naturalHeight;
- ctx.drawImage(newImage,0,0,canvas.width,canvas.height); // This is where things actually happen. Draw image to the canvas
- processImage(canvas, ctx); // Let's start modifying the image. goto: processImage()
- newImage.orig.src = canvas.toDataURL();
- newImage.orig.style.visibility = "visible";
- };
- };
- fr.readAsDataURL(blob);
- }
- });
- }
- });
- // Constants for the Loyd–Steinberg dithering that will be applied to the images. I don't really understand entirely how it works but I managed to impliment it.
- var lumR = [];
- var lumG = [];
- var lumB = [];
- for (var i = 0; i < 256; i++) {
- lumR[i] = i * 0.299;
- lumG[i] = i * 0.587;
- lumB[i] = i * 0.114;
- }
- function processImage(canvas, ctx) { // This is the method where our images are actually colored and stuff. (I really wish I could use workers as to not tax the main thread and have a laggy loading experience but with userscripts the browser won't allow that as a violation of the dreaded cross-origin policy)
- var imgData = ctx.getImageData(0,0,canvas.width,canvas.height); // Get image data of the canvas which really just gets the individual pixel colors of the image
- for(var i = 0; i < imgData.data.length; i += 4) { // Loop through the pixels (that's a lot of for loops. I must be crazy.
- var avg = (imgData.data[i] + imgData.data[i + 1] + imgData.data[i + 2]) / 3; // Get the average color of the pixel
- imgData.data[i] = Math.floor(lumR[imgData.data[i]] + lumG[imgData.data[i+1]] + lumB[imgData.data[i+2]]); // Make image 16 bit. This helps a lot with preventing an extremely grainy image.
- // Loyd-Steinberg dithering
- var newPixel = imgData.data[i] < 129 ? 0 : 255; // If the pixel is less than half then make it black, otherwise fully colored.
- var err = Math.floor((imgData.data[i] - newPixel) / 16);
- imgData.data[i] = newPixel;
- imgData.data[i + 4 ] += err * 7;
- imgData.data[i + 4 * canvas.width - 4] += err * 3;
- imgData.data[i + 4 * canvas.width] += err * 5;
- imgData.data[i + 4 * canvas.width + 4] += err * 1;
- imgData.data[i + 1] = imgData.data[i + 2] = imgData.data[i]; // Make the image greyscale again
- imgData.data[i] *= (color.red / 255); // Set red
- imgData.data[i + 1] *= (color.green / 255); // Set green
- imgData.data[i + 2] *= (color.blue / 255); // Set blue
- }
- ctx.putImageData(imgData, 0, 0); // Place the modified pixel data back on our canvas. It is now 2bit green.
- }
- function update() { // This is for the animation of the lines running down the screen
- requestAnimationFrame(update); // We want a frame after this, duh. Request it.
- effect.clearRect(0,0,window.innerWidth,window.innerHeight); // Clear our previous lines
- effect.fillStyle = "rgb(" + color.red + "," + color.green + "," + color.blue + ")"; // I'd set these globally but I was having some strange issues. No matter, two lines won't hurt our 60fps of lines running down our screen.
- effect.globalAlpha = 0.07;
- for(var i = lineOffset - 50; i < window.innerHeight + 100; i += 100) { // Space the lines 100px away from eachother
- effect.fillRect(0, i, window.innerWidth, 30); // fill it, 30 pixels thick/
- }
- lineOffset += 1; // set the offset + 1 pixel so they run down the screen on the next frame
- if(lineOffset >= 100) { // If it's below the screen send it back to the top
- lineOffset = 0;
- }
- }
- update(); // Now let's begin the animation
- function rgb(r, g, b) {
- return {red: r, green: g, blue: b};
- }
- // This is our stylesheet. I put it at the bottom for readability purposes.
- var styleSheet = `
- @import 'https://fonts.googleapis.com/css?family=VT323';
- *:not(#effectCanvas) {
- background-color: #000 !important;
- background-image: none !important;
- border-color: rgb(${color.red}, ${color.green}, ${color.blue}) !important;
- color: rgb(${color.red}, ${color.green}, ${color.blue}) !important;
- font-family: 'VT323', monospace !important;
- font-size: 16pt;
- }
- #effectCanvas {
- pointer-events: none;
- }
- a, a:link, a:visited {
- color: rgb(${color.red}, ${color.green}, ${color.blue}) !important;
- text-decoration: underline !important;
- }
- ::-webkit-scrollbar {
- display: none;
- }
- .bordercolor {
- background-color: rgb(${color.red}, ${color.green}, ${color.blue}) !important;
- border: 1px solid rgb(${color.red}, ${color.green}, ${color.blue});
- }
- #effectCanvas {
- background-image:url(http://i.imgur.com/NwGZfUP.png) !important;
- background-size: 100% 100% !important;
- }
- input[type='radio'] {
- -webkit-appearance: none;
- border: 1px solid rgb(${color.red}, ${color.green}, ${color.blue});
- padding: 5px;
- }
- input[type='radio']:checked {
- background-color: rgb(${color.red}, ${color.green}, ${color.blue}) !important;
- }
- *, *:hover {
- //cursor: url(https://i.imgur.com/jHZgg47.png), default !important;
- outline: none !important;
- }
- .quote {
- font-size: 15pt;
- padding: 2px;
- margin-top: 10px;
- }
- .smalltext {
- font-size: 10pt;
- }
- img {
- visibility: hidden;
- }
- ::selection {
- color: #000;
- background-color: rgb(${color.red}, ${color.green}, ${color.blue});
- }
- ::-moz-selection {
- color: #000;
- background-color: rgb(${color.red}, ${color.green}, ${color.blue});
- }
- a:active {
- background-color: rgb(${color.red}, ${color.green}, ${color.blue}) !important;
- color: #000 !important;
- //cursor: url(https://i.imgur.com/jHZgg47.png), default !important;
- }
- `;
- /* Changelog
- 1.0 - Initial release
- 1.0.1 - Changed text selection color and curors
- 1.0.2 - Link styling
- 1.1 - Dithering and less poppy loading
- 1.1.1 - Added option for "Always allow all domains" so that you don't need to hit accept every time a new image domain is accessed
- 1.2 - Custom color support, optimiztion, and works on every page
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement