Add support for Uint8(Clamped)Array input (#2511)

This commit is contained in:
Leon Radley
2021-01-06 10:49:24 +01:00
committed by GitHub
parent bf1b326988
commit 4821a11223
8 changed files with 141 additions and 33 deletions

View File

@@ -90,8 +90,22 @@ const debuglog = util.debuglog('sharp');
* // Convert an animated GIF to an animated WebP
* await sharp('in.gif', { animated: true }).toFile('out.webp');
*
* @param {(Buffer|string)} [input] - if present, can be
* a Buffer containing JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or raw pixel image data, or
* @example
* // Read a raw array of pixels and save it to a png
* const input = Uint8Array.from([255, 255, 255, 0, 0, 0]); // or Uint8ClampedArray
* const image = sharp(input, {
* // because the input does not contain its dimensions or how many channels it has
* // we need to specify it in the constructor options
* raw: {
* width: 2,
* height: 1,
* channels: 3
* }
* });
* await image.toFile('my-two-pixels.png');
*
* @param {(Buffer|Uint8Array|Uint8ClampedArray|string)} [input] - if present, can be
* a Buffer / Uint8Array / Uint8ClampedArray containing JPEG, PNG, WebP, AVIF, GIF, SVG, TIFF or 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.
* @param {Object} [options] - if present, is an Object with optional attributes.

View File

@@ -31,6 +31,9 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
} else if (is.buffer(input)) {
// Buffer
inputDescriptor.buffer = input;
} else if (is.uint8Array(input)) {
// Uint8Array or Uint8ClampedArray
inputDescriptor.buffer = Buffer.from(input.buffer);
} else if (is.plainObject(input) && !is.defined(inputOptions)) {
// Plain Object descriptor, e.g. create
inputOptions = input;

View File

@@ -48,6 +48,15 @@ const buffer = function (val) {
return val instanceof Buffer;
};
/**
* Is this value a Uint8Array or Uint8ClampedArray object?
* @private
*/
const uint8Array = function (val) {
// allow both since Uint8ClampedArray simply clamps the values between 0-255
return val instanceof Uint8Array || val instanceof Uint8ClampedArray;
};
/**
* Is this value a non-empty string?
* @private
@@ -110,6 +119,7 @@ module.exports = {
fn: fn,
bool: bool,
buffer: buffer,
uint8Array: uint8Array,
string: string,
number: number,
integer: integer,

View File

@@ -104,6 +104,20 @@ function toFile (fileOut, callback) {
* .then(({ data, info }) => { ... })
* .catch(err => { ... });
*
* @example
* const data = await sharp('my-image.jpg')
* // output the raw pixels
* .raw()
* .toBuffer();
*
* // create a more type safe way to work with the raw pixel data
* // this will not copy the data, instead it will change `data`s underlying ArrayBuffer
* // so `data` and `pixelArray` point to the same memory location
* const pixelArray = new Uint8ClampedArray(data.buffer);
*
* // When you are done changing the pixelArray, sharp takes the `pixelArray` as an input
* await sharp(pixelArray).toFile('my-changed-image.jpg');
*
* @param {Object} [options]
* @param {boolean} [options.resolveWithObject] Resolve the Promise with an Object containing `data` and `info` properties instead of resolving only with `data`.
* @param {Function} [callback]