Упаковка 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
Переработан он так, чтобы с кириллицей и вообще уникодом проблем не было.
no subject
Date: 2010-11-18 01:39 am (UTC)no subject
Date: 2010-11-18 01:42 am (UTC)no subject
Date: 2010-11-18 01:58 am (UTC)а это как раз самый геморройный в целом этап, люди скрипты страшного размера для этого городят.
no subject
Date: 2010-11-18 02:14 am (UTC)no subject
Date: 2010-11-18 02:18 am (UTC)no subject
Date: 2010-11-18 02:32 am (UTC)no subject
Date: 2010-11-18 02:34 am (UTC)no subject
Date: 2010-11-18 03:12 am (UTC)no subject
Date: 2010-11-18 03:22 am (UTC)кстати, у меня результат упаковки 16-битного одноканального png получился хуже, чем 8-битного RGB. совершенно контринтуитивно для меня.
no subject
Date: 2010-11-18 01:52 am (UTC)у меня наоборот, в хроме (9.0.576.0) не показал, а в фф (3.6.7) показал.
И по http://ermouth.com/testpngpack.html так же
no subject
Date: 2010-11-18 01:55 am (UTC)no subject
Date: 2010-11-18 02:15 am (UTC)А в канарейке вообще страница не отображается %)
no subject
Date: 2010-11-18 02:00 am (UTC)no subject
Date: 2010-11-18 02:02 am (UTC)no subject
Date: 2010-11-18 02:10 am (UTC)X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
no subject
Date: 2010-11-18 02:11 am (UTC)no subject
Date: 2010-11-18 02:43 am (UTC)собственно говоря тыкание "просмотр кода элемента" вместо "просмотр кода страницы" в хроме так же все показывает.
короче говоря, хуй с винтом искать не пришлось, но хитрожопость очень интересная, ага ))
no subject
Date: 2010-11-18 02:48 am (UTC)no subject
Date: 2010-11-18 02:49 am (UTC)no subject
Date: 2010-11-18 02:54 am (UTC)no subject
Date: 2010-11-18 02:59 am (UTC)например, если тебе надо изъёбистую сортировку/фильтровку делать, под которую неловко задействовать слабый сервер. проще выгрузить кучу мусора и разбираться с ней на клиенте.
так кстати работает PrintMe -- малонагруженный сервер при очень прожорливом клиенте.
no subject
Date: 2010-11-18 03:10 am (UTC)no subject
Date: 2010-11-18 03:12 am (UTC)no subject
Date: 2010-11-18 02:46 am (UTC)no subject
Date: 2010-11-18 06:33 am (UTC)я не знаю, насколько динамическое сжатие менее эффективно, допустим что намного
но всё же, как массивы передаваемых данных подготавливаются, в фотошопе специально обученными обезьянами?
практическое применение какое?
no subject
Date: 2010-11-18 01:44 pm (UTC)no subject
Date: 2010-11-18 11:18 am (UTC)