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

<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.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 ()
	{
	var i, tab;
	tab = [];
	for (i=0;i<=255;i++)
		{
		tab[String.fromCharCode(i)] = i;
		}
	CES.data.tab_ord = tab;
	}

CES.func.tabChr = function ()
	{
	var i, tab;
	tab = [];
	for (i=0;i<=255;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.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 = CES.data.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.mapAddByte = function()
	{
	CES.data.map += CES.func.chr(CES.data.map_last_byte);
	CES.data.map_byte = 0;
	CES.data.map_bit  = 7;
	}

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.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();
		}
	}


CES.func.compress = function (input)
	{
	var freq;
	CES.data.input = input;
	CES.func.tabFreq();
	CES.func.tabOrd();
	CES.func.tabChr();
//	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;
	document.getElementById('ces_out').innerHTML = CES.data.map.length + ' / ' + CES.data.input.length;
	}

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); ";
CES.func.compress(input);
</script>

