huffman数据压缩算法验证成功

This commit is contained in:
ranchuan
2023-11-22 18:02:53 +08:00
commit f93b275e60
20 changed files with 1392 additions and 0 deletions

23
.vscode/c_cpp_properties.json vendored Normal file
View File

@@ -0,0 +1,23 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"C:/MinGW/include/"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"__WIN32__",
"DLL_EXPORT"
],
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "windows-gcc-x64",
"compilerPath": "C:/MinGW/bin/gcc.exe"
}
],
"version": 4
}

5
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"files.associations": {
"coder_lib.h": "c"
}
}

15
Makefile Normal file
View File

@@ -0,0 +1,15 @@
CC = gcc
SRCS = $(wildcard *.c)
STR = $(subst from,to,from your heart)
all:
$(CC) $(SRCS) -o hello
clean:
rm -rf *.exe

10
ReadMe.txt Normal file
View File

@@ -0,0 +1,10 @@
使用gcc编译一个文件
gcc hello.c -o hello
2023.11.22
huffman数据压缩算法验证成功

219
bytearray.c Normal file
View File

@@ -0,0 +1,219 @@
#include "bytearray.h"
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
// #include "board.h"
// #include "mystdlib.h"
// #include "debug.h"
// #include "rtthread.h"
#define ARR_MAX_PRINT_LEN 200
#define ARRAY_APPEND_SKIP 2048
#define rt_mutex_t void *
// 使用时保证不要在不同线程同时修改,可以不用保护以提高速度
#define rt_mutex_create(...) 0
#define rt_mutex_delete(...)
#define rt_mutex_take(...)
#define rt_mutex_release(...)
struct _array_def{
int32_t all;
int32_t used;
rt_mutex_t mutex;
uint8_t data[0];
};
array_def *arr_creat(void)
{
array_def *a;
static uint16_t count=0;
char s1[16]={0};
sprintf(s1,"arr_mut#%d",count);
int size=0;
size+=sizeof(array_def);
size+=ARRAY_APPEND_SKIP;
a=malloc(size);
param_check(a);
a->all=ARRAY_APPEND_SKIP;
a->used=0;
a->mutex=rt_mutex_create(s1,RT_IPC_FLAG_FIFO);
count++;
return a;
}
static array_def *arr_expend(array_def *a)
{
array_def *r;
int size=0;
int cpysize=0;
size+=sizeof(array_def);
size+=a->all+ARRAY_APPEND_SKIP;
r=malloc(size);
param_check(r);
cpysize=sizeof(array_def)+a->used;
memcpy(r,a,cpysize);
r->all+=ARRAY_APPEND_SKIP;
free(a);
return r;
}
array_def *_arr_append(array_def **a,uint8_t d)
{
param_check(a);
param_check(*a);
array_def *r=*a;
rt_mutex_take(r->mutex,RT_WAITING_FOREVER);
if((*a)->used>=(*a)->all)
{
r=arr_expend(*a);
}
r->data[r->used]=d;
r->used++;
rt_mutex_release(r->mutex);
*a=r;
return r;
}
uint8_t arr_get(array_def *a,int index)
{
uint8_t ret=0;
param_check(a);
rt_mutex_take(a->mutex,RT_WAITING_FOREVER);
if(index<0) index=a->used+index;
if((index>=0&&index<a->used)==0) ret=0;
else ret=a->data[index];
rt_mutex_release(a->mutex);
return ret;
}
void arr_reset(array_def *a,uint8_t d,int index)
{
param_check(a);
rt_mutex_take(a->mutex,RT_WAITING_FOREVER);
if(index<0) index=a->used+index;
if((index>=0&&index<a->used)==0){}
else a->data[index]=d;
rt_mutex_release(a->mutex);
}
uint8_t *arr_data(array_def *a)
{
param_check(a);
return a->data;
}
int arr_length(array_def *a)
{
param_check(a);
return a->used;
}
// 截取数组
array_def *arr_mid(array_def *a,int start,int len)
{
param_check(a);
array_def *r;
r=arr_creat();
if(start<0) start=a->used+start;
if((start>=0&&start<a->used)==0)
{
return r;
}
if(start+len>a->used)
{
len=a->used-start;
}
for(int i=0;i<len;i++)
{
//_arr_append(&r,arr_get(a,i+start));
_arr_append(&r,a->data[i+start]);
}
//return tappend(r,0);
return r;
}
// 移除一些数据,返回实际移除的数据长度
int arr_remove(array_def *a,int start,int len)
{
param_check(a);
if(start<0) start=a->used+start;
if((start>=0&&start<a->used)==0)
{
return 0;
}
if(start+len>a->used)
{
len=a->used-start;
}
int move_len=a->used-(start+len);
memcpy(&a->data[start],&a->data[start+len],move_len);
a->used-=len;
return len;
}
// 输出打印字符串
char *arr_string(array_def *a)
{
param_check(a);
array_def *d=arr_creat();
param_check(d);
// DBG_LOG("d=%08x,a=%08x",d,a);
// DBG_LOG("%s:length(a)==%d.",__func__,arr_length(a));
int len=0;
char s[20];
int index=0;
arr_append(d,'[');
for(int i=0;i<arr_length(a);i++)
{
sprintf(s,"%02x",arr_get(a,i));
// sprintf(s,"%02x",(uint8_t)i);
len=strlen(s);
arr_appends(d,s,len);
arr_append(d,',');
index++;
if(index>=ARR_MAX_PRINT_LEN){
// 超过20字节的 只打印前20字节
sprintf(s,"...(%d)",arr_length(a));
len=strlen(s);
arr_appends(d,s,len);
break;
}
}
arr_append(d,']');
len=arr_length(d);
char *ptr=malloc(len+1);
param_check(ptr);
memcpy(ptr,arr_data(d),len);
arr_delete(d);
ptr[len]=0;
return ptr;
}

47
bytearray.h Normal file
View File

@@ -0,0 +1,47 @@
#ifndef bytearray_h__
#define bytearray_h__
#include "stdint.h"
struct _array_def;
typedef struct _array_def array_def;
array_def *arr_creat(void);
uint8_t arr_get(array_def *a,int index);
void arr_reset(array_def *a,uint8_t d,int index);
array_def *arr_mid(array_def *a,int start,int len);
uint8_t *arr_data(array_def *a);
int arr_length(array_def *a);
int arr_remove(array_def *a,int start,int len);
char *arr_string(array_def *a);
#define arr_delete(a) {free(a);a=0;}
#define arr_append(a,d) _arr_append(&a,d)
#define arr_appends(a,d,len) for(int i=0;i<len;i++){_arr_append(&a,((uint8_t *)d)[i]);}
#define arr_appends_from(a,b) {\
uint8_t *d=arr_data(b);\
arr_appends(a,d,arr_length(b));}
#define arr_append_num(a,num,d) for(int i=0;i<num;i++){_arr_append(&a,d);}
#define arr_clear(a) arr_remove(a,0,arr_length(a))
#define arr_duplicate(a) arr_mid(a,0,arr_length(a))
// 转化为临时指针
// #define arr_temp(a) tappend(a,0)
#define arr_temp(a) a
#define param_check(a)
array_def *_arr_append(array_def **a,uint8_t d);
#endif

203
coder_lib.c Normal file
View File

