4chan Image Resizer

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

当前为 2019-10-30 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 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]}