4chan Image Resizer

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

目前為 2019-10-30 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==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]}