@@ -0,0 +1,203 @@
#include "coder_lib.h"
#include "string.h"
#include "mystring.h"
#include "string.h"
#include "crc.h"
#include "stdio.h"
/*
+-----------------------------------------------------------------------+
| 管壳码格式(ascii) |
+-----------------------------------------------------------------------+
| 13byte |
+-----------------------------------------------------------------------+
| 雷管厂代号 | 生产年份 | 生产月份 | 生产日 | 特征号 | 流水号 |
+------------+------------+------------+----------+----------+----------+
| 2byte | 1byte | 2byte | 2byte | 1byte | 5byte |
+-----------------------------------------------------------------------+
+-----------------------------------------------------------------------+
| UID码格式(ascii) |
+-----------------------------------------------------------------------+
| 16byte |
+-----------------------------------------------------------------------+
| 芯片厂代号 | 生产年份 | 雷管厂代号 | 月 | 日 | 特征码 | 盒号 | 序号 |
+------------+----------+------------+-----+-----+--------+------+------+
| 2byte | 2byte | 2byte |2byte|2byte| 1byte | 3byte| 2byte|
+-----------------------------------------------------------------------+
+-----------------------------------------------------------------------+
| UID码存储格式(hex) |
+-----------------------------------------------------------------------+
| 8byte |
+-----------------------------------------------------------------------+
| 芯片厂代号 | 雷管厂代号 | 年月日 | 特征码盒号序号 | crc8 |
+------------+------------+------------------+-------------------+------+
| 1byte | 1byte | 2byte(大端) | 3byte(大端) | 1byte|
+-----------------------------------------------------------------------+
年月日(ascii)->年月日(hex)
年(y),月(m),日(d)
time=((((y[0]-'0')*10)+(y[1]-'0'))<<9)|\
((((m[0]-'0')*10)+(m[1]-'0'))<<5)|\
(((d[0]-'0')*10)+(d[1]-'0'))
特征码盒号序号(ascii)->特征码盒号序号(hex)
特征码(c),盒号(b),序号(i)
code=c*10000+((b[0]-'0')*100+(b[1]-'0')*10+(b[2]-'0'))*100+\
((i[1]-'0')*10+(i[2]-'0'))
*/
// 根据管壳码和年份信息生成uid的年份信息
static int coder_calc_year(const char *year,const char shell_year,char *uid_year)
{
int y=0;
for(int i=0;i<4;i++)
{
y*=10;y+=year[i]-'0';
}
// year是实时数据鉴于12月31生产的雷管year可能不同
// 此时year-1来保证与uid码上的相同
if(year[3]!=shell_year)
y--;
uid_year[0]=y%100/10+'0';
uid_year[1]=y%10+'0';
if(uid_year[1]==shell_year)
return 0;
else
return -1;
}
// 管壳码转uid码
int coder_shell_to_uid(const char *year,const char *shell_code,char *uid_code)
{
int ret=0;
memset(uid_code,0,16);
// 添加芯片企业代号(2byte)
memcpy(&uid_code[0],"AD",2);
// 添加年份(2y=byte)
ret=coder_calc_year(year,shell_code[2],&uid_code[2]);
// 添加雷管厂代号(2byte)
memcpy(&uid_code[4],&shell_code[0],2);
// 添加月日特征码流水号
memcpy(&uid_code[6], &shell_code[3],10);
return ret;
}
// 转换hex字符串为一个byte
static int coder_strhex_to_byte(const char *str_hex)
{
char buff[3]={0};
buff[0]=str_hex[0];
buff[1]=str_hex[1];
return str_ahextoi(buff);
}
// 转换int字符串为一个整形
static int coder_strint_to_byte(const char *str_int,int len)
{
char buff[10]={0};
if(len>10) return 0;
memcpy(buff,str_int,len);
return str_atoi(buff);
}
// uid码转存储码
int coder_uid_to_save(const char *uid_code,uint8_t *save_code)
{
uint16_t ymd=0;
uint32_t feature=0;
save_code[0]=coder_strhex_to_byte(&uid_code[0]);
save_code[1]=coder_strhex_to_byte(&uid_code[4]);
ymd=coder_strint_to_byte(&uid_code[2],2)<<9;
ymd|=coder_strint_to_byte(&uid_code[6],2)<<5;
ymd|=coder_strint_to_byte(&uid_code[8],2);
save_code[2]=ymd>>8;
save_code[3]=ymd&0xff;
feature=uid_code[10]*100000;
feature+=coder_strint_to_byte(&uid_code[11],3)*100;
feature+=coder_strint_to_byte(&uid_code[14],2);
save_code[4]=feature>>16;
save_code[5]=feature>>8;
save_code[6]=feature&0xff;
save_code[7]=crc_crc8(save_code,7);
return 0;
}
// 转换byte为hex字符串
static int coder_byte_to_strhex(const uint8_t byte,char *str_hex)
{
char buff[10]={0};
sprintf(buff,"%02X",byte);
str_hex[0]=buff[0];
str_hex[1]=buff[1];
return 0;
}
// 转换int为int字符串
static int coder_int_to_strint(const int n,char *str_int,int len)
{
char buff[10]={0};
sprintf(buff,"%05d",n);
memcpy(str_int,buff+(strlen(buff)-len),len);
return 0;
}
// 存储码转uid
int coder_save_to_uid(const uint8_t *save_code,char *uid_code)
{
uint16_t ymd=0;
uint32_t feature=0;
int ret=0;
if(save_code[7]!=crc_crc8(save_code,7))
{
return -1;
}
ret|=coder_byte_to_strhex(save_code[0],&uid_code[0]);
ret|=coder_byte_to_strhex(save_code[1],&uid_code[4]);
ymd=(save_code[2]<<8)|save_code[3];
feature=(save_code[4]<<16)|(save_code[5]<<8)|(save_code[6]);
ret|=coder_int_to_strint(ymd>>9,&uid_code[2],2);
ret|=coder_int_to_strint((ymd>>5)&0x0f,&uid_code[6],2);
ret|=coder_int_to_strint((ymd)&0x1f,&uid_code[8],2);
uid_code[10]=feature/100000;
ret|=coder_int_to_strint(feature%100000/100,&uid_code[11],3);
ret|=coder_int_to_strint(feature%100,&uid_code[14],2);
return ret;
}
// uid码转管壳码
int coder_uid_to_shell(const char *uid_code,char *shell_code)
{
memset(shell_code,0,13);
// 添加雷管厂代号
memcpy(&shell_code[0],&uid_code[4],2);
// 添加生产年份
memcpy(&shell_code[2],&uid_code[3],1);
// 添加月日特征码流水号
memcpy(&shell_code[3],&uid_code[6],10);
return 0;
}

