이 글은 Mozilla Evangelism팀의 Paul Rouget이 쓴 글이며 그는 프랑스 파리에 살면서 open video on the web이라는 작업을 진행했습니다.
Canvas는 간단하게 HTML 페이지 내에 비트맵 데이터를 넣을 수 있는 방법입니다. 즉, 이를 통해 사각형, 곡선, 다각형 등 다양한 개체를 표현할 수 있습니다. 그러나 어떤 측면에서는 픽셀 데이터 즉 이미지를 이용할 필요가 있습니다. Firefox 3.5에서는 canvas 요소에 createImageData라는 기능을 추가했습니다. createImageData는 canvas 위에 동작하는 픽셀을 추가하여 호출 할 수 있는 메소드입니다. 단일 호출에 대해 이야기하고 있기 때문에 전체 문맥 중에 createImageData를 넣고 캔버스에서 픽셀을 직접적으로 업데이트하거나 다룰 수 있는 호출을 할 수 있습니다.
픽셀 데이터 가져오기
캔버스에서 픽셀을 바로 처리할 수 없습니다. 이를 위해 먼저 데이터를 바깥으로 복사를 한 후 변경 한 다음 캔버스 안으로 다시 집어 넣어야 합니다. getImageData를 호출하면 캔버스 밖으로 사각형을 복사할 수 있습니다. 간단한 소스 코드는 아래와 같습니다.
var canvas = document.getElementById('myCanvasElt'); var ctx = canvas.getContext('2d'); var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);
canvasData 객체는 픽셀 데이터를 포함하며 다음과 같은 구성을 가지고 있습니다.
canvasData { width: unsigned long, // the width of the canvas height: unsigned long, // the height of the canvas data: CanvasPixelArray // the values of the pixels }
데이터는 간단한 배열로 구성되어 있고 각 픽셀 항목에 하나의 값을 가지고 있으며 왼쪽에서 오른쪽으로 위에서 아래로 RGBA 값순서로 표시합니다. 예를 들어 2×2 캔버스의 경우 4개의 픽셀이 16개의 값을 가지게 됩니다.
0,0 0,1 1,0 1,1 RGBA RGBA RGBA RGBA
따라서 여러분은 width * height * 4와 같은 공식으로 배열의 크기를 계산할 수 있습니다. 매우 큰 캔버스의 경우 x=20, y=20인 파란색 픽셀의 배열 크기는 다음과 같은 코드로 알아 낼 수 있습니다.
var x = 10; var y = 10; var blue = canvasData.data[(y * width + x) * 4 + 2];
각 RGB 값은 0..255 사이의 값을 가지고 0은 투명 하고 255는 불투명 합니다.
새로운 픽셀 세트 만들기
긁은 자국으로 부터 새로운 매트릭스를 만들려고 한다면 createImageData를 호출하면 되는데 이 때 두가지 인자인 height와 매트릭스의 width를 넘기면 됩니다. 이 때 createImageData 호출은 현재 캔버스 밖으로 픽셀을 복사하는 게 아니라 투명한 검은색인 (255,255,255,0) 값을 가진 빈 픽셀 매트릭스를 생성합니다. 아래는 캔버스 사이즈에 맞는 픽셀 세트를 만드는 코드 입니다.
var canvas = document.getElementById('myCanvasElt'); var ctx = canvas.getContext('2d'); var canvasData = ctx.createImageData(canvas.width, canvas.height);
이 메소드는 픽셀 데이터를 만들때만 사용해야 합니다. 이전 버전의 파이어폭스에서는 JavaScript 객체 밖으로 canvasData 객체를 만들 거나 나중에 캔버스 데이터를 업데이트하는데 호출하는데 사용하기도 했습니다. 이 기능은 일반적 자바스크립트 객체 대신 특별한 객체를 사용하기 위해 웹킷과 함께 호환성을 유지 합니다.
픽셀 업데이트
일단 canvasData 객체를 만들었으면 여러분은 배열을 통해 픽셀 값을 바꿀 수 있습니다. 아래에 배열을 읽어서 그 값을 바꾸는 샘플 코드가 있습니다.
for (var x = 0; x < canvasData.width; x++) { for (var y = 0; y < canvasData.height; y++) { // Index of the pixel in the array var idx = (x + y * width) * 4; // If you want to know the values of the pixel var r = canvasData.data[idx + 0]; var g = canvasData.data[idx + 1]; var b = canvasData.data[idx + 2]; var a = canvasData.data[idx + 3]; //[...] do what you want with these values // If you want to update the values of the pixel canvasData.data[idx + 0] = ...; // Red channel canvasData.data[idx + 1] = ...; // Green channel canvasData.data[idx + 2] = ...; // Blue channel canvasData.data[idx + 3] = ...; // Alpha channel } }
캔버스 데이터 변경
이제 픽셀 데이터를 변경했으면 간단한 putImageData 기능을 호출합니다. 이는 canvasData 객체를 가져와서 캔버스 안으로 사각형 픽셀 데이터를 가져와 원하는 x,y 위치에 그리게 됩니다.
var canvas = document.getElementById('myCanvasElt'); var ctx = canvas.getContext('2d'); var canvasData = ctx.putImageData(canvasData, 0, 0);
getImageData 샘플 코드
아래에는 칼라 이미지를 회색조로 바꾸는 샘플 코드 입니다. 이 기능의 실제 데모를 구동해 보실 수 있습니다.
var canvas = document.getElementById('myCanvasElt'); var ctx = canvas.getContext('2d'); var canvasData = ctx.getImageData(0, 0, canvas.width, canvas.height); for (var x = 0; x < canvasData.width; x++) { for (var y = 0; y < canvasData.height; y++) { // Index of the pixel in the array var idx = (x + y * canvas.width) * 4; // The RGB values var r = canvasData.data[idx + 0]; var g = canvasData.data[idx + 1]; var b = canvasData.data[idx + 2]; // Update the values of the pixel; var gray = (r + g + b) / 3; canvasData.data[idx + 0] = gray; canvasData.data[idx + 1] = gray; canvasData.data[idx + 2] = gray; } } ctx.putImageData(canvasData, 0, 0);
createImageData 샘플 코드
아래 코드는 캔버스 안으로 프랙탈 도형을 그리는 샘플 코드입니다. 이 코드 역시 데모 사이트에서 확인 가능합니다.
var canvas = document.getElementById('myCanvasElt'); var ctx = canvas.getContext('2d'); var canvasData = ctx.createImageData(canvas.width, canvas.height); // Mandelbrot function computeColor(x, y) { x = 2.5 * (x/canvas.width - 0.5); y = 2 * (y/canvas.height - 0.5); var x0 = x; var y0 = y; var iteration = 0; var max_iteration = 100; while (x * x + y * y <= 4 && iteration < max_iteration ) { var xtemp = x*x - y*y + x0; y = 2*x*y + y0; x = xtemp; iteration++; } return Math.round(255 * iteration / max_iteration); } for (var x = 0; x < canvasData.width; x++) { for (var y = 0; y < canvasData.height; y++) { var color = computeColor(x, y); // Index of the pixel in the array var idx = (x + y * canvas.width) * 4; // Update the values of the pixel; canvasData.data[idx + 0] = color; canvasData.data[idx + 1] = color; canvasData.data[idx + 2] = color; canvasData.data[idx + 3] = 255; } } ctx.putImageData(canvasData, 0, 0);
참고 문헌
Canvas에 대해 더 알고 싶으시다면 Mozilla 개발자 센터 문서를 자세히 살펴 보시기 바랍니다.
댓글이 없습니다.