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

@vibrant/core

Package Overview
Dependencies
Maintainers
0
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vibrant/core - npm Package Compare versions

Comparing version 3.2.1-alpha.1 to 4.0.0-alpha.1

dist/cjs/builder.cjs

49

package.json
{
"name": "@vibrant/core",
"version": "3.2.1-alpha.1",
"version": "4.0.0-alpha.1",
"description": "Core vibrant classes",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "vitest run",
"test:watch": "vitest watch",
"build": "vite build"
},
"main": "lib/index.js",
"types": "lib/index.d.ts",
"type": "module",
"types": "dist/esm/index.d.ts",
"main": "dist/cjs/index.cjs",
"module": "dist/esm/index.js",
"exports": {
".": {
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/cjs/index.d.cts",
"default": "./dist/cjs/index.cjs"
}
},
"./package.json": "./package.json"
},
"sideEffects": false,
"files": [
"dist",
"src"
],
"author": {

@@ -20,11 +42,14 @@ "name": "akfish",

"dependencies": {
"@vibrant/color": "^3.2.1-alpha.1",
"@vibrant/generator": "^3.2.1-alpha.1",
"@vibrant/image": "^3.2.1-alpha.1",
"@vibrant/quantizer": "^3.2.1-alpha.1",
"@vibrant/types": "^3.2.1-alpha.1",
"@vibrant/worker": "^3.2.1-alpha.1"
"@vibrant/color": "^4.0.0-alpha.1",
"@vibrant/generator": "^4.0.0-alpha.1",
"@vibrant/image": "^4.0.0-alpha.1",
"@vibrant/quantizer": "^4.0.0-alpha.1",
"@vibrant/types": "^4.0.0-alpha.1",
"@vibrant/worker": "^4.0.0-alpha.1"
},
"devDependencies": {
"typescript": "^3.7.2"
"@tanstack/config": "^0.14.2",
"typescript": "^4.5.2",
"vite": "^6.0.3",
"vitest": "^2.1.8"
},

@@ -34,3 +59,3 @@ "publishConfig": {

},
"gitHead": "e667d4c12e1de66e251d451710b093e9cb4630c2"
"gitHead": "968ad565c625279b5d3e2baf3e5da7f764551ade"
}

@@ -1,90 +0,82 @@