36
coder_lib.h Normal file
View File

@@ -0,0 +1,36 @@
#ifndef coder_lib_h__
#define coder_lib_h__
#include "stdint.h"
// 管壳码转uid码
int coder_shell_to_uid(const char *year,const char *shell_code,char *uid_code);
// uid码转存储码
int coder_uid_to_save(const char *uid_code,uint8_t *save_code);
// 存储码转uid
int coder_save_to_uid(const uint8_t *save_code,char *uid_code);
// uid码转管壳码
int coder_uid_to_shell(const char *uid_code,char *shell_code);
#endif

109
crc.c Normal file
View File

@@ -0,0 +1,109 @@
#include "crc.h"
uint8_t crc_crc8(const uint8_t *data,int num)
{
uint8_t crc = 0;
uint16_t j,i;
for (j = 0; j < num; j++)
{
crc ^= *(data+j);
for ( i = 0; i < 8; i++)
{
if ((crc & 0x01) != 0)
{
crc >>= 1;
crc ^= 0x8c;
}
else
{
crc >>= 1;
}
}
}
return crc;
}
void crc_crc16(const uint8_t *data, int len,uint8_t *lb,uint8_t *hb)
{
if (len > 0)
{
uint16_t crc = 0xFFFF;
int i = 0;
for (; i < len; i++)
{
crc = (uint16_t)(crc ^ (data[i]));
for (int j = 0; j < 8; j++)
{
crc = (crc & 1) != 0 ? (uint16_t)((crc >> 1) ^ 0xA001) : (uint16_t)(crc >> 1);
}
}
uint8_t hi = (uint8_t)((crc & 0xFF00) >> 8); //高位置
uint8_t lo = (uint8_t)(crc & 0x00FF); //低位置
*lb=lo;*hb=hi;
}
}
uint32_t crc_crc32(const uint8_t *data,int size)
{
uint32_t temp,crc=0xffffffff;
int i=0,j=0;
if((size%4)!=0)
{
return 0;
}
while(i<size)
{
temp=data[i]|(data[i+1]<<8)|(data[i+2]<<16)|(data[i+3]<<24);
i+=4;
for(j=0;j<32;j++)
{
if((crc^temp)&0x80000000)
crc=0x04c11db7^(crc<<1);
else
crc<<=1;
temp<<=1;
}
crc&=0xffffffff;
}
return crc;
}
void crc_sumcheck(const uint8_t *data,int size,uint8_t *chka,uint8_t *chkb)
{
if(chka==0) return;
if(chkb==0) return;
*chka=0;
*chkb=0;
for(int i=0;i<size;i++)
{
*chka+=data[i];
*chkb+=*chka;
}
}

