From dd98f335205d9250b2c1d12fd91a5fbdd0ac71a9 Mon Sep 17 00:00:00 2001 From: C85297 <95289555+C85297@users.noreply.github.com> Date: Thu, 5 Feb 2026 15:41:12 +0000 Subject: [PATCH] Fix sharpen image --- src/core/lib/ImageManipulation.mjs | 251 --------------------------- src/core/operations/BlurImage.mjs | 3 +- src/core/operations/SharpenImage.mjs | 3 +- tests/browser/02_ops.js | 4 +- tests/samples/Images.mjs | 6 - 5 files changed, 5 insertions(+), 262 deletions(-) delete mode 100644 src/core/lib/ImageManipulation.mjs diff --git a/src/core/lib/ImageManipulation.mjs b/src/core/lib/ImageManipulation.mjs deleted file mode 100644 index 63a80fe4..00000000 --- a/src/core/lib/ImageManipulation.mjs +++ /dev/null @@ -1,251 +0,0 @@ -/** - * Image manipulation resources - * - * @author j433866 [j433866@gmail.com] - * @copyright Crown Copyright 2019 - * @license Apache-2.0 - */ - -import OperationError from "../errors/OperationError.mjs"; - -/** - * Gaussian blurs an image. - * - * @param {jimp} input - * @param {number} radius - * @param {boolean} fast - * @returns {jimp} - */ -export function gaussianBlur (input, radius) { - try { - // From http://blog.ivank.net/fastest-gaussian-blur.html - const boxes = boxesForGauss(radius, 3); - for (let i = 0; i < 3; i++) { - input = boxBlur(input, (boxes[i] - 1) / 2); - } - } catch (err) { - throw new OperationError(`Error blurring image. (${err})`); - } - - return input; -} - -/** - * - * @param {number} radius - * @param {number} numBoxes - * @returns {Array} - */ -function boxesForGauss(radius, numBoxes) { - const idealWidth = Math.sqrt((12 * radius * radius / numBoxes) + 1); - - let wl = Math.floor(idealWidth); - - if (wl % 2 === 0) { - wl--; - } - - const wu = wl + 2; - - const mIdeal = (12 * radius * radius - numBoxes * wl * wl - 4 * numBoxes * wl - 3 * numBoxes) / (-4 * wl - 4); - const m = Math.round(mIdeal); - - const sizes = []; - for (let i = 0; i < numBoxes; i++) { - sizes.push(i < m ? wl : wu); - } - return sizes; -} - -/** - * Applies a box blur effect to the image - * - * @param {jimp} source - * @param {number} radius - * @returns {jimp} - */ -function boxBlur (source, radius) { - const width = source.bitmap.width; - const height = source.bitmap.height; - let output = source.clone(); - output = boxBlurH(source, output, width, height, radius); - source = boxBlurV(output, source, width, height, radius); - - return source; -} - -/** - * Applies the horizontal blur - * - * @param {jimp} source - * @param {jimp} output - * @param {number} width - * @param {number} height - * @param {number} radius - * @returns {jimp} - */ -function boxBlurH (source, output, width, height, radius) { - const iarr = 1 / (radius + radius + 1); - for (let i = 0; i < height; i++) { - let ti = 0, - li = ti, - ri = ti + radius; - const idx = source.getPixelIndex(ti, i); - const firstValRed = source.bitmap.data[idx], - firstValGreen = source.bitmap.data[idx + 1], - firstValBlue = source.bitmap.data[idx + 2], - firstValAlpha = source.bitmap.data[idx + 3]; - - const lastIdx = source.getPixelIndex(width - 1, i), - lastValRed = source.bitmap.data[lastIdx], - lastValGreen = source.bitmap.data[lastIdx + 1], - lastValBlue = source.bitmap.data[lastIdx + 2], - lastValAlpha = source.bitmap.data[lastIdx + 3]; - - let red = (radius + 1) * firstValRed; - let green = (radius + 1) * firstValGreen; - let blue = (radius + 1) * firstValBlue; - let alpha = (radius + 1) * firstValAlpha; - - for (let j = 0; j < radius; j++) { - const jIdx = source.getPixelIndex(ti + j, i); - red += source.bitmap.data[jIdx]; - green += source.bitmap.data[jIdx + 1]; - blue += source.bitmap.data[jIdx + 2]; - alpha += source.bitmap.data[jIdx + 3]; - } - - for (let j = 0; j <= radius; j++) { - const jIdx = source.getPixelIndex(ri++, i); - red += source.bitmap.data[jIdx] - firstValRed; - green += source.bitmap.data[jIdx + 1] - firstValGreen; - blue += source.bitmap.data[jIdx + 2] - firstValBlue; - alpha += source.bitmap.data[jIdx + 3] - firstValAlpha; - - const tiIdx = source.getPixelIndex(ti++, i); - output.bitmap.data[tiIdx] = Math.round(red * iarr); - output.bitmap.data[tiIdx + 1] = Math.round(green * iarr); - output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr); - output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr); - } - - for (let j = radius + 1; j < width - radius; j++) { - const riIdx = source.getPixelIndex(ri++, i); - const liIdx = source.getPixelIndex(li++, i); - red += source.bitmap.data[riIdx] - source.bitmap.data[liIdx]; - green += source.bitmap.data[riIdx + 1] - source.bitmap.data[liIdx + 1]; - blue += source.bitmap.data[riIdx + 2] - source.bitmap.data[liIdx + 2]; - alpha += source.bitmap.data[riIdx + 3] - source.bitmap.data[liIdx + 3]; - - const tiIdx = source.getPixelIndex(ti++, i); - output.bitmap.data[tiIdx] = Math.round(red * iarr); - output.bitmap.data[tiIdx + 1] = Math.round(green * iarr); - output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr); - output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr); - } - - for (let j = width - radius; j < width; j++) { - const liIdx = source.getPixelIndex(li++, i); - red += lastValRed - source.bitmap.data[liIdx]; - green += lastValGreen - source.bitmap.data[liIdx + 1]; - blue += lastValBlue - source.bitmap.data[liIdx + 2]; - alpha += lastValAlpha - source.bitmap.data[liIdx + 3]; - - const tiIdx = source.getPixelIndex(ti++, i); - output.bitmap.data[tiIdx] = Math.round(red * iarr); - output.bitmap.data[tiIdx + 1] = Math.round(green * iarr); - output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr); - output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr); - } - } - return output; -} - -/** - * Applies the vertical blur - * - * @param {jimp} source - * @param {jimp} output - * @param {number} width - * @param {number} height - * @param {number} radius - * @returns {jimp} - */ -function boxBlurV (source, output, width, height, radius) { - const iarr = 1 / (radius + radius + 1); - for (let i = 0; i < width; i++) { - let ti = 0, - li = ti, - ri = ti + radius; - - const idx = source.getPixelIndex(i, ti); - - const firstValRed = source.bitmap.data[idx], - firstValGreen = source.bitmap.data[idx + 1], - firstValBlue = source.bitmap.data[idx + 2], - firstValAlpha = source.bitmap.data[idx + 3]; - - const lastIdx = source.getPixelIndex(i, height - 1), - lastValRed = source.bitmap.data[lastIdx], - lastValGreen = source.bitmap.data[lastIdx + 1], - lastValBlue = source.bitmap.data[lastIdx + 2], - lastValAlpha = source.bitmap.data[lastIdx + 3]; - - let red = (radius + 1) * firstValRed; - let green = (radius + 1) * firstValGreen; - let blue = (radius + 1) * firstValBlue; - let alpha = (radius + 1) * firstValAlpha; - - for (let j = 0; j < radius; j++) { - const jIdx = source.getPixelIndex(i, ti + j); - red += source.bitmap.data[jIdx]; - green += source.bitmap.data[jIdx + 1]; - blue += source.bitmap.data[jIdx + 2]; - alpha += source.bitmap.data[jIdx + 3]; - } - - for (let j = 0; j <= radius; j++) { - const riIdx = source.getPixelIndex(i, ri++); - red += source.bitmap.data[riIdx] - firstValRed; - green += source.bitmap.data[riIdx + 1] - firstValGreen; - blue += source.bitmap.data[riIdx + 2] - firstValBlue; - alpha += source.bitmap.data[riIdx + 3] - firstValAlpha; - - const tiIdx = source.getPixelIndex(i, ti++); - output.bitmap.data[tiIdx] = Math.round(red * iarr); - output.bitmap.data[tiIdx + 1] = Math.round(green * iarr); - output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr); - output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr); - } - - for (let j = radius + 1; j < height - radius; j++) { - const riIdx = source.getPixelIndex(i, ri++); - const liIdx = source.getPixelIndex(i, li++); - red += source.bitmap.data[riIdx] - source.bitmap.data[liIdx]; - green += source.bitmap.data[riIdx + 1] - source.bitmap.data[liIdx + 1]; - blue += source.bitmap.data[riIdx + 2] - source.bitmap.data[liIdx + 2]; - alpha += source.bitmap.data[riIdx + 3] - source.bitmap.data[liIdx + 3]; - - const tiIdx = source.getPixelIndex(i, ti++); - output.bitmap.data[tiIdx] = Math.round(red * iarr); - output.bitmap.data[tiIdx + 1] = Math.round(green * iarr); - output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr); - output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr); - } - - for (let j = height - radius; j < height; j++) { - const liIdx = source.getPixelIndex(i, li++); - red += lastValRed - source.bitmap.data[liIdx]; - green += lastValGreen - source.bitmap.data[liIdx + 1]; - blue += lastValBlue - source.bitmap.data[liIdx + 2]; - alpha += lastValAlpha - source.bitmap.data[liIdx + 3]; - - const tiIdx = source.getPixelIndex(i, ti++); - output.bitmap.data[tiIdx] = Math.round(red * iarr); - output.bitmap.data[tiIdx + 1] = Math.round(green * iarr); - output.bitmap.data[tiIdx + 2] = Math.round(blue * iarr); - output.bitmap.data[tiIdx + 3] = Math.round(alpha * iarr); - } - } - return output; -} diff --git a/src/core/operations/BlurImage.mjs b/src/core/operations/BlurImage.mjs index ffdb1876..ba46080f 100644 --- a/src/core/operations/BlurImage.mjs +++ b/src/core/operations/BlurImage.mjs @@ -9,7 +9,6 @@ import OperationError from "../errors/OperationError.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; -import { gaussianBlur } from "../lib/ImageManipulation.mjs"; import { Jimp, JimpMime } from "jimp"; /** @@ -73,7 +72,7 @@ class BlurImage extends Operation { case "Gaussian": if (isWorkerEnvironment()) self.sendStatusMessage("Gaussian blurring image..."); - image = gaussianBlur(image, blurAmount); + image.gaussian(blurAmount); break; } diff --git a/src/core/operations/SharpenImage.mjs b/src/core/operations/SharpenImage.mjs index 5223127f..0dd1f890 100644 --- a/src/core/operations/SharpenImage.mjs +++ b/src/core/operations/SharpenImage.mjs @@ -8,7 +8,6 @@ import Operation from "../Operation.mjs"; import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; -import { gaussianBlur } from "../lib/ImageManipulation.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; import { Jimp, JimpMime } from "jimp"; @@ -81,7 +80,7 @@ class SharpenImage extends Operation { self.sendStatusMessage( "Sharpening image... (Blurring cloned image)", ); - const blurImage = gaussianBlur(image.clone(), radius); + const blurImage = image.clone().gaussian(radius); if (isWorkerEnvironment()) self.sendStatusMessage( diff --git a/tests/browser/02_ops.js b/tests/browser/02_ops.js index 8f739610..e3be0c03 100644 --- a/tests/browser/02_ops.js +++ b/tests/browser/02_ops.js @@ -62,7 +62,9 @@ module.exports = { testOp(browser, "Bit shift right", "test input", ":29:\u0010478::"); testOp(browser, "Blowfish Decrypt", "10884e15427dd84ec35204e9c8e921ae", "test_output", [{"option": "Hex", "string": "1234567801234567"}, {"option": "Hex", "string": "0011223344556677"}, "CBC", "Hex", "Raw"]); testOp(browser, "Blowfish Encrypt", "test input", "f0fadbd1d90d774f714248cf26b96410", [{"option": "Hex", "string": "1234567801234567"}, {"option": "Hex", "string": "0011223344556677"}, "CBC", "Raw", "Hex"]); - testOp(browser, ["From Hex", "Blur Image", "To Base64"], Images.PNG_HEX, Images.PNG_BLUR_B64); + testOp(browser, ["From Hex", "Blur Image", "SHA2"], Images.PNG_HEX, "24f2e89f3e00cc35f551bbc48ea82e76474946ce0282183494d1ca3d3b0012c27b6102c4368ae056dc7fecb6df7886d86ff3d29b7e5965493f30c371eee9a24e"); + testOp(browser, ["From Hex", "Blur Image", "SHA2"], Images.PNG_HEX, "2c49d89fc10c94352c9a19f82de353c37928831d6f976a6b36eb918825a0ba027980801838228a4a0da63f1886e4fa59b6666f992ad2d2b7d4622253dc034052", [[], [5, "Gaussian"], []]); + testOp(browser, ["From Hex", "Sharpen Image", "SHA2"], Images.PNG_HEX, "acc7027642c2eeb67d7356a80ed8a1bdce9adabf656ea1294e47723f506626a7aa41f1660fa844a1e1e83b17180017ab0d5bccd7f6a341692832020dc887eaa5"); testOpHtml(browser, "Bombe", "XTSYN WAEUG EZALY NRQIM AMLZX MFUOD AWXLY LZCUZ QOQBQ JLCPK NDDRW F", "table tr:last-child td:first-child", "ECG", ["3-rotor", "LEYJVCNIXWPBQMDRTAKZGFUHOS", "BDFHJLCPRTXVZNYEIWGAKMUSQO