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

@vibrant/quantizer-mmcq

Package Overview
Dependencies
Maintainers
2
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vibrant/quantizer-mmcq - npm Package Compare versions

Comparing version 3.0.0 to 3.1.0-0

4

lib/pqueue.d.ts

@@ -8,9 +8,9 @@ export interface PQueueComparator<T> {

private _comparator;
private _sort();
private _sort;
constructor(comparator: PQueueComparator<T>);
push(item: T): void;
peek(index?: number): T;
pop(): T;
pop(): T | undefined;
size(): number;
map<U>(mapper: (item: T, index: number) => any): U[];
}

@@ -86,3 +86,3 @@ "use strict";

~~(mult * (g1 + g2 + 1) / 2),
~~(mult * (b1 + b2 + 1) / 2),
~~(mult * (b1 + b2 + 1) / 2)
];

@@ -89,0 +89,0 @@ }

{
"name": "@vibrant/quantizer-mmcq",
"version": "3.0.0",
"version": "3.1.0-0",
"description": "MMCQ quantzier for vibrant",
"scripts": {
"build:module": "tsc",
"test": "echo \"Error: no test specified\" && exit 1"

@@ -11,4 +10,11 @@ },

"types": "lib/index.d.ts",
"author": "",
"license": "ISC",
"author": {
"name": "akfish",
"email": "akfish@gmail.com"
},
"bugs": {
"url": "https://github.com/akfish/node-vibrant/issues"
},
"homepage": "https://github.com/akfish/node-vibrant",
"license": "MIT",
"dependencies": {

@@ -20,3 +26,3 @@ "@vibrant/color": "^3.0.0",

"devDependencies": {
"typescript": "latest"
"typescript": "^3.2.2"
},

@@ -23,0 +29,0 @@ "publishConfig": {

import { Quantizer, QuantizerOptions } from '@vibrant/quantizer'
import {
Pixels
Pixels
} from '@vibrant/image'

@@ -11,61 +11,61 @@ import { Filter, Swatch } from '@vibrant/color'

function _splitBoxes(pq: PQueue<VBox>, target: number): void {
let lastSize = pq.size()
while (pq.size() < target) {
let vbox = pq.pop()
function _splitBoxes (pq: PQueue<VBox>, target: number): void {
let lastSize = pq.size()
while (pq.size() < target) {
let vbox = pq.pop()
if (vbox && vbox.count() > 0) {
let [vbox1, vbox2] = vbox.split()
if (vbox && vbox.count() > 0) {
let [vbox1, vbox2] = vbox.split()
pq.push(vbox1)
if (vbox2 && vbox2.count() > 0) pq.push(vbox2)
pq.push(vbox1)
if (vbox2 && vbox2.count() > 0) pq.push(vbox2)
// No more new boxes, converged
if (pq.size() === lastSize) {
break
} else {
lastSize = pq.size()
}
} else {
break
}
// No more new boxes, converged
if (pq.size() === lastSize) {
break
} else {
lastSize = pq.size()
}
} else {
break
}
}
}
const MMCQ = (pixels: Pixels, opts: QuantizerOptions): Array<Swatch> => {
if (pixels.length === 0 || opts.colorCount < 2 || opts.colorCount > 256) {
throw new Error('Wrong MMCQ parameters')
}
if (pixels.length === 0 || opts.colorCount < 2 || opts.colorCount > 256) {
throw new Error('Wrong MMCQ parameters')
}
let vbox = VBox.build(pixels)
let colorCount = vbox.histogram.colorCount
let pq = new PQueue<VBox>((a, b) => a.count() - b.count())
let vbox = VBox.build(pixels)
let colorCount = vbox.histogram.colorCount
let pq = new PQueue<VBox>((a, b) => a.count() - b.count())
pq.push(vbox)
pq.push(vbox)
// first set of colors, sorted by population
_splitBoxes(pq, fractByPopulations * opts.colorCount)
// first set of colors, sorted by population
_splitBoxes(pq, fractByPopulations * opts.colorCount)
// Re-order
let pq2 = new PQueue<VBox>((a, b) => a.count() * a.volume() - b.count() * b.volume())
pq2.contents = pq.contents
// Re-order
let pq2 = new PQueue<VBox>((a, b) => a.count() * a.volume() - b.count() * b.volume())
pq2.contents = pq.contents
// next set - generate the median cuts using the (npix * vol) sorting.
_splitBoxes(pq2, opts.colorCount - pq2.size())
// next set - generate the median cuts using the (npix * vol) sorting.
_splitBoxes(pq2, opts.colorCount - pq2.size())
// calculate the actual colors
return generateSwatches(pq2)
// calculate the actual colors
return generateSwatches(pq2)
}
function generateSwatches(pq: PQueue<VBox>) {
let swatches: Swatch[] = []
while (pq.size()) {
let v = pq.pop()
let color = v.avg()
let [r, g, b] = color
swatches.push(new Swatch(color, v.count()))
}
return swatches
function generateSwatches (pq: PQueue<VBox>) {
let swatches: Swatch[] = []
while (pq.size()) {
let v = pq.pop()!
let color = v.avg()
let [r, g, b] = color
swatches.push(new Swatch(color, v.count()))
}
return swatches
}
export default MMCQ
export default MMCQ
export interface PQueueComparator<T> {
(a: T, b: T): number
(a: T, b: T): number
}
export default class PQueue<T> {
contents: T[]
private _sorted: boolean
private _comparator: PQueueComparator<T>
private _sort(): void {
if (!this._sorted) {
this.contents.sort(this._comparator)
this._sorted = true
}
contents: T[]
private _sorted: boolean
private _comparator: PQueueComparator<T>
private _sort (): void {
if (!this._sorted) {
this.contents.sort(this._comparator)
this._sorted = true
}
}
constructor(comparator: PQueueComparator<T>) {
this._comparator = comparator
this.contents = []
this._sorted = false
}
push(item: T): void {
this.contents.push(item)
this._sorted = false
}
peek(index?: number): T {
this._sort()
index = typeof index === 'number' ? index : this.contents.length - 1
return this.contents[index]
}
pop(): T {
this._sort()
return this.contents.pop()
}
size(): number {
return this.contents.length
}
map<U>(mapper: (item: T, index: number) => any): U[] {
this._sort()
return this.contents.map(mapper)
}
}
constructor (comparator: PQueueComparator<T>) {
this._comparator = comparator
this.contents = []
this._sorted = false
}
push (item: T): void {
this.contents.push(item)
this._sorted = false
}
peek (index?: number): T {
this._sort()
index = typeof index === 'number' ? index : this.contents.length - 1
return this.contents[index]
}
pop () {
this._sort()
return this.contents.pop()
}
size (): number {
return this.contents.length
}
map<U> (mapper: (item: T, index: number) => any): U[] {
this._sort()
return this.contents.map(mapper)
}
}

@@ -5,9 +5,9 @@ import { Vec3, Filter } from '@vibrant/color'

export interface Dimension {
r1: number
r2: number
g1: number
g2: number
b1: number
b2: number
[d: string]: number
r1: number
r2: number
g1: number
g2: number
b1: number
b2: number
[d: string]: number
}

@@ -19,222 +19,219 @@

export default class VBox {
static build(pixels: Pixels): VBox {
let h = new Histogram(pixels, { sigBits: SIGBITS })
let { rmin, rmax, gmin, gmax, bmin, bmax } = h
return new VBox(rmin, rmax, gmin, gmax, bmin, bmax, h)
}
static build (pixels: Pixels): VBox {
let h = new Histogram(pixels, { sigBits: SIGBITS })
let { rmin, rmax, gmin, gmax, bmin, bmax } = h
return new VBox(rmin, rmax, gmin, gmax, bmin, bmax, h)
}
dimension: Dimension
dimension: Dimension
private _volume = -1
private _avg: Vec3
private _count = -1
private _volume = -1
private _avg: Vec3 | null
private _count = -1
constructor(
r1: number, r2: number,
g1: number, g2: number,
b1: number, b2: number,
public histogram: Histogram
) {
// NOTE: dimension will be mutated by split operation.
// It must be specified explicitly, not from histogram
this.dimension = { r1, r2, g1, g2, b1, b2 }
}
constructor (
r1: number, r2: number,
g1: number, g2: number,
b1: number, b2: number,
public histogram: Histogram
) {
// NOTE: dimension will be mutated by split operation.
// It must be specified explicitly, not from histogram
this.dimension = { r1, r2, g1, g2, b1, b2 }
}
invalidate(): void {
this._volume = this._count = -1
this._avg = null
}
invalidate (): void {
this._volume = this._count = -1
this._avg = null
}
volume(): number {
if (this._volume < 0) {
let { r1, r2, g1, g2, b1, b2 } = this.dimension
this._volume = (r2 - r1 + 1) * (g2 - g1 + 1) * (b2 - b1 + 1)
}
return this._volume
volume (): number {
if (this._volume < 0) {
let { r1, r2, g1, g2, b1, b2 } = this.dimension
this._volume = (r2 - r1 + 1) * (g2 - g1 + 1) * (b2 - b1 + 1)
}
return this._volume
}
count(): number {
if (this._count < 0) {
let { hist, getColorIndex } = this.histogram
let { r1, r2, g1, g2, b1, b2 } = this.dimension
let c = 0
count (): number {
if (this._count < 0) {
let { hist, getColorIndex } = this.histogram
let { r1, r2, g1, g2, b1, b2 } = this.dimension
let c = 0
for (let r = r1; r <= r2; r++) {
for (let g = g1; g <= g2; g++) {
for (let b = b1; b <= b2; b++) {
let index = getColorIndex(r, g, b)
c += hist[index]
}
}
}
this._count = c
for (let r = r1; r <= r2; r++) {
for (let g = g1; g <= g2; g++) {
for (let b = b1; b <= b2; b++) {
let index = getColorIndex(r, g, b)
c += hist[index]
}
}
return this._count
}
this._count = c
}
return this._count
}
clone(): VBox {
let { histogram } = this
let { r1, r2, g1, g2, b1, b2 } = this.dimension
return new VBox(r1, r2, g1, g2, b1, b2, histogram)
}
clone (): VBox {
let { histogram } = this
let { r1, r2, g1, g2, b1, b2 } = this.dimension
return new VBox(r1, r2, g1, g2, b1, b2, histogram)
}
avg(): Vec3 {
if (!this._avg) {
let { hist, getColorIndex } = this.histogram
let { r1, r2, g1, g2, b1, b2 } = this.dimension
let ntot = 0
let mult = 1 << (8 - SIGBITS)
let rsum: number
let gsum: number
let bsum: number
rsum = gsum = bsum = 0
avg (): Vec3 {
if (!this._avg) {
let { hist, getColorIndex } = this.histogram
let { r1, r2, g1, g2, b1, b2 } = this.dimension
let ntot = 0
let mult = 1 << (8 - SIGBITS)
let rsum: number
let gsum: number
let bsum: number
rsum = gsum = bsum = 0
for (let r = r1; r <= r2; r++) {
for (let g = g1; g <= g2; g++) {
for (let b = b1; b <= b2; b++) {
var index = getColorIndex(r, g, b);
var h = hist[index];
ntot += h;
rsum += (h * (r + 0.5) * mult);
gsum += (h * (g + 0.5) * mult);
bsum += (h * (b + 0.5) * mult);
}
}
}
if (ntot) {
this._avg = [
~~(rsum / ntot),
~~(gsum / ntot),
~~(bsum / ntot)
]
} else {
this._avg = [
~~(mult * (r1 + r2 + 1) / 2),
~~(mult * (g1 + g2 + 1) / 2),
~~(mult * (b1 + b2 + 1) / 2),
]
}
for (let r = r1; r <= r2; r++) {
for (let g = g1; g <= g2; g++) {
for (let b = b1; b <= b2; b++) {
let index = getColorIndex(r, g, b)
let h = hist[index]
ntot += h
rsum += (h * (r + 0.5) * mult)
gsum += (h * (g + 0.5) * mult)
bsum += (h * (b + 0.5) * mult)
}
}
}
if (ntot) {
this._avg = [
~~(rsum / ntot),
~~(gsum / ntot),
~~(bsum / ntot)
]
} else {
this._avg = [
~~(mult * (r1 + r2 + 1) / 2),
~~(mult * (g1 + g2 + 1) / 2),
~~(mult * (b1 + b2 + 1) / 2)
]
}
}
return this._avg
}
return this._avg
}
contains(rgb: Vec3): boolean {
let [r, g, b] = rgb
let { r1, r2, g1, g2, b1, b2 } = this.dimension
r >>= RSHIFT
g >>= RSHIFT
b >>= RSHIFT
contains (rgb: Vec3): boolean {
let [r, g, b] = rgb
let { r1, r2, g1, g2, b1, b2 } = this.dimension
r >>= RSHIFT
g >>= RSHIFT
b >>= RSHIFT
return r >= r1 && r <= r2
&& g >= g1 && g <= g2
&& b >= b1 && b <= b2
}
return r >= r1 && r <= r2
&& g >= g1 && g <= g2
&& b >= b1 && b <= b2
}
split(): VBox[] {
let { hist, getColorIndex } = this.histogram
let { r1, r2, g1, g2, b1, b2 } = this.dimension
let count = this.count()
if (!count) return []
if (count === 1) return [this.clone()]
let rw = r2 - r1 + 1
let gw = g2 - g1 + 1
let bw = b2 - b1 + 1
split (): VBox[] {
let { hist, getColorIndex } = this.histogram
let { r1, r2, g1, g2, b1, b2 } = this.dimension
let count = this.count()
if (!count) return []
if (count === 1) return [this.clone()]
let rw = r2 - r1 + 1
let gw = g2 - g1 + 1
let bw = b2 - b1 + 1
let maxw = Math.max(rw, gw, bw)
let accSum: Uint32Array = null
let sum: number
let total: number
sum = total = 0
let maxw = Math.max(rw, gw, bw)
let accSum: Uint32Array | null = null
let sum: number
let total: number
sum = total = 0
let maxd: 'r' | 'g' | 'b' = null
let maxd: 'r' | 'g' | 'b' | null = null
if (maxw === rw) {
maxd = 'r'
accSum = new Uint32Array(r2 + 1)
for (let r = r1; r <= r2; r++) {
sum = 0
for (let g = g1; g <= g2; g++) {
for (let b = b1; b <= b2; b++) {
let index = getColorIndex(r, g, b);
sum += hist[index];
}
}
total += sum;
accSum[r] = total;
}
} else if (maxw === gw) {
maxd = 'g'
accSum = new Uint32Array(g2 + 1)
for (let g = g1; g <= g2; g++) {
sum = 0
for (let r = r1; r <= r2; r++) {
for (let b = b1; b <= b2; b++) {
let index = getColorIndex(r, g, b);
sum += hist[index];
}
}
total += sum;
accSum[g] = total;
}
} else {
maxd = 'b'
accSum = new Uint32Array(b2 + 1)
for (let b = b1; b <= b2; b++) {
sum = 0
for (let r = r1; r <= r2; r++) {
for (let g = g1; g <= g2; g++) {
let index = getColorIndex(r, g, b);
sum += hist[index];
}
}
total += sum;
accSum[b] = total;
}
if (maxw === rw) {
maxd = 'r'
accSum = new Uint32Array(r2 + 1)
for (let r = r1; r <= r2; r++) {
sum = 0
for (let g = g1; g <= g2; g++) {
for (let b = b1; b <= b2; b++) {
let index = getColorIndex(r, g, b)
sum += hist[index]
}
}
let splitPoint = -1
let reverseSum = new Uint32Array(accSum.length)
for (let i = 0; i < accSum.length; i++) {
let d = accSum[i];
if (splitPoint < 0 && d > total / 2) splitPoint = i
reverseSum[i] = total - d
total += sum
accSum[r] = total
}
} else if (maxw === gw) {
maxd = 'g'
accSum = new Uint32Array(g2 + 1)
for (let g = g1; g <= g2; g++) {
sum = 0
for (let r = r1; r <= r2; r++) {
for (let b = b1; b <= b2; b++) {
let index = getColorIndex(r, g, b)
sum += hist[index]
}
}
total += sum
accSum[g] = total
}
} else {
maxd = 'b'
accSum = new Uint32Array(b2 + 1)
for (let b = b1; b <= b2; b++) {
sum = 0
for (let r = r1; r <= r2; r++) {
for (let g = g1; g <= g2; g++) {
let index = getColorIndex(r, g, b)
sum += hist[index]
}
}
total += sum
accSum[b] = total
}
}
let vbox = this
let splitPoint = -1
let reverseSum = new Uint32Array(accSum.length)
for (let i = 0; i < accSum.length; i++) {
let d = accSum[i]
if (splitPoint < 0 && d > total / 2) splitPoint = i
reverseSum[i] = total - d
}
function doCut(d: string): VBox[] {
let dim1 = d + '1'
let dim2 = d + '2'
let d1 = vbox.dimension[dim1]
let d2 = vbox.dimension[dim2]
let vbox1 = vbox.clone()
let vbox2 = vbox.clone()
let left = splitPoint - d1
let right = d2 - splitPoint
if (left <= right) {
d2 = Math.min(d2 - 1, ~~(splitPoint + right / 2))
d2 = Math.max(0, d2)
}
else {
d2 = Math.max(d1, ~~(splitPoint - 1 - left / 2))
d2 = Math.min(vbox.dimension[dim2], d2)
}
let vbox = this
function doCut (d: string): VBox[] {
let dim1 = d + '1'
let dim2 = d + '2'
let d1 = vbox.dimension[dim1]
let d2 = vbox.dimension[dim2]
let vbox1 = vbox.clone()
let vbox2 = vbox.clone()
let left = splitPoint - d1
let right = d2 - splitPoint
if (left <= right) {
d2 = Math.min(d2 - 1, ~~(splitPoint + right / 2))
d2 = Math.max(0, d2)
} else {
d2 = Math.max(d1, ~~(splitPoint - 1 - left / 2))
d2 = Math.min(vbox.dimension[dim2], d2)
}
while (!accSum[d2]) d2++
while (!accSum![d2]) d2++
let c2 = reverseSum[d2]
while (!c2 && accSum![d2 - 1]) c2 = reverseSum[--d2]
let c2 = reverseSum[d2]
while (!c2 && accSum[d2 - 1]) c2 = reverseSum[--d2]
vbox1.dimension[dim2] = d2
vbox2.dimension[dim1] = d2 + 1
vbox1.dimension[dim2] = d2
vbox2.dimension[dim1] = d2 + 1
return [vbox1, vbox2]
}
return [vbox1, vbox2]
}
return doCut(maxd)
}
return doCut(maxd)
}
}
}

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