this resolves the crash but not the weird flicker
This commit is contained in:
parent
d9fae875f4
commit
953db2f968
1 changed files with 77 additions and 41 deletions
|
@ -13,37 +13,70 @@ const colorToGrayscale = (color) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract color using canvas2d
|
* Extract colors from an image or SVG element using canvas
|
||||||
* @param {HTMLImageElement} image Image source
|
* @param {HTMLImageElement | SVGSVGElement} element Image or SVG source element
|
||||||
* @returns Colors represeting the image
|
* @returns {Promise<Array>} Colors representing the element
|
||||||
*/
|
*/
|
||||||
const extractColors = (image) => {
|
const extractColors = (element) => {
|
||||||
const canvas = document.createElement("canvas");
|
return new Promise((resolve, reject) => {
|
||||||
canvas.width = image.naturalWidth || image.width;
|
// Create a canvas with the same dimensions as the element
|
||||||
canvas.height = image.naturalHeight || image.height;
|
const canvas = document.createElement("canvas");
|
||||||
const ctx = canvas.getContext("2d");
|
let imageSource;
|
||||||
ctx.drawImage(image, 0, 0);
|
|
||||||
|
|
||||||
const imageData = ctx.getImageData(
|
if (element instanceof SVGSVGElement) {
|
||||||
0,
|
// SVG element handling
|
||||||
0,
|
canvas.width = element.viewBox.baseVal.width;
|
||||||
Math.max(1, canvas.width),
|
canvas.height = element.viewBox.baseVal.height;
|
||||||
Math.max(1, canvas.height)
|
|
||||||
);
|
|
||||||
const pixelData = imageData.data;
|
|
||||||
|
|
||||||
const colors = [];
|
const svgString = new XMLSerializer().serializeToString(element);
|
||||||
for (let i = 0; i < pixelData.length; i += 4) {
|
const svgBlob = new Blob([svgString], { type: "image/svg+xml" });
|
||||||
if (pixelData[i + 3] > 0) {
|
const svgUrl = URL.createObjectURL(svgBlob);
|
||||||
colors.push({
|
|
||||||
r: pixelData[i],
|
imageSource = new Image();
|
||||||
g: pixelData[i + 1],
|
imageSource.src = svgUrl;
|
||||||
b: pixelData[i + 2],
|
|
||||||
});
|
imageSource.onload = () => {
|
||||||
|
processImage(imageSource);
|
||||||
|
URL.revokeObjectURL(svgUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
imageSource.onerror = (error) => {
|
||||||
|
URL.revokeObjectURL(svgUrl);
|
||||||
|
reject(error);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Regular image handling
|
||||||
|
canvas.width = element.naturalWidth || element.width;
|
||||||
|
canvas.height = element.naturalHeight || element.height;
|
||||||
|
processImage(element);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return colors;
|
const processImage = (img) => {
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
ctx.drawImage(img, 0, 0);
|
||||||
|
|
||||||
|
const imageData = ctx.getImageData(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
Math.max(1, canvas.width),
|
||||||
|
Math.max(1, canvas.height)
|
||||||
|
);
|
||||||
|
const pixelData = imageData.data;
|
||||||
|
|
||||||
|
const colors = [];
|
||||||
|
for (let i = 0; i < pixelData.length; i += 4) {
|
||||||
|
if (pixelData[i + 3] > 0) {
|
||||||
|
colors.push({
|
||||||
|
r: pixelData[i],
|
||||||
|
g: pixelData[i + 1],
|
||||||
|
b: pixelData[i + 2],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(colors);
|
||||||
|
};
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,28 +84,31 @@ const extractColors = (image) => {
|
||||||
* @param {Mode} mode
|
* @param {Mode} mode
|
||||||
*/
|
*/
|
||||||
const changeTheme = (mode) => {
|
const changeTheme = (mode) => {
|
||||||
for (const item of document.getElementsByTagName("svg")) {
|
// Process SVG elements
|
||||||
const image = document.createElement("img");
|
for (const svgElement of document.getElementsByTagName("svg")) {
|
||||||
image.src = `data:image/svg+xml;base64,${btoa(
|
extractColors(svgElement)
|
||||||
new XMLSerializer().serializeToString(item)
|
.then((colors) => {
|
||||||
)}`;
|
applyFilter(mode, svgElement, colors);
|
||||||
|
})
|
||||||
image.width = item.viewBox.baseVal.width;
|
.catch((error) => {
|
||||||
image.height = item.viewBox.baseVal.height;
|
console.error("Error extracting colors:", error);
|
||||||
|
});
|
||||||
image.onload = () => {
|
|
||||||
applyFilter(mode, item, extractColors(image));
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SVG embedded in images as base64
|
// Process SVG images embedded as base64
|
||||||
for (const item of document.getElementsByTagName("img")) {
|
for (const item of document.getElementsByTagName("img")) {
|
||||||
if (!item.src.startsWith("data:image/svg+xml;base64,")) {
|
if (!item.src.startsWith("data:image/svg+xml;base64,")) {
|
||||||
// Exclude image who aren't SVG and base64 encoded
|
// Exclude images that aren't SVG and base64 encoded
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyFilter(mode, item, extractColors(item));
|
extractColors(item)
|
||||||
|
.then((colors) => {
|
||||||
|
applyFilter(mode, item, colors);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error extracting colors:", error);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue