PNG로 압축된 Prototype 코드 이미지
위 이미지는 124kb의 Prototype 라이브러리를 30kb의 8bit PNG 이미지로 만든 것입니다.

Jacob Seidelin씨가 이미지로부터 JavaScript 코드를 읽을 수 있는 스크립트를 작성했습니다. 이 작업에, 그는 canvas의 getImageData() 메소드를 사용했다고 합니다.

상세한 진행과정입니다:
첫번째 단계는 이 작업을 위한 최적의 이미지 포맷을 찾는 것이었습니다. 최적이라 함은 손실이 없으면서도 압축률이 좋은 것을 의미합니다. 웹 환경이므로, 우리의 선택지가 많지 않았고, JPEG는 손실이 있었기 때문에 우리는 GIF나 PNG를 선택해야 했습니다.
PNG에는 24bit와 8bit의 두가지 옵션이 있습니다. 24bit RGB 색상을 사용하면, 픽셀당 3byte의 데이터를 저장할 수 있고, 8bit의 인덱스 색상을 사용하면 픽셀당 1byte를 저장할 수 있습니다.
Photoshop에서의 간단한 테스트를 통해 우리는 100x100 크기의 24bit 색상이 있는 무작위 노이즈 이미지는 20KB 정도로 압축이 되고, 300x100 크기의 흑백 무작위 노이즈 이미지는 5KB로 압축된다는 것을 알게 되었습니다. 보통의 5bit GIF는 8bit PNG보다 조금 무거워서 우리는 PNG를 선택하게 되었습니다.

이제 JavaScript를 PNG 파일의 색상 데이터로 변환해야 합니다. 목적을 달성하기 위해 저는 JavaScript 파일을 읽어들여, PNG 파일을 만들고 각각의 픽셀이 0-255의 값을 가져가 스크립트의 각 문자에 대응하도록 했습니다.

여기서 문제가 발생했는데, 이미지가 트루 칼라 이미지로 만들어졌고 우리는 그것을 8bit 인덱스 이미지로 변환해야 했지만 PHP는 정확하게 변환하지 못했습니다. 아마도 PHP/GD를 이용해 팔레트 사용 이미지를 만들 수 있는 방법이 있을 것 같지만, 아직까지 보지는 못했습니다. 현재의 해결책은 Photoshop 같은 프로그램으로 이미지를 만들어 8bit로 변환하는 것입니다.

이제 우리는 훌륭하고 PNG 파일 형태로 압축된 JavaScript를 가지게 되었습니다. 이번엔 클라이언트로 다시 이들을 내보내야 합니다. Canvas 엘리먼트에서, drawImage()를 사용해서 그림을 그린 후, getImageData()를 사용해서 모든 픽셀 데이터를 읽을 수 있습니다. 이 데이터들은 각 픽셀이 4가지 요소(RGBA)를 가지는 큰 배열 형태의 값입니다. 우리가 4가지 값씩 읽어들여, eval()로 이들을 하나로 묶어 집어넣습니다. 그럼 완료군요.
그리고 읽기 함수는 여기에 있습니다.

주의: 이 방법은 단순히 재미를 위해서 시도한 것이므로, 실제로 사용해도 된다는 것은 아닙니다. 그를 염두에 두고, 마리오 게임에서 동작되는 것을 보십시오.

from Compression using Canvas and PNG on Ajaxian
TAG
Posted by 행복한고니 트랙백 0 : 댓글 2

댓글을 달아 주세요

  1. addr | edit/del | reply BlogIcon Draco 2008.05.09 01:26

    GZip같은 기존의 압축 전송 방식이 있긴 합니다만...
    꽤나 독특한 발상이네요.

    • addr | edit/del BlogIcon 행복한고니 2008.05.09 13:02 신고

      네, 아이디어가 독특하죠. ^^
      GZip은 서버측 작업이 필요하지만, 이 방식은 서버에 의존하지 않고 스크립트만으로 해결할 수 있다는 점이 특징인 것 같습니다.