28
crc.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef crc_h__
#define crc_h__
#include "stdint.h"
uint8_t crc_crc8(const uint8_t *data,int num);
void crc_crc16(const uint8_t *data, int len,uint8_t *lb,uint8_t *hb);
uint32_t crc_crc32(const uint8_t *data,int size);
void crc_sumcheck(const uint8_t *data,int size,uint8_t *chka,uint8_t *chkb);
#endif

15
for_hello.c Normal file
View File

@@ -0,0 +1,15 @@
#include "stdio.h"
int for_hello(void){
printf("i am in \"%s\"\n",__FILE__);
return 0;
}

46
hello.c Normal file
View File

@@ -0,0 +1,46 @@
#include "stdio.h"
#include "string.h"
// #include "coder_lib.h"
#include "huffman.h"
// 验证管壳码算法
// int main(int num,char *str[]){
// uint8_t d_[12]={0};
// char uid[20]={0};
// coder_shell_to_uid("2023","5830628A00004",uid);
// printf("uid=%s\r\n",uid);
// coder_uid_to_save(uid,d_);
// printf("slave:, uid_pw=%02X %02X %02X %02X %02X %02X %02X %02X "
// "%02X %02X %02X %02X ",d_[0],d_[1],d_[2],d_[3],d_[4],d_[5],d_[6],d_[7],
// d_[8],d_[9],d_[10],d_[11]);
// return 0;
// }
// 验证huffman算法
int main(int argc, char *argv[])
{
uint8_t str_in[]="2023 5830628A000005830628A000015830628A000025830628A000035830628A000045830628A000055830628A000065830628A000075830628A000085830628A00009";
array_def *a=arr_creat();
arr_appends(a,str_in,strlen(str_in));
array_def *out=hm_encode(a);
printf("endode:%s\n",arr_string(out));
array_def *de=hm_decode(out);
printf("decde:%s\n",arr_data(de));
return 0;
}

BIN
hello.exe Normal file

Binary file not shown.

424
huffman.c Normal file
View File

