diff --git a/src/core/lib/Jimp.mjs b/src/core/lib/Jimp.mjs new file mode 100644 index 00000000..e6290f72 --- /dev/null +++ b/src/core/lib/Jimp.mjs @@ -0,0 +1,21 @@ +/** + * Jimp image library with additional plugins. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + */ + +import { Jimp as BaseJimp, JimpMime, PNGFilterType, ResizeStrategy, EdgeAction } from "jimp"; +import webp from "@jimp/wasm-webp"; + +/** + * Configure Jimp with WebP support + */ +const Jimp = new BaseJimp({ + plugins: [webp], + formats: [webp] +}); + +export { Jimp, JimpMime, PNGFilterType, ResizeStrategy, EdgeAction }; +export default Jimp; diff --git a/src/core/operations/AddTextToImage.mjs b/src/core/operations/AddTextToImage.mjs index c137b492..389acab7 100644 --- a/src/core/operations/AddTextToImage.mjs +++ b/src/core/operations/AddTextToImage.mjs @@ -16,7 +16,7 @@ import { measureText, measureTextHeight, loadFont, -} from "jimp"; +} from "../lib/Jimp.mjs"; /** * Add Text To Image operation diff --git a/src/core/operations/BlurImage.mjs b/src/core/operations/BlurImage.mjs index ba46080f..e9fb44a4 100644 --- a/src/core/operations/BlurImage.mjs +++ b/src/core/operations/BlurImage.mjs @@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; -import { Jimp, JimpMime } from "jimp"; +import { Jimp, JimpMime } from "../lib/Jimp.mjs"; /** * Blur Image operation diff --git a/src/core/operations/ContainImage.mjs b/src/core/operations/ContainImage.mjs index 0304733b..8e04f528 100644 --- a/src/core/operations/ContainImage.mjs +++ b/src/core/operations/ContainImage.mjs @@ -15,7 +15,7 @@ import { ResizeStrategy, HorizontalAlign, VerticalAlign, -} from "jimp"; +} from "../lib/Jimp.mjs"; /** * Contain Image operation diff --git a/src/core/operations/ConvertImageFormat.mjs b/src/core/operations/ConvertImageFormat.mjs index 8cb8bade..0963a651 100644 --- a/src/core/operations/ConvertImageFormat.mjs +++ b/src/core/operations/ConvertImageFormat.mjs @@ -8,16 +8,7 @@ import Operation from "../Operation.mjs"; import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; -import { Jimp as BaseJimp, JimpMime, PNGFilterType } from "jimp"; -import webp from "@jimp/wasm-webp"; - -/** - * Configure Jimp with WebP support - */ -const Jimp = new BaseJimp({ - plugins: [webp], - formats: [webp] -}); +import { Jimp, JimpMime, PNGFilterType } from "../lib/Jimp.mjs"; function canTranscodeViaCanvas() { return ( @@ -31,7 +22,7 @@ function canTranscodeViaCanvas() { } async function transcodeViaCanvas(input, inputMime, outputMime, quality) { - const {Blob: BlobCtor, createImageBitmap: createImageBitmapFn, OffscreenCanvas: OffscreenCanvasCtor, document} = + const { Blob: BlobCtor, createImageBitmap: createImageBitmapFn, OffscreenCanvas: OffscreenCanvasCtor, document } = globalThis; const inputBytes = input instanceof ArrayBuffer ? new Uint8Array(input) : input; @@ -52,7 +43,7 @@ async function transcodeViaCanvas(input, inputMime, outputMime, quality) { const ctx = canvas.getContext("2d"); if (!ctx) throw new Error("Unable to initialise canvas context"); - if (outputMime === "image/jpeg") { + if (outputMime === "image/jpeg" || outputMime === "image/webp") { ctx.fillStyle = "#ffffff"; ctx.fillRect(0, 0, bitmap.width, bitmap.height); } @@ -98,7 +89,7 @@ class ConvertImageFormat extends Operation { this.name = "Convert Image Format"; this.module = "Image"; this.description = - "Converts an image between different formats. Supported output formats:

Note: GIF and WebP files are supported for input, but cannot be outputted."; + "Converts an image between different formats. Supported output formats:

Note: GIF files are supported for input, but cannot be outputted."; this.infoURL = "https://wikipedia.org/wiki/Image_file_formats"; this.inputType = "ArrayBuffer"; this.outputType = "ArrayBuffer"; @@ -107,10 +98,10 @@ class ConvertImageFormat extends Operation { { name: "Output Format", type: "option", - value: ["JPEG", "PNG", "BMP", "TIFF"], + value: ["JPEG", "PNG", "BMP", "TIFF", "WEBP"], }, { - name: "JPEG Quality", + name: "Quality (JPEG/WebP)", type: "number", value: 80, min: 1, @@ -137,12 +128,13 @@ class ConvertImageFormat extends Operation { * @returns {byteArray} */ async run(input, args) { - const [format, jpegQuality, pngFilterType, pngDeflateLevel] = args; + const [format, quality, pngFilterType, pngDeflateLevel] = args; const formatMap = { JPEG: JimpMime.jpeg, PNG: JimpMime.png, BMP: JimpMime.bmp, TIFF: JimpMime.tiff, + WEBP: "image/webp", }; const pngFilterMap = { @@ -167,8 +159,11 @@ class ConvertImageFormat extends Operation { canTranscodeViaCanvas() ) { try { - const outputMime = mime === JimpMime.jpeg ? "image/jpeg" : "image/png"; - const quality = outputMime === "image/jpeg" ? jpegQuality : undefined; + let outputMime; + if (mime === JimpMime.jpeg) outputMime = "image/jpeg"; + else if (mime === "image/webp") outputMime = "image/webp"; + else outputMime = "image/png"; + return await transcodeViaCanvas(input, inputMime, outputMime, quality); } catch (err) { // If canvas fails, we can fall back to Jimp @@ -185,8 +180,9 @@ class ConvertImageFormat extends Operation { let buffer; switch (mime) { case JimpMime.jpeg: + case "image/webp": buffer = await image.getBuffer(mime, { - quality: jpegQuality, + quality: quality, }); break; case JimpMime.png: diff --git a/src/core/operations/CoverImage.mjs b/src/core/operations/CoverImage.mjs index bf9a9bd1..640d9e06 100644 --- a/src/core/operations/CoverImage.mjs +++ b/src/core/operations/CoverImage.mjs @@ -15,7 +15,7 @@ import { ResizeStrategy, HorizontalAlign, VerticalAlign, -} from "jimp"; +} from "../lib/Jimp.mjs"; /** * Cover Image operation diff --git a/src/core/operations/CropImage.mjs b/src/core/operations/CropImage.mjs index 6b5047bc..e796277f 100644 --- a/src/core/operations/CropImage.mjs +++ b/src/core/operations/CropImage.mjs @@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; -import { Jimp, JimpMime } from "jimp"; +import { Jimp, JimpMime } from "../lib/Jimp.mjs"; /** * Crop Image operation diff --git a/src/core/operations/DitherImage.mjs b/src/core/operations/DitherImage.mjs index f21c1f88..e0146a23 100644 --- a/src/core/operations/DitherImage.mjs +++ b/src/core/operations/DitherImage.mjs @@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; -import { Jimp, JimpMime } from "jimp"; +import { Jimp, JimpMime } from "../lib/Jimp.mjs"; /** * Image Dither operation diff --git a/src/core/operations/ExtractLSB.mjs b/src/core/operations/ExtractLSB.mjs index e64831b1..a3e2d7e4 100644 --- a/src/core/operations/ExtractLSB.mjs +++ b/src/core/operations/ExtractLSB.mjs @@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs"; import Utils from "../Utils.mjs"; import { fromBinary } from "../lib/Binary.mjs"; import { isImage } from "../lib/FileType.mjs"; -import { Jimp } from "jimp"; +import { Jimp } from "../lib/Jimp.mjs"; /** * Extract LSB operation diff --git a/src/core/operations/ExtractRGBA.mjs b/src/core/operations/ExtractRGBA.mjs index b0fe3888..d17633ab 100644 --- a/src/core/operations/ExtractRGBA.mjs +++ b/src/core/operations/ExtractRGBA.mjs @@ -7,7 +7,7 @@ import Operation from "../Operation.mjs"; import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; -import { Jimp } from "jimp"; +import { Jimp } from "../lib/Jimp.mjs"; import { RGBA_DELIM_OPTIONS } from "../lib/Delim.mjs"; diff --git a/src/core/operations/FlipImage.mjs b/src/core/operations/FlipImage.mjs index cf9c747f..bd02e08a 100644 --- a/src/core/operations/FlipImage.mjs +++ b/src/core/operations/FlipImage.mjs @@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; -import { Jimp, JimpMime } from "jimp"; +import { Jimp, JimpMime } from "../lib/Jimp.mjs"; /** * Flip Image operation diff --git a/src/core/operations/GenerateImage.mjs b/src/core/operations/GenerateImage.mjs index 053e4ba1..558c9fa8 100644 --- a/src/core/operations/GenerateImage.mjs +++ b/src/core/operations/GenerateImage.mjs @@ -10,7 +10,7 @@ import Utils from "../Utils.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; -import { Jimp, JimpMime, ResizeStrategy, rgbaToInt } from "jimp"; +import { Jimp, JimpMime, ResizeStrategy, rgbaToInt } from "../lib/Jimp.mjs"; /** * Generate Image operation diff --git a/src/core/operations/ImageBrightnessContrast.mjs b/src/core/operations/ImageBrightnessContrast.mjs index b15503d4..827a4789 100644 --- a/src/core/operations/ImageBrightnessContrast.mjs +++ b/src/core/operations/ImageBrightnessContrast.mjs @@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; -import { Jimp, JimpMime } from "jimp"; +import { Jimp, JimpMime } from "../lib/Jimp.mjs"; /** * Image Brightness / Contrast operation diff --git a/src/core/operations/ImageFilter.mjs b/src/core/operations/ImageFilter.mjs index c7c4dde2..67fb09e9 100644 --- a/src/core/operations/ImageFilter.mjs +++ b/src/core/operations/ImageFilter.mjs @@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; -import { Jimp, JimpMime } from "jimp"; +import { Jimp, JimpMime } from "../lib/Jimp.mjs"; /** * Image Filter operation diff --git a/src/core/operations/ImageHueSaturationLightness.mjs b/src/core/operations/ImageHueSaturationLightness.mjs index e0a1910a..a258a10c 100644 --- a/src/core/operations/ImageHueSaturationLightness.mjs +++ b/src/core/operations/ImageHueSaturationLightness.mjs @@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; -import { Jimp, JimpMime } from "jimp"; +import { Jimp, JimpMime } from "../lib/Jimp.mjs"; /** * Image Hue/Saturation/Lightness operation diff --git a/src/core/operations/ImageOpacity.mjs b/src/core/operations/ImageOpacity.mjs index 4650b8d6..b483bd65 100644 --- a/src/core/operations/ImageOpacity.mjs +++ b/src/core/operations/ImageOpacity.mjs @@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; -import { Jimp, JimpMime } from "jimp"; +import { Jimp, JimpMime } from "../lib/Jimp.mjs"; /** * Image Opacity operation diff --git a/src/core/operations/InvertImage.mjs b/src/core/operations/InvertImage.mjs index cbf46748..73de6901 100644 --- a/src/core/operations/InvertImage.mjs +++ b/src/core/operations/InvertImage.mjs @@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; -import { Jimp, JimpMime } from "jimp"; +import { Jimp, JimpMime } from "../lib/Jimp.mjs"; /** * Invert Image operation diff --git a/src/core/operations/NormaliseImage.mjs b/src/core/operations/NormaliseImage.mjs index 9773761b..5423a0f5 100644 --- a/src/core/operations/NormaliseImage.mjs +++ b/src/core/operations/NormaliseImage.mjs @@ -8,7 +8,7 @@ import Operation from "../Operation.mjs"; import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; -import { Jimp, JimpMime } from "jimp"; +import { Jimp, JimpMime } from "../lib/Jimp.mjs"; /** * Normalise Image operation diff --git a/src/core/operations/RandomizeColourPalette.mjs b/src/core/operations/RandomizeColourPalette.mjs index 186023c2..6573e293 100644 --- a/src/core/operations/RandomizeColourPalette.mjs +++ b/src/core/operations/RandomizeColourPalette.mjs @@ -10,7 +10,7 @@ import Utils from "../Utils.mjs"; import { isImage } from "../lib/FileType.mjs"; import { runHash } from "../lib/Hash.mjs"; import { toBase64 } from "../lib/Base64.mjs"; -import { Jimp } from "jimp"; +import { Jimp } from "../lib/Jimp.mjs"; /** * Randomize Colour Palette operation diff --git a/src/core/operations/ResizeImage.mjs b/src/core/operations/ResizeImage.mjs index bec07c4e..7c91a273 100644 --- a/src/core/operations/ResizeImage.mjs +++ b/src/core/operations/ResizeImage.mjs @@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; -import { Jimp, JimpMime, ResizeStrategy } from "jimp"; +import { Jimp, JimpMime, ResizeStrategy } from "../lib/Jimp.mjs"; /** * Resize Image operation diff --git a/src/core/operations/RotateImage.mjs b/src/core/operations/RotateImage.mjs index 5a96ffab..2413dddc 100644 --- a/src/core/operations/RotateImage.mjs +++ b/src/core/operations/RotateImage.mjs @@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; -import { Jimp, JimpMime } from "jimp"; +import { Jimp, JimpMime } from "../lib/Jimp.mjs"; /** * Rotate Image operation diff --git a/src/core/operations/SharpenImage.mjs b/src/core/operations/SharpenImage.mjs index 1f5461f2..d9f35b4a 100644 --- a/src/core/operations/SharpenImage.mjs +++ b/src/core/operations/SharpenImage.mjs @@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; import { isWorkerEnvironment } from "../Utils.mjs"; -import { Jimp, JimpMime } from "jimp"; +import { Jimp, JimpMime } from "../lib/Jimp.mjs"; /** * Sharpen Image operation diff --git a/src/core/operations/SplitColourChannels.mjs b/src/core/operations/SplitColourChannels.mjs index 3a33b78c..40246b73 100644 --- a/src/core/operations/SplitColourChannels.mjs +++ b/src/core/operations/SplitColourChannels.mjs @@ -8,7 +8,7 @@ import Operation from "../Operation.mjs"; import OperationError from "../errors/OperationError.mjs"; import Utils from "../Utils.mjs"; import { isImage } from "../lib/FileType.mjs"; -import { Jimp, JimpMime } from "jimp"; +import { Jimp, JimpMime } from "../lib/Jimp.mjs"; /** * Split Colour Channels operation diff --git a/src/core/operations/ViewBitPlane.mjs b/src/core/operations/ViewBitPlane.mjs index 3740c10d..3db31c4b 100644 --- a/src/core/operations/ViewBitPlane.mjs +++ b/src/core/operations/ViewBitPlane.mjs @@ -9,7 +9,7 @@ import OperationError from "../errors/OperationError.mjs"; import Utils from "../Utils.mjs"; import { isImage } from "../lib/FileType.mjs"; import { toBase64 } from "../lib/Base64.mjs"; -import { Jimp } from "jimp"; +import { Jimp } from "../lib/Jimp.mjs"; /** * View Bit Plane operation