update image-q and other packages
This commit is contained in:
parent
9401cde3ce
commit
44af557581
|
@ -6,7 +6,7 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useSelector, shallowEqual } from 'react-redux';
|
import { useSelector, shallowEqual } from 'react-redux';
|
||||||
import fileDownload from 'js-file-download';
|
import fileDownload from 'js-file-download';
|
||||||
import { utils, applyPalette } from 'image-q';
|
import iq from 'image-q';
|
||||||
import { jt, t } from 'ttag';
|
import { jt, t } from 'ttag';
|
||||||
|
|
||||||
import printGIMPPalette from '../core/exportGPL';
|
import printGIMPPalette from '../core/exportGPL';
|
||||||
|
@ -43,6 +43,113 @@ function readFile(
|
||||||
fr.readAsDataURL(file);
|
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) {
|
function drawPixels(idxi8, width, height) {
|
||||||
const can = document.createElement('canvas');
|
const can = document.createElement('canvas');
|
||||||
can.width = width;
|
can.width = width;
|
||||||
|
@ -155,28 +262,23 @@ async function renderOutputImage(opts) {
|
||||||
height,
|
height,
|
||||||
aa,
|
aa,
|
||||||
);
|
);
|
||||||
pointContainer = utils.PointContainer.fromHTMLCanvasElement(image);
|
pointContainer = iq.utils.PointContainer.fromHTMLCanvasElement(image);
|
||||||
} else {
|
} else {
|
||||||
pointContainer = utils.PointContainer.fromHTMLImageElement(image);
|
pointContainer = iq.utils.PointContainer.fromHTMLImageElement(image);
|
||||||
}
|
}
|
||||||
// dither
|
// dither
|
||||||
const { colors, strategy, colorDist } = 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');
|
const progEl = document.getElementById('qprog');
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
pointContainer = await applyPalette(pointContainer, palette, {
|
pointContainer = await quantize(
|
||||||
colorDistanceFormula: colorDist,
|
pointContainer,
|
||||||
imageQuantization: strategy,
|
colors,
|
||||||
onProgress: (progress) => {
|
colorDist,
|
||||||
|
strategy,
|
||||||
|
(progress) => {
|
||||||
progEl.innerHTML = `Loading... ${Math.round(progress)} %`;
|
progEl.innerHTML = `Loading... ${Math.round(progress)} %`;
|
||||||
},
|
},
|
||||||
});
|
);
|
||||||
progEl.innerHTML = 'Done';
|
progEl.innerHTML = 'Done';
|
||||||
image = drawPixels(
|
image = drawPixels(
|
||||||
pointContainer.toUint8Array(),
|
pointContainer.toUint8Array(),
|
||||||
|
@ -220,8 +322,8 @@ function Converter() {
|
||||||
|
|
||||||
const [selectedCanvas, selectCanvas] = useState(canvasId);
|
const [selectedCanvas, selectCanvas] = useState(canvasId);
|
||||||
const [selectedFile, selectFile] = useState(null);
|
const [selectedFile, selectFile] = useState(null);
|
||||||
const [selectedStrategy, selectStrategy] = useState('nearest');
|
const [selectedStrategy, selectStrategy] = useState('Nearest');
|
||||||
const [selectedColorDist, selectColorDist] = useState('euclidean');
|
const [selectedColorDist, selectColorDist] = useState('Euclidean');
|
||||||
const [selectedScaleKeepRatio, selectScaleKeepRatio] = useState(true);
|
const [selectedScaleKeepRatio, selectScaleKeepRatio] = useState(true);
|
||||||
const [scaleData, setScaleData] = useState({
|
const [scaleData, setScaleData] = useState({
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
@ -236,8 +338,6 @@ function Converter() {
|
||||||
offsetY: 0,
|
offsetY: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
const input = document.createElement('canvas');
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedFile) {
|
if (selectedFile) {
|
||||||
const canvas = canvases[selectedCanvas];
|
const canvas = canvases[selectedCanvas];
|
||||||
|
@ -346,21 +446,14 @@ function Converter() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
['nearest',
|
['Nearest',
|
||||||
'riemersma',
|
'Riemersma',
|
||||||
'floyd-steinberg',
|
...Object.keys(iq.image.ErrorDiffusionArrayKernel),
|
||||||
'false-floyd-steinberg',
|
].map((strat) => (
|
||||||
'stucki',
|
<option
|
||||||
'atkinson',
|
value={strat}
|
||||||
'jarvis',
|
selected={(selectedStrategy === strat)}
|
||||||
'burkes',
|
>{strat}</option>
|
||||||
'sierra',
|
|
||||||
'two-sierra',
|
|
||||||
'sierra-lite'].map((strat) => (
|
|
||||||
<option
|
|
||||||
value={strat}
|
|
||||||
selected={(selectedStrategy === strat)}
|
|
||||||
>{strat}</option>
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
|
@ -373,21 +466,11 @@ function Converter() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
['cie94-textiles',
|
ColorDistanceCalculators.map((strat) => (
|
||||||
'cie94-graphic-arts',
|
<option
|
||||||
'ciede2000',
|
value={strat}
|
||||||
'color-metric',
|
selected={(selectedColorDist === strat)}
|
||||||
'euclidean',
|
>{strat}</option>
|
||||||
'euclidean-bt709-noalpha',
|
|
||||||
'euclidean-bt709',
|
|
||||||
'manhattan',
|
|
||||||
'manhattan-bt709',
|
|
||||||
'manhattan-nommyde',
|
|
||||||
'pngquant'].map((strat) => (
|
|
||||||
<option
|
|
||||||
value={strat}
|
|
||||||
selected={(selectedColorDist === strat)}
|
|
||||||
>{strat}</option>
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user