ermouth: (Default)
ermouth ([personal profile] ermouth) wrote2010-11-18 04:31 am
Entry tags:

Упаковка js, css и html в… png

Это для веб-деятелей пост. Остальным будет неинтересно. Веб-деятели будут реально в ахуе.

Общая идея такая. Упаковать html-страничку с помощью png, а потом распаковать на клиенте в картинку, а картинку превратить обратно в код с помощью canvas.getImageData().data.

Такой подход, за счёт того, что png использует LZW-упаковку, по эффективности близкую к ZIP, позволяет очень сильно сократить размер передаваемых данных. Забегая вперёд скажу, что у меня получилось 88 кб UTF-8 файла превратить в 17 кб.

Помимо этого распаковка картинки на клиенте и превращение её в код очень сильно затрудняют вскрытие кода странички (во всяком случае в хроме).

Как это сделать?

1. Превратить исходный код в UTF-16

Для этого надо исходный текст сохранить из редактора как UTF-16 codepage 1200 (это двухбайтный Юникод с LSB first). Размер файла примерно вдвое вырастет, но нам это пофигу.

2. Подогнать размер файла

Нам надо, чтобы размер файла в байтах делился на 3 и на любое более-менее (>300) крупное нечётное число. Чтобы узнать, на что делится число, идите на http://www.wolframalpha.com, наколачивайте в окошке число и смотрите про него всё. Дальше очевидно (для тупых – просто добавляем пробелы куданить в файле, один пробел – два байта).

3. Превратить файл в png

В фотошопе вызываем File > Open File As…, указываем наш файл и формат Photoshop RAW.

В появившемся меню ставим 3 канала, нажимаем Guess чтобы подобрать размеры. Ширина обязательно должна быть нечётной, это почему то очень важно. У меня получилось так:

image

Открывается такая вот примерно картинка:

textpng1

Это так выглядит код считалки для liteprint.me. Сохраняем картинку как png (Save for Web).

Ура.

4. Загрузить картинку, распаковать её и выполнить код

Конструкция примерно такая:

<script>
var x = function(z, m, ix ) {  
  var o = new Image();
  o.onload = function() {
    var s = "",
        c = document.createElement("canvas"),
        t = c.getContext("2d"),
        w = o.width,
        h = o.height;
    c.width = c.style.width = w;
    c.height = c.style.height = h;
    t.drawImage(o, 0, 0);
    var b = t.getImageData( 0, 0, w, h ).data;  
    for(var i= 0; i <b.length-7; i += 8) {
        if (i!=0) s += String.fromCharCode(b[i]+b[i+1]*256);
        s += String.fromCharCode(b[i+2]+b[i+4]*256);
        s += String.fromCharCode(b[i+5]+b[i+6]*256);
    }
    m(s, ix);
  }
  o.src = z;
}
function xDrawAll (s, ix) {
    document.write(s);
}
</script> 
<body onload="x('http://ermouth.com/textpng1.png',xDrawAll,0)">
</body>

Как это работает, можно посмотреть в гугл-хроме на http://ermouth.com/testpngpack1.html. В других браузерах, поддерживающих canvas, не работает – но можно добиться работы, просто было лень.

В файерфоксе и сафари работает http://ermouth.com/testpngpack.html – первый опыт, в котором вместо UTF-16 я использовал Windows-1251 и немного другой раскодировщик.

Чтобы считалка заработала, просто потыкайте ссылки, которые виды продукции рядом с лого )))

Попробуйте ещё ради интереса посмотреть в отладчике код, что в хроме, что в Firebug’е о_О У меня не получилось.


Код раскодировщика взят и переработан отсюда http://bit.ly/aQa478 

Переработан он так, чтобы с кириллицей и вообще уникодом проблем не было.


Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
No Subject Icon Selected
More info about formatting