import {
Options
} from './options'
import {
Callback
} from '@vibrant/types'
import {
ImageClass,
ImageSource
} from '@vibrant/image'
import { Options } from "./options";
import { Callback } from "@vibrant/types";
import { ImageClass, ImageSource } from "@vibrant/image";
import {
Filter,
Palette
} from '@vibrant/color'
import Vibrant from './'
import { assignDeep } from './utils'
import { Filter, Palette } from "@vibrant/color";
import Vibrant from "./";
import { assignDeep } from "./utils";
export default class Builder {
private _src: ImageSource
private _opts: Partial<Options>
constructor (src: ImageSource, opts: Partial<Options> = {}) {
this._src = src
this._opts = assignDeep({}, Vibrant.DefaultOpts, opts)
private _src: ImageSource;
private _opts: Partial<Options>;
constructor(src: ImageSource, opts: Partial<Options> = {}) {
this._src = src;
this._opts = assignDeep({}, Vibrant.DefaultOpts, opts);
}
maxColorCount (n: number): Builder {
this._opts.colorCount = n
return this
maxColorCount(n: number): Builder {
this._opts.colorCount = n;
return this;
}
maxDimension (d: number): Builder {
this._opts.maxDimension = d
return this
maxDimension(d: number): Builder {
this._opts.maxDimension = d;
return this;
}
addFilter (name: string): Builder {
addFilter(name: string): Builder {
if (!this._opts.filters) {
this._opts.filters = [name]
this._opts.filters = [name];
} else {
this._opts.filters.push(name)
this._opts.filters.push(name);
}
return this
return this;
}
removeFilter (name: string): Builder {
removeFilter(name: string): Builder {
if (this._opts.filters) {
let i = this._opts.filters.indexOf(name)
if (i > 0) this._opts.filters.splice(i)
const i = this._opts.filters.indexOf(name);
if (i > 0) this._opts.filters.splice(i);
}
return this
return this;
}
clearFilters (): Builder {
this._opts.filters = []
return this
clearFilters(): Builder {
this._opts.filters = [];
return this;
}
quality (q: number): Builder {
this._opts.quality = q
return this
quality(q: number): Builder {
this._opts.quality = q;
return this;
}
useImageClass (imageClass: ImageClass): Builder {
this._opts.ImageClass = imageClass
return this
useImageClass(imageClass: ImageClass): Builder {
this._opts.ImageClass = imageClass;
return this;
}
useGenerator (generator: string, options?: any): Builder {
if (!this._opts.generators) this._opts.generators = []
this._opts.generators.push(options ? { name: generator, options } : generator)
return this
useGenerator(generator: string, options?: any): Builder {
if (!this._opts.generators) this._opts.generators = [];
this._opts.generators.push(
options ? { name: generator, options } : generator
);
return this;
}
useQuantizer (quantizer: string, options?: any): Builder {
this._opts.quantizer = options ? { name: quantizer, options } : quantizer
return this
useQuantizer(quantizer: string, options?: any): Builder {
this._opts.quantizer = options ? { name: quantizer, options } : quantizer;
return this;
}
build (): Vibrant {
return new Vibrant(this._src, this._opts)
build(): Vibrant {
return new Vibrant(this._src, this._opts);
}
getPalette (cb?: Callback<Palette>): Promise<Palette> {
return this.build().getPalette(cb)
getPalette(cb?: Callback<Palette>): Promise<Palette> {
return this.build().getPalette(cb);
}
getSwatches (cb?: Callback<Palette>): Promise<Palette> {
return this.build().getPalette(cb)
getSwatches(cb?: Callback<Palette>): Promise<Palette> {
return this.build().getPalette(cb);
}
}

@@ -1,127 +0,139 @@

import { Options, buildProcessOptions } from './options'
import { Callback } from '@vibrant/types'
import { Image, ImageSource } from '@vibrant/image'
import { buildProcessOptions, Options } from "./options";
import { Callback } from "@vibrant/types";
import { Image, ImageSource } from "@vibrant/image";
import { Filter, Palette, Swatch } from '@vibrant/color'
import { Palette } from "@vibrant/color";
import Builder from './builder'
import { Pipeline, ProcessOptions, ProcessResult } from './pipeline'
import { assignDeep } from './utils'
import Builder from "./builder";
import { Pipeline, ProcessOptions, ProcessResult } from "./pipeline";
import { assignDeep } from "./utils";
export interface VibrantStatic {
from (src: ImageSource): Builder
from(src: ImageSource): Builder;
}
export default class Vibrant {
private _result: ProcessResult
private static _pipeline: Pipeline
static use (pipeline: Pipeline) {
this._pipeline = pipeline
private _result: ProcessResult;
private static _pipeline: Pipeline;
static use(pipeline: Pipeline) {
this._pipeline = pipeline;
}
static DefaultOpts: Partial<Options> = {
colorCount: 64,
quality: 5,
filters: []
filters: [],
};
static from(src: ImageSource): Builder {
return new Builder(src);
}
static from (src: ImageSource): Builder {
return new Builder(src)
get result() {
return this._result;
}
get result () {
return this._result
opts: Options;
constructor(private _src: ImageSource, opts?: Partial<Options>) {
this.opts = assignDeep({}, Vibrant.DefaultOpts, opts);
}
opts: Options
constructor (private _src: ImageSource, opts?: Partial<Options>) {
this.opts = assignDeep({}, Vibrant.DefaultOpts, opts)
}
private _process (
private _process(
image: Image,
opts?: Partial<ProcessOptions>
): Promise<ProcessResult> {
let { quantizer } = this.opts
const { quantizer } = this.opts;
image.scaleDown(this.opts)
image.scaleDown(this.opts);
let processOpts = buildProcessOptions(this.opts, opts)
const processOpts = buildProcessOptions(this.opts, opts);
return Vibrant._pipeline.process(image.getImageData(), processOpts)
return Vibrant._pipeline.process(image.getImageData(), processOpts);
}
palette (): Palette {
return this.swatches()
palette(): Palette {
return this.swatches();
}
swatches (): Palette {
swatches(): Palette {
throw new Error(
'Method deprecated. Use `Vibrant.result.palettes[name]` instead'
)
"Method deprecated. Use `Vibrant.result.palettes[name]` instead"
);
}
getPalette (name: string, cb?: Callback<Palette>): Promise<Palette>
getPalette (cb?: Callback<Palette>): Promise<Palette>
getPalette (): Promise<Palette> {
const arg0 = arguments[0]
const arg1 = arguments[1]
const name = typeof arg0 === 'string' ? arg0 : 'default'
const cb = typeof arg0 === 'string' ? arg1 : arg0
let image = new this.opts.ImageClass()
getPalette(name: string, cb?: Callback<Palette>): Promise<Palette>;
getPalette(cb?: Callback<Palette>): Promise<Palette>;
getPalette(): Promise<Palette> {
const arg0 = arguments[0];
const arg1 = arguments[1];
const name = typeof arg0 === "string" ? arg0 : "default";
const cb = typeof arg0 === "string" ? arg1 : arg0;
const image = new this.opts.ImageClass();
return image
.load(this._src)
.then(image => this._process(image, { generators: [name] }))
.then(result => {
this._result = result
return result.palettes[name]
.then((image) => this._process(image, { generators: [name] }))
.then((result) => {
this._result = result;
return result.palettes[name];
})
.then(res => {
image.remove()
.then((res) => {
image.remove();
if (cb) {
cb(undefined, res)
cb(undefined, res);
}
return res
return res;
})
.catch(err => {
image.remove()
.catch((err) => {
image.remove();
if (cb) {
cb(err)
cb(err);
}
return Promise.reject(err)
})
return Promise.reject(err);
});
}
getPalettes (
getPalettes(
names: string[],
cb?: Callback<Palette>
): Promise<{ [name: string]: Palette }>
getPalettes (cb?: Callback<Palette>): Promise<{ [name: string]: Palette }>
getPalettes (): Promise<{ [name: string]: Palette }> {
const arg0 = arguments[0]
const arg1 = arguments[1]
const names = Array.isArray(arg0) ? arg0 : ['*']
const cb = Array.isArray(arg0) ? arg1 : arg0
let image = new this.opts.ImageClass()
): Promise<{ [name: string]: Palette }>;
getPalettes(cb?: Callback<Palette>): Promise<{ [name: string]: Palette }>;
getPalettes(): Promise<{ [name: string]: Palette }> {
const arg0 = arguments[0];
const arg1 = arguments[1];
const names = Array.isArray(arg0) ? arg0 : ["*"];
const cb = Array.isArray(arg0) ? arg1 : arg0;
const image = new this.opts.ImageClass();
return image
.load(this._src)
.then(image =>
.then((image) =>
this._process(image, {
generators: names
generators: names,
})
)
.then(result => {
this._result = result
return result.palettes
.then((result) => {
this._result = result;
return result.palettes;
})
.then(res => {
image.remove()
.then((res) => {
image.remove();
if (cb) {
cb(undefined, res)
cb(undefined, res);
}
return res
return res;
})
.catch(err => {
image.remove()
.catch((err) => {
image.remove();
if (cb) {
cb(err)
cb(err);
}
return Promise.reject(err)
})
return Promise.reject(err);
});
}
}
export { BasicPipeline } from "./pipeline";
export { WorkerPipeline } from "./pipeline/worker/client";
export { runPipelineInWorker } from "./pipeline/worker/host";
export { Builder };

@@ -1,30 +0,38 @@

import { Palette, Swatch, Filter } from '@vibrant/color'
import { Image, ImageClass, ImageSource, ImageOptions } from '@vibrant/image'
import { Quantizer, QuantizerOptions } from '@vibrant/quantizer'
import { Generator } from '@vibrant/generator'
import { StageOptions, ProcessOptions } from './pipeline'
import { assignDeep } from './utils'
import { Palette, Swatch, Filter } from "@vibrant/color";
import { Image, ImageClass, ImageSource, ImageOptions } from "@vibrant/image";
import { Quantizer, QuantizerOptions } from "@vibrant/quantizer";
import { Generator } from "@vibrant/generator";
import { StageOptions, ProcessOptions } from "./pipeline";
import { assignDeep } from "./utils";
export interface Options extends ImageOptions, QuantizerOptions {
useWorker: boolean
ImageClass: ImageClass
quantizer: string | StageOptions
generators: (string | StageOptions)[]
filters: string[]
useWorker: boolean;
ImageClass: ImageClass;
quantizer: string | StageOptions;
generators: (string | StageOptions)[];
filters: string[];
}
export function buildProcessOptions (opts: Options, override?: Partial<ProcessOptions>): ProcessOptions {
let { colorCount, quantizer, generators, filters } = opts
export function buildProcessOptions(
opts: Options,
override?: Partial<ProcessOptions>
): ProcessOptions {
const { colorCount, quantizer, generators, filters } = opts;
// Merge with common quantizer options
let commonQuantizerOpts = { colorCount }
let q = typeof quantizer === 'string'
? { name: quantizer, options: {} }
: quantizer
q.options = assignDeep({}, commonQuantizerOpts, q.options)
const commonQuantizerOpts = { colorCount };
const q =
typeof quantizer === "string"
? { name: quantizer, options: {} }
: quantizer;
q.options = assignDeep({}, commonQuantizerOpts, q.options);
return assignDeep({}, {
quantizer: q,
generators,
filters
}, override)
return assignDeep(
{},
{
quantizer: q,
generators,
filters,
},
override
);
}

@@ -1,21 +0,21 @@

import { ImageData, applyFilters } from '@vibrant/image'
import { Quantizer } from '@vibrant/quantizer'
import { Generator } from '@vibrant/generator'
import { Palette, Swatch, Filter } from '@vibrant/color'
import { ImageData, applyFilters } from "@vibrant/image";
import { Quantizer } from "@vibrant/quantizer";
import { Generator } from "@vibrant/generator";
import { Palette, Swatch, Filter } from "@vibrant/color";
export class Stage<T> {
private _map: { [name: string]: T } = {}
constructor (protected pipeline: BasicPipeline) { }
names () {
return Object.keys(this._map)
private _map: { [name: string]: T } = {};
constructor(protected pipeline: BasicPipeline) {}
names() {
return Object.keys(this._map);
}
has (name: string) {
return !!this._map[name]
has(name: string) {
return !!this._map[name];
}
get (name: string) {
return this._map[name]
get(name: string) {
return this._map[name];
}
register (name: string, stageFn: T) {
this._map[name] = stageFn
return this.pipeline
register(name: string, stageFn: T) {
this._map[name] = stageFn;
return this.pipeline;
}

@@ -25,27 +25,27 @@ }

export interface ProcessResult {
colors: Swatch[]
palettes: { [name: string]: Palette }
colors: Swatch[];
palettes: { [name: string]: Palette };
}
export interface StageOptions {
name: string
options?: any
name: string;
options?: any;
}
export interface ProcessOptions {
filters: string[]
quantizer: string | StageOptions
generators: (string | StageOptions)[]
filters: string[];
quantizer: string | StageOptions;
generators: (string | StageOptions)[];
}
interface StageTask<Q> {
name: string
fn: Q
options?: any
name: string;
fn: Q;
options?: any;
}
interface ProcessTasks {
filters: StageTask<Filter>[]
quantizer: StageTask<Quantizer>
generators: StageTask<Generator>[]
filters: StageTask<Filter>[];
quantizer: StageTask<Quantizer>;
generators: StageTask<Generator>[];
}

@@ -56,31 +56,31 @@

// generator: Stage<Generator>
process (imageData: ImageData, opts: ProcessOptions): Promise<ProcessResult>
process(imageData: ImageData, opts: ProcessOptions): Promise<ProcessResult>;
}
export class BasicPipeline implements Pipeline {
private _buildProcessTasks ({
private _buildProcessTasks({
filters,
quantizer,
generators
generators,
}: ProcessOptions): ProcessTasks {
// Support wildcard for generators
if (generators.length === 1 && generators[0] === '*') {
generators = this.generator.names()
if (generators.length === 1 && generators[0] === "*") {
generators = this.generator.names();
}
return {
filters: filters.map(f => createTask(this.filter, f)),
filters: filters.map((f) => createTask(this.filter, f)),
quantizer: createTask(this.quantizer, quantizer),
generators: generators.map(g => createTask(this.generator, g))
}
function createTask<Q> (
generators: generators.map((g) => createTask(this.generator, g)),
};
function createTask<Q>(
stage: Stage<Q>,
o: string | StageOptions
): StageTask<Q> {
let name: string
let options: any
if (typeof o === 'string') {
name = o
let name: string;
let options: any;
if (typeof o === "string") {
name = o;
} else {
name = o.name
options = o.options
name = o.name;
options = o.options;
}

@@ -91,34 +91,37 @@

fn: stage.get(name),
options
}
options,
};
}
}
filter: Stage<Filter> = new Stage(this)
quantizer: Stage<Quantizer> = new Stage(this)
generator: Stage<Generator> = new Stage(this)
async process (
filter: Stage<Filter> = new Stage(this);
quantizer: Stage<Quantizer> = new Stage(this);
generator: Stage<Generator> = new Stage(this);
async process(
imageData: ImageData,
opts: ProcessOptions
): Promise<ProcessResult> {
let { filters, quantizer, generators } = this._buildProcessTasks(opts)
const imageFilterData = await this._filterColors(filters, imageData)
const colors = await this._generateColors(quantizer, imageFilterData)
const palettes = await this._generatePalettes(generators, colors)
const { filters, quantizer, generators } = this._buildProcessTasks(opts);
const imageFilterData = await this._filterColors(filters, imageData);
const colors = await this._generateColors(quantizer, imageFilterData);
const palettes = await this._generatePalettes(generators, colors);
return {
colors,
palettes
}
palettes,
};
}
private _filterColors (filters: StageTask<Filter>[], imageData: ImageData) {
private _filterColors(filters: StageTask<Filter>[], imageData: ImageData) {
return Promise.resolve(
applyFilters(imageData, filters.map(({ fn }) => fn))
)
applyFilters(
imageData,
filters.map(({ fn }) => fn)
)
);
}
private _generateColors (
private _generateColors(
quantizer: StageTask<Quantizer>,
imageData: ImageData
) {
return Promise.resolve(quantizer.fn(imageData.data, quantizer.options))
return Promise.resolve(quantizer.fn(imageData.data, quantizer.options));
}
private async _generatePalettes (
private async _generatePalettes(
generators: StageTask<Generator>[],

@@ -130,14 +133,11 @@ colors: Swatch[]

generators.map(({ fn, options }) => Promise.resolve(fn(colors, options)))
)
);
// Map the values to the expected name
return Promise.resolve(
promiseArr.reduce(
(promises, promiseVal, i) => {
promises[generators[i].name] = promiseVal
return promises
},
{} as { [name: string]: Palette }
)
)
promiseArr.reduce((promises, promiseVal, i) => {
promises[generators[i].name] = promiseVal;
return promises;
}, {} as { [name: string]: Palette })
);
}
}

@@ -1,5 +0,5 @@

import { Pipeline, ProcessOptions, ProcessResult } from '../index'
import WorkerManager, { TaskWorkerClass } from '@vibrant/worker'
import { Swatch, Palette } from '@vibrant/color'
import { mapValues } from '../../utils'
import { Pipeline, ProcessOptions, ProcessResult } from "../index";
import WorkerManager, { TaskWorkerClass } from "@vibrant/worker";
import { Swatch, Palette } from "@vibrant/color";
import { mapValues } from "../../utils";

@@ -10,17 +10,21 @@ /**

export class WorkerPipeline implements Pipeline {
private _manager = new WorkerManager()
constructor (protected PipelineWorker: TaskWorkerClass) {
this._manager.register('pipeline', PipelineWorker)
private _manager = new WorkerManager();
constructor(protected PipelineWorker: TaskWorkerClass) {
this._manager.register("pipeline", PipelineWorker);
}
private _rehydrate (result: ProcessResult) {
let { colors, palettes } = result
result.colors = colors.map((s) => Swatch.clone(s))
private _rehydrate(result: ProcessResult) {
const { colors, palettes } = result;
result.colors = colors.map((s) => Swatch.clone(s));
result.palettes = mapValues(palettes, (p) => mapValues(p, (c) => c ? Swatch.clone(c) : null) as Palette)
return result
result.palettes = mapValues(
palettes,
(p) => mapValues(p, (c) => (c ? Swatch.clone(c) : null)) as Palette
);
return result;
}
process (imageData: ImageData, opts: ProcessOptions): Promise<ProcessResult> {
return this._manager.invokeWorker('pipeline', [imageData, opts], [imageData.data.buffer])
.then((result) => this._rehydrate(result as ProcessResult))
process(imageData: ImageData, opts: ProcessOptions): Promise<ProcessResult> {
return this._manager
.invokeWorker("pipeline", [imageData, opts], [imageData.data.buffer])
.then((result) => this._rehydrate(result as ProcessResult));
}
}

@@ -1,8 +0,6 @@

import runInWorker from '@vibrant/worker/lib/worker'
import { Pipeline } from '../index'
import { runInWorker } from "@vibrant/worker";
import { Pipeline } from "../index";
export default function runPipelineInWorker (self: Window, pipeline: Pipeline) {
runInWorker(self, (imageData, opts) =>
pipeline.process(imageData, opts)
)
export function runPipelineInWorker(self: Window, pipeline: Pipeline) {
runInWorker(self, (imageData, opts) => pipeline.process(imageData, opts));
}

@@ -1,12 +0,15 @@

export function mapValues<T, R> (o: { [key: string]: T }, mapper: (v: T) => R): { [key: string]: R } {
let result: { [key: string]: R } = {}
export function mapValues<T, R>(
o: { [key: string]: T },
mapper: (v: T) => R
): { [key: string]: R } {
const result: { [key: string]: R } = {};
for (const key in o) {
if (o.hasOwnProperty(key)) {
const v = o[key]
result[key] = mapper(v)
const v = o[key];
result[key] = mapper(v);
}
}
return result
return result;
}

@@ -18,21 +21,24 @@

*/
export function assignDeep<T> (target: Partial<T>, ...sources: (Partial<T> | undefined)[]): T {
sources.forEach(s => {
if (!s) return
export function assignDeep<T>(
target: Partial<T>,
...sources: (Partial<T> | undefined)[]
): T {
sources.forEach((s) => {
if (!s) return;
for (const key in s) {
if (s.hasOwnProperty(key)) {
const v = s[key] as any
const v = s[key] as any;
if (Array.isArray(v)) {
// Shallow copy
target[key] = v.slice(0) as any
} else if (typeof v === 'object') {
if (!target[key]) target[key] = {} as any
assignDeep<any>(target[key] as any, v)
target[key] = v.slice(0) as any;
} else if (typeof v === "object") {
if (!target[key]) target[key] = {} as any;
assignDeep<any>(target[key] as any, v);
} else {
target[key] = v
target[key] = v;
}
}
}
})
return target as T
});
return target as T;
}
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