포토샵, 라이트룸 등의 이미지 보정 프로그램으로 특정 색을 강조하거나 흑백으로 만들기가 아주 쉽다. 그렇다면 웹 페이지로 그것을 구현이 가능할까?
<div id="Pics">
<img id="myImage" src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Colorwheel.svg/1200px-Colorwheel.svg.png" alt="x"></img>
<canvas id="myCanvas"></canvas>
</div>
var imageObj = document.getElementById("myImage");
var canvas = imageObj.nextSibling;
canvas.height = imageObj.height;
canvas.width = imageObj.width;
var ctx = canvas.getContext('2d');
ctx.drawImage(imageObj, 0, 0, imageObj.width, imageObj.height);
var id= ctx.getImageData(0, 0, imageObj.width, imageObj.height);
Id가 myImage인 객체의 엘레먼트를 받아서 imageObj변수에 넣었다.
그리고 nextSibling를 사용하여 imageObj의 다음에 있는 객체 즉 myCanvas를
변수 canvas에 넣었다.
다음으로는 canvas의 넓이와 높이를 imageObj와 동일하게 만들고
2d 그래픽을 다룰 것이므로 var ctx = canvas.getContext('2d') 캔버스를 2d로 정한다.
ctx.drawImage(imageObj, 0, 0, imageObj.width, imageObj.height);
var id= ctx.getImageData(0, 0, imageObj.width, imageObj.height);
이후에 ctx에 위와 같은 값으로 omageObj의 이미지를 그리고 그것을 픽셀 단위로 쪼개서
id에 저장한다.
for (var i = 0; i < id.data.length-4; i += 4) {
if(filter==="RED"){
if((id.data[i+1]>id.data[i+2]+40) ||(id.data[i]-id.data[i+1])<10 || (id.data[i]-id.data[i+2])<25){
id.data[i] = id.data[i+1] = id.data[i+2] = (id.data[i]+ id.data[i+1] + id.data[i+2])/3;
//빨강 필터
}
}
if(filter==="GREEN"){
if((id.data[i+1]-id.data[i])<0|| (id.data[i+1]-id.data[i+2])<0 ||(id.data[i]>id.data[i+2]+150)){
id.data[i] = id.data[i+1] = id.data[i+2] = (id.data[i]+ id.data[i+1] + id.data[i+2])/3;
//초록 필터
}
}
if(filter==="BLUE"){
if( (id.data[i]-id.data[i+1])>30 || (id.data[i]>id.data[i+2]) || (id.data[i+2]<id.data[i+1]-0)) {
id.data[i] = id.data[i+1] = id.data[i+2] = (id.data[i]+ id.data[i+1] + id.data[i+2])/3;
//파랑 필터
}
}
if(filter==="YELLOW"){
if((id.data[i+1]-id.data[i])<-20|| (id.data[i+1]-id.data[i+2])<0 || (id.data[i]-id.data[i+2])<30){
id.data[i] = id.data[i+1] = id.data[i+2] = (id.data[i]+ id.data[i+1] + id.data[i+2])/3;
//노랑 필터
}
}
}
리액트 state값에 따라 색상을 정하였으며
canvas위에 그려진 이미지를 픽셀단위로 쪼개 id에 저장하였는데
이는 RGBA순서로 4개씩 저장이 되므로 for문을 통해 for (var i = 0; i < id.data.length-4; i += 4)와 같이 4개의 i당 1개의 색을 가지므로 모든 픽셀을 검토할 수 있다.
특정 계열의 색상을 rgb로 단순히 구분하기는 매우 어려워 가능한 한 간단한 방식으로 직접 확인하며 조건을 정해주었다.
ctx.putImageData(id, 0, 0);
그리고 마지막에 이미지 데이터를 다시 캔버스 ctx에 넣어서 모든 픽셀을 조사하여 원하는 값을 변경한 결과물을 생산해낼 수 있다.
빨간색을 제외하고 흑백으로 만든 상태
빨간색을 제외하고 흑백으로 만든 상태