<div id="ces_out"></div>

<script src='zlib.pretty.js'></script>
<!--script src='zlib.min.js'></script-->
<!--script src='zip.min.js'></script-->

<script>
// ces.pas - myslim si, ze to deli byte po 2 bitech, spocita pocet opakovani a podle toho vytvori mapy true/false. Ktere navic zasifruje huffmanem.
var CES = {};
CES.data = {};
CES.data.input = '';
CES.data.tab_freq = [];
CES.data.tab_ord = [];
CES.data.tab_chr = [];
CES.data.map = '';
CES.data.map_bit  = 7;
CES.data.map_byte = 0;
CES.func = {};

CES.func.tabOrd = function ()
	{
	var i, tab;
	tab = [];
	for (i=0;i<256;i++)
		{
		tab[String.fromCharCode(i)] = i;
		}
	CES.data.tab_ord = tab;
	}

CES.func.tabChr = function ()
	{
	var i, tab;
	tab = [];
	for (i=0;i<256;i++)
		{
		tab[i] = String.fromCharCode(i);
		}
	CES.data.tab_chr = tab;
	}

CES.func.ord = function (chr)
	{
	return CES.data.tab_ord[chr];
	}

CES.func.chr = function (ord)
	{
	return CES.data.tab_chr[ord];
	}

CES.func.tabFreq = function ()
	{
	var i, freq, chr;
	freq = [];
	for (i=0;i<=255;i++)
		{
		chr = CES.func.chr(i);
		freq[chr] = [0,0,0,0];
		freq[chr][(i)    & 0x03] += 1;
		freq[chr][(i>>2) & 0x03] += 1;
		freq[chr][(i>>4) & 0x03] += 1;
		freq[chr][(i>>6) & 0x03] += 1;
		}
	CES.data.tab_freq = freq;
	}

CES.func.inputFreq = function (input)
	{
	var i, end_i, freq, freq_byte, chr;
	freq  = [0,0,0,0];
	end_i = input.length;
	for (i=0;i<end_i;i++)
		{
		chr = input.charAt(i);
		freq_byte = CES.data.tab_freq[chr];
		freq[0] += freq_byte[0];
		freq[1] += freq_byte[1];
		freq[2] += freq_byte[2];
		freq[3] += freq_byte[3];
		}
	return freq;
	}

//CES.func.mapAdd = function(bool)
//	{
//	CES.data.map += bool ? 1 : 0;
//	}

CES.func.mapAddReset = function()
	{
	CES.data.map_byte = 0;
	CES.data.map_bit  = 7;
	}

CES.func.mapAddByte = function()
	{
	CES.data.map += CES.func.chr(CES.data.map_byte);
	CES.func.mapAddReset();
	}

CES.func.mapAdd = function(bool)
	{
	var b,n;
	b = CES.data.map_bit;
	n = (bool * 1);
	CES.data.map_byte = CES.data.map_byte | (n << b);
	if (b>0)
		{
		b--
		CES.data.map_bit = b;
		return;
		}
	CES.func.mapAddByte();
	}
/*
var m_b:byte;
begin
  if ovl_bit=0 then mapa[ovl_byte]:=0;
  if co_dat=true then
    begin
      m_b:=1;
      m_b:=m_b shl ovl_bit;
      mapa[ovl_byte]:=mapa[ovl_byte]+m_b;
    end;
  inc(ovl_bit);
  if ovl_bit=8 then begin ovl_bit:=0;inc(ovl_byte);end;
*/

CES.func.mapAddAll = function(m,n)
	{
	if (m==0)
		{
		CES.func.mapAdd(n==0);
		}
	else {if (m==1)
		{
		if (n==1)
			{
			CES.func.mapAdd(true);
			}
		if (n==2 || n==3)
			{
			CES.func.mapAdd(false);
			}
		}
	else {if (m==2)
		{
		if (n==2)
			{
			CES.func.mapAdd(true);
			}
		if (n==3)
			{
			CES.func.mapAdd(false);
			}
		}}}
	}

CES.func.huffAddAll = function (n)
	{
	if (n==0)
		{
		CES.func.mapAdd(true);
		return;
		}
	else {if (n==1)
		{
		CES.func.mapAdd(false);
		CES.func.mapAdd(false);
		return;
		}
	else {if (n==2)
		{
		CES.func.mapAdd(false);
		CES.func.mapAdd(true);
		CES.func.mapAdd(false);
		return;
		}}}
	CES.func.mapAdd(false);
	CES.func.mapAdd(false);
	CES.func.mapAdd(false);
	}