@@ -0,0 +1,424 @@
#include "stdlib.h"
#include "stdio.h"
#include "bytearray.h"
#include "string.h"
// huffman编码的实现
#define DBG_WARN printf
#define DBG_LOG printf
typedef struct _huff_tree{
uint8_t data;
uint8_t pos;// 位置左为1右为0
uint16_t count;
struct _huff_tree *parant;
struct _huff_tree *left;
struct _huff_tree *right;
}huff_tree;
typedef struct{
huff_tree *tree;
int index_table_index;
huff_tree *index_table[256];
uint16_t count_table[256];
array_def *out;
array_def *in;
int in_bit_count;
int arr_bit_index;
}huffman_def;
static int hm_calc_value_of_tree(huff_tree *t);
// 按出现频次排序
static void hm_sort_index_table(huff_tree **table,int num)
{
for(int i=0;i<num;i++)
{
huff_tree *item=table[i];
for (int j=i;j<num;j++)
{
if(hm_calc_value_of_tree(table[j])>hm_calc_value_of_tree(item))
{
table[i]=table[j];
table[j]=item;
item=table[i];
}
}
}
}
// 打印index_table
static void hm_index_table_print(huffman_def *h){
DBG_LOG("-----index_table-----\n");
for(int i=0;i<h->index_table_index;i++){
DBG_LOG("index:%d,data:%02x,count:%d\n",i,h->index_table[i]->data,h->index_table[i]->count);
}
}
// 打印数据的编码
static void hm_data_code_print(huffman_def *h){
huff_tree *t;
DBG_LOG("------data code------\n");
for(int i=0;i<h->index_table_index;i++){
t=h->index_table[i];
DBG_LOG("%c:",t->data);
while(t->parant){
DBG_LOG("%d",t->pos);
t=t->parant;
}
DBG_LOG("\n");
}
}
static void hm_calc_count(huffman_def *h,array_def *d)
{
int num=arr_length(d);
int index;
memset(h->count_table,0,256);
// DBG_LOG("calc count_table\n");
for(int i=0;i<num;i++)
{
h->count_table[arr_get(d,i)]++;
}
// DBG_LOG("calc index_table\n");
for(int i=0;i<256;i++)
{
if(h->count_table[i]>0){
index=h->index_table_index;
h->index_table[index]=calloc(1,sizeof(huff_tree));
h->index_table[index]->count=h->count_table[i];
h->index_table[index]->data=i;
h->index_table_index++;
}
}
// DBG_LOG("sort index_table\n");
hm_sort_index_table(h->index_table,h->index_table_index);
// hm_index_table_print(h);
}
// 计算树的值
static int hm_calc_value_of_tree(huff_tree *t)
{
int sum=0;
if(t->left&&t->right)
sum=hm_calc_value_of_tree(t->left)+hm_calc_value_of_tree(t->right);
else
sum=t->count;
// DBG_LOG("tree sum:%d\n",sum);
return sum;
}
// 打印huffman树
static void hm_tree_print(huff_tree *t)
{
if(t->left&&t->right){
DBG_LOG("point:,count:%d\n",hm_calc_value_of_tree(t));
hm_tree_print(t->left);
hm_tree_print(t->right);
}else{
DBG_LOG("data:%d,count:%d\n",t->data,t->count);
}
}
// 建立huffman树
static void hm_creat_tree(huffman_def *h)
{
int tail=h->index_table_index;
huff_tree *sub1,*sub2;
huff_tree **table=calloc(tail,sizeof(huff_tree *));
for(int i=0;i<tail;i++){
table[i]=h->index_table[i];
}
while(tail>1){
huff_tree *temp;
sub1=table[tail-1];
sub2=table[tail-2];
// 大在左,小在右
temp=calloc(1,sizeof(huff_tree));
sub1->parant=temp;
sub2->parant=temp;
// 左为1右为0
if(hm_calc_value_of_tree(sub1)>hm_calc_value_of_tree(sub2)){
temp->left=sub1;
sub1->pos=1;
temp->right=sub2;
sub2->pos=0;
}else{
temp->left=sub2;
sub2->pos=1;
temp->right=sub1;
sub1->pos=0;
}
table[tail-2]=temp;
tail--;
hm_sort_index_table(table,tail);
// DBG_LOG("-----table-----\n");
// for(int i=0;i<tail;i++){
// DBG_LOG("index:%d,count:%d\n",i,hm_calc_value_of_tree(table[i]));
// }
}
h->tree=table[0];
free(table);
}
// 删除树
static void hm_del_tree(huff_tree *t)
{
if(t->left&&t->right){
hm_del_tree(t->left);
hm_del_tree(t->right);
}
free(t);
}
// 数据中添加一个bit
static void hm_add_bit(array_def *d,int bit,int *index)
{
int len=arr_length(d);
if(*index<len*8){
uint8_t c=arr_get(d,-1);
c|=bit<<(*index%8);
arr_reset(d,c,-1);
}else{
arr_append(d,bit);
}
(*index)++;
}
// 根据数据添加bit
static int hm_encode_byte(huffman_def *h,uint8_t d)
{
huff_tree *t=0;
// 这里默认一定能找到对应的值
for(int i=0;i<h->index_table_index;i++)
{
t=h->index_table[i];
if(t->data==d)
break;
}
if(t->data!=d){
DBG_WARN("can not encode.\n");
exit(-1);
}
while(t->parant){
hm_add_bit(h->out,t->pos,&h->arr_bit_index);
t=t->parant;
}
// char *str=arr_string(h->out);
// DBG_LOG("index:%d,out data:%s\n",h->arr_bit_index,str);
// free(str);
return 0;
}
// 生成索引
static array_def *hm_creat_index_table(huffman_def *h)
{
array_def *a=arr_creat();
int temp;
int diff;
arr_append(a,h->index_table_index);
hm_index_table_print(h);
for(int i=0;i<h->index_table_index;i++)
{
arr_append(a,h->index_table[i]->data);
temp=h->index_table[i]->count;
while(temp>0){
if(temp>=255) diff=255;
else diff=temp;
arr_append(a,diff);
temp-=diff;
}
}
// 填充0个数
temp=arr_length(h->out)*8-h->arr_bit_index;
arr_append(a,temp);
// char *str=arr_string(a);
// DBG_LOG("arr index table:%s\n",str);
// free(str);
return arr_temp(a);
}
// huffman编码
/*
压缩后数据格式
data[0]:索引表长度
data[1~n]:索引表,每个索引由值(1byte)和频次(1byte,小于255)(2byte,大于等于255,频次由两个字节相加)
data[n+1]:数据中填充0个数
data[n+2~m]:压缩后的数据
*/
array_def *hm_encode(array_def *data)
{
int input_len=arr_length(data);
huffman_def *h=calloc(1,sizeof(huffman_def));
array_def *ret=0;
h->out=arr_creat();
// DBG_LOG("calc count\n");
hm_calc_count(h,data);
// DBG_LOG("creat tree\n");
hm_creat_tree(h);
// DBG_LOG("encode byte\n");
for(int i=0;i<input_len;i++)
{
hm_encode_byte(h,arr_get(data,i));
}
ret=hm_creat_index_table(h);
hm_del_tree(h->tree);
arr_appends_from(ret,h->out);
arr_delete(h->out);
free(h);
DBG_LOG("lenth_in:%d,length_encode:%d\n",input_len,arr_length(ret));
return arr_temp(ret);
}
// 读取编码表,返回数据开始的位置
static int hm_unpack_count(huffman_def *h,array_def *d)
{
int num=arr_get(d,0);
int index=1;
uint8_t temp;
for(int i=0;i<num;i++)
{
h->index_table[i]=calloc(1,sizeof(huff_tree));
h->index_table[i]->data=arr_get(d,index);index++;
do{
temp=arr_get(d,index);index++;
h->index_table[i]->count+=temp;
}while(temp==0xff);
h->index_table_index++;
}
temp=arr_get(d,index);index++;
h->in_bit_count=(arr_length(d)-index)*8-temp;
h->in=arr_mid(d,index,arr_length(d)-index);
// hm_index_table_print(h);
printf("bitcount:%d,\n",h->in_bit_count);
return index;
}
// 获取指定index的bit值
static inline int hm_get_bit(array_def *d,int index)
{
uint8_t t=arr_get(d,index/8);
return t&(1<<(index%8))?1:0;
}
// 对比树节点匹配返回bit数不匹配返回0
static inline int hm_cmp_bits(huffman_def *h,huff_tree *t)
{
int count=0;
// DBG_LOG("tree pos:",t->pos);
while(t){
// DBG_LOG("%d",t->pos);
if(hm_get_bit(h->in,h->arr_bit_index+count)!=t->pos){
// DBG_LOG(" |failed\n");
return 0;
}
else{
count++;
t=t->parant;
}
}
h->arr_bit_index+=count;
// DBG_LOG(" |ok,\n");
return count;
}
static uint8_t hm_decode_byte(huffman_def *h)
{
huff_tree *t=h->tree;
int bit;
// DBG_LOG("decode:");
while(t->left&&t->right){
bit=hm_get_bit(h->in,h->arr_bit_index-1);
// DBG_LOG("%d",bit);
if(bit==t->left->pos)
t=t->left;
else
t=t->right;
h->arr_bit_index--;
}
// DBG_LOG(" | decode byte:%c\n",t->data);
return t->data;
}
static int hm_calc_decode_len(huffman_def *h)
{
int sum=0;
for(int i=0;i<h->index_table_index;i++){
sum+=h->index_table[i]->count;
}
DBG_LOG("data len for decode:%d\n",sum);
return sum;
}
// huffman解码
/*
*/
array_def *hm_decode(array_def *data)
{
huffman_def *h=calloc(1,sizeof(huffman_def));
int decode_len,decode_index;
array_def *ret=arr_creat();
uint8_t *decode_data=0;
uint8_t c;
hm_unpack_count(h,data);
hm_creat_tree(h);
// hm_data_code_print(h);
// hm_tree_print(h->tree);
decode_len=hm_calc_decode_len(h);
decode_index=decode_len;
decode_data=calloc(decode_len+1,sizeof(uint8_t));
h->arr_bit_index=h->in_bit_count;
while(h->arr_bit_index>0){
c=hm_decode_byte(h);
decode_data[decode_index-1]=c;
decode_index--;
}
DBG_LOG("del tree\n");
hm_del_tree(h->tree);
DBG_LOG("del h->in\n");
//arr_delete(h->in);
DBG_LOG("free h\n");
free(h);
// arr_appends(ret,decode_data,decode_len);
DBG_LOG("decode:%s\n",decode_data);
free(decode_data);
return arr_temp(ret);
}

19
huffman.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef huffman_h__
#define huffman_h__
#include "bytearray.h"
// huffman编码的实现
array_def *hm_encode(array_def *data);
array_def *hm_decode(array_def *data);
#endif

74
mystring.c Normal file
View File

@@ -0,0 +1,74 @@
/*
*
* 把整数字符串传化为int,直到遇到非数字字符
*
*/
static int str_ainttoi(const char *s)
{
int ret=0;
int sig=1;
if(*s=='-'){
s++;
sig=-1;
}
while(*s)
{
if(*s>='0'&&*s<='9')
{
ret*=10;
ret+=*s-'0';
}
else return ret;
s++;
}
return ret*sig;
}
int str_ahextoi(const char *s)
{
int ret=0;
while(*s)
{
if(*s>='0'&&*s<='9')
{
ret*=16;
ret+=*s-'0';
}
else if(*s>='a'&&*s<='f')
{
ret*=16;
ret+=*s-'a'+10;
}
else if(*s>='A'&&*s<='F')
{
ret*=16;
ret+=*s-'A'+10;
}
else return ret;
s++;
}
return ret;
}
int str_atoi(const char *s)
{
if(s[0]=='0'&&((s[1]=='x')||(s[1]=='X'))){
return str_ahextoi(&s[2]);
}else{
return str_ainttoi(s);
}
}

