diff --git a/lib/constructor.js b/lib/constructor.js index b69adb73..7e67411f 100644 --- a/lib/constructor.js +++ b/lib/constructor.js @@ -113,8 +113,8 @@ const debuglog = util.debuglog('sharp'); * } * }).toFile('text_rgba.png'); * - * @param {(Buffer|Uint8Array|Uint8ClampedArray|Int8Array|Uint16Array|Int16Array|Uint32Array|Int32Array|Float32Array|Float64Array|string)} [input] - if present, can be - * a Buffer / Uint8Array / Uint8ClampedArray containing JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image data, or + * @param {(Buffer|ArrayBuffer|Uint8Array|Uint8ClampedArray|Int8Array|Uint16Array|Int16Array|Uint32Array|Int32Array|Float32Array|Float64Array|string)} [input] - if present, can be + * a Buffer / ArrayBuffer / Uint8Array / Uint8ClampedArray containing JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image data, or * a TypedArray containing raw pixel image data, or * a String containing the filesystem path to an JPEG, PNG, WebP, AVIF, GIF, SVG or TIFF image file. * JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data can be streamed into the object when not present. diff --git a/lib/index.d.ts b/lib/index.d.ts index cce81714..6b6e0543 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -29,6 +29,7 @@ declare function sharp(options?: sharp.SharpOptions): sharp.Sharp; declare function sharp( input?: | Buffer + | ArrayBuffer | Uint8Array | Uint8ClampedArray | Int8Array diff --git a/lib/input.js b/lib/input.js index 3b403d89..971da50c 100644 --- a/lib/input.js +++ b/lib/input.js @@ -47,6 +47,11 @@ function _createInputDescriptor (input, inputOptions, containerOptions) { throw Error('Input Buffer is empty'); } inputDescriptor.buffer = input; + } else if (is.arrayBuffer(input)) { + if (input.byteLength === 0) { + throw Error('Input bit Array is empty'); + } + inputDescriptor.buffer = Buffer.from(input, 0, input.byteLength); } else if (is.typedArray(input)) { if (input.length === 0) { throw Error('Input Bit Array is empty'); diff --git a/lib/is.js b/lib/is.js index 24b8a957..a7724a63 100644 --- a/lib/is.js +++ b/lib/is.js @@ -71,6 +71,14 @@ const typedArray = function (val) { return false; }; +/** + * Is this value an ArrayBuffer object? + * @private + */ +const arrayBuffer = function (val) { + return val instanceof ArrayBuffer; +}; + /** * Is this value a non-empty string? * @private @@ -134,6 +142,7 @@ module.exports = { bool: bool, buffer: buffer, typedArray: typedArray, + arrayBuffer: arrayBuffer, string: string, number: number, integer: integer, diff --git a/test/unit/io.js b/test/unit/io.js index 79d1d6bc..57ae935e 100644 --- a/test/unit/io.js +++ b/test/unit/io.js @@ -150,6 +150,23 @@ describe('Input/output', function () { readable.pipe(pipeline).pipe(writable); }); + it('Read from ArrayBuffer and write to Buffer', async () => { + const uint8array = Uint8Array.from([255, 255, 255, 0, 0, 0]); + const arrayBuffer = new ArrayBuffer(uint8array.byteLength); + new Uint8Array(arrayBuffer).set(uint8array); + const { data, info } = await sharp(arrayBuffer, { + raw: { + width: 2, + height: 1, + channels: 3 + } + }).toBuffer({ resolveWithObject: true }); + + assert.deepStrictEqual(uint8array, new Uint8Array(data)); + assert.strictEqual(info.width, 2); + assert.strictEqual(info.height, 1); + }); + it('Read from Uint8Array and write to Buffer', async () => { const uint8array = Uint8Array.from([255, 255, 255, 0, 0, 0]); const { data, info } = await sharp(uint8array, { diff --git a/test/unit/raw.js b/test/unit/raw.js index 6f8bef98..e3513ed0 100644 --- a/test/unit/raw.js +++ b/test/unit/raw.js @@ -11,6 +11,9 @@ describe('Raw pixel data', function () { assert.throws(function () { sharp(Buffer.from('')); }, /empty/); + assert.throws(function () { + sharp(new ArrayBuffer(0)); + }, /empty/); assert.throws(function () { sharp(new Uint8Array(0)); }, /empty/);