CES.func.huff = function (input)
	{
	var freq, order, map,i,end_i,j,end_j, m,n;
	freq = CES.func.inputFreq(input);
	order = [0,1,2,3];
	order.sort(function(b,a){return freq[a]-freq[b];});	//desc
	CES.func.mapAddReset();
	CES.data.map = '';
	end_i = input.length;
	for (i=0;i<end_i;i++)
		{
		m = CES.func.ord(input[i]);
		n = m & 0x03; m >>= 2; CES.func.huffAddAll(order[n]);
		n = m & 0x03; m >>= 2; CES.func.huffAddAll(order[n]);
		n = m & 0x03; m >>= 2; CES.func.huffAddAll(order[n]);
		n = m & 0x03;          CES.func.huffAddAll(order[n]);
		}
	if (CES.data.map_bit>0)
		{
		CES.func.mapAddByte();
		}
	return CES.data.map;
	}

CES.func.inputToMap = function (freq,input)
	{
	var order, map,i,end_i,j,end_j, m,n;
//var x;
	order = [0,1,2,3];
	order.sort(function(b,a){return freq[a]-freq[b];});	//desc
//	alert([freq,order]);
	end_i = input.length;
	end_j = freq.length - 1;
//old_x = 0;
	for (j=0;j<end_j;j++)
		{
		for (i=0;i<end_i;i++)
			{
			m = CES.func.ord(input[i]);
			n = m & 0x03; m >>= 2; CES.func.mapAddAll(j,order[n]);
			n = m & 0x03; m >>= 2; CES.func.mapAddAll(j,order[n]);
			n = m & 0x03; m >>= 2; CES.func.mapAddAll(j,order[n]);
			n = m & 0x03;          CES.func.mapAddAll(j,order[n]);
			}
//	CES.data.map += '|';
//x = CES.data.map.length - old_x;
//old_x = CES.data.map.length;
//	CES.data.map += ' ' + (x>>2);
//	CES.data.map += '<br>';
		}
//	CES.data.map += ' '+(CES.data.map.length-3)+'/'+(input.length<<3) + ' '+ input.length;
	if (CES.data.map_bit>0)
		{
		CES.func.mapAddByte();
		}
	return CES.data.map;
	}

CES.func.compress = function (input)
	{
	var freq, output;
	CES.data.input = input;
//	alert(CES.data.tab_freq.toSource())
	freq = CES.func.inputFreq(CES.data.input);
//	alert(freq);
	out = CES.func.inputToMap(freq,CES.data.input)
//	document.getElementById('ces_out').innerHTML = CES.data.map;
//	plain = CES.data.map;
//	var deflate = new Zlib.Deflate(plain);
//	var compressed = deflate.compress();

//	out = CES.data.map;
//alert(Zlib.Zip)
//comp = Zlib.Zip.compress(input)
//zlib = new Zlib
//comp = Zlib.RawDeflate(input)

/*
    const data = new Buffer([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23]);
    const compressed = Zlib.deflateSync(data);
const decompressed = Zlib.inflateSync(compressed);
*/

//zlib.deflate(input);

//var zlib = require('zlib');
//alert(Zlib.RawDeflate.toSource())
//var comp;
//comp = Zlib.RawDeflate(input).output;
//	document.getElementById('ces_out').innerHTML = result.length + ' / ' + CES.data.input.length;
//	})

//	out = CES.func.huff(out);
	document.getElementById('ces_out').innerHTML = out.length + ' / ' + input.length;
	}


CES.func.init = function ()
	{
	CES.func.tabOrd();
	CES.func.tabChr();
	CES.func.tabFreq();
	}

