Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ndarray-pixels

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ndarray-pixels - npm Package Compare versions

Comparing version 2.0.3 to 2.0.4

5

dist/browser-get-pixels.d.ts
import type { NdArray } from 'ndarray';
export declare function getPixelsInternal(buffer: Uint8Array, mimeType: string): Promise<NdArray<Uint8Array>>;
export type GetPixelsCallback = (err: string | Event | null, pixels?: NdArray) => void;
export default getPixels;
declare function getPixels(path: string, callback: GetPixelsCallback): void;
declare function getPixels(path: string | Uint8Array, type: string, callback: GetPixelsCallback): void;

14

dist/browser-save-pixels.d.ts
import type { NdArray } from 'ndarray';
export interface EncoderOptions {
export interface SavePixelsOptions {
quality?: number;
}
export declare function savePixelsInternal(array: NdArray, mimeType: string): Promise<Uint8Array>;
export declare function savePixelsInternal(array: NdArray, mimeType: string, options?: EncoderOptions): Promise<Uint8Array>;
export default savePixels;
declare function savePixels(array: NdArray, type: 'canvas'): HTMLCanvasElement;
declare function savePixels(array: NdArray, type: 'png'): Readable;
declare function savePixels(array: NdArray, type: 'jpeg' | 'jpg', options?: SavePixelsOptions): Readable;
declare class Readable {
private _promise;
constructor(_promise: Promise<Uint8Array>);
on(event: 'data' | 'error' | 'end', fn: (res?: Uint8Array | Error) => void): this;
static from(promise: Promise<Uint8Array>): Readable;
}

@@ -14,3 +14,3 @@ import type { NdArray } from 'ndarray';

*/
declare function getPixels(data: Uint8Array, mimeType: string): Promise<NdArray<Uint8Array>>;
declare function getPixels(data: string | Uint8Array, mimeType?: string): Promise<NdArray>;
/**

@@ -30,3 +30,3 @@ * Encodes an `ndarray` as image data in the given format.

*/
declare function savePixels(pixels: NdArray<Uint8Array>, mimeType: string): Promise<Uint8Array>;
declare function savePixels(pixels: NdArray, mimeType: string): Promise<Uint8Array>;
export { getPixels, savePixels };

@@ -1,134 +0,2 @@

import ndarray from 'ndarray';
import ops from 'ndarray-ops';
function getPixelsInternal(buffer, mimeType) {
// Warn for Data URIs, URLs, and file paths. Support removed in v3.
if (!(buffer instanceof Uint8Array)) {
throw new Error('[ndarray-pixels] Input must be Uint8Array or Buffer.');
}
const blob = new Blob([buffer], {
type: mimeType
});
const path = URL.createObjectURL(blob); // Decode image with Canvas API.
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = function () {
URL.revokeObjectURL(path);
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
const pixels = context.getImageData(0, 0, img.width, img.height);
resolve(ndarray(new Uint8Array(pixels.data), [img.width, img.height, 4], [4, 4 * img.width, 1], 0));
};
img.onerror = err => {
URL.revokeObjectURL(path);
reject(err);
};
img.src = path;
});
}
async function savePixelsInternal(array, mimeType, options = {}) {
// Create HTMLCanvasElement and write pixel data.
const canvas = document.createElement('canvas');
canvas.width = array.shape[0];
canvas.height = array.shape[1];
const context = canvas.getContext('2d');
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
putPixelData(array, imageData.data);
context.putImageData(imageData, 0, 0);
const quality = options.quality ? options.quality / 100 : undefined; // Encode to target format.
switch (mimeType) {
case 'image/jpeg':
return streamCanvas(canvas, 'image/jpeg', quality);
default:
return streamCanvas(canvas, mimeType);
}
}
/** Creates readable stream from given HTMLCanvasElement and options. */
function streamCanvas(canvas, mimeType, quality) {
return new Promise((resolve, reject) => {
canvas.toBlob(async blob => {
if (blob) {
resolve(new Uint8Array(await blob.arrayBuffer()));
} else {
reject(new Error('[ndarray-pixels] Failed to canvas.toBlob().'));
}
}, mimeType, quality);
});
}
function putPixelData(array, data, frame = -1) {
if (array.shape.length === 4) {
return putPixelData(array.pick(frame), data, 0);
} else if (array.shape.length === 3) {
if (array.shape[2] === 3) {
ops.assign(ndarray(data, [array.shape[0], array.shape[1], 3], [4, 4 * array.shape[0], 1]), array);
ops.assigns(ndarray(data, [array.shape[0] * array.shape[1]], [4], 3), 255);
} else if (array.shape[2] === 4) {
ops.assign(ndarray(data, [array.shape[0], array.shape[1], 4], [4, array.shape[0] * 4, 1]), array);
} else if (array.shape[2] === 1) {
ops.assign(ndarray(data, [array.shape[0], array.shape[1], 3], [4, 4 * array.shape[0], 1]), ndarray(array.data, [array.shape[0], array.shape[1], 3], [array.stride[0], array.stride[1], 0], array.offset));
ops.assigns(ndarray(data, [array.shape[0] * array.shape[1]], [4], 3), 255);
} else {
throw new Error('[ndarray-pixels] Incompatible array shape.');
}
} else if (array.shape.length === 2) {
ops.assign(ndarray(data, [array.shape[0], array.shape[1], 3], [4, 4 * array.shape[0], 1]), ndarray(array.data, [array.shape[0], array.shape[1], 3], [array.stride[0], array.stride[1], 0], array.offset));
ops.assigns(ndarray(data, [array.shape[0] * array.shape[1]], [4], 3), 255);
} else {
throw new Error('[ndarray-pixels] Incompatible array shape.');
}
return data;
}
/**
* Decodes image data to an `ndarray`.
*
* MIME type is optional when given a path or URL, and required when given a Uint8Array.
*
* Accepts `image/png` or `image/jpeg` in Node.js, and additional formats on browsers with
* the necessary support in Canvas 2D.
*
* @param data
* @param mimeType `image/jpeg`, `image/png`, etc.
* @returns
*/
async function getPixels(data, mimeType) {
return getPixelsInternal(data, mimeType);
}
/**
* Encodes an `ndarray` as image data in the given format.
*
* If the source `ndarray` was constructed manually with default stride, use
* `ndarray.transpose(1, 0)` to reshape it and ensure an identical result from getPixels(). For an
* ndarray created by getPixels(), this isn't necessary.
*
* Accepts `image/png` or `image/jpeg` in Node.js, and additional formats on browsers with
* the necessary support in Canvas 2D.
*
* @param pixels ndarray of shape W x H x 4.
* @param mimeType `image/jpeg`, `image/png`, etc.
* @returns
*/
async function savePixels(pixels, mimeType) {
return savePixelsInternal(pixels, mimeType);
}
export { getPixels, savePixels };
import e from"ndarray";import t from"ndarray-ops";function a(e,t,a={}){const i=document.createElement("canvas");i.width=e.shape[0],i.height=e.shape[1];const o=i.getContext("2d"),h=o.getImageData(0,0,i.width,i.height);try{n(e,h.data)}catch(e){return s.from(Promise.reject(e))}o.putImageData(h,0,0);const p=a.quality?a.quality/100:void 0;switch(t){case"canvas":return i;case"jpg":case"jpeg":return r(i,"image/jpeg",p);case"png":return r(i,"image/png");default:throw new Error("[ndarray-pixels] Unsupported file type: "+t)}}function r(e,t,a){const r=new Promise((r,n)=>{e.toBlob(async e=>{e?r(new Uint8Array(await e.arrayBuffer())):n(new Error("[ndarray-pixels] Failed to canvas.toBlob()."))},t,a)});return s.from(r)}function n(a,r,s=-1){if(4===a.shape.length)return n(a.pick(s),r,0);if(3===a.shape.length)if(3===a.shape[2])t.assign(e(r,[a.shape[0],a.shape[1],3],[4,4*a.shape[0],1]),a),t.assigns(e(r,[a.shape[0]*a.shape[1]],[4],3),255);else if(4===a.shape[2])t.assign(e(r,[a.shape[0],a.shape[1],4],[4,4*a.shape[0],1]),a);else{if(1!==a.shape[2])throw new Error("[ndarray-pixels] Incompatible array shape.");t.assign(e(r,[a.shape[0],a.shape[1],3],[4,4*a.shape[0],1]),e(a.data,[a.shape[0],a.shape[1],3],[a.stride[0],a.stride[1],0],a.offset)),t.assigns(e(r,[a.shape[0]*a.shape[1]],[4],3),255)}else{if(2!==a.shape.length)throw new Error("[ndarray-pixels] Incompatible array shape.");t.assign(e(r,[a.shape[0],a.shape[1],3],[4,4*a.shape[0],1]),e(a.data,[a.shape[0],a.shape[1],3],[a.stride[0],a.stride[1],0],a.offset)),t.assigns(e(r,[a.shape[0]*a.shape[1]],[4],3),255)}return r}class s{constructor(e){this._promise=void 0,this._promise=e}on(e,t){return"data"===e?this._promise.then(t):"error"===e?this._promise.catch(t):"end"===e&&this._promise.finally(t),this}static from(e){return new s(e)}}async function i(t,a){return t instanceof Uint8Array&&"undefined"!=typeof Buffer&&(t=Buffer.from(t)),new Promise((r,n)=>{!function(t,a,r){if(r=r||a,t instanceof Uint8Array){if("string"!=typeof a)throw new Error("[ndarray-pixels] Type must be given for Uint8Array image data");const e=new Blob([t],{type:a});t=URL.createObjectURL(e)}const n=new Image;n.crossOrigin="anonymous",n.onload=function(){URL.revokeObjectURL(t);const a=document.createElement("canvas");a.width=n.width,a.height=n.height;const s=a.getContext("2d");s.drawImage(n,0,0);const i=s.getImageData(0,0,n.width,n.height);r(null,e(new Uint8Array(i.data),[n.width,n.height,4],[4,4*n.width,1],0))},n.onerror=e=>{URL.revokeObjectURL(t),r(e)},n.src=t}(t,a,(e,t)=>{t&&!e?r(t):n(e)})})}async function o(e,t){return new Promise((r,n)=>{const s=[],i=t.replace("image/","");a(e,i).on("data",e=>s.push(e)).on("end",()=>r(function(e){let t=0;for(const a of e)t+=a.byteLength;const a=new Uint8Array(t);let r=0;for(const t of e)a.set(t,r),r+=t.byteLength;return a}(s))).on("error",e=>n(e))})}export{i as getPixels,o as savePixels};
//# sourceMappingURL=ndarray-pixels-browser.modern.js.map