29
mystring.h Normal file
View File

@@ -0,0 +1,29 @@
#ifndef mystring_h__
#define mystring_h__
#include "stdint.h"
int str_ahextoi(const char *s);
int str_atoi(const char *s);
#endif

23
sdl/.vscode/c_cpp_properties.json vendored Normal file
View File

@@ -0,0 +1,23 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"C:/MinGW/include/"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"__WIN32__",
"DLL_EXPORT"
],
"cStandard": "c17",
"cppStandard": "gnu++17",
"intelliSenseMode": "windows-gcc-x64",
"compilerPath": "C:/MinGW/bin/gcc.exe"
}
],
"version": 4
}

5
sdl/.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"files.associations": {
"sdl.h": "c"
}
}

62
sdl/hello_sdl.c Normal file
View File

@@ -0,0 +1,62 @@
//使用 SDL 和 标准 IO
#include <C:\MinGW\include\sdl2\SDL.h>
#include <stdio.h>
//定义屏幕尺寸常量
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
int main( int argc, char* args[] )
{
//将要渲染的窗口
SDL_Window* window = NULL;
//窗口含有的surface
SDL_Surface* screenSurface = NULL;
//初始化SDL
if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
}
else
{
//创建 window
window = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
if( window == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
}
else
{
//获取 window surface
screenSurface = SDL_GetWindowSurface( window );
//用白色填充surface
SDL_FillRect( screenSurface, NULL, SDL_MapRGB( screenSurface->format, 0xFF, 0xFF, 0xFF ) );
//更新surface
SDL_UpdateWindowSurface( window );
//延迟两秒
SDL_Delay( 2000 );
}
}
//销毁 window
SDL_DestroyWindow( window );
//退出 SDL subsystems
SDL_Quit();
return 0;}