我正在开发一个项目,我需要将缩写放在另一张图像上,它可以工作,但有一个问题。
function downloadURI(uri, name) {
const link = document.createElement('a');
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
function loadImage(url) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous'; // Avoid CORS issues if needed
img.onload = () => {
resolve(img);
};
img.onerror = (err) => {
console.error('Error loading image', err);
reject(err);
};
img.src = url;
});
}
async function createInitialsTextureWithImage(size = 2048, initials, imageUrl, color = [0, 0, 0]) {
const textOffsetY = -64;
const textSize = 250;
try {
await document.fonts.load(`normal ${textSize}px 'VCR OSD Mono'`);
const canvas = document.createElement('canvas');
canvas.width = size * 2;
canvas.height = size * 2;
const ctx = canvas.getContext('2d');
const backgroundImage = await loadImage(imageUrl);
ctx.clearRect(0, 0, size * 2, size * 2);
ctx.drawImage(backgroundImage, 0, 0, size * 2, size * 2);
ctx.fillStyle = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = `${textSize * 2}px 'VCR OSD Mono'`;
ctx.fillText(initials, (size * 2) / 2, (size * 2) / 2 + textOffsetY * 2);
const downscaledCanvas = document.createElement('canvas');
downscaledCanvas.width = size;
downscaledCanvas.height = size;
const downscaledCtx = downscaledCanvas.getContext('2d');
downscaledCtx.imageSmoothingEnabled = false;
downscaledCtx.drawImage(canvas, 0, 0, size, size);
return new Promise((resolve) => {
downscaledCanvas.toBlob((blob) => {
const file = new File([blob], 'initials.png', {
type: 'image/png'
});
resolve(file); // Resolve with the file
});
});
} catch (err) {
console.error('Error in createInitialsTextureWithImage:', err);
throw err;
}
}
function displayGeneratedImage(file) {
const imgElement = document.getElementById('generatedImage');
const imageURL = URL.createObjectURL(file);
downloadURI(imageURL, 'test.png'); // use to downloa it to local
imgElement.src = imageURL;
}
document.getElementById('generateButton').addEventListener('click', async () => {
try {
const initials = 'NM';
//const imageUrl = 'https://i.imgur.com/Gtwc8mZ.png';
const imageUrl = 'https://i.imgur.com/V7K11Px.png';
const file = await createInitialsTextureWithImage(2048, initials, imageUrl, [0, 0, 0]);
displayGeneratedImage(file);
} catch (error) {
console.error('Error generating image:', error);
}
});
<link href="https://fonts.cdnfonts.com/css/vcr-osd-mono" rel="stylesheet">
<button id="generateButton">Generate</button>
<br><br>
<img id="generatedImage" alt="Generated Initials Texture" style="height: 500px; border: 1px solid #000;">
问题是,生成的图像添加了一些抗锯齿功能,并且字母包含一些灰色。
是否可以摆脱这种抗锯齿功能?
我已经尝试过:
imageSmoothingEnabled
设置为 false
但他们都没有帮助。
更新1:
我正在将此功能用于项目的另一部分:
combinedTextureUrl = await createInitialsTextureWithImage(2048, initials, textureLookup);
downloadURI(combinedTextureUrl, 'test.png');
发生这种情况是因为从生成的图像中可以看出,它就像:
更新2:
由于某种原因,
downloadURI
不会在StackOverflow上触发,因此我创建了this fiddle,它将结果图像下载到本地,从而生成带有抗锯齿文本的结果。
我已经找到了问题的解决方案。
我总是有一个具有 2-3 种颜色的图像,并且我知道缩写的颜色始终是黑色,因此我可以设置一个循环来检查每个像素并将其替换为黑色或白色。
const imageData = rotatedCtx.getImageData(0, 0, size, size);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
const grayscale = 0.3 * r + 0.59 * g + 0.11 * b;
const newColor = grayscale < 128 ? 0 : 255;
data[i] = data[i + 1] = data[i + 2] = newColor;
}
rotatedCtx.putImageData(imageData, 0, 0);
通过这种方法,它用黑色代替了灰色边缘的颜色。