Greasy Fork

4chan Image Resizer

Automatically downscales uploaded pre-submit images. Requires 4chan X.

目前为 2019-10-30 提交的版本。查看 最新版本

// ==UserScript==
// @name         4chan Image Resizer
// @namespace    https://greasyfork.org/en/users/393416
// @version      1.0
// @description  Automatically downscales uploaded pre-submit images. Requires 4chan X.
// @author       greenronia
// @match        *://boards.4chan.org/*
// @match        *://boards.4channel.org/*
// @grant        none
// ==/UserScript==
console.log("[ImageResizer] Initialized");
//Checking if QuickReply dialogue is open.
document.addEventListener('QRDialogCreation', function(listenForQRDC) {
    var checkBox = document.getElementById("imgResize");
    //Checking if the check box already exists
    if (!checkBox) {
        appendCheckBox();
    }
    else {
        console.log("[ImageResizer][Error] Check box already exists");
    }
    //Listening for clicks on check box
    document.getElementById("imgResize").addEventListener("click", checkState);
    checkState(1);
    console.log("[QRFile] Listening...");
    //QRFile | Listening for QRFile, in response to: QRGetFile | Request File
    document.addEventListener('QRFile', function(GetFile) {
        console.log("[QRFile] File served: " + GetFile.detail);

        const file = GetFile.detail;
        //Initialize an instance of a FileReader
        const reader = new FileReader();

        //console.log("Type: " + file.type);
        //Checking if file is JPG or PNG
        if (file.type == "image/jpeg" || file.type == "image/png") {
            console.log("Correct FileType: " + file.type);
            reader.onload = function(resize) {
                var img = new Image();
                img.src = reader.result;
                img.onload = function() {
                    //Accepted image dimensions
					//(img.height == 1080)
                    if (img.width == 1920) {    //ADJUST HERE
                        console.log("INPUT Dimensions OK: " + img.width + "x" + img.height);
                        var canvas = document.createElement("canvas");
                        //Target image dimensions. Don't try to upscale images! 
                        var MAX_WIDTH = 1280;   //ADJUST HERE
                        var MAX_HEIGHT = 720;   //ADJUST HERE
                        var width = img.width;
                        var height = img.height;
                        //Calculating dimensions
                        if (width > height) {
                            if (width > MAX_WIDTH) {
                                height *= MAX_WIDTH / width;
                                width = MAX_WIDTH;
                            }
                        } else {
                            if (height > MAX_HEIGHT) {
                                width *= MAX_HEIGHT / height;
                                height = MAX_HEIGHT;
                            }
                        }
                        console.log("OUTPUT Dimesnions: " + width + "x" + height);
                        // resize the canvas to the new dimensions
                        canvas.width = width;
                        canvas.height = height;
                        // scale & draw the image onto the canvas
                        var ctx = canvas.getContext("2d");
                        ctx.drawImage(img, 0, 0, width, height);
                        //DEBUG Show image
                        //document.body.appendChild(canvas)

                        //Converts dataURI to blob
                        function dataURItoBlob(dataURI) {
                            // convert base64/URLEncoded data component to raw binary data held in a string
                            var byteString;
                            if (dataURI.split(',')[0].indexOf('base64') >= 0) { byteString = atob(dataURI.split(',')[1]); }
                            else { byteString = unescape(dataURI.split(',')[1]); }

                            // separate out the mime component
                            var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

                            // write the bytes of the string to a typed array
                            var ia = new Uint8Array(byteString.length);
                            for (var i = 0; i < byteString.length; i++) {
                                ia[i] = byteString.charCodeAt(i);
                            }

                            return new Blob([ia], {
                                type: mimeString
                            });
                        }
                        //canvas to dataURL | jpeg quality (0-1)
                        var dataURL = canvas.toDataURL('image/jpeg', 0.92); //ADJUST HERE
                        //dataURL to blob
                        var blob = dataURItoBlob(dataURL);
                        //Stop classObserver | prevent trigger loop
                        classObserver.disconnect();
                        console.log("[classObserver] Stopping...");
                        //QRSetFile | Set the resized image to upload
                        var detail = {
                            file: blob,
                            name: 'autoResized'
                        };
                        var event = new CustomEvent('QRSetFile', {
                            bubbles: true,
                            detail: detail
                        });
                        document.dispatchEvent(event);
                        console.log("[QRSetFile] File Sent");
                        //Notification
                        var FSInfo = "Original size: (" + formatBytes(file.size) + ", " + img.width + "x" + img.height + ") \n New size: (" + formatBytes(blob.size)+ ", " + width + "x" + height +")";
                        var msgDetail = {type: 'info', content: FSInfo};
                        var msgEvent = new CustomEvent('CreateNotification', {bubbles: true, detail: msgDetail});
                        document.dispatchEvent(msgEvent);
                        //Restart classObserver
                        classObserver.observe(targetNode, observerOptions);
                        console.log("<END> \n[classObserver] Restarting...");

                    } else {
                        console.log("<END>\n[Error] BAD INPUT Dimensions: " + img.width + "x" + img.height);
                        return;
                    }
                }
            }
            // Read the file
            reader.readAsDataURL(file);
        } else {
            console.log("<END>\n [Error] Invalid FileType: " + file.type);
        }
    }, false);
    //Observing if a file is uploaded or not | checking if div (with id: "file-n-submit") has class named: "has-file"
    function callback(mutationList, observer) {
        if (document.getElementById("file-n-submit").classList.contains("has-file") === true && checkState(2) === true) {
            console.log("<START>\n[classObserver] File detected")
            //QRGetFile | Request File
            console.log("[QRGetFile] Requesting file...");
            document.dispatchEvent(new CustomEvent('QRGetFile'));

        } else if (checkState(2) === false) {
            console.log("[classObserver] ImageResizer is disabled");
            return;
        }
        else {
            console.log("[classObserver] No file");
        }
    }
    //MutationObserver. Checks if div (with id "file-n-submit") has its class attribute changed
    const targetNode = document.getElementById('file-n-submit');
    var observerOptions = {
        attributes: true
    };
    var classObserver = new MutationObserver(callback);
    console.log("[classObserver] Starting...");
    classObserver.observe(targetNode, observerOptions);
}, false);
//Add a label with a check box for ImageResize in QR, AFTER label with an id "autohide"
function appendCheckBox() {
    var labelElem = document.createElement("label");
    var inputElem = document.createElement("input");
    inputElem.type = "checkbox";
    inputElem.id = "imgResize";
    inputElem.title = "image-resize";
    var reference = document.getElementById('autohide');
    reference.parentNode.parentNode.insertBefore(labelElem, parent.nextSibling)
    labelElem.appendChild(inputElem);
    labelElem.innerHTML += "Resize";
    //Checked by default
    document.getElementById("imgResize").checked = true; //ADJUST HERE
}
//Check box state
function checkState(caller) {
    var state = document.getElementById("imgResize").checked;
    if (state === true) {
        if (caller != 2) console.log("[ImageResizer] Enabled");
        return true;
    } else {
        if (caller != 2) console.log("[ImageResizer] Disabled");
        return false;
    };
}
//Bloat
function formatBytes(a,b){if(0==a)return"0 Bytes";var c=1024,d=b||2,e=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],f=Math.floor(Math.log(a)/Math.log(c));return parseFloat((a/Math.pow(c,f)).toFixed(d))+" "+e[f]}