@@ -1,31 +0,4 @@

import ndarray from 'ndarray';
import sharp from 'sharp';
import getPixelsInternal from 'get-pixels';
import savePixelsInternal from 'save-pixels';
async function getPixelsInternal(buffer, _mimeType) {
// Warn for Data URIs, URLs, and file paths. Support removed in v3.
if (!(buffer instanceof Uint8Array)) {
throw new Error('[ndarray-pixels] Input must be Uint8Array or Buffer.');
}
const {
data,
info
} = await sharp(buffer).ensureAlpha().raw().toBuffer({
resolveWithObject: true
});
return ndarray(new Uint8Array(data), [info.width, info.height, 4], [4, 4 * info.width | 0, 1], 0);
}
async function savePixelsInternal(pixels, mimeType) {
const [width, height, channels] = pixels.shape;
const format = mimeType.replace('image/', '');
return sharp(pixels.data, {
raw: {
width,
height,
channels
}
}).toFormat(format).toBuffer();
}
/**

@@ -45,3 +18,16 @@ * Decodes image data to an `ndarray`.

async function getPixels(data, mimeType) {
return getPixelsInternal(data);
// In Node.js, get-pixels needs a Buffer and won't accept Uint8Array.
if (data instanceof Uint8Array && typeof Buffer !== 'undefined') {
data = Buffer.from(data);
}
return new Promise((resolve, reject) => {
getPixelsInternal(data, mimeType, (err, pixels) => {
if (pixels && !err) {
resolve(pixels);
} else {
reject(err);
}
});
});
}

@@ -65,6 +51,28 @@ /**

async function savePixels(pixels, mimeType) {
return savePixelsInternal(pixels, mimeType);
return new Promise((resolve, reject) => {
const chunks = [];
const internalType = mimeType.replace('image/', '');
savePixelsInternal(pixels, internalType).on('data', d => chunks.push(d)).on('end', () => resolve(concat(chunks))).on('error', e => reject(e));
});
}
function concat(arrays) {
let totalByteLength = 0;
for (const array of arrays) {
totalByteLength += array.byteLength;
}
const result = new Uint8Array(totalByteLength);
let byteOffset = 0;
for (const array of arrays) {
result.set(array, byteOffset);
byteOffset += array.byteLength;
}
return result;
}
export { getPixels, savePixels };
//# sourceMappingURL=ndarray-pixels-node.modern.js.map
import { NdArray } from 'ndarray';
export declare function savePixelsInternal(pixels: NdArray<Uint8Array>, mimeType: string): Promise<Uint8Array>;
export declare function savePixelsInternal(pixels: NdArray<Uint8Array | Uint8ClampedArray>, mimeType: string): Promise<Uint8Array>;
{
"name": "ndarray-pixels",
"version": "2.0.3",
"description": "ndarray-pixels",
"type": "module",
"sideEffects": false,
"types": "./dist/index.d.ts",
"main": "./dist/ndarray-pixels-node.cjs",
"module": "./dist/ndarray-pixels-browser.modern.js",
"exports": {
"types": "./dist/index.d.ts",
"node": {
"require": "./dist/ndarray-pixels-node.cjs",
"default": "./dist/ndarray-pixels-node.modern.js"
},
"default": {
"require": "./dist/ndarray-pixels-browser.cjs",
"default": "./dist/ndarray-pixels-browser.modern.js"
}
},
"repository": "github:donmccurdy/ndarray-pixels",
"author": "Don McCurdy <dm@donmccurdy.com>",
"license": "MIT",
"scripts": {
"dist": "yarn dist:node && yarn dist:browser",
"dist:node": "microbundle build --raw --no-compress --target node --format modern,cjs src/index.ts --output dist/ndarray-pixels-node.js",
"dist:browser": "microbundle build --raw --no-compress --target web --format modern,cjs src/index.ts --output dist/ndarray-pixels-browser.js --alias ./node-get-pixels=./browser-get-pixels.ts,./node-save-pixels=./browser-save-pixels.ts",
"clean": "rm -rf dist/*",
"test": "yarn test:node && yarn test:browser",
"test:node": "tape test/node.test.cjs | tap-spec",
"test:browser": "browserify test/browser.test.cjs | tape-run | tap-spec",
"docs": "typedoc src/index.ts --plugin typedoc-plugin-markdown --out ./docs --hideBreadcrumbs && cat docs/modules.md | tail -n +12 | replace-between --target README.md --token API && rm -rf docs",
"preversion": "yarn dist && yarn test",
"version": "yarn dist && yarn docs && git add -u",
"postversion": "git push && git push --tags && npm publish"
},
"dependencies": {
"@types/ndarray": "^1.0.11",
"ndarray": "^1.0.19",
"ndarray-ops": "^1.2.2",
"sharp": "^0.32.1"
},
"devDependencies": {
"@types/ndarray-ops": "1.2.4",
"@types/node": "20.3.1",
"@types/sharp": "^0.32.0",
"@types/tape": "5.6.0",
"@typescript-eslint/eslint-plugin": "5.59.11",
"@typescript-eslint/parser": "5.59.11",
"browserify": "17.0.0",
"eslint": "8.42.0",
"microbundle": "0.15.1",
"regenerator-runtime": "0.13.11",
"replace-between": "0.0.8",
"source-map-support": "0.5.21",
"tap-spec": "5.0.0",
"tape": "5.6.3",
"tape-run": "10.0.0",
"typedoc": "0.24.8",
"typedoc-plugin-markdown": "3.15.3",
"typescript": "5.1.3"
},
"files": [
"dist/",
"src/",
"README.md",
"LICENSE",
"package.json"
]
"name": "ndarray-pixels",
"version": "2.0.4",
"description": "ndarray-pixels",
"type": "module",
"sideEffects": false,
"types": "./dist/index.d.ts",
"main": "./dist/ndarray-pixels-node.cjs",
"module": "./dist/ndarray-pixels-browser.modern.js",
"exports": {
"types": "./dist/index.d.ts",
"node": {
"require": "./dist/ndarray-pixels-node.cjs",
"default": "./dist/ndarray-pixels-node.modern.js"
},
"default": {
"require": "./dist/ndarray-pixels-browser.cjs",
"default": "./dist/ndarray-pixels-browser.modern.js"
}
},
"repository": "github:donmccurdy/ndarray-pixels",
"author": "Don McCurdy <dm@donmccurdy.com>",
"license": "MIT",
"scripts": {
"dist": "yarn dist:node && yarn dist:browser",
"dist:node": "microbundle build --raw --target node --format modern,cjs src/index.ts --output dist/ndarray-pixels-node.js",
"dist:browser": "microbundle build --raw --target web --format modern,cjs src/index.ts --output dist/ndarray-pixels-browser.js --alias get-pixels=./browser-get-pixels.ts,save-pixels=./browser-save-pixels.ts",
"clean": "rm -rf dist/*",
"test": "yarn test:node && yarn test:browser",
"test:node": "tape test/node.test.cjs | tap-spec",
"test:browser": "browserify test/browser.test.cjs | tape-run | tap-spec",
"docs": "typedoc src/index.ts --plugin typedoc-plugin-markdown --out ./docs --hideBreadcrumbs && cat docs/modules.md | tail -n +12 | replace-between --target README.md --token API && rm -rf docs",
"preversion": "yarn dist && yarn test",
"version": "yarn dist && yarn docs && git add -u",
"postversion": "git push && git push --tags && npm publish"
},
"dependencies": {
"@types/ndarray": "^1.0.11",
"get-pixels": "^3.3.3",
"ndarray": "^1.0.19",
"ndarray-ops": "^1.2.2",
"save-pixels": "^2.3.6"
},
"devDependencies": {
"@types/get-pixels": "3.3.2",
"@types/ndarray-ops": "1.2.4",
"@types/node": "20.1.4",
"@types/save-pixels": "2.3.2",
"@types/tape": "5.6.0",
"@typescript-eslint/eslint-plugin": "5.59.8",
"@typescript-eslint/parser": "5.59.8",
"browserify": "17.0.0",
"eslint": "8.42.0",
"microbundle": "0.15.1",
"regenerator-runtime": "0.13.11",
"replace-between": "0.0.8",
"source-map-support": "0.5.21",
"tap-spec": "5.0.0",
"tape": "5.6.3",
"tape-run": "10.0.0",
"typedoc": "0.24.7",
"typedoc-plugin-markdown": "3.15.3",
"typescript": "5.1.3"
},
"files": [
"dist/",
"src/",
"README.md",
"LICENSE",
"package.json"
]
}

@@ -12,8 +12,10 @@ # ndarray-pixels

In Node.js, this package uses [get-pixels](https://www.npmjs.com/package/get-pixels) and [save-pixels](https://www.npmjs.com/package/save-pixels). While both packages could be used on the web, they require polyfills for Node.js builtins. Browserify handles that automatically, but more modern bundlers do not. Moreover, the polyfills increase package size significantly. To avoid these problems, web builds of `ndarray-pixels` reimplement the same functionality with the more portable Canvas API.
## Supported Formats
| Platform | JPEG | PNG | Other |
|----------|------|-----|-------------------------------------------------------------------------------------------------------|
| Node.js | ✅ | ✅ | Based on [sharp support](https://sharp.pixelplumbing.com/) |
| Web | ✅ | ✅ | Based on [browser support](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob) |
| Platform | JPEG | PNG | Other |
|----------|------|-----|-------|
| Node.js | ✅ | ✅ | ❌ |
| Web | ✅ | ✅ | Based on [browser support](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob) |

@@ -83,3 +85,3 @@ ### Known Bugs

▸ **getPixels**(`data`, `mimeType`): `Promise`<`NdArray`<`Uint8Array`\>\>
▸ **getPixels**(`data`, `mimeType?`): `Promise`<`NdArray`\>

@@ -97,12 +99,12 @@ Decodes image data to an `ndarray`.

| :------ | :------ | :------ |
| `data` | `Uint8Array` | |
| `mimeType` | `string` | `image/jpeg`, `image/png`, etc. |
| `data` | `string` \| `Uint8Array` | |
| `mimeType?` | `string` | `image/jpeg`, `image/png`, etc. |
#### Returns
`Promise`<`NdArray`<`Uint8Array`\>\>
`Promise`<`NdArray`\>
#### Defined in
[index.ts:17](https://github.com/donmccurdy/ndarray-pixels/blob/63dde63/src/index.ts#L17)
[index.ts:17](https://github.com/donmccurdy/ndarray-pixels/blob/f667d9c/src/index.ts#L17)

@@ -128,3 +130,3 @@ ___

| :------ | :------ | :------ |
| `pixels` | `NdArray`<`Uint8Array`\> | ndarray of shape W x H x 4. |
| `pixels` | `NdArray`<`TypedArray` \| `GenericArray`<`number`\> \| `number`[]\> | ndarray of shape W x H x 4. |
| `mimeType` | `string` | `image/jpeg`, `image/png`, etc. |

@@ -138,3 +140,3 @@

[index.ts:35](https://github.com/donmccurdy/ndarray-pixels/blob/63dde63/src/index.ts#L35)
[index.ts:48](https://github.com/donmccurdy/ndarray-pixels/blob/f667d9c/src/index.ts#L48)
<!--- API END --->
import ndarray from 'ndarray';
import type { NdArray } from 'ndarray';
export function getPixelsInternal(
buffer: Uint8Array,
mimeType: string
): Promise<NdArray<Uint8Array>> {
// Warn for Data URIs, URLs, and file paths. Support removed in v3.
if (!(buffer instanceof Uint8Array)) {
throw new Error('[ndarray-pixels] Input must be Uint8Array or Buffer.');
export type GetPixelsCallback = (err: string | Event | null, pixels?: NdArray) => void;
export default getPixels;
function getPixels(path: string, callback: GetPixelsCallback): void;
function getPixels(path: string | Uint8Array, type: string, callback: GetPixelsCallback): void
function getPixels(path: string | Uint8Array, typeOrCallback: string | GetPixelsCallback, callback?: GetPixelsCallback): void {
callback = callback || typeOrCallback as GetPixelsCallback;
// Construct a Blob URL for Uint8Array inputs.
if (path instanceof Uint8Array) {
if (typeof typeOrCallback !== 'string') {
throw new Error('[ndarray-pixels] Type must be given for Uint8Array image data');
}
const blob = new Blob([path], {type: typeOrCallback});
path = URL.createObjectURL(blob);
}
const blob = new Blob([buffer], { type: mimeType });
const path = URL.createObjectURL(blob);
// Decode image with Canvas API.
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = function () {
URL.revokeObjectURL(path as string);
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = function() {
URL.revokeObjectURL(path as string);
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const context = canvas.getContext('2d')!;
context.drawImage(img, 0, 0);
const pixels = context.getImageData(0, 0, img.width, img.height);
resolve(
ndarray(
new Uint8Array(pixels.data),
[img.width, img.height, 4],
[4, 4 * img.width, 1],
0
)
);
};
img.onerror = (err) => {
URL.revokeObjectURL(path as string);
reject(err);
};
img.src = path;
});
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const context = canvas.getContext('2d')!;
context.drawImage(img, 0, 0);
const pixels = context.getImageData(0, 0, img.width, img.height)
callback!(null, ndarray(new Uint8Array(pixels.data), [img.width, img.height, 4], [4, 4*img.width, 1], 0));
}
img.onerror = (err) => {
URL.revokeObjectURL(path as string);
callback!(err);
};
img.src = path;
}

@@ -5,17 +5,14 @@ import ndarray from 'ndarray';

export interface EncoderOptions {
quality?: number;
}
export interface SavePixelsOptions {quality?: number}
export async function savePixelsInternal(array: NdArray, mimeType: string): Promise<Uint8Array>;
export async function savePixelsInternal(
array: NdArray,
mimeType: string,
options?: EncoderOptions
): Promise<Uint8Array>;
export async function savePixelsInternal(
array: NdArray,
mimeType: string,
options: EncoderOptions = {}
): Promise<Uint8Array> {
export default savePixels;
function savePixels(array: NdArray, type: 'canvas'): HTMLCanvasElement;
function savePixels(array: NdArray, type: 'png'): Readable;
function savePixels(array: NdArray, type: 'jpeg' | 'jpg', options?: SavePixelsOptions): Readable;
function savePixels(
array: NdArray, type: 'canvas' | 'png' | 'jpeg' | 'jpg',
options: SavePixelsOptions = {}
): Readable | HTMLCanvasElement {
// Create HTMLCanvasElement and write pixel data.

@@ -29,3 +26,9 @@ const canvas = document.createElement('canvas');

putPixelData(array, imageData.data);
try {
handleData(array, imageData.data);
} catch (e) {
// Pass errors to stream, to match 'save-pixels' behavior.
return Readable.from(Promise.reject(e));
}
context.putImageData(imageData, 0, 0);

@@ -36,7 +39,12 @@

// Encode to target format.
switch (mimeType) {
case 'image/jpeg':
switch (type) {
case 'canvas':
return canvas;
case 'jpg':
case 'jpeg':
return streamCanvas(canvas, 'image/jpeg', quality);
case 'png':
return streamCanvas(canvas, 'image/png');
default:
return streamCanvas(canvas, mimeType);
throw new Error('[ndarray-pixels] Unsupported file type: ' + type);
}

@@ -46,23 +54,16 @@ }

/** Creates readable stream from given HTMLCanvasElement and options. */
function streamCanvas(
canvas: HTMLCanvasElement,
mimeType: string,
quality?: number
): Promise<Uint8Array> {
return new Promise<Uint8Array>((resolve, reject) => {
canvas.toBlob(
async (blob) => {
if (blob) {
resolve(new Uint8Array(await blob.arrayBuffer()));
} else {
reject(new Error('[ndarray-pixels] Failed to canvas.toBlob().'));
}
},
mimeType,
quality
);
function streamCanvas(canvas: HTMLCanvasElement, mimeType: string, quality?: number): Readable {
const promise = new Promise<Uint8Array>((resolve, reject) => {
canvas.toBlob(async (blob) => {
if (blob) {
resolve(new Uint8Array(await blob.arrayBuffer()));
} else {
reject(new Error('[ndarray-pixels] Failed to canvas.toBlob().'));
}
}, mimeType, quality);
});
return Readable.from(promise);
}
function putPixelData(
function handleData(
array: NdArray,

@@ -72,14 +73,31 @@ data: Uint8Array | Uint8ClampedArray,

): Uint8Array | Uint8ClampedArray {
if (array.shape.length === 4) {
return putPixelData(array.pick(frame), data, 0);
return handleData(array.pick(frame), data, 0);
} else if (array.shape.length === 3) {
if (array.shape[2] === 3) {
ops.assign(
ndarray(data, [array.shape[0], array.shape[1], 3], [4, 4 * array.shape[0], 1]),
ndarray(
data,
[array.shape[0], array.shape[1], 3],
[4, 4 * array.shape[0], 1]
),
array
);
ops.assigns(ndarray(data, [array.shape[0] * array.shape[1]], [4], 3), 255);
ops.assigns(
ndarray(
data,
[array.shape[0] * array.shape[1]],
[4],
3
),
255
);
} else if (array.shape[2] === 4) {
ops.assign(
ndarray(data, [array.shape[0], array.shape[1], 4], [4, array.shape[0] * 4, 1]),
ndarray(
data,
[array.shape[0], array.shape[1], 4],
[4, array.shape[0] * 4, 1]
),
array

@@ -89,4 +107,8 @@ );

ops.assign(
ndarray(data, [array.shape[0], array.shape[1], 3], [4, 4 * array.shape[0], 1]),
ndarray(
data,
[array.shape[0], array.shape[1], 3],
[4, 4 * array.shape[0], 1]
),
ndarray(
array.data,

@@ -98,3 +120,11 @@ [array.shape[0], array.shape[1], 3],

);
ops.assigns(ndarray(data, [array.shape[0] * array.shape[1]], [4], 3), 255);
ops.assigns(
ndarray(
data,
[array.shape[0] * array.shape[1]],
[4],
3
),
255
);
} else {

@@ -105,11 +135,17 @@ throw new Error('[ndarray-pixels] Incompatible array shape.');

ops.assign(
ndarray(data, [array.shape[0], array.shape[1], 3], [4, 4 * array.shape[0], 1]),
ndarray(
array.data,
[array.shape[0], array.shape[1], 3],
[array.stride[0], array.stride[1], 0],
array.offset
)
ndarray(data,
[array.shape[0], array.shape[1], 3],
[4, 4 * array.shape[0], 1]),
ndarray(array.data,
[array.shape[0], array.shape[1], 3],
[array.stride[0], array.stride[1], 0],
array.offset)
);
ops.assigns(ndarray(data, [array.shape[0] * array.shape[1]], [4], 3), 255);
ops.assigns(
ndarray(data,
[array.shape[0] * array.shape[1]],
[4],
3),
255
);
} else {

@@ -120,1 +156,20 @@ throw new Error('[ndarray-pixels] Incompatible array shape.');

}
class Readable {
constructor (private _promise: Promise<Uint8Array>) {}
on(event: 'data' | 'error' | 'end', fn: (res?: Uint8Array | Error) => void): this {
if (event === 'data') {
this._promise.then(fn);
} else if (event === 'error') {
this._promise.catch(fn)
} else if (event === 'end') {
this._promise.finally(fn);
}
return this;
}
static from (promise: Promise<Uint8Array>): Readable {
return new Readable(promise);
}
}

@@ -0,4 +1,4 @@

import getPixelsInternal from 'get-pixels';
import type { NdArray } from 'ndarray';
import { getPixelsInternal } from './node-get-pixels';
import { savePixelsInternal } from './node-save-pixels';
import savePixelsInternal from 'save-pixels';

@@ -17,4 +17,17 @@ /**

*/
async function getPixels(data: Uint8Array, mimeType: string): Promise<NdArray<Uint8Array>> {
return getPixelsInternal(data, mimeType);
async function getPixels (data: string | Uint8Array, mimeType?: string): Promise<NdArray> {
// In Node.js, get-pixels needs a Buffer and won't accept Uint8Array.
if (data instanceof Uint8Array && typeof Buffer !== 'undefined') {
data = Buffer.from(data);
}
return new Promise((resolve, reject) => {
getPixelsInternal(data, mimeType!, (err: Error | null, pixels: NdArray) => {
if (pixels && !err) {
resolve(pixels);
} else {
reject(err);
}
});
});
}

@@ -36,6 +49,30 @@

*/
async function savePixels(pixels: NdArray<Uint8Array>, mimeType: string): Promise<Uint8Array> {
return savePixelsInternal(pixels, mimeType);
async function savePixels (pixels: NdArray, mimeType: string): Promise<Uint8Array> {
return new Promise((resolve, reject) => {
const chunks: Uint8Array[] = [];
const internalType = mimeType.replace('image/', '') as 'png' | 'gif';
savePixelsInternal(pixels, internalType)
.on('data', (d: Uint8Array) => chunks.push(d))
.on('end', () => resolve(concat(chunks)))
.on('error', (e: Error) => reject(e));
});
}
export { getPixels, savePixels };
function concat (arrays: Uint8Array[]): Uint8Array {
let totalByteLength = 0;
for (const array of arrays) {
totalByteLength += array.byteLength;
}
const result = new Uint8Array(totalByteLength);
let byteOffset = 0;
for (const array of arrays) {
result.set(array, byteOffset);
byteOffset += array.byteLength;
}
return result;
}
export {getPixels, savePixels};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc