Jessie_ Posted October 23, 2019 Share Posted October 23, 2019 (edited) the greasemonkey userscript: Spoiler // ==UserScript== // @name no animated avatars // @version 1 // @match https://forums.kleientertainment.com/* // @run-at document-end // @noframes // ==/UserScript== "use strict"; if (window.top !== window.self) return; let canvas = document.createElement("canvas"), ctx = canvas.getContext("2d"), recognised = {}; let canvas_toBlob = function(img) { let _recognised = recognised; return function(blob) { let url = URL.createObjectURL(blob); for (let im of _recognised[img.src]) im.src = url; // remember images that have already been converted, // this saves a lot of time _recognised[img.src] = url; img.src = url; }; }; let img2_onload = function(img, sig) { let _canvas = canvas, _ctx = ctx, _canvas_toBlob = canvas_toBlob; return function() { let w, h; if (sig) { // signature image, use normal height & width w = img.naturalWidth; h = img.naturalHeight; } else { // avatar image, limit height & width to up to 120 let nw = img.naturalWidth, nh = img.naturalHeight; if (nw === nh) { w = Math.min(120, nw); h = w; } else if (nw > nh) { w = Math.min(120, nw); h = Math.round(nh / nw * w); } else if (nh > nw) { h = Math.min(120, nh); w = Math.round(nw / nh * h); } } _canvas.width = w; _canvas.height = h; _ctx.drawImage(img, 0, 0, w, h); _canvas.toBlob(_canvas_toBlob(img), "image/png", 1); }; }; let convertimage = function(img, sig) { // create a new image element // its purpose is to wait for the image to finish loading let img2 = new Image(); img2.onload = img2_onload(img, sig); img2.src = img.src; }; let xhr_onload = function(img, sig) { let _convertimage = convertimage, _recognised = recognised; return function() { if (this.readyState !== this.DONE) return; let mime = this.getResponseHeader("Content-Type"); if ( // check mime type for gif for apng mime === "image/gif" || mime === "image/apng" || // just assume it's animated if the mime type is unknown mime === "application/x-unknown" || mime === "" ) { // animated _convertimage(img, sig); return; } // not animated for (let im of _recognised[img.src]) im.src = img.src; _recognised[img.src] = img.src; }; }; // loop through an array of image elements // to check if they should be converted or not let convertimages = function(imgs, sig) { for (let i = 0, len = imgs.length; i < len; i++) { let img = imgs[i]; if (img.ignore) continue; else img.ignore = true; if (img.tagName !== "IMG") // not an image element, // use its child instead img = img.children[0]; let src = img.src, rec = recognised[src]; if (!rec) { // image isn't recognised, // proceed normally } else if (typeof rec === "string") { // image was already converted, // skip the whole process img.src = rec; continue; } else { // image is being processed rec.push(img); continue; } let lower = src.toLowerCase(), start = lower.lastIndexOf("."); if ( // check for file extension, ignore if it's not animated lower.indexOf(".png", start) === start || lower.indexOf(".jpg", start) === start || lower.indexOf(".jpeg", start) === start ) continue; else if ( lower.indexOf(".gif", start) === start || lower.indexOf(".apng", start) === start ) { recognised[src] = []; convertimage(img, sig); continue; } recognised[src] = []; // this is reached if the available extension is not gif/png/jpg/jpeg // desperate measure: use an xhr request to get the mimetype let xhr = new XMLHttpRequest(); xhr.open("HEAD", src, true); xhr.onload = xhr_onload(img, sig); xhr.send(); } }; // look for animated images within signatures let checksignatures = function(sigs) { for (let i = 0, len = sigs.length; i < len; i++) { let sig = sigs[i]; if (sig.ignore) continue; else sig.ignore = true; convertimages(sig.getElementsByTagName("IMG"), true); } }; let iframe_onload = function() { convertimages(this.document.getElementsByClassName("ipsUserPhoto"), false); }; // look for animated avatars within iframes let checkiframes = function(iframes) { for (let i = 0, len = iframes.length; i < len; i++) { let iframe = iframes[i]; if (iframe.ignore) continue; else iframe.ignore = true; if (iframe.src.indexOf("https://forums.kleientertainment.com") !== 0) continue; iframe.contentWindow.addEventListener("load", iframe_onload); } }; let avatars = document.getElementsByClassName("ipsUserPhoto"), signatures = document.querySelectorAll("#siglimit"), iframes = document.getElementsByTagName("IFRAME"); // look for avatars when the main page is loaded convertimages(avatars, false); checksignatures(signatures); checkiframes(iframes); // look for avatars when new elements get added new MutationObserver(function() { convertimages(avatars, false); checksignatures(signatures); checkiframes(iframes); }).observe(document.body, { childList: true, subtree: true, attributes: false, characterData: false }); Â i've kinda grown tired of seeing a lot of animated avatars on this forum, so here's my attempt at stopping the eyesore what this script does is look for animated avatars, then convert the first frame into a png image so it can't be animated (as a bonus, this affects animated signatures too) example of how it should look like: to use it, install Greasemonkey on your browser, create a new userscript, copy+paste the code above, then save it tested on: - extension = Greasemonkey 4.9 - browser = Mozilla Firefox 71.0b3 - os = Debian 11 (bullseye) i'm not really used to writing javascript, so if you think you can improve or optimise the script, then please tell me - - - - - - - - - - - - - - - - - - - - edit: here's a version that's compatible with tampermonkey and google chrome: Spoiler // ==UserScript== // @name no animated avatars // @version 1 // @grant GM.xmlHttpRequest // @match https://forums.kleientertainment.com/* // @connect klei.com // @connect googleusercontent.com // @connect gravatar.com // @connect wp.com // @connect * // @run-at document-end // @noframes // ==/UserScript== "use strict"; if (window.top !== window.self) return; let canvas = document.createElement("canvas"), ctx = canvas.getContext("2d"), recognised = {}; let canvas_toBlob = function(img) { let _recognised = recognised; return function(blob) { let url = URL.createObjectURL(blob); for (let im of _recognised[img.src]) im.src = url; // remember images that have already been converted, // this saves a lot of time _recognised[img.src] = url; img.src = url; }; }; let convertimage = function(img, sig) { let _canvas = canvas, _ctx = ctx, _canvas_toBlob = canvas_toBlob; return function(response) { let w, h; if (sig) { // signature image, use normal height & width w = img.naturalWidth; h = img.naturalHeight; } else { // avatar image, limit height & width to up to 120 let nw = img.naturalWidth, nh = img.naturalHeight; if (nw === nh) { w = Math.min(120, nw); h = w; } else if (nw > nh) { w = Math.min(120, nw); h = Math.round(nh / nw * w); } else if (nh > nw) { h = Math.min(120, nh); w = Math.round(nw / nh * h); } } _canvas.width = w; _canvas.height = h; _ctx.drawImage(response, 0, 0, w, h); _canvas.toBlob(_canvas_toBlob(img), "image/png", 1); }; }; let xhr_onload = function(img, sig) { let _convertimage = convertimage, _recognised = recognised; return function(xhr) { if (xhr.readyState !== xhr.DONE) return; let mime = xhr.response.type; if ( // check mime type for gif for apng mime === "image/gif" || mime === "image/apng" || // just assume it's animated if the mime type is unknown mime === "application/x-unknown" || mime === "" ) { // animated createImageBitmap(xhr.response).then(_convertimage(img, sig)); return; } // not animated for (let im of _recognised[img.src]) im.src = img.src; _recognised[img.src] = img.src; }; }; // loop through an array of image elements // to check if they should be converted or not let convertimages = function(imgs, sig) { for (let i = 0, len = imgs.length; i < len; i++) { let img = imgs[i]; if (img.ignore) continue; else img.ignore = true; if (img.tagName !== "IMG") // not an image element, // use its child instead img = img.children[0]; let src = img.src, rec = recognised[src]; if (!rec) { // image isn't recognised, // proceed normally } else if (typeof rec === "string") { // image was already converted, // skip the whole process img.src = rec; continue; } else { // image is being processed rec.push(img); continue; } let lower = src.toLowerCase(), start = lower.lastIndexOf("."); if ( // check for file extension, ignore if it's not animated lower.indexOf(".png", start) === start || lower.indexOf(".jpg", start) === start || lower.indexOf(".jpeg", start) === start ) continue; recognised[src] = []; GM.xmlHttpRequest({ method: "GET", url: src, responseType: "blob", onload: xhr_onload(img, sig) }); } }; // look for animated images within signatures let checksignatures = function(sigs) { for (let i = 0, len = sigs.length; i < len; i++) { let sig = sigs[i]; if (sig.ignore) continue; else sig.ignore = true; convertimages(sig.getElementsByTagName("IMG"), true); } }; let iframe_onload = function() { convertimages(this.document.getElementsByClassName("ipsUserPhoto"), false); }; // look for animated avatars within iframes let checkiframes = function(iframes) { for (let i = 0, len = iframes.length; i < len; i++) { let iframe = iframes[i]; if (iframe.ignore) continue; else iframe.ignore = true; if (iframe.src.indexOf("https://forums.kleientertainment.com") !== 0) continue; iframe.contentWindow.addEventListener("load", iframe_onload); } }; let avatars = document.getElementsByClassName("ipsUserPhoto"), signatures = document.querySelectorAll("#siglimit"), iframes = document.getElementsByTagName("IFRAME"); // look for avatars when the main page is loaded convertimages(avatars, false); checksignatures(signatures); checkiframes(iframes); // look for avatars when new elements get added new MutationObserver(function() { convertimages(avatars, false); checksignatures(signatures); checkiframes(iframes); }).observe(document.body, { childList: true, subtree: true, attributes: false, characterData: false }); Â to use it, install Tampermonkey on your browser, create a new userscript, copy+paste the code above, then save it choose either the "always allow" or the "always allow domain" option when this screen appears: tested on: - extension = Tampermonkey 4.8.41 - browser = Ungoogled Chromium 76.0.3809.132 - os = Debian 11 (bullseye) Edited October 28, 2019 by Jessie223 Link to comment Share on other sites More sharing options...
I_Link_I Posted October 24, 2019 Share Posted October 24, 2019 1.Cool. 2.You monster!How could you do that to the poor GIFs?! Link to comment Share on other sites More sharing options...
watermelen671 Posted October 25, 2019 Share Posted October 25, 2019 Finally, I can be rid of the eye cancer that is certain people's profile pictures. Link to comment Share on other sites More sharing options...
Xenologist Posted October 25, 2019 Share Posted October 25, 2019 Here's a question, is there a way of getting it without any of the web browser extensions? Link to comment Share on other sites More sharing options...
Jessie_ Posted October 26, 2019 Author Share Posted October 26, 2019 9 hours ago, Xenologist said: Here's a question, is there a way of getting it without any of the web browser extensions? no Link to comment Share on other sites More sharing options...
DragonMage156 Posted October 27, 2019 Share Posted October 27, 2019 On 10/24/2019 at 10:11 PM, I_Link_I said: 2.You monster!How could you do that to the poor GIFs?! I feel more sorry for @Asparagus being the example. On 10/26/2019 at 3:10 AM, watermelen671 said: Finally, I can be rid of the eye cancer that is certain people's profile pictures. Sorry Melen XD but I promise it'll end after halloween (atleast mine will). Link to comment Share on other sites More sharing options...
watermelen671 Posted October 27, 2019 Share Posted October 27, 2019 2 hours ago, DragonMage156 said: Sorry Melen XD but I promise it'll end after halloween (atleast mine will). Doesn't even work...smh. Link to comment Share on other sites More sharing options...
Jessie_ Posted October 27, 2019 Author Share Posted October 27, 2019 2 minutes ago, watermelen671 said: Doesn't even work...smh. which script are you using for which extension and which browser? the first script should only work with greasemonkey + firefox the second script should work with tampermonkey + firefox/chromium/edge/safari/opera (note i've only tested them on firefox and chromium) Link to comment Share on other sites More sharing options...
watermelen671 Posted October 27, 2019 Share Posted October 27, 2019 2 minutes ago, Jessie223 said: which script are you using for which extension and which browser? the first script should only work with greasemonkey + firefox the second script should work with tampermonkey + firefox/chromium/edge/safari/opera (note i've only tested them on firefox and chromium) I added the second one...I'm on chrome, and @DragonMage156's profile pic is still moving. Mage...please...just change it. Link to comment Share on other sites More sharing options...
Jessie_ Posted October 27, 2019 Author Share Posted October 27, 2019 1 minute ago, watermelen671 said: I added the second one...I'm on chrome, and @DragonMage156's profile pic is still moving. Mage...please...just change it. open the console (ctrl + shift + j) and refresh the page if you see this error message "Uncaught (in promise) DOMException: Failed to execute 'toBlob' on 'HTMLCanvasElement': Tainted canvases may not be exported." then you're probably running chrome with the "disable-reading-from-canvas" flag if different error messages appear, then please tell me also make sure it's enabled properly, like so: Link to comment Share on other sites More sharing options...
DragonMage156 Posted October 27, 2019 Share Posted October 27, 2019 6 hours ago, watermelen671 said: Mage...please...just change it. Fine! Just for you. Link to comment Share on other sites More sharing options...
Recommended Posts