@thi.ng/pixel
Advanced tools
Comparing version 1.0.5 to 2.0.0
14
api.d.ts
@@ -64,2 +64,6 @@ import type { FloatArray, Fn, Fn2, Fn3, FnN, FnU2, IObjectOf, NumericArray, TypedArray, UintType } from "@thi.ng/api"; | ||
/** | ||
* Number of possible values in channel (i.e. `1 << size`) | ||
*/ | ||
num: number; | ||
/** | ||
* Bit shift offset (in bits, not shifted value) | ||
@@ -100,6 +104,2 @@ */ | ||
setFloat: ChannelSetter<number>; | ||
/** | ||
* Applies ordered dithering to given channel value. | ||
*/ | ||
dither: (mat: BayerMatrix, steps: number, x: number, y: number, val: number) => number; | ||
} | ||
@@ -297,8 +297,2 @@ /** | ||
} | ||
export declare type BayerSize = 1 | 2 | 4 | 8 | 16 | 32 | 64; | ||
export interface BayerMatrix { | ||
mat: number[][]; | ||
invSize: number; | ||
mask: number; | ||
} | ||
export declare type PoolTemplate = Fn3<string[], number, number, string>; | ||
@@ -305,0 +299,0 @@ export interface ConvolutionKernelSpec { |
@@ -1,2 +0,2 @@ | ||
import { isNumber } from "@thi.ng/checks"; | ||
import { isNumber } from "@thi.ng/checks/is-number"; | ||
/** | ||
@@ -3,0 +3,0 @@ * Creates a canvas element of given size, obtains its 2D drawing |
221
CHANGELOG.md
@@ -6,187 +6,172 @@ # Change Log | ||
## [1.0.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@1.0.4...@thi.ng/pixel@1.0.5) (2021-09-03) | ||
# [2.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@1.0.5...@thi.ng/pixel@2.0.0) (2021-10-12) | ||
**Note:** Version bump only for package @thi.ng/pixel | ||
### Build System | ||
* major update of ALL pkgs (export maps, ESM only) ([0d1d6ea](https://github.com/thi-ng/umbrella/commit/0d1d6ea9fab2a645d6c5f2bf2591459b939c09b6)) | ||
### Code Refactoring | ||
# [0.11.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.10.5...@thi.ng/pixel@0.11.0) (2021-08-04) | ||
* **pixel:** replace static PackedBuffer methods ([8e5d2db](https://github.com/thi-ng/umbrella/commit/8e5d2db6815ad1bf0e20cbbf7ab6628340125e10)) | ||
* **pixel:** restructure package ([698130a](https://github.com/thi-ng/umbrella/commit/698130acf10056c30f0d7caae259df366a2484ce)) | ||
### Features | ||
### BREAKING CHANGES | ||
* **pixel:** add DominantColorOpts ([a57882b](https://github.com/thi-ng/umbrella/commit/a57882bbbf2f3520eb5ec849d548fb47c08c3bff)) | ||
* **pixel:** replace static PackedBuffer methods w/ standalone functions | ||
- add packedBufferFromImage() | ||
- add packedBufferFromCanvas() | ||
- remove deprecated buffer() ctor fn | ||
* **pixel:** migrate dither ops to new pkg thi.ng/pixel-dither | ||
- remove dither related types & functions | ||
- remove PackedBuffer.dither() | ||
- move internal helpers | ||
* discontinue CommonJS & UMD versions | ||
- only ESM modules will be published from now on | ||
- CJS obsolete due to ESM support in recent versions of node: | ||
- i.e. launch NodeJS via: | ||
- `node --experimental-specifier-resolution=node --experimental-repl-await` | ||
- in the node REPL use `await import(...)` instead of `require()` | ||
- UMD obsolete due to widespread browser support for ESM | ||
Also: | ||
- normalize/restructure/reorg all package.json files | ||
- cleanup all build scripts, remove obsolete | ||
- switch from mocha to @thi.ng/testament for all tests | ||
# [0.10.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.9.0...@thi.ng/pixel@0.10.0) (2021-04-19) | ||
### Features | ||
* **pixel:** add dominantColors(), update deps ([ad0617e](https://github.com/thi-ng/umbrella/commit/ad0617e6ed3077d8d0c1549416afc27df261edc9)) | ||
## [1.0.5](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@1.0.4...@thi.ng/pixel@1.0.5) (2021-09-03) | ||
**Note:** Version bump only for package @thi.ng/pixel | ||
# [0.11.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.10.5...@thi.ng/pixel@0.11.0) (2021-08-04) | ||
# [0.9.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.8.1...@thi.ng/pixel@0.9.0) (2021-04-03) | ||
### Features | ||
- **pixel:** add DominantColorOpts ([a57882b](https://github.com/thi-ng/umbrella/commit/a57882bbbf2f3520eb5ec849d548fb47c08c3bff)) | ||
### Features | ||
# [0.10.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.9.0...@thi.ng/pixel@0.10.0) (2021-04-19) | ||
* **pixel:** add .upsize() impls, fix convolve() ([08f0d7c](https://github.com/thi-ng/umbrella/commit/08f0d7c200fa03bc4fb017d3dbc9237581af19ee)) | ||
* **pixel:** add imagePyramid() iterator ([7f77e07](https://github.com/thi-ng/umbrella/commit/7f77e07089eca68b5825715c3709312d4374c37a)) | ||
* **pixel:** add IToImageData & impls ([3172e1e](https://github.com/thi-ng/umbrella/commit/3172e1eb8582901bddf12281e65df618e4d4f476)) | ||
* **pixel:** update/fix convolution, add LANCZOS ([eadefda](https://github.com/thi-ng/umbrella/commit/eadefda5f119ee8453edb3df3109ebcba692b429)) | ||
### Features | ||
- **pixel:** add dominantColors(), update deps ([ad0617e](https://github.com/thi-ng/umbrella/commit/ad0617e6ed3077d8d0c1549416afc27df261edc9)) | ||
# [0.9.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.8.1...@thi.ng/pixel@0.9.0) (2021-04-03) | ||
### Features | ||
- **pixel:** add .upsize() impls, fix convolve() ([08f0d7c](https://github.com/thi-ng/umbrella/commit/08f0d7c200fa03bc4fb017d3dbc9237581af19ee)) | ||
- **pixel:** add imagePyramid() iterator ([7f77e07](https://github.com/thi-ng/umbrella/commit/7f77e07089eca68b5825715c3709312d4374c37a)) | ||
- **pixel:** add IToImageData & impls ([3172e1e](https://github.com/thi-ng/umbrella/commit/3172e1eb8582901bddf12281e65df618e4d4f476)) | ||
- **pixel:** update/fix convolution, add LANCZOS ([eadefda](https://github.com/thi-ng/umbrella/commit/eadefda5f119ee8453edb3df3109ebcba692b429)) | ||
## [0.8.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.8.0...@thi.ng/pixel@0.8.1) (2021-03-20) | ||
## [0.8.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.8.0...@thi.ng/pixel@0.8.1) (2021-03-20) | ||
### Bug Fixes | ||
### Bug Fixes | ||
- **pixel:** update convolve() for even kernel sizes ([b086224](https://github.com/thi-ng/umbrella/commit/b086224a51c0dd23b4cae1d158c1e1236328d445)) | ||
* **pixel:** update convolve() for even kernel sizes ([b086224](https://github.com/thi-ng/umbrella/commit/b086224a51c0dd23b4cae1d158c1e1236328d445)) | ||
# [0.8.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.7.4...@thi.ng/pixel@0.8.0) (2021-03-17) | ||
### Features | ||
- **pixel:** add bicubic samplers, fix resize() ([951fa9e](https://github.com/thi-ng/umbrella/commit/951fa9e1263db6f165dcaee3c951c09b43e42fef)) | ||
- **pixel:** add defIndexed() HOF pixel format ([c13a568](https://github.com/thi-ng/umbrella/commit/c13a5687fac6d08c14d80f380b5c664422b18a3e)) | ||
- **pixel:** add defSampler(), resize() ([aa71eb7](https://github.com/thi-ng/umbrella/commit/aa71eb7a2ccf02fa543c68308371143882ae5e5f)), closes [#256](https://github.com/thi-ng/umbrella/issues/256) | ||
- **pixel:** add float format samplers, update various types ([6f9dae6](https://github.com/thi-ng/umbrella/commit/6f9dae6010118e491ed161fa4a5bd40ec4719ad4)) | ||
# [0.7.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.6.1...@thi.ng/pixel@0.7.0) (2021-03-03) | ||
### Bug Fixes | ||
# [0.8.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.7.4...@thi.ng/pixel@0.8.0) (2021-03-17) | ||
- **pixel:** add clamping for float->ABGR conversion ([41540e0](https://github.com/thi-ng/umbrella/commit/41540e085b2261208e44e6f25b327e3371eae2df)) | ||
- **pixel:** fix POOL_NEAREST index ([b98d05d](https://github.com/thi-ng/umbrella/commit/b98d05d7827d98d3971bdbcd562735b96fa9b7ec)) | ||
### Features | ||
* **pixel:** add bicubic samplers, fix resize() ([951fa9e](https://github.com/thi-ng/umbrella/commit/951fa9e1263db6f165dcaee3c951c09b43e42fef)) | ||
* **pixel:** add defIndexed() HOF pixel format ([c13a568](https://github.com/thi-ng/umbrella/commit/c13a5687fac6d08c14d80f380b5c664422b18a3e)) | ||
* **pixel:** add defSampler(), resize() ([aa71eb7](https://github.com/thi-ng/umbrella/commit/aa71eb7a2ccf02fa543c68308371143882ae5e5f)), closes [#256](https://github.com/thi-ng/umbrella/issues/256) | ||
* **pixel:** add float format samplers, update various types ([6f9dae6](https://github.com/thi-ng/umbrella/commit/6f9dae6010118e491ed161fa4a5bd40ec4719ad4)) | ||
- **pixel:** add 5x5 kernel presets ([56f96f4](https://github.com/thi-ng/umbrella/commit/56f96f4842e6a57087a565a8e5ce82e590da7d66)) | ||
- **pixel:** add convolve() & preset kernels ([6a31dc3](https://github.com/thi-ng/umbrella/commit/6a31dc38f3f0ae48853d899420d0fbebcc6b8678)) | ||
- **pixel:** add defKernel() kernel fn codegen ([25b97a3](https://github.com/thi-ng/umbrella/commit/25b97a341fa54ee8a82e3083fcb85a8061db8b1f)) | ||
- **pixel:** add defLargeKernel(), conv presets ([9c71165](https://github.com/thi-ng/umbrella/commit/9c71165adb71103fa88a5486987f270fecd2f439)) | ||
- **pixel:** add gradientImage() & FLOAT_NORMAL format ([78683b7](https://github.com/thi-ng/umbrella/commit/78683b701418bf184b2a1327cfd5e50397d687e0)) | ||
- **pixel:** add IEmpty impls for Float/PackedBuffer ([46ac1a1](https://github.com/thi-ng/umbrella/commit/46ac1a1906b256eefab0934efea300c67db7ea28)) | ||
- **pixel:** add normalMap(), add more kernels ([f32686d](https://github.com/thi-ng/umbrella/commit/f32686d463ffcb49b37e9b1b811ff5de06b58fed)) | ||
- **pixel:** add POOL_THRESHOLD preset ([5f1c1de](https://github.com/thi-ng/umbrella/commit/5f1c1dea87251f8a584cbe94d83784e7e4cc31a5)) | ||
- **pixel:** add step size support for normalMap() ([ab72a79](https://github.com/thi-ng/umbrella/commit/ab72a79532baab3f07f53419cb5970e90e97e0dd)) | ||
- **pixel:** add/update buffer factory fns ([ba38e13](https://github.com/thi-ng/umbrella/commit/ba38e137c6913d048bb4d678137241ee179d160c)) | ||
- **pixel:** update PackedBuffer.fromCanvas() ([3bdb086](https://github.com/thi-ng/umbrella/commit/3bdb0860bcd35a0475e83ebe948847f1ecd42db6)) | ||
- **pixel:** update/extend/refactor convolveChannel/Image() ([6692865](https://github.com/thi-ng/umbrella/commit/6692865d5facb75bf667056afa9cfee93ade2da6)) | ||
# [0.7.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.6.1...@thi.ng/pixel@0.7.0) (2021-03-03) | ||
### Bug Fixes | ||
* **pixel:** add clamping for float->ABGR conversion ([41540e0](https://github.com/thi-ng/umbrella/commit/41540e085b2261208e44e6f25b327e3371eae2df)) | ||
* **pixel:** fix POOL_NEAREST index ([b98d05d](https://github.com/thi-ng/umbrella/commit/b98d05d7827d98d3971bdbcd562735b96fa9b7ec)) | ||
### Features | ||
* **pixel:** add 5x5 kernel presets ([56f96f4](https://github.com/thi-ng/umbrella/commit/56f96f4842e6a57087a565a8e5ce82e590da7d66)) | ||
* **pixel:** add convolve() & preset kernels ([6a31dc3](https://github.com/thi-ng/umbrella/commit/6a31dc38f3f0ae48853d899420d0fbebcc6b8678)) | ||
* **pixel:** add defKernel() kernel fn codegen ([25b97a3](https://github.com/thi-ng/umbrella/commit/25b97a341fa54ee8a82e3083fcb85a8061db8b1f)) | ||
* **pixel:** add defLargeKernel(), conv presets ([9c71165](https://github.com/thi-ng/umbrella/commit/9c71165adb71103fa88a5486987f270fecd2f439)) | ||
* **pixel:** add gradientImage() & FLOAT_NORMAL format ([78683b7](https://github.com/thi-ng/umbrella/commit/78683b701418bf184b2a1327cfd5e50397d687e0)) | ||
* **pixel:** add IEmpty impls for Float/PackedBuffer ([46ac1a1](https://github.com/thi-ng/umbrella/commit/46ac1a1906b256eefab0934efea300c67db7ea28)) | ||
* **pixel:** add normalMap(), add more kernels ([f32686d](https://github.com/thi-ng/umbrella/commit/f32686d463ffcb49b37e9b1b811ff5de06b58fed)) | ||
* **pixel:** add POOL_THRESHOLD preset ([5f1c1de](https://github.com/thi-ng/umbrella/commit/5f1c1dea87251f8a584cbe94d83784e7e4cc31a5)) | ||
* **pixel:** add step size support for normalMap() ([ab72a79](https://github.com/thi-ng/umbrella/commit/ab72a79532baab3f07f53419cb5970e90e97e0dd)) | ||
* **pixel:** add/update buffer factory fns ([ba38e13](https://github.com/thi-ng/umbrella/commit/ba38e137c6913d048bb4d678137241ee179d160c)) | ||
* **pixel:** update PackedBuffer.fromCanvas() ([3bdb086](https://github.com/thi-ng/umbrella/commit/3bdb0860bcd35a0475e83ebe948847f1ecd42db6)) | ||
* **pixel:** update/extend/refactor convolveChannel/Image() ([6692865](https://github.com/thi-ng/umbrella/commit/6692865d5facb75bf667056afa9cfee93ade2da6)) | ||
# [0.6.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.5.1...@thi.ng/pixel@0.6.0) (2021-01-13) | ||
### Features | ||
* **pixel:** add downsample() for both buffer types ([0b9b0fa](https://github.com/thi-ng/umbrella/commit/0b9b0fad5ce7edcfaf50be767a73f8cc3fe7ebfe)) | ||
- **pixel:** add downsample() for both buffer types ([0b9b0fa](https://github.com/thi-ng/umbrella/commit/0b9b0fad5ce7edcfaf50be767a73f8cc3fe7ebfe)) | ||
# [0.5.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.4.10...@thi.ng/pixel@0.5.0) (2021-01-02) | ||
### Features | ||
* **pixel:** add FLOAT_HSVA format, update FloatFormatSpec ([118c4ed](https://github.com/thi-ng/umbrella/commit/118c4edbacd75249262f26962153f614148cedec)) | ||
* **pixel:** add FloatBuffer.fromPacked() ([abd1ca8](https://github.com/thi-ng/umbrella/commit/abd1ca80d455999dd8c3af87d24b4f1905d7806d)) | ||
- **pixel:** add FLOAT_HSVA format, update FloatFormatSpec ([118c4ed](https://github.com/thi-ng/umbrella/commit/118c4edbacd75249262f26962153f614148cedec)) | ||
- **pixel:** add FloatBuffer.fromPacked() ([abd1ca8](https://github.com/thi-ng/umbrella/commit/abd1ca80d455999dd8c3af87d24b4f1905d7806d)) | ||
# [0.4.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.3.6...@thi.ng/pixel@0.4.0) (2020-07-22) | ||
### Features | ||
- **pixel:** add flipY() ([a5593c0](https://github.com/thi-ng/umbrella/commit/a5593c06a6ae61eccb9ecbaa4b3828ce0b29fbc0)) | ||
# [0.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.2.0...@thi.ng/pixel@0.3.0) (2020-05-29) | ||
# [0.4.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.3.6...@thi.ng/pixel@0.4.0) (2020-07-22) | ||
### Features | ||
- **pixel:** add dither support for int buffers/formats ([4475fc1](https://github.com/thi-ng/umbrella/commit/4475fc14c65029e88a7216519350527fa3d2c3dc)) | ||
- **pixel:** add FloatBuffer and float format support ([d6c490f](https://github.com/thi-ng/umbrella/commit/d6c490fb22b3d43f188f85662bb431f59daa7f32)) | ||
- **pixel:** add/update float formats, tests ([6eb1f67](https://github.com/thi-ng/umbrella/commit/6eb1f671858c234e53f231ad8af0f07f2a423d96)) | ||
### Features | ||
# [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.1.20...@thi.ng/pixel@0.2.0) (2020-05-19) | ||
* **pixel:** add flipY() ([a5593c0](https://github.com/thi-ng/umbrella/commit/a5593c06a6ae61eccb9ecbaa4b3828ce0b29fbc0)) | ||
### Features | ||
- **pixel:** add .copy(), update .blitCanvas() ([f4b2c3e](https://github.com/thi-ng/umbrella/commit/f4b2c3e374b45bd26396e436f3e71e9d3afbc131)) | ||
- **pixel:** update canvas2d(), imageCanvas() ([65929a2](https://github.com/thi-ng/umbrella/commit/65929a2ee6be9915e14bf69389520739073af5ee)) | ||
## [0.1.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.1.3...@thi.ng/pixel@0.1.4) (2019-09-21) | ||
### Bug Fixes | ||
- **pixel:** clamp values in PackedChannel.setFloat() ([ce78467](https://github.com/thi-ng/umbrella/commit/ce78467)) | ||
# [0.3.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.2.0...@thi.ng/pixel@0.3.0) (2020-05-29) | ||
# 0.1.0 (2019-07-31) | ||
### Bug Fixes | ||
### Features | ||
- **pixel:** byte order fixes, extract luminance fns ([b3c79e3](https://github.com/thi-ng/umbrella/commit/b3c79e3)) | ||
- **pixel:** fast-route check in setChannel() ([b59069a](https://github.com/thi-ng/umbrella/commit/b59069a)) | ||
- **pixel:** update 16bit formats & handling in getChannel ([aa15179](https://github.com/thi-ng/umbrella/commit/aa15179)) | ||
- **pixel:** update clampRegion(), adjust src pos if dest is outside ([bb6ba47](https://github.com/thi-ng/umbrella/commit/bb6ba47)) | ||
- **pixel:** update prepRegions() ([ad8d2d7](https://github.com/thi-ng/umbrella/commit/ad8d2d7)) | ||
* **pixel:** add dither support for int buffers/formats ([4475fc1](https://github.com/thi-ng/umbrella/commit/4475fc14c65029e88a7216519350527fa3d2c3dc)) | ||
* **pixel:** add FloatBuffer and float format support ([d6c490f](https://github.com/thi-ng/umbrella/commit/d6c490fb22b3d43f188f85662bb431f59daa7f32)) | ||
* **pixel:** add/update float formats, tests ([6eb1f67](https://github.com/thi-ng/umbrella/commit/6eb1f671858c234e53f231ad8af0f07f2a423d96)) | ||
### Features | ||
# [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.1.20...@thi.ng/pixel@0.2.0) (2020-05-19) | ||
### Features | ||
* **pixel:** add .copy(), update .blitCanvas() ([f4b2c3e](https://github.com/thi-ng/umbrella/commit/f4b2c3e374b45bd26396e436f3e71e9d3afbc131)) | ||
* **pixel:** update canvas2d(), imageCanvas() ([65929a2](https://github.com/thi-ng/umbrella/commit/65929a2ee6be9915e14bf69389520739073af5ee)) | ||
## [0.1.4](https://github.com/thi-ng/umbrella/compare/@thi.ng/pixel@0.1.3...@thi.ng/pixel@0.1.4) (2019-09-21) | ||
### Bug Fixes | ||
* **pixel:** clamp values in PackedChannel.setFloat() ([ce78467](https://github.com/thi-ng/umbrella/commit/ce78467)) | ||
# 0.1.0 (2019-07-31) | ||
### Bug Fixes | ||
* **pixel:** byte order fixes, extract luminance fns ([b3c79e3](https://github.com/thi-ng/umbrella/commit/b3c79e3)) | ||
* **pixel:** fast-route check in setChannel() ([b59069a](https://github.com/thi-ng/umbrella/commit/b59069a)) | ||
* **pixel:** update 16bit formats & handling in getChannel ([aa15179](https://github.com/thi-ng/umbrella/commit/aa15179)) | ||
* **pixel:** update clampRegion(), adjust src pos if dest is outside ([bb6ba47](https://github.com/thi-ng/umbrella/commit/bb6ba47)) | ||
* **pixel:** update prepRegions() ([ad8d2d7](https://github.com/thi-ng/umbrella/commit/ad8d2d7)) | ||
### Features | ||
* **pixel:** ([#106](https://github.com/thi-ng/umbrella/issues/106)) add IBlend interface/impls, refactor IBlit ([e068f46](https://github.com/thi-ng/umbrella/commit/e068f46)) | ||
* **pixel:** ([#106](https://github.com/thi-ng/umbrella/issues/106)) add Uint16Buffer, update IColorChannel, add Channel.GRAY ([3088646](https://github.com/thi-ng/umbrella/commit/3088646)) | ||
* **pixel:** add 16bit formats, add docs, update readme ([5d72c37](https://github.com/thi-ng/umbrella/commit/5d72c37)) | ||
* **pixel:** add buffer() syntax sugar, PackedBuffer.forEach ([bc17ac9](https://github.com/thi-ng/umbrella/commit/bc17ac9)) | ||
* **pixel:** add channel float accessors, update PackedChannel ([b4168f8](https://github.com/thi-ng/umbrella/commit/b4168f8)) | ||
* **pixel:** add invert, add/split interfaces, refactor blit fns ([22a456a](https://github.com/thi-ng/umbrella/commit/22a456a)) | ||
* **pixel:** add PackedBuffer.fromCanvas(), update readme ([ac283ee](https://github.com/thi-ng/umbrella/commit/ac283ee)) | ||
* **pixel:** add pre/postmultiply & isPremultiplied checks ([969d6b8](https://github.com/thi-ng/umbrella/commit/969d6b8)) | ||
* **pixel:** complete rewrite/simplify/extend using format descriptors ([cde7bf9](https://github.com/thi-ng/umbrella/commit/cde7bf9)) | ||
* **pixel:** initial import pixel buffer pkg ([1836ea7](https://github.com/thi-ng/umbrella/commit/1836ea7)) | ||
* **pixel:** updat setChannel, add ALPHA8, update readme ([899f1a3](https://github.com/thi-ng/umbrella/commit/899f1a3)) | ||
* **pixel:** update canvasPixels() ([5ea200d](https://github.com/thi-ng/umbrella/commit/5ea200d)) | ||
- **pixel:** ([#106](https://github.com/thi-ng/umbrella/issues/106)) add IBlend interface/impls, refactor IBlit ([e068f46](https://github.com/thi-ng/umbrella/commit/e068f46)) | ||
- **pixel:** ([#106](https://github.com/thi-ng/umbrella/issues/106)) add Uint16Buffer, update IColorChannel, add Channel.GRAY ([3088646](https://github.com/thi-ng/umbrella/commit/3088646)) | ||
- **pixel:** add 16bit formats, add docs, update readme ([5d72c37](https://github.com/thi-ng/umbrella/commit/5d72c37)) | ||
- **pixel:** add buffer() syntax sugar, PackedBuffer.forEach ([bc17ac9](https://github.com/thi-ng/umbrella/commit/bc17ac9)) | ||
- **pixel:** add channel float accessors, update PackedChannel ([b4168f8](https://github.com/thi-ng/umbrella/commit/b4168f8)) | ||
- **pixel:** add invert, add/split interfaces, refactor blit fns ([22a456a](https://github.com/thi-ng/umbrella/commit/22a456a)) | ||
- **pixel:** add PackedBuffer.fromCanvas(), update readme ([ac283ee](https://github.com/thi-ng/umbrella/commit/ac283ee)) | ||
- **pixel:** add pre/postmultiply & isPremultiplied checks ([969d6b8](https://github.com/thi-ng/umbrella/commit/969d6b8)) | ||
- **pixel:** complete rewrite/simplify/extend using format descriptors ([cde7bf9](https://github.com/thi-ng/umbrella/commit/cde7bf9)) | ||
- **pixel:** initial import pixel buffer pkg ([1836ea7](https://github.com/thi-ng/umbrella/commit/1836ea7)) | ||
- **pixel:** updat setChannel, add ALPHA8, update readme ([899f1a3](https://github.com/thi-ng/umbrella/commit/899f1a3)) | ||
- **pixel:** update canvasPixels() ([5ea200d](https://github.com/thi-ng/umbrella/commit/5ea200d)) |
@@ -1,2 +0,2 @@ | ||
import { Fn, FnN3, NumericArray } from "@thi.ng/api"; | ||
import type { Fn, FnN3, NumericArray } from "@thi.ng/api"; | ||
import type { ConvolutionKernelSpec, ConvolveOpts, KernelSpec, PoolTemplate } from "./api"; | ||
@@ -3,0 +3,0 @@ import { FloatBuffer } from "./float"; |
@@ -1,7 +0,10 @@ | ||
import { assert } from "@thi.ng/api"; | ||
import { isFunction } from "@thi.ng/checks"; | ||
import { clamp, lanczos } from "@thi.ng/math"; | ||
import { isFunction } from "@thi.ng/checks/is-function"; | ||
import { assert } from "@thi.ng/errors/assert"; | ||
import { clamp } from "@thi.ng/math/interval"; | ||
import { lanczos } from "@thi.ng/math/mix"; | ||
import { ensureChannel } from "./checks"; | ||
import { FloatBuffer } from "./float"; | ||
import { FLOAT_GRAY } from "./format/float-gray"; | ||
import { asIntVec, ensureChannel, range } from "./utils"; | ||
import { __asIntVec } from "./internal/utils"; | ||
import { range } from "./range"; | ||
/** | ||
@@ -38,3 +41,3 @@ * Convolves a single channel from given `src` float buffer with provided | ||
for (let channel of opts.channels || range(src.format.channels.length)) { | ||
dest.setChannel(channel, convolve(Object.assign(Object.assign({}, state), { channel }))); | ||
dest.setChannel(channel, convolve({ ...state, channel })); | ||
} | ||
@@ -63,7 +66,13 @@ return dest; | ||
const initConvolve = (src, opts) => { | ||
const { kernel, channel, stride: sampleStride, scale, offset } = Object.assign({ channel: 0, offset: 0, scale: 1, stride: 1 }, opts); | ||
const { kernel, channel, stride: sampleStride, scale, offset, } = { | ||
channel: 0, | ||
offset: 0, | ||
scale: 1, | ||
stride: 1, | ||
...opts, | ||
}; | ||
const size = kernel.size; | ||
const [kw, kh] = asIntVec(size); | ||
const [strideX, strideY] = asIntVec(sampleStride); | ||
const [offsetX, offsetY] = asIntVec(offset); | ||
const [kw, kh] = __asIntVec(size); | ||
const [strideX, strideY] = __asIntVec(sampleStride); | ||
const [offsetX, offsetY] = __asIntVec(offset); | ||
assert(strideX >= 1 && strideY >= 1, `illegal stride: ${sampleStride}`); | ||
@@ -70,0 +79,0 @@ const { width, height, stride: srcStride, rowStride } = src; |
import type { Fn2 } from "@thi.ng/api"; | ||
import { KMeansOpts } from "@thi.ng/k-means"; | ||
import type { KMeansOpts } from "@thi.ng/k-means"; | ||
import type { FloatBuffer } from "./float"; | ||
@@ -4,0 +4,0 @@ export interface DominantColorOpts extends KMeansOpts { |
@@ -1,2 +0,2 @@ | ||
import { kmeans } from "@thi.ng/k-means"; | ||
import { kmeans } from "@thi.ng/k-means/kmeans"; | ||
/** | ||
@@ -3,0 +3,0 @@ * Takes a {@link FloatBuffer} and applies k-means clustering to extract the |
@@ -1,2 +0,2 @@ | ||
import { Fn2, ICopy, IEmpty, NumericArray } from "@thi.ng/api"; | ||
import type { Fn2, ICopy, IEmpty, NumericArray } from "@thi.ng/api"; | ||
import type { BlendFnFloat, BlitOpts, Filter, FloatFormat, FloatFormatSpec, FloatSampler, IBlend, IBlit, IInvert, IPixelBuffer, IResizable, IToImageData, PackedFormat } from "./api"; | ||
@@ -3,0 +3,0 @@ import { PackedBuffer } from "./packed"; |
45
float.js
@@ -1,9 +0,11 @@ | ||
import { assert } from "@thi.ng/api"; | ||
import { isNumber, isString } from "@thi.ng/checks"; | ||
import { clamp01 } from "@thi.ng/math"; | ||
import { isNumber } from "@thi.ng/checks/is-number"; | ||
import { isString } from "@thi.ng/checks/is-string"; | ||
import { assert } from "@thi.ng/errors/assert"; | ||
import { clamp01 } from "@thi.ng/math/interval"; | ||
import { ensureChannel, ensureSize } from "./checks"; | ||
import { defFloatFormat } from "./format/float-format"; | ||
import { FLOAT_GRAY } from "./format/float-gray"; | ||
import { __clampRegion, __prepRegions } from "./internal/utils"; | ||
import { PackedBuffer } from "./packed"; | ||
import { defSampler } from "./sample"; | ||
import { clampRegion, ensureChannel, ensureSize, prepRegions } from "./utils"; | ||
export function floatBuffer(...args) { | ||
@@ -17,13 +19,2 @@ return args[0] instanceof PackedBuffer | ||
export class FloatBuffer { | ||
constructor(w, h, fmt, pixels) { | ||
this.width = w; | ||
this.height = h; | ||
this.format = fmt.__float | ||
? fmt | ||
: defFloatFormat(fmt); | ||
this.stride = fmt.channels.length; | ||
this.rowStride = w * this.stride; | ||
this.pixels = pixels || new Float32Array(w * h * this.stride); | ||
this.__empty = (Object.freeze(new Array(this.stride).fill(0))); | ||
} | ||
/** | ||
@@ -48,2 +39,20 @@ * Creates a new `FloatBuffer` from given {@link PackedBuffer} and using | ||
} | ||
width; | ||
height; | ||
stride; | ||
rowStride; | ||
pixels; | ||
format; | ||
__empty; | ||
constructor(w, h, fmt, pixels) { | ||
this.width = w; | ||
this.height = h; | ||
this.format = fmt.__float | ||
? fmt | ||
: defFloatFormat(fmt); | ||
this.stride = fmt.channels.length; | ||
this.rowStride = w * this.stride; | ||
this.pixels = pixels || new Float32Array(w * h * this.stride); | ||
this.__empty = (Object.freeze(new Array(this.stride).fill(0))); | ||
} | ||
as(fmt) { | ||
@@ -125,3 +134,3 @@ const { width, height, stride, pixels, format: sfmt } = this; | ||
this.ensureFormat(dest); | ||
const { sx, sy, dx, dy, rw, rh } = prepRegions(this, dest, opts); | ||
const { sx, sy, dx, dy, rw, rh } = __prepRegions(this, dest, opts); | ||
if (rw < 1 || rh < 1) | ||
@@ -144,3 +153,3 @@ return dest; | ||
this.ensureFormat(dest); | ||
const { sx, sy, dx, dy, rw, rh } = prepRegions(this, dest, opts); | ||
const { sx, sy, dx, dy, rw, rh } = __prepRegions(this, dest, opts); | ||
if (rw < 1 || rh < 1) | ||
@@ -174,3 +183,3 @@ return dest; | ||
getRegion(x, y, width, height) { | ||
const [sx, sy, w, h] = clampRegion(x, y, width, height, this.width, this.height); | ||
const [sx, sy, w, h] = __clampRegion(x, y, width, height, this.width, this.height); | ||
return this.blit(new FloatBuffer(w, h, this.format), { | ||
@@ -177,0 +186,0 @@ sx, |
@@ -1,2 +0,2 @@ | ||
import { swapLane13 } from "@thi.ng/binary"; | ||
import { swapLane13 } from "@thi.ng/binary/swizzle"; | ||
import { Lane } from "../api"; | ||
@@ -3,0 +3,0 @@ import { defPackedFormat } from "./packed-format"; |
@@ -1,8 +0,13 @@ | ||
import { clamp01 } from "@thi.ng/math"; | ||
import { clamp01 } from "@thi.ng/math/interval"; | ||
import { Lane } from "../api"; | ||
import { luminanceABGR } from "../utils"; | ||
import { __luminanceABGR } from "../internal/utils"; | ||
export const defFloatFormat = (fmt) => { | ||
const chan = fmt.channels; | ||
const chanShift = chan.reduce((acc, ch) => ((acc[ch] = (3 - ch) << 3), acc), {}); | ||
const res = Object.assign(Object.assign({}, fmt), { size: chan.length, shift: chanShift, __float: true }); | ||
const res = { | ||
...fmt, | ||
size: chan.length, | ||
shift: chanShift, | ||
__float: true, | ||
}; | ||
if (fmt.convert) { | ||
@@ -43,3 +48,3 @@ Object.assign(res, fmt.convert); | ||
res.toABGR = (col) => ((((clamp01(col[0]) * 0xff + 0.5) | 0) * 0x010101) | 0xff000000) >>> 0; | ||
res.fromABGR = (col, out = []) => ((out[0] = luminanceABGR(col) / 0xff), out); | ||
res.fromABGR = (col, out = []) => ((out[0] = __luminanceABGR(col) / 0xff), out); | ||
}; | ||
@@ -68,3 +73,3 @@ const defConvert2 = (res, from, to) => { | ||
res.fromABGR = (col, out = []) => { | ||
out[gray] = luminanceABGR(col) / 0xff; | ||
out[gray] = __luminanceABGR(col) / 0xff; | ||
out[alpha] = from(col, alpha); | ||
@@ -71,0 +76,0 @@ return out; |
@@ -1,2 +0,3 @@ | ||
import { clamp01, EPS } from "@thi.ng/math"; | ||
import { EPS } from "@thi.ng/math/api"; | ||
import { clamp01 } from "@thi.ng/math/interval"; | ||
import { Lane } from "../api"; | ||
@@ -3,0 +4,0 @@ import { defFloatFormat } from "./float-format"; |
@@ -1,2 +0,2 @@ | ||
import { clamp } from "@thi.ng/math"; | ||
import { clamp } from "@thi.ng/math/interval"; | ||
import { Lane } from "../api"; | ||
@@ -3,0 +3,0 @@ const from = (x) => x / 127.5 - 1; |
import { Lane } from "../api"; | ||
import { luminanceABGR } from "../utils"; | ||
import { __luminanceABGR } from "../internal/utils"; | ||
import { defPackedFormat } from "./packed-format"; | ||
@@ -11,5 +11,5 @@ export const GRAY_ALPHA16 = defPackedFormat({ | ||
], | ||
fromABGR: (x) => (((luminanceABGR(x) + 0.5) | 0) * 0x0101) | | ||
fromABGR: (x) => (((__luminanceABGR(x) + 0.5) | 0) * 0x0101) | | ||
(((x >>> 8) & 0xff0000) * 0x0101), | ||
toABGR: (x) => ((x & 0xff000000) | (((x >>> 8) & 0xff) * 0x010101)) >>> 0, | ||
}); |
import { Lane } from "../api"; | ||
import { luminanceABGR } from "../utils"; | ||
import { __luminanceABGR } from "../internal/utils"; | ||
import { defPackedFormat } from "./packed-format"; | ||
@@ -12,4 +12,4 @@ export const GRAY_ALPHA8 = defPackedFormat({ | ||
], | ||
fromABGR: (x) => luminanceABGR(x) | ((x >>> 16) & 0xff00), | ||
fromABGR: (x) => __luminanceABGR(x) | ((x >>> 16) & 0xff00), | ||
toABGR: (x) => (((x & 0xff00) << 16) | ((x & 0xff) * 0x010101)) >>> 0, | ||
}); |
import { Lane } from "../api"; | ||
import { luminanceABGR } from "../utils"; | ||
import { __luminanceABGR } from "../internal/utils"; | ||
import { defPackedFormat } from "./packed-format"; | ||
@@ -8,4 +8,4 @@ export const GRAY16 = defPackedFormat({ | ||
channels: [{ size: 16, lane: Lane.RED }], | ||
fromABGR: (x) => ((luminanceABGR(x) + 0.5) | 0) * 0x0101, | ||
fromABGR: (x) => ((__luminanceABGR(x) + 0.5) | 0) * 0x0101, | ||
toABGR: (x) => (0xff000000 | ((x >>> 8) * 0x010101)) >>> 0, | ||
}); |
import { Lane } from "../api"; | ||
import { luminanceABGR } from "../utils"; | ||
import { __luminanceABGR } from "../internal/utils"; | ||
import { defPackedFormat } from "./packed-format"; | ||
@@ -8,4 +8,4 @@ export const GRAY8 = defPackedFormat({ | ||
channels: [{ size: 8, lane: Lane.RED }], | ||
fromABGR: (x) => luminanceABGR(x), | ||
fromABGR: (x) => __luminanceABGR(x), | ||
toABGR: (x) => (0xff000000 | ((x & 0xff) * 0x010101)) >>> 0, | ||
}); |
@@ -1,2 +0,2 @@ | ||
import { NumericArray } from "@thi.ng/api"; | ||
import type { NumericArray } from "@thi.ng/api"; | ||
/** | ||
@@ -3,0 +3,0 @@ * Creates an indexed color {@link PackedFormat} using the provided palette (in |
@@ -1,3 +0,4 @@ | ||
import { assert } from "@thi.ng/api"; | ||
import { swapLane13 } from "@thi.ng/binary"; | ||
import { swapLane13 } from "@thi.ng/binary/swizzle"; | ||
import { argminN } from "@thi.ng/distance/argmin"; | ||
import { assert } from "@thi.ng/errors/assert"; | ||
import { Lane } from "../api"; | ||
@@ -25,3 +26,3 @@ import { defPackedFormat } from "./packed-format"; | ||
channels: [{ size: 8, lane: Lane.RED }], | ||
fromABGR: (x) => closestColor(x, palette), | ||
fromABGR: (x) => argminN(x, palette, distBGR), | ||
toABGR: (x) => palette[x], | ||
@@ -31,13 +32,1 @@ }); | ||
const distBGR = (a, b) => Math.hypot(((a >> 16) & 0xff) - ((b >> 16) & 0xff), ((a >> 8) & 0xff) - ((b >> 8) & 0xff), (a & 0xff) - (b & 0xff)); | ||
const closestColor = (col, palette) => { | ||
let closest = 0; | ||
let minD = Infinity; | ||
for (let i = palette.length; --i >= 0;) { | ||
const d = distBGR(col, palette[i]); | ||
if (d < minD) { | ||
closest = i; | ||
minD = d; | ||
} | ||
} | ||
return closest; | ||
}; |
@@ -1,5 +0,4 @@ | ||
import { assert } from "@thi.ng/api"; | ||
import { clamp01 } from "@thi.ng/math"; | ||
import { compileFromABGR, compileToABGR } from "../codegen"; | ||
import { orderedDither } from "../dither"; | ||
import { assert } from "@thi.ng/errors/assert"; | ||
import { clamp01 } from "@thi.ng/math/interval"; | ||
import { __compileFromABGR, __compileToABGR } from "../internal/codegen"; | ||
const defChannel = (ch, idx, shift) => { | ||
@@ -15,2 +14,3 @@ const num = 1 << ch.size; | ||
size: ch.size, | ||
num, | ||
abgrShift: 24 - lane * 8 - shift, | ||
@@ -25,3 +25,2 @@ lane, | ||
setFloat: (src, x) => setInt(src, clamp01(x) * mask0), | ||
dither: (mat, steps, x, y, val) => orderedDither(mat, steps, num, num, x, y, val), | ||
}; | ||
@@ -42,5 +41,5 @@ }; | ||
channels, | ||
fromABGR: fmt.fromABGR || compileFromABGR(channels), | ||
toABGR: fmt.toABGR || compileToABGR(channels, !!fmt.alpha), | ||
fromABGR: fmt.fromABGR || __compileFromABGR(channels), | ||
toABGR: fmt.toABGR || __compileToABGR(channels, !!fmt.alpha), | ||
}; | ||
}; |
export * from "./api"; | ||
export * from "./canvas"; | ||
export * from "./codegen"; | ||
export * from "./convolve"; | ||
export * from "./dither"; | ||
export * from "./dominant-colors"; | ||
@@ -11,4 +9,4 @@ export * from "./float"; | ||
export * from "./pyramid"; | ||
export * from "./range"; | ||
export * from "./sample"; | ||
export * from "./utils"; | ||
export * from "./format/packed-format"; | ||
@@ -15,0 +13,0 @@ export * from "./format/abgr8888"; |
export * from "./api"; | ||
export * from "./canvas"; | ||
export * from "./codegen"; | ||
export * from "./convolve"; | ||
export * from "./dither"; | ||
export * from "./dominant-colors"; | ||
@@ -11,4 +9,4 @@ export * from "./float"; | ||
export * from "./pyramid"; | ||
export * from "./range"; | ||
export * from "./sample"; | ||
export * from "./utils"; | ||
export * from "./format/packed-format"; | ||
@@ -15,0 +13,0 @@ export * from "./format/abgr8888"; |
@@ -0,5 +1,6 @@ | ||
import { ensureChannel } from "./checks"; | ||
import { convolveChannel } from "./convolve"; | ||
import { FloatBuffer } from "./float"; | ||
import { FLOAT_NORMAL } from "./format/float-norm"; | ||
import { asVec, ensureChannel } from "./utils"; | ||
import { __asVec } from "./internal/utils"; | ||
/** | ||
@@ -24,6 +25,12 @@ * Computes normal map image (aka gradient in X & Y directions and a static Z | ||
export const normalMap = (src, opts) => { | ||
const { channel, step, scale, z } = Object.assign({ channel: 0, step: 0, scale: 1, z: 1 }, opts); | ||
const { channel, step, scale, z } = { | ||
channel: 0, | ||
step: 0, | ||
scale: 1, | ||
z: 1, | ||
...opts, | ||
}; | ||
ensureChannel(src.format, channel); | ||
const spec = [-1, ...new Array(step).fill(0), 1]; | ||
const [sx, sy] = asVec(scale); | ||
const [sx, sy] = __asVec(scale); | ||
const dest = new FloatBuffer(src.width, src.height, FLOAT_NORMAL); | ||
@@ -30,0 +37,0 @@ dest.setChannel(0, convolveChannel(src, { |
157
package.json
{ | ||
"name": "@thi.ng/pixel", | ||
"version": "1.0.5", | ||
"version": "2.0.0", | ||
"description": "Typedarray integer & float pixel buffers w/ customizable formats, blitting, dithering, convolution", | ||
"type": "module", | ||
"module": "./index.js", | ||
"main": "./lib/index.js", | ||
"umd:main": "./lib/index.umd.js", | ||
"typings": "./index.d.ts", | ||
"sideEffects": false, | ||
"repository": { | ||
@@ -27,29 +27,24 @@ "type": "git", | ||
"scripts": { | ||
"build": "yarn clean && yarn build:es6 && node ../../scripts/bundle-module", | ||
"build:release": "yarn clean && yarn build:es6 && node ../../scripts/bundle-module all", | ||
"build:es6": "tsc --declaration", | ||
"build:test": "rimraf build && tsc -p test/tsconfig.json", | ||
"build:check": "tsc --isolatedModules --noEmit", | ||
"test": "mocha test", | ||
"cover": "nyc mocha test && nyc report --reporter=lcov", | ||
"clean": "rimraf *.js *.d.ts *.map .nyc_output build coverage doc lib", | ||
"doc:readme": "ts-node -P ../../tools/tsconfig.json ../../tools/src/readme.ts", | ||
"doc": "typedoc --excludePrivate --out doc --theme ../../tools/doc/typedoc-theme src/index.ts", | ||
"build": "yarn clean && tsc --declaration", | ||
"clean": "rimraf *.js *.d.ts *.map doc format internal", | ||
"doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts", | ||
"doc:ae": "mkdir -p .ae/doc .ae/temp && node_modules/.bin/api-extractor run --local --verbose", | ||
"pub": "yarn build:release && yarn publish --access public" | ||
"doc:readme": "yarn doc:stats && ../../scripts/node-esm ../../tools/src/readme.ts", | ||
"doc:stats": "../../scripts/node-esm ../../tools/src/module-stats.ts", | ||
"pub": "yarn build && yarn publish --access public", | ||
"test": "testament test" | ||
}, | ||
"dependencies": { | ||
"@thi.ng/api": "^7.2.0", | ||
"@thi.ng/binary": "^2.2.11", | ||
"@thi.ng/checks": "^2.9.11", | ||
"@thi.ng/k-means": "^0.3.6", | ||
"@thi.ng/math": "^4.0.6", | ||
"@thi.ng/porter-duff": "^1.0.2" | ||
"@thi.ng/api": "^8.0.0", | ||
"@thi.ng/binary": "^3.0.0", | ||
"@thi.ng/checks": "^3.0.0", | ||
"@thi.ng/distance": "^2.0.0", | ||
"@thi.ng/errors": "^2.0.0", | ||
"@thi.ng/k-means": "^0.4.0", | ||
"@thi.ng/math": "^5.0.0", | ||
"@thi.ng/porter-duff": "^2.0.0" | ||
}, | ||
"files": [ | ||
"*.js", | ||
"*.d.ts", | ||
"lib", | ||
"format" | ||
], | ||
"devDependencies": { | ||
"@thi.ng/testament": "^0.1.0" | ||
}, | ||
"keywords": [ | ||
@@ -93,3 +88,109 @@ "8bit", | ||
}, | ||
"sideEffects": false, | ||
"files": [ | ||
"*.js", | ||
"*.d.ts", | ||
"format", | ||
"internal" | ||
], | ||
"exports": { | ||
".": { | ||
"import": "./index.js" | ||
}, | ||
"./api": { | ||
"import": "./api.js" | ||
}, | ||
"./canvas": { | ||
"import": "./canvas.js" | ||
}, | ||
"./checks": { | ||
"import": "./checks.js" | ||
}, | ||
"./convolve": { | ||
"import": "./convolve.js" | ||
}, | ||
"./dominant-colors": { | ||
"import": "./dominant-colors.js" | ||
}, | ||
"./float": { | ||
"import": "./float.js" | ||
}, | ||
"./format/abgr8888": { | ||
"import": "./format/abgr8888.js" | ||
}, | ||
"./format/alpha8": { | ||
"import": "./format/alpha8.js" | ||
}, | ||
"./format/argb1555": { | ||
"import": "./format/argb1555.js" | ||
}, | ||
"./format/argb4444": { | ||
"import": "./format/argb4444.js" | ||
}, | ||
"./format/argb8888": { | ||
"import": "./format/argb8888.js" | ||
}, | ||
"./format/bgr888": { | ||
"import": "./format/bgr888.js" | ||
}, | ||
"./format/float-format": { | ||
"import": "./format/float-format.js" | ||
}, | ||
"./format/float-gray-alpha": { | ||
"import": "./format/float-gray-alpha.js" | ||
}, | ||
"./format/float-gray": { | ||
"import": "./format/float-gray.js" | ||
}, | ||
"./format/float-hsva": { | ||
"import": "./format/float-hsva.js" | ||
}, | ||
"./format/float-norm": { | ||
"import": "./format/float-norm.js" | ||
}, | ||
"./format/float-rgb": { | ||
"import": "./format/float-rgb.js" | ||
}, | ||
"./format/float-rgba": { | ||
"import": "./format/float-rgba.js" | ||
}, | ||
"./format/gray-alpha16": { | ||
"import": "./format/gray-alpha16.js" | ||
}, | ||
"./format/gray-alpha8": { | ||
"import": "./format/gray-alpha8.js" | ||
}, | ||
"./format/gray16": { | ||
"import": "./format/gray16.js" | ||
}, | ||
"./format/gray8": { | ||
"import": "./format/gray8.js" | ||
}, | ||
"./format/indexed": { | ||
"import": "./format/indexed.js" | ||
}, | ||
"./format/packed-format": { | ||
"import": "./format/packed-format.js" | ||
}, | ||
"./format/rgb565": { | ||
"import": "./format/rgb565.js" | ||
}, | ||
"./format/rgb888": { | ||
"import": "./format/rgb888.js" | ||
}, | ||
"./normal-map": { | ||
"import": "./normal-map.js" | ||
}, | ||
"./packed": { | ||
"import": "./packed.js" | ||
}, | ||
"./pyramid": { | ||
"import": "./pyramid.js" | ||
}, | ||
"./range": { | ||
"import": "./range.js" | ||
}, | ||
"./sample": { | ||
"import": "./sample.js" | ||
} | ||
}, | ||
"thi.ng": { | ||
@@ -104,3 +205,3 @@ "related": [ | ||
}, | ||
"gitHead": "d971cb3f9b215a95483f78f1a8614015e331146f" | ||
"gitHead": "9ac1344b38b565eb894306fbf72233b6c0b2d115" | ||
} |
@@ -1,3 +0,4 @@ | ||
import { Fn2, ICopy, IEmpty, UIntArray } from "@thi.ng/api"; | ||
import { BayerMatrix, BayerSize, BlendFnInt, BlitOpts, Filter, IBlend, IBlit, IInvert, IntSampler, IPixelBuffer, IResizable, IToImageData, PackedFormat, PackedFormatSpec } from "./api"; | ||
import type { Fn2, ICopy, IEmpty } from "@thi.ng/api"; | ||
import { UIntArray } from "@thi.ng/api/typedarray"; | ||
import { BlendFnInt, BlitOpts, Filter, IBlend, IBlit, IInvert, IntSampler, IPixelBuffer, IResizable, IToImageData, PackedFormat, PackedFormatSpec } from "./api"; | ||
/** | ||
@@ -14,17 +15,20 @@ * Syntax sugar for {@link PackedBuffer} ctor. | ||
/** | ||
* @deprecated use {@link packedBuffer} instead. | ||
* Creates a new pixel buffer from given HTML image element with optional | ||
* support for format conversion (default: {@link ABGR8888} & resizing. | ||
* | ||
* @param img | ||
* @param fmt | ||
* @param width | ||
* @param height | ||
*/ | ||
export declare const buffer: typeof packedBuffer; | ||
export declare const packedBufferFromImage: (img: HTMLImageElement, fmt?: PackedFormat | undefined, width?: number | undefined, height?: number | undefined) => PackedBuffer; | ||
/** | ||
* Creates a new pixel buffer from given HTML canvas element with optional | ||
* support for format conversion (default: {@link ABGR8888}. | ||
* | ||
* @param canvas | ||
* @param fmt | ||
*/ | ||
export declare const packedBufferFromCanvas: (canvas: HTMLCanvasElement, fmt?: PackedFormat) => PackedBuffer; | ||
export declare class PackedBuffer implements IPixelBuffer<UIntArray, number>, IToImageData, IResizable<PackedBuffer, IntSampler>, IBlend<PackedBuffer, BlendFnInt>, IBlit<PackedBuffer>, IInvert<PackedBuffer>, ICopy<PackedBuffer>, IEmpty<PackedBuffer> { | ||
/** | ||
* Creates a new pixel buffer from given HTML image element with optional | ||
* support for format conversion (default: {@link ABGR8888} & resizing. | ||
* | ||
* @param img | ||
* @param fmt | ||
* @param width | ||
* @param height | ||
*/ | ||
static fromImage(img: HTMLImageElement, fmt?: PackedFormat, width?: number, height?: number | undefined): PackedBuffer; | ||
static fromCanvas(canvas: HTMLCanvasElement, fmt?: PackedFormat): PackedBuffer; | ||
readonly width: number; | ||
@@ -56,20 +60,2 @@ readonly height: number; | ||
/** | ||
* Applies in-place, ordered dithering using provided dither matrix | ||
* (or matrix size) and desired number of dither levels, optionally | ||
* specified individually (per channel). Each channel is be | ||
* processed independently. Channels can be excluded from dithering | ||
* by setting their target colors to zero or negative numbers. | ||
* | ||
* @remarks | ||
* A `size` of 1 will result in simple posterization of each | ||
* channel. The `numColors` value(s) MUST be in the `[0 .. | ||
* numColorsInChannel]` interval. | ||
* | ||
* Also see: {@link defBayer}, {@link ditherPixels}. | ||
* | ||
* @param size - dither matrix/size | ||
* @param numColors - num target colors/steps | ||
*/ | ||
dither(size: BayerSize | BayerMatrix, numColors: number | number[]): this; | ||
/** | ||
* Flips image vertically. | ||
@@ -76,0 +62,0 @@ */ |
142
packed.js
@@ -1,12 +0,14 @@ | ||
import { assert, typedArray, uintTypeForBits, } from "@thi.ng/api"; | ||
import { isNumber, isString } from "@thi.ng/checks"; | ||
import { isPremultipliedInt, postmultiplyInt, premultiplyInt, } from "@thi.ng/porter-duff"; | ||
import { typedArray, uintTypeForBits } from "@thi.ng/api/typedarray"; | ||
import { isNumber } from "@thi.ng/checks/is-number"; | ||
import { isString } from "@thi.ng/checks/is-string"; | ||
import { assert } from "@thi.ng/errors/assert"; | ||
import { isPremultipliedInt, postmultiplyInt, premultiplyInt, } from "@thi.ng/porter-duff/premultiply"; | ||
import { Lane, } from "./api"; | ||
import { canvasPixels, imageCanvas } from "./canvas"; | ||
import { compileGrayFromABGR, compileGrayToABGR } from "./codegen"; | ||
import { defBayer } from "./dither"; | ||
import { ensureChannel, ensureSize } from "./checks"; | ||
import { ABGR8888 } from "./format/abgr8888"; | ||
import { defPackedFormat } from "./format/packed-format"; | ||
import { __compileGrayFromABGR, __compileGrayToABGR } from "./internal/codegen"; | ||
import { __clampRegion, __prepRegions, __setChannelConvert, __setChannelSame, __setChannelUni, __transformABGR, } from "./internal/utils"; | ||
import { defSampler } from "./sample"; | ||
import { clampRegion, ensureChannel, ensureSize, prepRegions, setChannelConvert, setChannelSame, setChannelUni, transformABGR, } from "./utils"; | ||
export function packedBuffer(...args) { | ||
@@ -19,6 +21,41 @@ return args[0] instanceof PackedBuffer | ||
/** | ||
* @deprecated use {@link packedBuffer} instead. | ||
* Creates a new pixel buffer from given HTML image element with optional | ||
* support for format conversion (default: {@link ABGR8888} & resizing. | ||
* | ||
* @param img | ||
* @param fmt | ||
* @param width | ||
* @param height | ||
*/ | ||
export const buffer = packedBuffer; | ||
export const packedBufferFromImage = (img, fmt, width, height = width) => packedBufferFromCanvas(imageCanvas(img, width, height).canvas, fmt); | ||
/** | ||
* Creates a new pixel buffer from given HTML canvas element with optional | ||
* support for format conversion (default: {@link ABGR8888}. | ||
* | ||
* @param canvas | ||
* @param fmt | ||
*/ | ||
export const packedBufferFromCanvas = (canvas, fmt = ABGR8888) => { | ||
const ctx = canvasPixels(canvas); | ||
const w = canvas.width; | ||
const h = canvas.height; | ||
let dest; | ||
if (fmt === ABGR8888) { | ||
dest = ctx.pixels; | ||
} | ||
else { | ||
dest = typedArray(fmt.type, w * h); | ||
const src = ctx.pixels; | ||
const from = fmt.fromABGR; | ||
for (let i = dest.length; --i >= 0;) { | ||
dest[i] = from(src[i]); | ||
} | ||
} | ||
return new PackedBuffer(w, h, fmt, dest); | ||
}; | ||
export class PackedBuffer { | ||
width; | ||
height; | ||
format; | ||
pixels; | ||
constructor(w, h, fmt, pixels) { | ||
@@ -32,32 +69,2 @@ this.width = w; | ||
} | ||
/** | ||
* Creates a new pixel buffer from given HTML image element with optional | ||
* support for format conversion (default: {@link ABGR8888} & resizing. | ||
* | ||
* @param img | ||
* @param fmt | ||
* @param width | ||
* @param height | ||
*/ | ||
static fromImage(img, fmt, width, height = width) { | ||
return PackedBuffer.fromCanvas(imageCanvas(img, width, height).canvas, fmt); | ||
} | ||
static fromCanvas(canvas, fmt = ABGR8888) { | ||
const ctx = canvasPixels(canvas); | ||
const w = canvas.width; | ||
const h = canvas.height; | ||
let dest; | ||
if (fmt === ABGR8888) { | ||
dest = ctx.pixels; | ||
} | ||
else { | ||
dest = typedArray(fmt.type, w * h); | ||
const src = ctx.pixels; | ||
const from = fmt.fromABGR; | ||
for (let i = dest.length; --i >= 0;) { | ||
dest[i] = from(src[i]); | ||
} | ||
} | ||
return new PackedBuffer(w, h, fmt, dest); | ||
} | ||
get stride() { | ||
@@ -104,3 +111,3 @@ return 1; | ||
let dw = dest.width; | ||
const { sx, sy, dx, dy, rw, rh } = prepRegions(this, dest, opts); | ||
const { sx, sy, dx, dy, rw, rh } = __prepRegions(this, dest, opts); | ||
if (rw < 1 || rh < 1) | ||
@@ -123,3 +130,3 @@ return dest; | ||
let dw = dest.width; | ||
const { sx, sy, dx, dy, rw, rh } = prepRegions(this, dest, opts); | ||
const { sx, sy, dx, dy, rw, rh } = __prepRegions(this, dest, opts); | ||
if (rw < 1 || rh < 1) | ||
@@ -160,3 +167,3 @@ return dest; | ||
getRegion(x, y, width, height, fmt) { | ||
const [sx, sy, w, h] = clampRegion(x, y, width, height, this.width, this.height); | ||
const [sx, sy, w, h] = __clampRegion(x, y, width, height, this.width, this.height); | ||
return this.blit(new PackedBuffer(w, h, fmt || this.format), { | ||
@@ -175,4 +182,4 @@ sx, | ||
channels: [{ size: chan.size, lane: Lane.RED }], | ||
fromABGR: compileGrayFromABGR(chan.size), | ||
toABGR: compileGrayToABGR(chan.size), | ||
fromABGR: __compileGrayFromABGR(chan.size), | ||
toABGR: __compileGrayToABGR(chan.size), | ||
}); | ||
@@ -192,3 +199,3 @@ const src = this.pixels; | ||
if (isNumber(src)) { | ||
setChannelUni(dbuf, src, set); | ||
__setChannelUni(dbuf, src, set); | ||
} | ||
@@ -200,6 +207,6 @@ else { | ||
if (chan.size === schan.size) { | ||
setChannelSame(dbuf, sbuf, schan.int, set); | ||
__setChannelSame(dbuf, sbuf, schan.int, set); | ||
} | ||
else { | ||
setChannelConvert(dbuf, sbuf, this.format.fromABGR, src.format.toABGR, chan.maskA); | ||
__setChannelConvert(dbuf, sbuf, this.format.fromABGR, src.format.toABGR, chan.maskA); | ||
} | ||
@@ -218,7 +225,7 @@ } | ||
premultiply() { | ||
transformABGR(this.pixels, this.format, premultiplyInt); | ||
__transformABGR(this.pixels, this.format, premultiplyInt); | ||
return this; | ||
} | ||
postmultiply() { | ||
transformABGR(this.pixels, this.format, postmultiplyInt); | ||
__transformABGR(this.pixels, this.format, postmultiplyInt); | ||
return this; | ||
@@ -244,41 +251,2 @@ } | ||
/** | ||
* Applies in-place, ordered dithering using provided dither matrix | ||
* (or matrix size) and desired number of dither levels, optionally | ||
* specified individually (per channel). Each channel is be | ||
* processed independently. Channels can be excluded from dithering | ||
* by setting their target colors to zero or negative numbers. | ||
* | ||
* @remarks | ||
* A `size` of 1 will result in simple posterization of each | ||
* channel. The `numColors` value(s) MUST be in the `[0 .. | ||
* numColorsInChannel]` interval. | ||
* | ||
* Also see: {@link defBayer}, {@link ditherPixels}. | ||
* | ||
* @param size - dither matrix/size | ||
* @param numColors - num target colors/steps | ||
*/ | ||
dither(size, numColors) { | ||
const { pixels, format, width } = this; | ||
const steps = isNumber(numColors) | ||
? new Array(format.channels.length).fill(numColors) | ||
: numColors; | ||
const mat = isNumber(size) ? defBayer(size) : size; | ||
for (let i = 0, n = pixels.length, nc = format.channels.length, x = 0, y = 0; i < n; i++) { | ||
let col = pixels[i]; | ||
for (let j = 0; j < nc; j++) { | ||
const ch = format.channels[j]; | ||
const cs = steps[j]; | ||
cs > 0 && | ||
(col = ch.setInt(col, ch.dither(mat, cs, x, y, ch.int(col)))); | ||
} | ||
pixels[i] = col; | ||
if (++x === width) { | ||
x = 0; | ||
y++; | ||
} | ||
} | ||
return this; | ||
} | ||
/** | ||
* Flips image vertically. | ||
@@ -285,0 +253,0 @@ */ |
@@ -1,2 +0,2 @@ | ||
import { assert } from "@thi.ng/api"; | ||
import { assert } from "@thi.ng/errors/assert"; | ||
import { convolveImage, LANCZOS } from "./convolve"; | ||
@@ -3,0 +3,0 @@ /** |
@@ -304,2 +304,3 @@ <!-- This file is generated - DO NOT EDIT! --> | ||
- [@thi.ng/pixel-dither](https://github.com/thi-ng/umbrella/tree/develop/packages/pixel-dither) - Extensible image dithering w/ various algorithm presets | ||
- [@thi.ng/pixel-io-netpbm](https://github.com/thi-ng/umbrella/tree/develop/packages/pixel-io-netpbm) - Multi-format NetPBM reader & writer support for [@thi.ng/pixel](https://github.com/thi-ng/umbrella/tree/develop/packages/pixel) | ||
@@ -320,11 +321,19 @@ | ||
ES module import: | ||
```html | ||
// ES module | ||
<script type="module" src="https://unpkg.com/@thi.ng/pixel?module" crossorigin></script> | ||
<script type="module" src="https://cdn.skypack.dev/@thi.ng/pixel"></script> | ||
``` | ||
// UMD | ||
<script src="https://unpkg.com/@thi.ng/pixel/lib/index.umd.js" crossorigin></script> | ||
[Skypack documentation](https://docs.skypack.dev/) | ||
For NodeJS (v14.6+): | ||
```text | ||
node --experimental-specifier-resolution=node --experimental-repl-await | ||
> const pixel = await import("@thi.ng/pixel"); | ||
``` | ||
Package sizes (gzipped, pre-treeshake): ESM: 9.22 KB / CJS: 9.52 KB / UMD: 9.23 KB | ||
Package sizes (gzipped, pre-treeshake): ESM: 8.85 KB | ||
@@ -336,2 +345,4 @@ ## Dependencies | ||
- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/develop/packages/checks) | ||
- [@thi.ng/distance](https://github.com/thi-ng/umbrella/tree/develop/packages/distance) | ||
- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/develop/packages/errors) | ||
- [@thi.ng/k-means](https://github.com/thi-ng/umbrella/tree/develop/packages/k-means) | ||
@@ -354,5 +365,8 @@ - [@thi.ng/math](https://github.com/thi-ng/umbrella/tree/develop/packages/math) | ||
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/pixel/pixel-basics.png" width="240"/> | Pixel buffer manipulations | [Demo](https://demo.thi.ng/umbrella/pixel-basics/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/pixel-basics) | | ||
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/pixel-dither.jpg" width="240"/> | Showcase of various dithering algorithms | [Demo](https://demo.thi.ng/umbrella/pixel-dither/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/pixel-dither) | | ||
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/pixel-indexed.jpg" width="240"/> | Image dithering and remapping using indexed palettes | [Demo](https://demo.thi.ng/umbrella/pixel-indexed/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/pixel-indexed) | | ||
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/pixel-sorting.png" width="240"/> | Interactive pixel sorting tool using thi.ng/color & thi.ng/pixel | [Demo](https://demo.thi.ng/umbrella/pixel-sorting/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/pixel-sorting) | | ||
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/porter-duff/porter-duff2.png" width="240"/> | Port-Duff image compositing / alpha blending | [Demo](https://demo.thi.ng/umbrella/porter-duff/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/porter-duff) | | ||
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/scenegraph-image.png" width="240"/> | 2D scenegraph & image map based geometry manipulation | [Demo](https://demo.thi.ng/umbrella/scenegraph-image/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/scenegraph-image) | | ||
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/shader-ast-tunnel.jpg" width="240"/> | WebGL & Canvas2D textured tunnel shader | [Demo](https://demo.thi.ng/umbrella/shader-ast-tunnel/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/shader-ast-tunnel) | | ||
| <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/shader-ast-workers.jpg" width="240"/> | Fork-join worker-based raymarch renderer | [Demo](https://demo.thi.ng/umbrella/shader-ast-workers/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/shader-ast-workers) | | ||
@@ -359,0 +373,0 @@ | <img src="https://raw.githubusercontent.com/thi-ng/umbrella/develop/assets/examples/text-canvas-image.png" width="240"/> | Textmode image warping w/ 16bit color output | [Demo](https://demo.thi.ng/umbrella/text-canvas-image/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/text-canvas-image) | |
@@ -1,3 +0,5 @@ | ||
import { assert } from "@thi.ng/api"; | ||
import { clamp, fract, mixBicubic, mixBilinear, mod } from "@thi.ng/math"; | ||
import { assert } from "@thi.ng/errors/assert"; | ||
import { clamp } from "@thi.ng/math/interval"; | ||
import { mixBicubic, mixBilinear } from "@thi.ng/math/mix"; | ||
import { fract, mod } from "@thi.ng/math/prec"; | ||
export function defSampler(src, filter = "linear", wrap = "clamp") { | ||
@@ -60,3 +62,3 @@ const isFloat = !!src.format.__float; | ||
}; | ||
const sampleFNC = ({ pixels, width, height, rowStride, stride, }) => (x, y) => { | ||
const sampleFNC = ({ pixels, width, height, rowStride, stride }) => (x, y) => { | ||
let i; | ||
@@ -68,3 +70,3 @@ return x >= 0 && x < width && y >= 0 && y < height | ||
}; | ||
const sampleFNW = ({ pixels, width, height, rowStride, stride, }) => (x, y) => { | ||
const sampleFNW = ({ pixels, width, height, rowStride, stride }) => (x, y) => { | ||
let i = mod(y | 0, height) * rowStride + mod(x | 0, width) * stride; | ||
@@ -71,0 +73,0 @@ return pixels.slice(i, i + stride); |
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
0
458
5
Yes
147671
8
1
74
2738
+ Added@thi.ng/distance@^2.0.0
+ Added@thi.ng/errors@^2.0.0
+ Added@thi.ng/api@8.11.21(transitive)
+ Added@thi.ng/arrays@2.10.17(transitive)
+ Added@thi.ng/binary@3.4.44(transitive)
+ Added@thi.ng/checks@3.7.0(transitive)
+ Added@thi.ng/compare@2.4.13(transitive)
+ Added@thi.ng/compose@3.0.24(transitive)
+ Added@thi.ng/distance@2.4.108(transitive)
+ Added@thi.ng/equiv@2.1.77(transitive)
+ Added@thi.ng/errors@2.5.27(transitive)
+ Added@thi.ng/heaps@2.1.93(transitive)
+ Added@thi.ng/hex@2.3.65(transitive)
+ Added@thi.ng/k-means@0.4.9(transitive)
+ Added@thi.ng/math@5.11.21(transitive)
+ Added@thi.ng/memoize@4.0.11(transitive)
+ Added@thi.ng/porter-duff@2.1.99(transitive)
+ Added@thi.ng/random@3.8.54.1.12(transitive)
+ Added@thi.ng/strings@3.9.6(transitive)
+ Added@thi.ng/timestamp@1.1.6(transitive)
+ Added@thi.ng/transducers@9.2.20(transitive)
+ Added@thi.ng/vectors@7.12.22(transitive)
- Removed@thi.ng/api@7.2.0(transitive)
- Removed@thi.ng/arrays@1.0.3(transitive)
- Removed@thi.ng/binary@2.2.11(transitive)
- Removed@thi.ng/checks@2.9.11(transitive)
- Removed@thi.ng/compare@1.3.34(transitive)
- Removed@thi.ng/compose@1.4.36(transitive)
- Removed@thi.ng/distance@1.0.7(transitive)
- Removed@thi.ng/equiv@1.0.45(transitive)
- Removed@thi.ng/errors@1.3.4(transitive)
- Removed@thi.ng/heaps@1.3.1(transitive)
- Removed@thi.ng/hex@1.0.4(transitive)
- Removed@thi.ng/k-means@0.3.6(transitive)
- Removed@thi.ng/math@4.0.6(transitive)
- Removed@thi.ng/memoize@2.1.21(transitive)
- Removed@thi.ng/porter-duff@1.0.2(transitive)
- Removed@thi.ng/random@2.4.8(transitive)
- Removed@thi.ng/transducers@7.9.2(transitive)
- Removed@thi.ng/vectors@6.2.0(transitive)
Updated@thi.ng/api@^8.0.0
Updated@thi.ng/binary@^3.0.0
Updated@thi.ng/checks@^3.0.0
Updated@thi.ng/k-means@^0.4.0
Updated@thi.ng/math@^5.0.0
Updated@thi.ng/porter-duff@^2.0.0