update image-q and other packages

This commit is contained in:
HF 2022-01-01 01:35:18 +01:00
parent 9401cde3ce
commit 44af557581

View File

@ -6,7 +6,7 @@
import React, { useState, useEffect } from 'react';
import { useSelector, shallowEqual } from 'react-redux';
import fileDownload from 'js-file-download';
import { utils, applyPalette } from 'image-q';
import iq from 'image-q';
import { jt, t } from 'ttag';
import printGIMPPalette from '../core/exportGPL';
@ -43,6 +43,113 @@ function readFile(
fr.readAsDataURL(file);
}
const ColorDistanceCalculators = [
'Euclidean',
'Manhattan',
'CIEDE2000',
'CIE94Textiles',
'CIE94GraphicArts',
'EuclideanBT709NoAlpha',
'EuclideanBT709',
'ManhattanBT709',
'CMetric',
'PNGQuant',
'ManhattanNommyde',
];
function quantize(
pointContainer,
colors,
colorDist,
strategy,
onProgress,
) {
return new Promise((resolve, reject) => {
// read colors into palette
const palette = new iq.utils.Palette();
palette.add(iq.utils.Point.createByRGBA(0, 0, 0, 0));
colors.forEach((clr) => {
const [r, g, b] = clr;
const point = iq.utils.Point.createByRGBA(r, g, b, 255);
palette.add(point);
});
// construct color distance calculator
let distance;
switch (colorDist) {
case 'Euclidean':
distance = new iq.distance.Euclidean();
break;
case 'Manhattan':
distance = new iq.distance.Manhattan();
break;
case 'CIEDE2000':
distance = new iq.distance.CIEDE2000();
break;
case 'CIE94Textiles':
distance = new iq.distance.CIE94Textiles();
break;
case 'CIE94GraphicArts':
distance = new iq.distance.CIE94GraphicArts();
break;
case 'EuclideanBT709NoAlpha':
distance = new iq.distance.EuclideanBT709NoAlpha();
break;
case 'EuclideanBT709':
distance = new iq.distance.EuclideanBT709();
break;
case 'ManhattanBT709':
distance = new iq.distance.ManhattanBT709();
break;
case 'CMetric':
distance = new iq.distance.CMetric();
break;
case 'PNGQuant':
distance = new iq.distance.PNGQuant();
break;
case 'ManhattanNommyde':
distance = new iq.distance.ManhattanNommyde();
break;
default:
distance = new iq.distance.Euclidean();
}
// construct image quantizer
let imageQuantizer;
if (strategy === 'Nearest') {
imageQuantizer = new iq.image.NearestColor(distance);
} else if (strategy === 'Riemersma') {
imageQuantizer = new iq.image.ErrorDiffusionRiemersma(distance);
} else {
imageQuantizer = new iq.image.ErrorDiffusionArray(
distance,
iq.image.ErrorDiffusionArrayKernel[strategy],
true,
0,
false,
);
}
// quantize
let outPointContainer;
const iterator = imageQuantizer.quantize(pointContainer, palette);
const next = () => {
try {
const result = iterator.next();
if (result.done) {
resolve(outPointContainer);
} else {
if (result.value.pointContainer) {
outPointContainer = result.value.pointContainer;
}
if (onProgress) onProgress(result.value.progress);
setTimeout(next, 10);
}
} catch (error) {
reject(error);
}
};
setTimeout(next, 10);
});
}
function drawPixels(idxi8, width, height) {
const can = document.createElement('canvas');
can.width = width;
@ -155,28 +262,23 @@ async function renderOutputImage(opts) {
height,
aa,
);
pointContainer = utils.PointContainer.fromHTMLCanvasElement(image);
pointContainer = iq.utils.PointContainer.fromHTMLCanvasElement(image);
} else {
pointContainer = utils.PointContainer.fromHTMLImageElement(image);
pointContainer = iq.utils.PointContainer.fromHTMLImageElement(image);
}
// dither
const { colors, strategy, colorDist } = dither;
const palette = new utils.Palette();
palette.add(utils.Point.createByRGBA(0, 0, 0, 0));
colors.forEach((clr) => {
const [r, g, b] = clr;
const point = utils.Point.createByRGBA(r, g, b, 255);
palette.add(point);
});
const progEl = document.getElementById('qprog');
// eslint-disable-next-line no-await-in-loop
pointContainer = await applyPalette(pointContainer, palette, {
colorDistanceFormula: colorDist,
imageQuantization: strategy,
onProgress: (progress) => {
pointContainer = await quantize(
pointContainer,
colors,
colorDist,
strategy,
(progress) => {
progEl.innerHTML = `Loading... ${Math.round(progress)} %`;
},
});
);
progEl.innerHTML = 'Done';
image = drawPixels(
pointContainer.toUint8Array(),
@ -220,8 +322,8 @@ function Converter() {
const [selectedCanvas, selectCanvas] = useState(canvasId);
const [selectedFile, selectFile] = useState(null);
const [selectedStrategy, selectStrategy] = useState('nearest');
const [selectedColorDist, selectColorDist] = useState('euclidean');
const [selectedStrategy, selectStrategy] = useState('Nearest');
const [selectedColorDist, selectColorDist] = useState('Euclidean');
const [selectedScaleKeepRatio, selectScaleKeepRatio] = useState(true);
const [scaleData, setScaleData] = useState({
enabled: false,
@ -236,8 +338,6 @@ function Converter() {
offsetY: 0,
});
const input = document.createElement('canvas');
useEffect(() => {
if (selectedFile) {
const canvas = canvases[selectedCanvas];
@ -346,21 +446,14 @@ function Converter() {
}}
>
{
['nearest',
'riemersma',
'floyd-steinberg',
'false-floyd-steinberg',
'stucki',
'atkinson',
'jarvis',
'burkes',
'sierra',
'two-sierra',
'sierra-lite'].map((strat) => (
<option
value={strat}
selected={(selectedStrategy === strat)}
>{strat}</option>
['Nearest',
'Riemersma',
...Object.keys(iq.image.ErrorDiffusionArrayKernel),
].map((strat) => (
<option
value={strat}
selected={(selectedStrategy === strat)}
>{strat}</option>
))
}
</select>
@ -373,21 +466,11 @@ function Converter() {
}}
>
{
['cie94-textiles',
'cie94-graphic-arts',
'ciede2000',
'color-metric',
'euclidean',
'euclidean-bt709-noalpha',
'euclidean-bt709',
'manhattan',
'manhattan-bt709',
'manhattan-nommyde',
'pngquant'].map((strat) => (
<option
value={strat}
selected={(selectedColorDist === strat)}
>{strat}</option>
ColorDistanceCalculators.map((strat) => (
<option
value={strat}
selected={(selectedColorDist === strat)}
>{strat}</option>
))
}
</select>