I’m currently working on a project where I need to convert the colors depending on how many elements that array has (let say if there are 4 elements in array then it will convert into 4 color pattern). and textureFile
is a file to place on the image itself, so it is like multiply
effect on Photoshop. It places image, but problem is with the rotation. Image should be a tiled knitting, but I get weird result.
Image itself is 10×10 and texture is 40×16 in a pixels.
This image is what I get:
and this is how it should be:
I have tried to rotate the texture by 45, -90 and etc, but that does not do the work.
My code:
export async function replaceColors(imageDataFile, colorArray, textureFile = null, rotationAngle = 0) {
return new Promise((resolve) => {
const image = new Image();
const reader = new FileReader();
reader.onload = function (event) {
image.onload = function () {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const { width, height } = image;
canvas.width = width;
canvas.height = height;
context.drawImage(image, 0, 0, width, height);
const imageData = context.getImageData(0, 0, width, height);
const imageDataArray = imageData.data;
const numColors = colorArray.length;
const thresholdStep = 255 / numColors;
for (let i = 0; i < imageDataArray.length; i += 4) {
const avg = (imageDataArray[i] + imageDataArray[i + 1] + imageDataArray[i + 2]) / 3;
let colorIndex = Math.floor(avg / thresholdStep);
colorIndex = Math.min(colorIndex, numColors - 1); // Ensure colorIndex is within bounds
imageDataArray[i] = colorArray[colorIndex][0];
imageDataArray[i + 1] = colorArray[colorIndex][1];
imageDataArray[i + 2] = colorArray[colorIndex][2];
}
context.putImageData(imageData, 0, 0);
if (textureFile) {
const textureImage = new Image();
const textureReader = new FileReader();
textureReader.onload = function (textureEvent) {
textureImage.onload = function () {
const patternCanvas = document.createElement('canvas');
const patternContext = patternCanvas.getContext('2d');
const { width: textureWidth, height: textureHeight } = textureImage;
patternCanvas.width = textureWidth;
patternCanvas.height = textureHeight;
// Draw the texture image onto the pattern canvas
patternContext.drawImage(textureImage, 0, 0, textureWidth, textureHeight);
const pattern = context.createPattern(patternCanvas, 'repeat');
context.setTransform(1, 0, 0, 1, 0, 0); // Reset transformation matrix
context.globalAlpha = 1.0; // Set opacity to 100%
context.globalCompositeOperation = 'multiply'; // Use multiply blend mode
context.fillStyle = pattern;
context.fillRect(0, 0, width, height);
canvas.toBlob((blob) => {
const file = new File([blob], 'replaced.png', { type: 'image/png' });
resolve(file);
}, 'image/png');
};
textureImage.src = textureEvent.target.result;
};
textureReader.readAsDataURL(textureFile);
} else {
canvas.toBlob((blob) => {
const file = new File([blob], 'replaced.png', { type: 'image/png' });
resolve(file);
}, 'image/png');
}
};
image.src = event.target.result;
};
reader.readAsDataURL(imageDataFile);
});
}