Упаковка js, css и html в… png
Nov. 18th, 2010 04:31 am![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.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 чтобы подобрать размеры. Ширина обязательно должна быть нечётной, это почему то очень важно. У меня получилось так:
Открывается такая вот примерно картинка:
Это так выглядит код считалки для 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
Переработан он так, чтобы с кириллицей и вообще уникодом проблем не было.