HTML5, Canvas 에는 그려진 내용을 URL 문자열로 반환해 주는 함수가 제공된다

Canvas 객체의 toDataURL() 함수를 통해 캔버스에 그린 그림을 문자열 형태로 변환할 수 있는데,
이 문자열에는 이미지 MIME 타입과 인코딩 방법 그리고 인코딩 된 이미지 데이터 문자열이 포함된다

대략 다음과 같은 모습이다
https://t1.daumcdn.net/cfile/tistory/226CDB4956E6D5F802"FONT-FAMILY: Tahoma">그럼, 실제 Canvas 내용이 문자열로 변환된 것을 확인해 보자
아래 그림은 Canvas에 적당히 그림을 그리고 toDataURL() 함수를 이용해 URL문자열을 띄워 본 것이다


toDataURL() 로 반환된 것이 문자열이라는 것은 다음과 같이 타입조사를 해 보면 알 수 있다
alert(typeof canvas.toDataURL()); //string 이 출력됨

이 문자열은 Canvas에 그려진 내용을 Data URL로 변환한 것이기 때문에 그 자체로 이미지 정보가 된다

따라서 이 문자열을 이미지 객체에 바인딩하거나 다른 이미지로 생성할 수 있게 된다

Canvas 에 그린 그림을 이미지로 변환하기
한 가지 간단한 샘플을 만들어 보자.
Canvas 로 그린 내용을 문자열로 변환하여 img 요소의 src 로 사용하는 것이다
Canvas 에 그리기 작업을 수행하는 코드는 이전 글인 [HTML5] Canvas '마무로 데모' 코드를 이용하므로 구현 코드는 생략하도록 한다. 이 글에서는 Canvas 결과를 이미지 소스로 바인딩하는 것을 제시한다

다음 코드와 같이 Canvas와 버턴, 그리고 img 요소를 정의한다
Canvas에 그림을 그리고 버턴을 클릭하면 오른쪽 img 요소에 그 내용이 이미지 소스로 활용되는 예이다

<canvas id="drawCanvas" width="200" height="200" style=" position: relative; border: 1px solid #000;"></canvas>
<button onclick="toDataURL();">이미지로 변환=></button>     
<img id="myImage">
.....
<script type="text/javascript">
function toDataURL(){
  var myImage = document.getElementById('myImage');
  myImage.src = canvas.toDataURL();
}
</script>

데모를 실행하고 캔버스에 적당히 그림을 그린 후 이미지 변환을 클릭하면 오른쪽에 이미지가 표시된다
이렇게 생성된 이미지는 완전한 하나의 이미지 객체 이므로 로컬에 이미지로 저장하는 등의 이미지 작업이 가능하다


참고로 이렇게 생성된 이미지의 HTML 코드는 아래와 같다



Canvas 에 그린 그림을 다른 Canvas 로 복사하기
이번에는 Canvas에 그린 내용을 다른 Canvas로 옮기는 즉 복사하는 예를 살펴보자.
복사 방법이야 여러 가지가 있을 수 있겠지만 여기서는 toDataURL() 함수로 반환된 이미지데이터문자열을 이용해서 복사하는 방법을 알아보자

언뜻 생각하기에 toDataURL() 함수가 있다면 fromDataURL() 함수가 있지 않을까 생각이 든다
다시말해 캔버스 내용을 URL 문자열로 반환해 주는 함수가 있다면 역으로 URL 문자열을 캔버스 내용으로 사용할 수 있는 함수 말이다. 그런데 찾아 보니 그런 함수는 없어 보인다. 아쉬운 부분이다

그렇다면 우리가 직접 fromDataURL 함수를 만들어 보기로 하자
아래 코드와 같이 두 개의 Canvas를 정의하고 왼쪽 캔버스의 내용을 오른쪽 캔버스로 복사하기 위해 toDataURL()로 얻어진 문자열을 이미지 객체의 소스로 바인딩하고 이미지가 로딩될 때 복사 대상 캔버스의 drawImage 함수를 이용해 이미지를 그리는 로직이다.
<canvas id="drawCanvas" width="200" height="200" style=" position: relative; border: 1px solid #000;"></canvas>
<button onclick="fromDataURL();">캔버스 복사=></button>                  
<canvas id="copyCanvas" width="200" height="200" style=" position: relative; border: 1px solid #000;"></canvas>
...
<script type="text/javascript">
function fromDataURL(){       
  var copyCanvas = document.getElementById('copyCanvas');    
  var copyContext = copyCanvas.getContext('2d'); 
 
  var image = new Image();
  image.src = canvas.toDataURL(); 
 
  image.onload = function(){
    copyContext.drawImage(image,0,0);
  } 
}
</script>


데모를 실행한 결과 화면은 아래와 같다


어떻게 보면 fromDataURL() 함수는 끼워 맞춘 듯한 느낌이다
하지만 toDataURL()로 얻어진 이미지데이터문자열을 이런 형태로도 이용할 수 있다는 힌트만 가지면 되겠다

