15色以下に減色した画像を、画像解析し色レイヤーごとに表示(画像表示縮小追加)
画像の色情報と色レイヤー
15色に減色webアプリはこちら
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>画像の色情報と色レイヤー</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
input[type="file"] {
margin-bottom: 10px;
}
.colorLayerContainer {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.colorLayer {
margin: 5px;
border: 1px solid #ccc;
width: 50px;
height: 50px;
}
.colorLayerImageContainer {
margin: 5px;
width: 400px;
height: auto;
text-align: center;
}
.colorLayerImage {
max-width: 100%;
max-height: 400px;
}
</style>
</head>
<body>
<input type="file" id="imageUploader" accept="image/*">
<div id="colorLayers" class="colorLayerContainer"></div>
<div id="colorLayerImage" class="colorLayerImageContainer"></div>
<br/><br/><br/><br/>
<script>
const errorMargin = 3;
let img;
document.getElementById('imageUploader').addEventListener('change', function(e) {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = function(e) {
img = new Image();
img.onload = function() {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
const imageData = ctx.getImageData(0, 0, img.width, img.height);
const colors = extractColors(imageData);
const mergedColors = mergeSimilarColors(colors);
displayColorLayers(mergedColors, img.width, img.height);
displayColorImageLayers(mergedColors, imageData);
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
});
function extractColors(imageData) {
const colors = {};
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 roundedColor = roundColorValues(r, g, b);
colors[roundedColor] = (colors[roundedColor] || 0) + 1;
}
return colors;
}
function roundColorValues(r, g, b) {
const roundedR = Math.round(r / errorMargin) * errorMargin;
const roundedG = Math.round(g / errorMargin) * errorMargin;
const roundedB = Math.round(b / errorMargin) * errorMargin;
return `${roundedR},${roundedG},${roundedB}`;
}
function mergeSimilarColors(colors) {
const mergedColors = {};
for (const color1 in colors) {
let isMerged = false;
for (const color2 in mergedColors) {
if (isSimilarColor(color1, color2)) {
mergedColors[color2] += colors[color1];
isMerged = true;
break;
}
}
if (!isMerged) {
mergedColors[color1] = colors[color1];
}
}
return mergedColors;
}
function isSimilarColor(color1, color2) {
const [r1, g1, b1] = color1.split(',').map(Number);
const [r2, g2, b2] = color2.split(',').map(Number);
return Math.abs(r1 - r2) <= errorMargin &&
Math.abs(g1 - g2) <= errorMargin &&
Math.abs(b1 - b2) <= errorMargin;
}
function displayColorLayers(colors, imageWidth, imageHeight) {
const colorLayersDiv = document.getElementById('colorLayers');
colorLayersDiv.innerHTML = '';
for (const color in colors) {
const colorLayerCanvas = document.createElement('canvas');
colorLayerCanvas.width = imageWidth;
colorLayerCanvas.height = imageHeight;
colorLayerCanvas.classList.add('colorLayer');
const colorLayerCtx = colorLayerCanvas.getContext('2d');
const [r, g, b] = color.split(',').map(Number);
const imageData = colorLayerCtx.createImageData(imageWidth, imageHeight);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
data[i] = r;
data[i + 1] = g;
data[i + 2] = b;
data[i + 3] = 255;
}
colorLayerCtx.putImageData(imageData, 0, 0);
colorLayersDiv.appendChild(colorLayerCanvas);
}
}
function extractColorPixels(imageData, color) {
const width = imageData.width;
const height = imageData.height;
const colorLayerCanvas = document.createElement('canvas');
const colorLayerCtx = colorLayerCanvas.getContext('2d');
colorLayerCanvas.width = width;
colorLayerCanvas.height = height;
const imageDataCopy = new ImageData(new Uint8ClampedArray(imageData.data), width, height);
const data = imageDataCopy.data;
const colorComponents = color.split(',').map(Number);
const r = colorComponents[0];
const g = colorComponents[1];
const b = colorComponents[2];
for (let i = 0; i < data.length; i += 4) {
const pixelR = data[i];
const pixelG = data[i + 1];
const pixelB = data[i + 2];
if (Math.abs(pixelR - r) <= errorMargin && Math.abs(pixelG - g) <= errorMargin && Math.abs(pixelB - b) <= errorMargin) {
data[i + 3] = 255;
} else {
data[i + 3] = 0;
}
}
colorLayerCtx.putImageData(imageDataCopy, 0, 0);
return colorLayerCanvas;
}
function displayColorImageLayers(colors, imageData) {
const colorLayerImageDiv = document.getElementById('colorLayerImage');
colorLayerImageDiv.innerHTML = '';
for (const color in colors) {
const colorLayerCanvas = extractColorPixels(imageData, color);
colorLayerCanvas.classList.add('colorLayerImage');
colorLayerImageDiv.appendChild(colorLayerCanvas);
}
}
</script>
</body>
</html>