一、要点
1、字典的关键字256表示开始,257表示结束;
2、压缩是针对文件的,9位的压缩码要转成8位ascii便于保存为文件;
3、解压时,将ASCII码转成二进制,恢复成9位压缩码再解压;
4、本程序只是针对压缩码小于512,即9bits的。实际情况中,当压缩码大于511后,改成10bits;大于1023,,用11bits;大于2048的,用12bits;不会使用13bits的,即编码不大于4096。
5、本程序能够以表格显示压缩和解压过程;建议用0-9,a-Z等可以显示的字符来测试。
二、程序
class LZW
{
private static function initDict() {
$dict = range("\0", "\xFF");
return $dict;
}
public static function encode($str) {
$dict = self::initDict();
$root = '';
$key = '';
$num = 258;
$out = array();
$bits = '%09b';
$html = '
index | Input | Root | Root+Input | Dictionary | Out |
$out = [];
$out[] = 256;
$skey = '';
for ($i = 0;$i < strlen($str);$i++) {
if ($num > 511)$bits = '%010b';
if ($num > 1023)$bits = '%011b';
if ($num > 2047)$bits = '%012b';
$in = substr($str,$i,1);
$skey = $skey.'.'.ord($in);
$html.= '
'.($i+1).''.$in.'('.ord($in).')'.$root.'';$key = array_search($root.$in,$dict);
if ($key) {
$root = $root.$in;
$html.= '
'.$root.'--';} else
{
$out[] = array_search($root,$dict);
$html.= '
'.$root.$in.'['.$num.']='.$root.$in.''.array_search($root,$dict).'';$dict[$num] = $root.$in;
$num = $num+1;
$root = $in;
$skey = ord($in);
}
}
$out[] = array_search($root,$dict);
$html.= '
'.($i+1).'-'.$root.'--'.array_search($root,$dict).'';$out[] = 257;
$html.= '
';echo $html;
$str = '';
$bits = '%09b';
$ar = [];
echo '压缩输出值(10进制):'.implode('|',$out);
$bin = [];
$bo = [];
for ($i = 0;$i < count($out);$i++) {
$bo[] = sprintf($bits,$out[$i]);
}
echo '
';
echo '压缩输出值(9bits二进制):'.implode('|',$bo);
echo '
';
$bos = implode('',$bo);
for ($i = 0;$i < strlen($bos)%8;$i++) {
$bos.= '0';
}
$bos = chunk_split($bos,8,"|");
$bos = explode('|',$bos);
for ($i = 0;$i < count($bos)-1;$i++) {
$bin[] = base_convert(bindec($bos[$i]),10,16);
$ar[] = chr(bindec($bos[$i]));
}
echo '压缩输出值(8bits字节):'.implode('|',$bin);
//var_dump($out);
//var_dump($dict);
return implode('',$ar);
}
/**
* 输出的code先是9bits的,即255~511,当字典的code数量大于511,改成10bits...,即不是定bits
*/
public static function decode($str) {
$dict = self::initDict();
$num = 258;
$in = '';
$skey = '';
$bin = [];
for ($i = 0;$i < strlen($str);$i++) {
$a = substr($str,$i,1);
$in.= sprintf('%08b',ord($a));
$bin[] = sprintf('%02X',ord($a));
}
echo '
';
echo '输入压缩值(8bits字节):'.implode('|',$bin);
$out = array();
$html = '
Index | Input | Root | Root+Input | Dictionary | Out |
$root = '';
$step = 9;
//显示255-511
echo '
';
echo '转换压缩值(9bits二进制):'.chunk_split($in,9,"|");
for ($i = 0;$i < strlen($in);$i = $i+$step) {
$bstr = substr($in,$i,$step);
echo $bstr.'[]';
if (strlen($bstr) < $step)break;
$b = bindec(substr($in,$i,$step));
if ($b == 257)break;
if ($b == 256 || $num > 4095) {
$dict = self::initDict();
$root = '';
$num = 258;
} else
{
$html.= '
'.($i/$step+1).''.$b.''.$root.'';if (isset($dict[$b])) {
$key = $root.substr($dict[$b],0,1);
if (array_search($key,$dict)) {
$root = $key;
$html.= '
'.$key.'--';$skey = $b;
} else
{
$out[] = $root;
$dict[$num] = $key;
$html.= '
'.$key.'['.$num.']='.$key.''.$root.'';$num = $num+1;
$root = $dict[$b];
$skey = $b;
}
} else
{
$key = $root.substr($root,0,1);
$dict[$num] = $key;
$html.= '
'.$root.substr($root,0,1).'['.$num.']='.$root.substr($root,0,1).''.$root.'';$num = $num+1;
$out[] = $root;
$root = $key;
$skey = $key;
}
}
if ($num > 511)$step = 10;
if ($num > 1023)$step = 11;
if ($num > 2047)$step = 12;
}
$html.= '
'.($i/$step+1).'-'.$root.'--'.$root.'';$html.= '
';echo $html;
$out[] = $root;
//var_dump($dict);
$str = '';
$bstr = implode('',$out);
for ($i = 0;$i < strlen($bstr);$i++) {
$str.= sprintf('%02X',ord(substr($bstr,$i,1)));
}
echo chunk_split($str,6,'|');
return implode('',$out);
}
}
lzljy
发布了16 篇原创文章 · 获赞 0 · 访问量 838
私信
关注
标签:TIFF,html,num,dict,key,图像文件,PHP,root,out
来源: https://blog.csdn.net/lzljy/article/details/103588206