4577058 [rkeene@sledge /home/rkeene/devel/dact-0.8.37]$ cat -n comp_snibble.c
  1 /*
  2  * Copyright (C) 2001, 2002, and 2003  Roy Keene
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU General Public License
  6  * as published by the Free Software Foundation; either version 2
  7  * of the License, or (at your option) any later version.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  * GNU General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU General Public License
 15  * along with this program; if not, write to the Free Software
 16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 17  *
 18  *      email: dact@rkeene.org
 19  */
 20 
 21 
 22 /*
 23     Example block compression routine for interfacing with DACT.
 24 
 25 
 26     Seminibble Compression (Actually, a 2bit Huffman Implementation)
 27 
 28 */
 29 
 30 
 31 #include "dact.h"
 32 #include "comp_snibble.h"
 33 #include "buffer.h"
 34 #include "sort.h"
 35 #include <stdio.h>
 36 #ifdef HAVE_UNISTD_H
 37 #include <unistd.h>
 38 #endif
 39 #ifdef HAVE_STDLIB_H
 40 #include <stdlib.h>
 41 #endif
 42 #ifdef HAVE_STRING_H
 43 #include <string.h>
 44 #endif
 45 
 46 
 47 /*
 48     mode        - DACT_MODE_COMPR or DACT_MODE_DECMP
 49                 Determine whether to compress or decompress.
 50     prev_block  - Previous (uncompressed) block.
 51     curr_block  - The data to be compressed.
 52     out_block   - Where to put data after compression.
 53     blk_size    - Size of prev_block and curr_block.
 54 */
 55 
 56 #if defined(USE_MODULES) && defined(AS_MODULE)
 57 #include "module.h"
 58 uint32_t DC_NUM=6;
 59 uint32_t DC_TYPE=DACT_MOD_TYPE_COMP;
 60 void *DC_ALGO=comp_snibble_algo;
 61 char *DC_NAME="Seminibble Encoding (MOD)";
 62 #endif
 63 
 64 int comp_snibble_algo(int mode, unsigned char *prev_block, unsigned char *curr_block, char *out_block, int blk_size, int
	bufsize) {
 65     switch(mode) {
 66         case DACT_MODE_COMPR:
 67             return(comp_snibble_compress(prev_block, curr_block, out_block, blk_size, bufsize));
 68             break; /* Heh */
 69         case DACT_MODE_DECMP:
 70             return(comp_snibble_decompress(prev_block, curr_block, out_block, blk_size, bufsize));
 71             break;
 72         default:
 73             printf("Unsupported mode: %i\n", mode);
 74             return(-1);
 75     }
 76 }
 77 
 78 int comp_snibble_compress(unsigned char *prev_block, unsigned char *curr_block, char *out_block, int blk_size, int
	bufsize) {
 79     const unsigned char hash_table[4]={0, 2, 6, 7};
 80     const unsigned char hash_len[8]=  {1, 0, 2, 0, 0, 0, 3, 3};
 81     unsigned char lookup_table[4]={0, 0, 0, 0};
 82     uint32_t freq[4]={0, 0, 0, 0};
 83     char *curr_cpy;
 84     int i,x,m,g=0;
 85 
 86     if ((curr_cpy=malloc(blk_size))==NULL) {
 87         return(-1);
 88     }
 89     memcpy(curr_cpy,curr_block,blk_size);
 90 
 91     bit_buffer_purge();
 92 
 93     for (i=0;i<blk_size;i++) {
 94         freq[(int) ((curr_cpy[i]&0xc0)>>6)]++;
 95         freq[(int) ((curr_cpy[i]&0x30)>>4)]++;
 96         freq[(int) ((curr_cpy[i]&0x0c)>>2)]++;
 97         freq[(int) ((curr_cpy[i]&0x03))]++;
 98     }
 99 
100     int_sort(freq,4,1);
101 
102     for (i=0;i<4;i++) lookup_table[freq[i]]=hash_table[i];
103 
104     bit_buffer_write(freq[0],2);
105     bit_buffer_write(freq[1],2);
106     bit_buffer_write(freq[2],2);
107 
108 /*
109     outsize=((int) ((((((float) (freq[0]&0xffff))/2)+(freq[1]&0xffff)+(((float)
	(freq[2]&0xffff)+(freq[3]&0xffff))*1.5))/4.0)+0.99));
110 
111 */
112     for (i=0;i<blk_size;i++) {
113         for (x=0;x<4;x++) {
114             m=((curr_cpy[i]&(3<<(x*2)))>>( x*2 ))  ;
115             bit_buffer_write(lookup_table[m],hash_len[lookup_table[m]]);
116             while (bit_buffer_size()>=8) out_block[g++]=((unsigned char) (bit_buffer_read(8)));
117         }
118     }
119     i=bit_buffer_size();
120     if (i!=0) out_block[g++]=bit_buffer_read(i)<<(8-i);
121 
122     free(curr_cpy);
123 
124     return(g);
125 
126 }
127 
128 int comp_snibble_decompress(unsigned char *prev_block, unsigned char *curr_block, char *out_block, int blk_size, int
	bufsize) {
129     const unsigned char lookup_table[8]={0, 0, 1, 0, 0, 0, 2, 3};
130     unsigned int freq[4];
131     unsigned int x, m=0;
132     unsigned int i, cnt=0, f=0, j=0;
133     int32_t g=0;
134 
135     freq[0]=(curr_block[0]&0xc0)>>6; /* 0 */
136     freq[1]=(curr_block[0]&0x30)>>4; /* 2 */
137     freq[2]=(curr_block[0]&0x0c)>>2; /* 6 */
138     for (i=0;i<4;i++) {
139         if (freq[0]!=i && freq[1]!=i && freq[2]!=i) freq[3]=i;
140     }
141     out_block[0]=0;
142 
143     bit_buffer_purge();
144 
145     bit_buffer_write(curr_block[g++]&0x03,2);
146 
147     while (1) {
148         while (((bit_buffer_size()+8)<=16) && g<=blk_size) bit_buffer_write(curr_block[g++],8);
149         x=bit_buffer_read(1);
150         m=(m<<1)+x;
151         cnt++;
152         if (x==0 || cnt==3) {
153             out_block[f]|=(freq[lookup_table[m]]<<( j )) ;
154             j+=2;
155 /* Obsficated comes to mind ... */
156             if (j==8) out_block[++f]=(j=0);
157             m=0;
158             cnt=0;
159         }
160         if (bit_buffer_size()==0 || f==bufsize) break;
161     }
162 
163     return(f);
164 }
4577059 [rkeene@sledge /home/rkeene/devel/dact-0.8.37]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2004-04-04 07:01:50