CES.func.init();
var input = 'Ahoj';	// 01 00 00 01 01 10 10 00 01 10 11 11 01 10 10 10 = 00 3x, 01 5x, 10 6x, 11 2x
var input = " // ces.pas - myslim si, ze to deli byte po 2 bitech, spocita pocet opakovani a podle toho vytvori mapy true/false. Ktere navic zasifruje huffmanem. var CES = {}; CES.data = {}; CES.data.input = ''; CES.data.tab_freq = []; CES.data.tab_ord = []; CES.data.map = ''; CES.func = {}; CES.func.tabFreq = function () { var i, freq, chr; freq = []; for (i=0;i<=255;i++) { chr = String.fromCharCode(i); freq[chr] = [0,0,0,0]; freq[chr][(i) & 0x03] += 1; freq[chr][(i>>2) & 0x03] += 1; freq[chr][(i>>4) & 0x03] += 1; freq[chr][(i>>6) & 0x03] += 1; } CES.data.tab_freq = freq; } CES.func.tabOrd = function () { //alert(String.fromCharCode(65)) var i, tab; tab = []; for (i=0;i<=255;i++) { tab[String.fromCharCode(i)] = i; } // alert(tab.toSource()) CES.data.tab_ord = tab; } CES.func.ord = function (chr) { return CES.data.tab_ord[chr]; } CES.func.inputFreq = function (input) { var i, end_i, freq, freq_byte, chr; freq = [0,0,0,0]; end_i = input.length; for (i=0;i>= 2; CES.func.mapAddAll(j,order[n]); n = m & 0x03; m >>= 2; CES.func.mapAddAll(j,order[n]); n = m & 0x03; m >>= 2; CES.func.mapAddAll(j,order[n]); n = m & 0x03; CES.func.mapAddAll(j,order[n]); } CES.data.map += '|'; } CES.data.map += ' '+(CES.data.map.length-3)+'/'+(input.length<<3); } CES.func.compress = function (input) { var freq; CES.data.input = input; CES.func.tabFreq(); CES.func.tabOrd(); // alert(CES.data.tab_freq.toSource()) freq = CES.func.inputFreq(CES.data.input); // alert(freq); CES.func.inputToMap(freq,CES.data.input) document.getElementById('ces_out').innerHTML = CES.data.map; } var input = 'Ahoj'; // 01 00 00 01 01 10 10 00 01 10 11 11 01 10 10 10 = 00 3x, 01 5x, 10 6x, 11 2x CES.func.compress(input); ";
var input = "UmFyIRoHAQDz4YLrCwEFBwAGAQGAgIAAp8/5fS4CAwuzCQSTGiD88nB1gAUAEnBhc3N3b3JkLWdlbmVyLmh0bQoDAkhmQJYEb8kByDmvBFBkQzMzPzUGX/3nL4OGbZalE2Um3La4m0rE003HImk6knZZa70BFFJGMok0krpkrvu7ZUwdB6E10xvw98ZQ6M3MzQNAJ8e3tG5u6Pt5g3cA/GDm+IcW1ubhLXurks2qnTZJaFjnrC1Sq1SdNKzZGPY5Cc1StUsUrUBP+v6h/EJuqj/ptuZSP31yLN3GGrxO59tF/11KQg27pMreF0XLXQCm42thwLjPPF73fVK5cQPMlefPHLyIzjr8nv74fMDoonXkO+dwJXDXnhzGJlzQGHvCV6xkwdHCps2adjn6bRKtKtzdVITfoKewuItlZ1hx9SjCrVxdvA+KzmCFfLkyerF3BMVCxgz2i0dgeRFgS0JrwDxl7m3Q1Cn/wcMCerbIs3RdHhtpkGhsV9JJCRDAkLwmBpCWX2tol999yfNm/A2Uk+VNNi7ojn9Fi8a5neFu7haWfYCKS8AtgzAA9bDglM2wZi3tkwo/ZZPkBQZb4RgIldAZV9W6y2Ham06iGlAL5xlpHBIImPyxiTIrXCCPt0ybTvidJTQVLYc4Tgb4z/mFxzubG0sFL5HwioYglZ0iRZ4d4lAik7d3t/0fh+P5cHpU4UgkEseeW2tcXu3r7Hw7GcDTbn+jGEkYseTL8Yh9CZA6XHT5KnLzevn9ntq9Fav0/pYs2ur9fd+3v/fvxDXgf+f/ter7Pt839fd55Uvc/uhM/j5fz29fX/3DP+/rU2+JWjN/MkUUsaFsieDQ6JTNisXSQz2MTMDDwry8xEImUM6YQjUS5qBiMrOARLUEMyg8RK0EMygxNA0Ocqf9pPys6judt5myu1eEbL0m+ByUextu3JSQid5kI+2S6wNpqyJxDcqnlENvqO8QXXPRGDtkr4rnihE3YYVNyGGg4iHipSdWNuSonQpLPkoknDQdGUbxM8FV3jnFJl02gLonoJR1ti5kMhbvCixxESoF2ZMNfQ3+qYXkZv6DG7YtzAf03ps0lQ3Lw/TNNR0fI6LpsfYNF2vh6Dp8PfGw95DulOFTZWNjhxHV3z9e+MT8CahwTvMS2KJBk0JyMsF4rLF5qhJHXD+RqdgI0UHtBTBlPcUkFfgIo4XlNsg9VBVjEBZK0Ba8881pNU+RJ9zCBD+VwHYAXW7AW5EpUigIiMlcD6b2zhz7URwyLoXXl9nEn3TgfzUGs+/lFHmRL01OgI9E6p6L0eij3jtFUUw8dosmI8hovIrq0+jGwivpNGYeqpPJzW6HPjjElDchhqqOkzEVnCKnOBQjzHxFjfo65SqG5TkiI5GyU8n0aiPnOlN3p2kTpp+Dmkx9TxkrL442mhka+d85Ztu+F1WxYfbah0U5gkhIKPmcigKD47aYYi3YMuHozVRzWViCKogEoA5k+knVDUbCJhdsmgHj0shBg20AkjnWr33pCmPm+jC6kvHqj2JUepaD7J43tYVyOLWzIbFryOGcQaXwn7Z5p8/XUxRUlmuOUZHfAR4eg26UYFBQrrBWQsA/M4l32Fio4VKbm8EXldXk/XeeI463iYuBhIpbt5ScRRFANdBPofXh4/2Lm+voFOm+zIN0tE8iBlZzrM6I/XXCOMzh96m+r6PST28ZvWIAHXdWUQMFBAA=";
input = window.atob(input);
//alert(input.length)
//encodedData = window.btoa('Hello, world');
//decodedData = window.atob(encodedData)
CES.func.compress(input);
</script>

