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 } |