HTML5
CANVAS 다루기 - 이미지
아거스
2011. 1. 17. 16:05
캔바스 관련 강좌 2회차 입니다.
금번 강좌 내용은 포스팅 제목과 같은 캔바스에서 이미지를 다루는 방법에 대하여 얘기할까 합니다.
위 예제는 하나의 이미지를 캔바스 크기만큼 수평, 수직방향으로 반복 패턴형태로 채우는 예제입니다.
캔바스에는 위에서 본 이미지 캡쳐외에도 여러 방식으로 이미지를 활용할 수 있는데요. 지금 말씀드릴 drawImage 메서드는 이런경우 유용하게 사용이 됩니다.
drawImage 메서드는 아래와 같이 3가지 방식의 파라미터를 지원합니다.
이제 예제를 하나 만들어 보겠습니다.
drawImage 메서드의 2번째 방식을 활용하여 이미지의 크기를 변경하고 해당 이미지를 4 X 3형태로 배치한 예제입니다.
물론 3번째 방식을 활용하면 원본 이미지의 일정부분을 슬라이싱하여 활용할 수 도 있습니다.
중첩된 for문안의 drawImage 메서드의 파라미터를 위와 같이 변경하면 원본 이미지의 일정 부분을 자른 후 캔바스에는 조금 더 크게 확대하여 4 X 3으로 배치시킨 것을 확인할 수 있습니다.
SVG와 캔바스의 차이점 중 하나가 바로 푸싱 픽셀(pushing pixels)입니다.
캔바스에서는 getImageData메서드를 활용하여 RGBA 형식의 픽셀 정보를 받아 올 수 있습니다.
※ getImageData / putImageData 메서드는 자바스크립트와 같은 동일근원정책(sam origin rule)을 따릅니다.
위 예제를 실행시켜보면 아래와 같이 픽셀정보를 담은 배열을 리턴합니다.
아래처럼 픽셀정보는 하나의 픽셀당 4개의 아이템으로 구성이 되는 것을 확인할 수 있습니다.
이렇게 픽셀정보를 다룰수 있기 때문에 많은 곳에 활용이 가능한 것을 알 수 있습니다.
대표적인 푸싱 픽셀 예제인 X-Ray기법도 쉽게 구현이 가능합니다.
지난 강좌에서는 CANVAS에 대한 기본적인 이해와 간단히 W3C의 샘플코드를 살펴보는 시간을 가졌습니다.
꽤나 많은 속성과 메서드를 가지고 있는 것을 볼 수 있었는데요. 아래 치트시트 정도는 출력해서 모니터 옆에 붙여놓는건 어떨까 싶습니다.
금번 강좌 내용은 포스팅 제목과 같은 캔바스에서 이미지를 다루는 방법에 대하여 얘기할까 합니다.
캔바스는 이미지나 비디오 혹은 또다른 캔바스로부터 이미지 캡쳐 및 리드로우가 가능합니다.
createPattern 메서드
먼저 createPattern 메서드에 대해서 간단히 알아보겠습니다.
(http://msdn.microsoft.com/en-us/library/ff975412(v=VS.85).aspx 참고)
일반적으로 createPattern메서드의 반환값을 fillStyle프로퍼티에 할당하는 방식으로 사용하며
CSS의 background-image 프로퍼티와 비슷한 기능을 한다고 생각하면 됩니다.
(http://msdn.microsoft.com/en-us/library/ff975412(v=VS.85).aspx 참고)
일반적으로 createPattern메서드의 반환값을 fillStyle프로퍼티에 할당하는 방식으로 사용하며
CSS의 background-image 프로퍼티와 비슷한 기능을 한다고 생각하면 됩니다.
<canvas width="372" height="182"></canvas> <script> var canvas = document.getElementsByTagName( "canvas" )[0], ctx, img = new Image(); img.src = "http://img-contents.daum-img.net/2010ci/daumlogo.gif"; if ( canvas.getContext ) { ctx = canvas.getContext( "2d" ); img.onload = function() { var pat = ctx.createPattern(img, "repeat"); ctx.fillStyle = pat; ctx.fillRect(0, 0, canvas.width, canvas.height); } } </script>
위 예제는 하나의 이미지를 캔바스 크기만큼 수평, 수직방향으로 반복 패턴형태로 채우는 예제입니다.
drawImage 메서드
캔바스에는 위에서 본 이미지 캡쳐외에도 여러 방식으로 이미지를 활용할 수 있는데요. 지금 말씀드릴 drawImage 메서드는 이런경우 유용하게 사용이 됩니다.
drawImage 메서드는 아래와 같이 3가지 방식의 파라미터를 지원합니다.
- drawImage( imageResource, dx, dy )
- drawImage( imageResource, dx, dy, dw, dh )
- drawImage( imageResource, sx, sy, sw, sh, dx, dy, dw, dh )
여기서 d는 최종 캔바스 영역을 말하고 s는 원본 이미지를 말합니다.
(x, y, w, h는 다 아실꺼라 생각합니다^^)
아래의 도식을 보시면 조금 더 쉽게 이해할 수 있습니다.
이제 예제를 하나 만들어 보겠습니다.
<canvas width="400" height="150"></canvas> <script> var ctx = document.getElementsByTagName( "canvas" )[0].getContext( "2d" ), img = new Image(); img.src = "http://img-contents.daum-img.net/2010ci/daumlogo.gif"; img.onload = function() { for ( var i = 0; i < 4; ++i ) { for ( var j = 0; j < 3; ++j ){ ctx.drawImage( img, j * 100, i * 100, 100 , 50 ); } } }; </script>
drawImage 메서드의 2번째 방식을 활용하여 이미지의 크기를 변경하고 해당 이미지를 4 X 3형태로 배치한 예제입니다.
물론 3번째 방식을 활용하면 원본 이미지의 일정부분을 슬라이싱하여 활용할 수 도 있습니다.
ctx.drawImage( img, 25, 0, 16, 17, j * 100, i * 30, 30 , 30 );
중첩된 for문안의 drawImage 메서드의 파라미터를 위와 같이 변경하면 원본 이미지의 일정 부분을 자른 후 캔바스에는 조금 더 크게 확대하여 4 X 3으로 배치시킨 것을 확인할 수 있습니다.
getImageData / putImageData 메서드
SVG와 캔바스의 차이점 중 하나가 바로 푸싱 픽셀(pushing pixels)입니다.
캔바스에서는 getImageData메서드를 활용하여 RGBA 형식의 픽셀 정보를 받아 올 수 있습니다.
<canvas></canvas> <script> var ctx = document.getElementsByTagName( "canvas" )[0].getContext( "2d" ), img = new Image(); img.src = "imageData.png"; img.onload = function () { ctx.canvas.width = img.width; ctx.canvas.height = img.height; ctx.drawImage( img, 0, 0 ); var pixels = ctx.getImageData( 0, 0, img.width, img.height ); console.log( pixels.data ); }; </script>
※ 위 예제에 사용된 이미지는 <이미지 다운받기>에서 받으시면 됩니다.
(아래는 확대한 이미지의 캡쳐입니다.)
※ getImageData / putImageData 메서드는 자바스크립트와 같은 동일근원정책(sam origin rule)을 따릅니다.
위 예제를 실행시켜보면 아래와 같이 픽셀정보를 담은 배열을 리턴합니다.
[
255, 0, 0, 255,
0, 255, 0, 255,
0, 0, 255, 255,
255, 255, 255, 255,
0, 0, 0, 255,
51, 51, 51, 255,
102, 102, 102, 255,
153, 153, 153, 255,
0, 0, 0, 255,
0, 0, 0, 191,
0, 0, 0, 128,
0, 0, 0, 64
]
255, 0, 0, 255,
0, 255, 0, 255,
0, 0, 255, 255,
255, 255, 255, 255,
0, 0, 0, 255,
51, 51, 51, 255,
102, 102, 102, 255,
153, 153, 153, 255,
0, 0, 0, 255,
0, 0, 0, 191,
0, 0, 0, 128,
0, 0, 0, 64
]
아래처럼 픽셀정보는 하나의 픽셀당 4개의 아이템으로 구성이 되는 것을 확인할 수 있습니다.
[
r1, g1, b1, a1,
r2, g2, b2, a2,
r3, g3, b3, a3,
...
]
r1, g1, b1, a1,
r2, g2, b2, a2,
r3, g3, b3, a3,
...
]
이렇게 픽셀정보를 다룰수 있기 때문에 많은 곳에 활용이 가능한 것을 알 수 있습니다.
대표적인 푸싱 픽셀 예제인 X-Ray기법도 쉽게 구현이 가능합니다.
<canvas></canvas> <script> var ctx = document.getElementsByTagName( "canvas" )[0].getContext( "2d" ), img = new Image(); img.src = "test.jpeg"; img.onload = function () { ctx.canvas.width = img.width; ctx.canvas.height = img.height; ctx.drawImage( img, 0, 0 ); var pixels = ctx.getImageData( 0, 0, img.width, img.height ); for (var i = 0, len = pixels.data.length; i < len; i += 4) { pixels.data[i + 0] = 255 - pixels.data[i + 0]; pixels.data[i + 1] = 255 - pixels.data[i + 1]; pixels.data[i + 2] = 255 - pixels.data[i + 2]; } ctx.putImageData( pixels, 0, 0 ); }; </script>
각 픽셀 정보 색상값(RGB)을 최대값인 255에서 빼 준 후 해당 픽셀정보로 이미지를 삽입하는 방식입니다.
쉽게 "반전효과"를 줄 수 있습니다.
오늘은 캔바스의 특징 중 이미지를 다루는 메서드들에 대하여 얘기했습니다.
쉽고 재미있는 캔바스로 오늘은 사진 놀이를 해보는 것은 어떨까요?