2010.11.24 추가>>
위에서, Canvas 그림을 다른 Canvas로 복사할 때 이미지객체를 생성하는 단계가 있었다
확인 해 보니, 이미지객체를 경유하지 않고 대상 Canvas에 원본 Canvas를 drawImage 해 주면 된다
따라서 단지 복사가 목적이라면 중간 경유로 사용된 이미지객체의 생성은 불필요 하겠다

fromDataURL 함수는 아래와 같이 수정하면 된다
function fromDataURL(){       
  var copyCanvas = document.getElementById('copyCanvas');    
  var copyContext = copyCanvas.getContext('2d'); 
  copyContext.drawImage(canvas,0,0);  
}


Canvas 내용을 문자열로 얻을 수 있다는 것은...
웹에서 다양한 시나리오를 구현할 수 있다는 의미가 된다
글에서 알아본 것과 같이 캔버스 내용을 이미지로 변환하여 로컬 컴퓨터에 저장할 수 있으며
또 다른 예로 캔버스 내용을 서버로 업로드 하여 다른 사람과 공유하거나 관리할 수 있게 된다
또한 캔버스 내용을 쿠키나 localStorage 등에 저장하여 계속 사용할 수 있으며 페이지 통신을 통해 두 페이지간 캔버스 내용을 교환할 수도 있다. 

결론적으로  문자열로 처리 가능한 모든 시나리오에 캔버스를 이용할 수 있다는 의미가 된다
다만 이렇게 생성한 이미지는 일반 이미지 파일과는 달리 브라우저에 캐시되지 않기 때문에
쇼핑몰 이미지 리스트와 같은 많은 이미지를 서버에서 불러와 캐시되는 시나리오에는 적합하지 않을 수 있다

자신만의 다양한 시나리오를 구상해 실현해 보기 바란다

....

참고로 toDataURL() 함수는 두개의 매개변수를 가지는데, 첫번째 인수는 이미지MIME 타입을 지정하는데 이용되며 나머지 인수는 이미지 품질 정도와 같은 추가 이미지 효과를 지정하는데 사용된다
이전 샘플과 같이 매개변수 없이 호출하게 되면 기본적으로 image/png 타입으로 설정된다
만일 jpeg 를 원한다면 다음의 코드가 가능하다

canvas.toDataURL("image/jpeg");

그러나 테스트를 해 보니 브라우저별로 지원되는 부분이 조금씩 다르니 참고하기 바란다

toDataURL 에 대한 더 자세한 내용은 다음의 W3C 스펙 설명을 확인 하자
http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#todataurl-method
Tags ,
  1. ihchoi

    참 좋아요

  2. NoPD

    Canvas 에 이미지 파일을 로딩하고 편집하는 것 혹시 해보셨나요?
    http://hacks.mozilla.or.kr/2010/07/an-html5-offline-image-editor-and-uploader-application/
    요런 예제들 보면 편집까지 해서 업로딩 하던데...
    개인적으로 조금 해보는데 잘 안되네요 ㅎㅎ...
    도움 받을 수 있을까요?

    • 박종명

      저도 명시하신 사이트를 봤습니다.
      http://m.mkexdev.net/87 , 이 글이 사이트를 참조해서 작성한 것이구요.. 이미지편집 부분은 아직 자세히 보지 못했네요.
      어떤 부분이 잘 안되는지 자세히 알려 주시면 도움드릴 수 있을 것 같습니다.

    • NoPD

      간단히 정리하면 안되는 부분은 이렇습니다.

      1. Canvas 에 PNG 파일을 로딩
      2. Canvas 의 이미지 위에 그림을 추가로 그림 (사각형 등...)
      3. Canvas 를 DATAURL 로 Export 해서 파일로 저장
      4. 다른 Canvas 에 DATAURL 을 로딩

      예상결과 : 이미지와 그림 그린것이 같이 출력됨
      실제결과 : 이미지는 없이 그림 그린것만 출력됨

      상식적으로 그냥 될 것 같은데...
      PNG 만 올려놓고 DATAURL 로 뽑은 것으로 다시 바인딩 해보면
      공백만 나오고 있습니다... 제가 뭔가 놓친것일까요? ^^;;;

    • 박종명

      DOM Exception 18, SECURITY_ERR 인것 같네요.
      혹시 로컬에서 테스트 하나요?

      Canvas에 drawImage 한 이미지가 다른 서버에 있으면 toDataURL호출 시 보안 에러 발생합니다.(웹의 원천서버정책입니다). 로컬 테스트 환경에서도 그렇구요.

      이미지가 자신의 도메인에 존재하는 것이면,
      서버에 올려두고 테스트 해 보시기 바랍니다

  3. 초보자

    안녕하세요~todatURL을 검색하다 들어오게 되었습니다

    저도 위에분처럼 그림을 올린 후에 다른 캔버스로 옮겨보고 싶은데 잘 안되네요...;

    서버에 올려두고 테스트 해보라고 하셨는데..

    죄송하지만 서버에 올려논다는 게 어떻게 하는건지 알 수 있을까요~??

    제가 아직 초보라 많이 부족해서요

submit