HTML - 캔버스 픽셀 조작
캔버스는 이미지를 픽셀 단위로 편집할 수 있는 메서드를 제공합니다.
이미지를 구성하는 픽셀정보를 래스터(Raster)라고 부르고 곧 비트맵이라 합니다. 이 비트맵에는 직사각형 격자 화소, 색의 점 등 이미지에 어떤 그림이 그려져 있는지를 저장합니다. 예를 들어 그림을 확대해 보면 아래 그림처럼 픽셀단위로 되어있음을 확인할 수 있습니다. 화소를 영문으로 표기하면 픽셀입니다.
메서드 | 설 명 |
---|---|
createImageData(w, h) | 빈 imageData를 생성. 기본값: 검정색
|
createImageData(imagedata) | imagedata로부터 사본 이미지 데이터를 생성
|
getImageData(x, y, w, h) | 캔버스 내용 전체나 일부 픽셀정보를 복사한 값을 imageData객체로 반환
|
putImageData(imagedata, x, y, dx, dy, dw, dh) | imagedata 객체를 지정된 영역에 붙여 넣기
dx, dy, dw, dh는 원본의 일부를 잘라서 사용할 때 |
다음 예제에서 createImageData() 를 이용해 빈 imageData를 생성한 다음 빈 객체가 반환한 픽셀 값을 원하는 대로 조작한 후 putImageData()로 이미지 사본을 생성합니다. createImageData() 이 반환하는 색상 값은 검정색 기본값입니다.
<style>
canvas {
width: 300px;
height: 100px;
border: 1px solid black;
}
</style>
<canvas id= "mycanvas"/>
<script type="text/javascript">
var canvas = document.getElementById('mycanvas');
canvas.width = 300;
canvas.height = 150;
var context = canvas.getContext('2d');
// 빈 이미지 데이터를 생성
var iData = context.createImageData(100, 100);
for (var i=0; i<iData.data.length; i+=4)
{
// R(빨간색) 값
iData.data[i + 0] = 190;
// G(녹색) 값
iData.data[i + 1] = 0;
// B(파란색) 값
iData.data[i + 2] = 210;
// A(투명도) 값
iData.data[i + 3] = 255;
}
context.putImageData(iData, 20, 20);
</script>
하나의 픽셀에는 RGBA 값 4개를 갖고 있습니다. R은 빨간색, G는 초록색, B는 파랑색, A는 알파(불투명도)를 의미하며 색상 값은 0~255사이의 값, 그리고 한 픽셀 당 4바이트를 차지합니다. 투명도는 0에 가까울수록 투명해집니다.
createImageData()나 getImageData()로부터 생성되는 imageData는 픽셀 값을 배열로 반환되며 위 그림에 나열한 것처럼 하나의 data 배열에 4개의 RGBA 값을 가지게 됩니다. 생성된 객체의 크기가 100(px) * 100(px) = 10,000(px)이고, 하나의 픽셀당 4개(=RGBA)의 값을 가지므로 이 값을 곱하기 4를 하면 40,000(px)가 됩니다.
<style>
canvas {
width: 300px;
height: 100px;
border: 1px solid black;
}
</style>
<canvas id="mycanvas"/>
<script type="text/javascript">
var canvas = document.getElementById('mycanvas');
canvas.width = 300;
canvas.height = 150;
var context = canvas.getContext('2d');
// 빈 이미지를 생성
var iData = context.createImageData(100, 100);
console.log(iData);
/*
결과:
ImageData {
data: Uint8ClampedArray(40000),
width: 100,
height: 100
}
*/
</script>
<style>
canvas {
width: 300px;
height: 200px;
border: 1px solid black;
}
</style>
<canvas id= "mycanvas"/>
<script type="text/javascript">
var canvas = document.getElementById('mycanvas');
var context = canvas.getContext('2d');
var iData = context.createImageData(150, 100);
for (var i = 0; i < iData.data.length; i += 3) {
iData.data[i + 0] = 100;
iData.data[i + 1] = 0;
iData.data[i + 2] = 0;
}
context.putImageData(iData, 10, 10);
</script>
다음은 getImageData()에 대한 예제입니다. 캔버스에 지정된 사각형의 픽셀 정보를 복사한 사본을 putImageData()를 이용해 지정된 위치에 붙여 넣습니다.
<style>canvas { border: 1px solid black; }</style>
<canvas id= "mycanvas"/>
<script type="text/javascript">
var canvas = document.getElementById('mycanvas');
canvas.width = 300;
canvas.height = 300;
var context = canvas.getContext('2d');
context.fillStyle = "red";
context.fillRect(55, 50, 200, 100);
var iData = context.getImageData(55, 50, 200, 100);
context.putImageData(iData, 55, 170);
</script>
<style>canvas { border: 1px solid black; }</style>
<canvas id= "mycanvas"/>
<script type="text/javascript">
var canvas = document.getElementById('mycanvas');
canvas.width = 200;
canvas.height = 200;
var context = canvas.getContext('2d');
context.fillStyle = "red";
context.fillRect(0,0,50,50);
context.fillStyle = "blue";
context.fillRect(10,10,30,30);
var iData = context.getImageData(0,0,50,50);
context.putImageData(iData,50,50,10,10,40,40);
</script>
캔버스에서 이미지를 픽셀단위로 편집하거나 다른 이미지로 만들기 위해서는 대상 이미지가 현재의 도메인과 동일해야 하며 만약 도메인이 다를 경우 이미지 데이터를 생성할 수 없습니다. 다음은 createImageData()를 이용해 현재 캔버스에서 다른 캔버스에 이미지를 복사해 보겠습니다.
<style>canvas { border: 1px solid black; }</style>
<canvas id="mycanvas"></canvas>
<canvas id="mycanvas2"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('mycanvas');
var canvas2 = document.getElementById('mycanvas2');
canvas.width = canvas.height = 300;
canvas2.width = canvas2.height = 300;
var context = canvas.getContext('2d');
var context2 = canvas2.getContext('2d');
var img = new Image();
img.onload = function(){
context.drawImage(img, 10, 30, canvas.width, 250);
var iData = context.getImageData(0, 0, canvas.width, canvas.height);
var iCopy = context.createImageData(iData);
for(var i=0; i < iData.data.length; i++) {
iCopy.data[i] = iData.data[i];
}
context2.putImageData(iCopy, 0, 0);
}
img.src = '8star.png';
</script>
다음 예제는 다른 캔버스에 조정된 이미지를 붙여 넣는 방법을 설명합니다.
<style>canvas { border: 1px solid black; }</style>
<canvas id="mycanvas"></canvas>
<canvas id="mycanvas2"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('mycanvas');
var canvas2 = document.getElementById('mycanvas2');
canvas.width = canvas.height = 300;
canvas2.width = canvas2.height = 300;
var context = canvas.getContext('2d');
var context2 = canvas2.getContext('2d');
var img = new Image();
img.onload = function(){
context.drawImage(img, 10, 30, canvas.width, 250);
var iData = context.getImageData(0, 0, canvas.width, canvas.height);
// 이미지를 원하는 영역만 잘라서 다른 캔버스에 붙여 넣음
context2.putImageData(iData, 0, 0, 50, 0, 200, 300);
}
img.src = '8star.png';
</script>
위 예제와 같은 방법을 이용하면 이미지에 필터 효과를 넣을 수 있습니다.
// 데이터 복사
for(var i=0; i < iData.data.length; i++) {
iCopy.data[i] = iData.data[i];
}
// 투명도 필터 적용.
for(var i=3; i < iData.data.length-4; i+=4) {
iData.data[i] = iData.data[i]/2;
}
// 네거티브 필터 적용
for(var i=0; i < iData.data.length - 4; i+=4) {
// 빨간 색상을 반전
iData.data[i] = 255-iData.data[i];
// 녹색 색상을 반전
iData.data[i+1] = 255-iData.data[i+1];
// 파란 색상을 반전
iData.data[i+2] = 255-iData.data[i+2];
}
// 흑백 필터 적용
for(var i=0; i < iData.data.length - 4; i+=4) {
// 픽셀 값 평균
average = ( iData.data[i] + iData.data[i+1] + iData.data[i+2] ) / 3;
// 평균 값 저장
iData.data[i] = iData.data[i+1] = iData.data[i+2] = average;
}
아래 그림은 투명도를 적용한 결과입니다.
다음은 네거티브 필터를 적용한 결과입니다.
마지막으로 흑백을 적용한 결과입니다.
0 댓글