html5 Canvas를 이용해 png 이미지 파일 만들기

캔버스에 그린 이미지를 PNG 이미지로 저장하는 방법이 필요해 찾아봤다. 평소에 구현해본게 아니라서 약간의 삽질이 있었지만 파일 구조를 좀 알고 있다면 그다지 어려운 일은 아니다. 참고로 본 설명은 Windows8 스토어 앱 개발에 필요했던 작업이라 WinJS 기준으로 설명하겠지만, 기본 원리는 다른 플랫폼이라도 동일할 것으로 생각된다.

1. 캔버스(Canvas)에 여러장의 이미지 로드하기

먼저 canvas를 이용해 이미지를 올려보자. HTML에 <canvas> 태그를 삽입하고 다음과 같은 코드를 이용해 이미지를 로드해본다.

var canvas = document.getElementById('canvas');
var cx = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function () {
    cx.drawImage(imageObj, 69, 50);
}
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';

document.getElementById('save').onclick = function () {
    saveToFile('test.png');
}

document.getElementById('load').onclick = function () {
    loadFromFile("test.png");
}

2. 캔버스 이미지 데이터 뽑아내기

이제 저장하기 버튼을 눌러서 캔버스에 그린 녀석들을 PNG 파일로  저장해보자. 저장할때는 캔버스에 있는 .toDataURL(‘image/png’) 이라는 메소드를  사용한다. 단, 원격지에 있는 이미지를 로드한 경우 보안 문제로 인해 다음과 같은 에러 메시지를 출력할 것이다.

Error: SECURITY_ERR: DOM Exception 18

따라서 .toDataURL() 메소드를 사용하려면 캔버스에 로드된 파일이 반드시 로컬에 위치해 있어야한다. 여튼 이 메소드는 캔버스의 픽셀 이미지를 Base64로 인코딩해서 다음과 같은 형태의 문자열 데이터로 출력해준다.

"data:image/png;base64,iVBORw0KGgoAAAANSuhEUgAAArwAAAH0......"

참고로 이 값을 이미지 태그의 src 주소에 넣으면 바로 이미지가 로드된다. 하지만 파일로 저장하려면 약간의 트릭이 필요하다. 먼저 PNG 데이터를 끄집어 내야한다.

3. PNG 이미지 데이터로 Blob 데이터 파일 만들기

PNG 파일에는 실제 이미지 데이터가 저장되어야 하기때문에 toDataURL() 로 출력된 문자열에서 “data:image/png;base64,” 이후로 나열된 문자열을 다시 디코딩해서 저장한다. 이런 이미지 데이터를 블럽(Blob) 데이터라고 얘기한다. WinJS의 경우 다음과 같은 메소드를 이용해 디코딩할수있다.

Windows.Security.Cryptography.CryptographicBuffer.decodeFromBase64String(인코드데이터)

파일로 저장하기위한 전체 메소드는 다음과 같이 작성했다. localFolder 객체는 앱 안에 저장되는 위치다.

var saveToFile = function (path) {
    var canvas = document.getElementById('canvas'),
        data = canvas.toDataURL('image/png'),
        localFolder = Windows.Storage.ApplicationData.current.localFolder,
        encodeData = data.replace("data:image/png;base64,", ""),
        decode = Windows.Security.Cryptography.CryptographicBuffer.decodeFromBase64String(encodeData);

    // mySample.txt의 이름으로 파일을 생성하고 동일한 이름이 있을 경우, 덮어쓴다.
    localFolder.createFileAsync(path, Windows.Storage.CreationCollisionOption.replaceExisting)
        .then(function (file) {
            // writeTextAsync메소들 통해 파일에 텍스트를 쓴다.
            return Windows.Storage.FileIO.writeBufferAsync(file, decode);
        });        
    };

4. 이미지 파일 로드하기

서두에도 잠깐 언급했지만, 이미지 파일을 로드는 간단하다. 그냥 이미지 파일 패스를 이미지 태그의 src 주소로 넣으면 끝이다. 일단 localFolder에 저장했으므로 localFolder에서 이미지 패스를 구해서 넣으면 끝! 코드는 아래와 같다.

var loadFromImage = function (path) {
    var localFolder = Windows.Storage.ApplicationData.current.localFolder;

    localFolder.getFileAsync(path).done(function (file) {
        var elTest = document.getElementById('test'), 
            img = new Image();

        img.src = URL.createObjectURL(file);
        elTest.appendChild(img);
    });    
};

국도 여행 (37번 국도와 391번 지방도)

2년전부터 해보고 싶었던 여행이 있었다. 바로 국도 여행!
그래서 국도 여행책도 샀는데,.. 한번도 펴보지 못하고… ㅋㅋㅋ
이제서야 다녀왔다. 서울 근교라서 그다지 멀지도 않고,..
드라이브 코스로 유명한 391번 지방도와 37번 국도 여행!
사용자 삽입 이미지급히 경로를 짜느라고, 먹거리는 거의 못찾아봤다.
올림픽대로에서 춘천으로 고속도로를 올라타고, 서종 IC에서 나오면된다.
아마 네비 찍고 가면, 서종 IC 이전에 나가라고 할텐데.. 서종 IC 길이 강을 따라 올라가는길이라..
뷰가 조금더 낫단다. 근데 뭐 겨울이라 다 거기서 거긴듯… ㅋㅋㅋ

근데 지방도라 그런지 차도없고, 신호등도 없고,.. 길도 꼬불꼬불… 올라갔다 내려갔다..
운전할맛나드라… ㅋㅋㅋ 그래도 과속은 위험한듯!

가는길에 조그마한 미술관과 쁘띠프랑스, 남이섬, 자라섬, 호명산 꼭대기에 있는 찻집 등등이 있고..
아침고요수목원도 있다. 아침고요수목원에서 3월까지 빛축제도 하던데…
주말엔 거의 GG 쳐야할듯 싶다. 정말 차량이 끝없이 이어져서 꼼짝을 안한다.
기다리다 3km 지점에서 일찌감치 포기!! ㅋㅋㅋ

날이 추워서 밖으로는 못나가고, 종일 운전하면서 간만에 진정 드라이빙모드!!
정말 오프로드 한번 해보고 싶다는 생각이 자꾸 들었다… ㅋㅋㅋ

지방도 주변에 음식점이 많긴한데,.. 맛집조사를 제대로 못해서..
그냥 남이섬 주변에서 닭갈비와 막국수 흡입해주고,.. 호명산 꼭대기에서 차 한잔 마시고..
유턴~!!

오랜만에 바람쐬고 기분도 업~!! 꽃피는 봄에 다시 와봐야지~ ㅋ

점빼러갔다가… 엄한 홍대나들이

지난 토요일의 일이다. 왼쪽 눈밑에 점이 생겼다. 생긴지 10개월정도 된 것 같다. 여드름 짜다가 색소침착이 일어난게 아닌가 싶다. 매끈하고(?) 깨끗한 얼굴에 점하나가 영~ 눈에 거슬린다. 보는 사람마다 뭐 묻은거 같다며… 그래! 빼야지 결심했다.

그날이 바로 지난 토요일이다. 패치멤버들과 단체로 피부과에 납시었다. 빼고싶었던 점은 달랑 하나! 근데 자세히 보니 거슬리는 점들이 몇개 보여서 같이 뺐다. 그런데!! 정작 빼고 싶었던 왼쪽 눈밑에 큰 점은 상처가 아물지 않았단다..-_-; 1달뒤에 상처가 아물면 빼기로 했다. 이런 ㅇㅎㅎ 뺄껀 못빼고 엄한 녀석들만 뺐다. 레이저 생각보다 더 따갑다. 조그만게 이정돈데.. 진정 큰 이점은 얼마나 따가울까?

여튼 이노무 점때문에 패치멤버들 총 견적이 60만원정도 나온듯 싶다. 하루에 60만원 ㅎㄷㄷ
점빼고 점심먹고, 수다떨다가… 과제하러 잠깐 회사 들렀다가.. 저녁먹으러 홍대 나들이 갔다.

난 홍대가 좋다. 강남보다는 홍대가 편하고, 거리상으로 서쪽에 있다보니 왠지 더 가깝게 느껴지고 그렇다. 실제로 자차로 서부간선과 서해안을 타면 30분도 안걸린다. 물론 길 안밀린다는 전제지만… 여튼 패치팡의 새로운 디자이너를 만났다. 일시키는데 밥도 안메기고 일을 시킬순 없지 않은가.. 그래서 갈매기살 좀 꿉어주고, 술을 못마신다하여 2차는 차를 마시러 갔다.

여기서 잠깐,… “7번가 피자”집이 새로 생겼뜨라.. 담엔 저기 가봐야지~ 했다.

다시, 2차로 홍대 카페거리쪽을 어슬렁대가가 조용한 수다장소를 찾아서 수다 삼매경~, 아무래도 패치멤버중에 내가 유일한 미혼인지라… 언제나 이야기의 한가지는 나의 연애문제다.ㅋ 그런데 이번엔 병서형과 선영누나의 러브스토리… ㅋㅋㅋㅋ 아~ 욱겨 쓰러지는줄 알았네… ㅋㅋㅋ

웃고 떠들다,.. 3차는 조폭 떡뽁이 머그러 갔다. 가는길에 불량식품도 한움쿰사고,.. 홍대 카페거리에서 상상마당쪽은 완전 반대편.. 아주 투어를 하는구나. 조폭 떡뽁이가 난 메워서 그냥 어묵꼬치 2개를 흡입해주고, 4차를 갔다. 4차는 월향… 월향은 또 어디더냐… 한참을 걸었다. 걷다보니 후미진곳에 떡허니 반짝이는 건물하나.. 전체가 월향이구나~ 얼씨구~~ 막걸리집 치고는 건물이 너무 카페같다 했는데.. 내부는 그냥 식당같다. ㅋㅋㅋ

막걸리가 술술 들어간다. 최근 1년동안 이렇게 술을 많이 마셔본 기억이 별로 없는듯 싶다. 확실히 어깨 뿌러지고 나서는 과음은 거의 피했는데.. 이날은 소수도 술술술… 막걸리도 술술술 들어가더니.. 밥배와 술과가 결국 꽉 차서 더이상 못먹겠뜨라.. 배터지는줄 알았다.

아침부터 점심, 저녁까지 하루종일 패치멤버들과 붙어다녔다. 지난 4월에 제주도에 놀러갔던 그 기억처럼 종일 붙어다녔다. 역시 패치멤버들은 재밌다.