FAXCOM.TXT
上传用户:szklead52
上传日期:2007-01-07
资源大小:5k
文件大小:24k
源码类别:

传真(Fax)编程

开发平台:

C/C++

  1. *****************************************************
  2. ****                                             ****
  3. ****   Faxdecod.c                                ****
  4. ****                                             ****
  5. *****************************************************
  6. /***************************************************************************
  7.    Faxdecoder : Usage faxdecoder <compressed_fax >uncompressed.fax
  8.    This program compresses a fax using a model based on an order 16 model.
  9.    Context is as follows : C = Context bits, P = bit being predicted
  10.       x
  11. xxxxxx
  12. xxxxxx
  13. xxxP
  14.    Variable names beginning with capital letters are arithmetic coding
  15.    variables used by the arithmetic coding routines.
  16. -------------------------------
  17.    Copyright Raymond P. Wilson 1989.
  18.    This program is a shareware program. If you use it then credit must be
  19.    given to the author (me). If you find this program useful please send
  20.    whatever you think it is worth ($25 is suggested) to :
  21. Raymond P. Wilson
  22. 38 Paremata St
  23. Atawhai
  24. Nelson
  25. New Zealand
  26.  **************************************************************************/
  27.  
  28. #include <stdio.h>
  29. #include <sys/time.h>
  30. #include <sys/resource.h>
  31. #include "coderdef.i"     /* My faxcoder definitions etc... */
  32. #include "arithdec.i" /* Arithmetic decoding functions and defs ... */
  33. /*************************************************************************
  34.    Function   : Initialise_model
  35.    Parameters : None
  36.    Returns    : Nothing
  37.    Initialise_model sets up all the structures and initialisation
  38.  required by the fax coder. 
  39.  ************************************************************************/
  40. void initialise_model()
  41. {
  42.    int i;
  43.    /* Initialise context bits and saved context arrays */
  44.   
  45.    for (i = 0;i < CONTEXT_WINDOW_BPL;i++)
  46.       saved[i] = 0;
  47.    /* Initialise context information array */
  48.   
  49.    for (i = 0;i < NUM_CONTEXTS;i++)
  50.    {
  51.       contexts[i].zero_count = 1;
  52.       contexts[i].sum = 2;   /* No explicit count of ones is kept */      
  53.    }      /* as this is implicit in the sum   */
  54. }
  55. /************************************************************************
  56.  
  57.    Function   : Decompress
  58.    Parameters : None
  59.    Returns    : Nothing
  60.    
  61.    Decompress decompresses a fax file read in from std input.
  62.    
  63.  ***********************************************************************/
  64.  
  65. void decompress()
  66. {
  67.    register codevalue S_low=0, S_high=0;
  68.       /* Arithmetic decoder vars high and low of range */
  69.    register int 
  70.       context,      /* Context at predicted bit */
  71.       bitnum,       /* Bit being compressed on current line */
  72.       S_bitstogo,   /* Arithmetic decoder var - used in inputting bits */
  73.       H = half,     /* Arithmetic decoder var - contains constant half */
  74.       last,         /* Shifting three bit field of last three bits read in */
  75.       bitsleft = 8, /* Mask for getting bit out of byte */
  76.       byte = 0;     /* Byte read in from  */
  77.    startinputingbits();
  78.    startdecoding();
  79.    for (line = 0;line < NUM_LINES;line++)
  80.    {
  81.       last = 0;   /* Clear shifting temporary storage for incoming bits */
  82.     /* Start iterating over bits in line - start in from edge of 'sheet'
  83.        to give white space at edge for context */
  84.       for (bitnum = CONTEXT_SIDE_BITS;
  85.            bitnum < (CONTEXT_SIDE_BITS + BITS_PER_LINE);bitnum++)
  86.       {
  87.    /* Work out context that precedes bit being predicted */
  88.          context = saved[bitnum] | (last >> 3);
  89.     /* Store that part of the context that will be used on the next line */ 
  90.  
  91.          saved[bitnum] = (context & CONTEXT_MASK) << 6;
  92.     
  93.     /* Decode the bit currently being decompressed and update the model */
  94.     /* Call arithmetic_decode_target to get position in range */
  95.         
  96.          if (arithmetic_decode_target(contexts[context].sum) 
  97.                < contexts[context].zero_count)
  98.          {  
  99.             /* Decode a zero bit */
  100.             arithmetic_decode_zero(contexts[context].zero_count,
  101.                                    contexts[context].sum);
  102.                                    
  103.             contexts[context].zero_count++; /* Increment zero bit count */
  104.             write_decoded0;                 /* Output a decoded zero */
  105.        /* Add a zero bit to shifting storage and add this to previously
  106.           stored context from two bits back */
  107.            
  108.             saved[bitnum-2] |= (last = (last << 1) & 0x38);            
  109.          }
  110.          else
  111.          {
  112.             /* 'Decode' a one bit */
  113.             arithmetic_decode_one(contexts[context].zero_count,
  114.                                   contexts[context].sum);
  115.                                   
  116.             write_decoded1; /* Write out a decoded ont bit */
  117.        /* Add a zero bit to shifting storage and add this to previously
  118.           stored context from two bits back */
  119.  
  120.             saved[bitnum-2] |= (last = ((last << 1) | 0x8) & 0x38);
  121.          }                                                         
  122.        /* Increment sum count and check to see if counts need halving */
  123.        
  124.          if ((++contexts[context].sum) == HALVE_LIMIT)  
  125.          {
  126.             contexts[context].zero_count = (contexts[context].zero_count >> 2) + 1;
  127.             contexts[context].sum = (contexts[context].sum >> 2) + 2;
  128.          }
  129.       }
  130.    }
  131. }
  132. /*************************************************************************
  133.                                  Main program.
  134.    
  135.  ************************************************************************/
  136.  
  137. main(argc,argv)
  138. int argc;
  139. char **argv;
  140. {
  141.    initialise_model();
  142.    fprintf(stderr,"Decompressing file, please wait.n");
  143.    start_time = get_time();              /* Get starting time */
  144.    decompress();  
  145.    total_time = get_time() - start_time; /* Get total time from difference */  
  146.    fprintf(stderr,"%s: Decompressed fax in %.3f seconds.n",argv[0],total_time);
  147.    exit(0);
  148. }
  149. *****************************************************
  150. ****                                             ****
  151. ****   Faxcoder.c                                ****
  152. ****                                             ****
  153. *****************************************************
  154. /***************************************************************************
  155.     Faxcoder : Usage faxcoder <fax_file.fax >output
  156.     This program compresses a fax using a model based on an order 16 model.
  157.     Context is as follows : x = Context bits, P = bit being predicted
  158.    
  159.       x
  160. xxxxxx
  161. xxxxxx
  162. xxxP
  163.  
  164.    Variable names beginning with capital letters are arithmetic coding
  165.    variables used by the arithmetic coding routines.
  166. -------------------------------
  167.    Copyright Raymond P. Wilson 1989.
  168.    This program is a shareware program. If you use it then credit must be
  169.    given to the author (me). If you find this program useful please send
  170.    whatever you think it is worth ($25 is suggested) to :
  171. Raymond P. Wilson
  172. 38 Paremata St
  173. Atawhai
  174. Nelson
  175. New Zealand
  176.     If you want to use this or parts of this program in a commercial product
  177.  then the authors permission is required.
  178.  **************************************************************************/
  179.  
  180. #include <stdio.h>
  181. #include <sys/time.h>
  182. #include <sys/resource.h>
  183. #include "coderdef.i"     /* My faxcoder definitions etc... */
  184. #include "arithcod.i" /* Arithmetic coding functions and defs... */
  185. /*************************************************************************
  186.    Function   : Initialise_model
  187.    Parameters : None
  188.    Returns    : Nothing
  189.    Initialise_model sets up all the structures and initialisation
  190.  required by the fax coder. 
  191.  ************************************************************************/
  192. void initialise_model()
  193. {
  194.    int i;
  195.    /* Initialise context bits and saved context arrays */
  196.   
  197.    for (i = 0;i < CONTEXT_WINDOW_BPL;i++)
  198.       saved[i] = 0;
  199.    /* Initialise context information array */
  200.   
  201.    for (i = 0;i < NUM_CONTEXTS;i++)
  202.    {
  203.       contexts[i].zero_count = 1;
  204.       contexts[i].sum = 2;
  205.    }
  206. }
  207. /************************************************************************
  208.    Function   : Compress
  209.    Parameters : None
  210.    Returns    : Nothing
  211.    
  212.    Compress compresses a fax file read in from std input.
  213.    
  214.  ***********************************************************************/
  215.  
  216. void compress()
  217. {
  218.    register codevalue S_low=0, S_high=0;
  219.       /* Arithmetic coder vars high and low of range */
  220.    register int 
  221.       context,      /* Context at predicted bit */
  222.       bitnum,       /* Bit being compressed on current line */
  223.       S_bitstogo,   /* Arithmetic coder var - used in inputting bits */
  224.       H = half,     /* Arithmetic coder var - contains constant half */
  225.       last,         /* Shifting three bit field of last three bits read in */
  226.       mask = 0,     /* Mask for getting bit out of byte */
  227.       byte = 0;     /* Byte read in from  */
  228.       
  229.    startoutputingbits();
  230.    startencoding();
  231.   
  232.    for (line = 0;line < NUM_LINES;line++)
  233.    {
  234.       last = 0;   /* Clear shifting temporary storage for incoming bits */
  235.     /* Start iterating over bits in line - start in from edge of 'sheet'
  236.        to give white space at edge for context */
  237.        
  238.       for (bitnum = CONTEXT_SIDE_BITS;
  239.            bitnum < (CONTEXT_SIDE_BITS + BITS_PER_LINE);bitnum++)
  240.       {
  241.       
  242.     /* Work out context that precedes bit being predicted */
  243.    
  244.          context = saved[bitnum] | (last >> 3);
  245.                    
  246.     /* Store that part of the context that will be used on to the next line */ 
  247.  
  248.          saved[bitnum] = (context & CONTEXT_MASK) << 6;
  249.     
  250.      /* Get the bit that is to be compressed */
  251.     
  252.          getabit()
  253.          
  254.     /* Code the bit currently being compressed and update the model */
  255.    
  256.          if (byte & mask)
  257.          {
  258.             arithmetic_encode_one(contexts[context].zero_count,
  259.                                   contexts[context].sum)
  260.                                   
  261.        /* Add a one bit to shifting storage and add this to previously
  262.           stored context from two bits back */
  263.                                         
  264.             saved[bitnum-2] |= (last = ((last << 1) | 0x8) & 0x38);
  265.          }
  266.          else
  267.          {
  268.             arithmetic_encode_zero(contexts[context].zero_count,
  269.                                    contexts[context].sum);
  270.        /* Add a zero bit to shifting storage and add this to previously
  271.           stored context from two bits back */
  272.             saved[bitnum-2] |= (last = (last << 1) & 0x38);
  273.             
  274.             contexts[context].zero_count++; /* Increment zero bit count */
  275.          }
  276.        /* Increment sum count and check to see if counts need halving */
  277.        
  278.          if ((++contexts[context].sum) == HALVE_LIMIT)  
  279.          {
  280.             contexts[context].zero_count = (contexts[context].zero_count >> 2) + 1;
  281.             contexts[context].sum = (contexts[context].sum >> 2) + 2;
  282.          }
  283.       }
  284.    }
  285.    /* Finish up encoding and finishing outputting bits */
  286.    doneencoding();
  287.    doneoutputingbits();
  288. }
  289. /*************************************************************************
  290.                                  Main program.
  291.    
  292.  ************************************************************************/
  293.  
  294. main(argc, argv)
  295. int argc;
  296. char **argv;
  297. {
  298.    initialise_model();
  299.    fprintf(stderr,"Compressing file, please wait...nn");
  300.    start_time = get_time();             /* Get starting time */
  301.    compress();
  302.    total_time = get_time() - start_time; /* Get total time from difference */
  303.    fprintf(stderr,"%s: compression %4.2f bpc (%4.2f : 1) in %.3f seconds.n",
  304.                   argv[0], (8 * cmpbytes)/(double)FAX_SIZE,
  305.                   FAX_SIZE/(float)cmpbytes, total_time);
  306.    exit(0);
  307. }
  308. *****************************************************
  309. ****                                             ****
  310. ****   Coderdef.i                                ****
  311. ****                                             ****
  312. *****************************************************
  313. /*********************************************************************
  314.    FAXCOM Copyright Raymond P. Wilson 1989.
  315.    This program is a shareware program. If you use it then credit must be
  316.    given to the author (me). If you find this program useful please send
  317.    ($25 is suggested) or whatever you think it is worth to :
  318. Raymond P. Wilson
  319. 38 Paremata St
  320. Atawhai
  321. Nelson
  322. New Zealand
  323. If you wish to use this, or parts of this, program in a commercial product then the authors permission is required.
  324. **********************************************************************/
  325. /* This file contains variable and macro definitions common to the
  326.    faxcoder and faxdecoder */
  327. #define NUM_LINES          2376    /* Number of lines in the fax */
  328. #define BYTES_PER_LINE     216     /* Bytes per line in fax */
  329. #define BITS_PER_LINE      (8 * BYTES_PER_LINE)
  330.    /* Bits on a fax line */
  331. #define FAX_SIZE           (NUM_LINES * BYTES_PER_LINE)
  332.    /* Size (in bytes) of a fax file */
  333. #define MODEL_ORDER        16      /* Number of bits of context */
  334. #define NUM_CONTEXTS       (1 << MODEL_ORDER)
  335. #define HALVE_LIMIT        16383   /* Halve counts when sum reaches this */
  336. #define CONTEXT_MASK       0x3ff /* This masks out unwanted portions of the
  337.                                     context from the bit immediately above */
  338.                                     
  339. #define CONTEXT_SIDE_BITS  3 /* Number bits to side of fax page to allow
  340. for context spilling over sides */
  341.                               
  342. #define CONTEXT_WINDOW_BPL (BITS_PER_LINE + 2 * CONTEXT_SIDE_BITS)
  343.      /* Bits per line for context bits array */
  344. int cmpbytes = 0,   /* Number of compressed bytes outputted */
  345.     line,           /* Line currently on in fax file */
  346.     saved[CONTEXT_WINDOW_BPL];
  347.                     /* Array that holds saved pieces of context */
  348. struct context_type    /* This structure holds the counts for zeros and the */
  349. {        /* sum of zeros and ones for a context               */
  350.    int zero_count, sum;
  351. } contexts[NUM_CONTEXTS]; /* The array that holds context information */
  352. /* Get a bit from the input file */
  353. #define getabit() 
  354.    if ((mask>>=1) ==0)
  355.    {
  356.       byte=getchar();
  357.       mask=0x80;
  358.    }
  359. /* Write a zero bit out to the output file */
  360. #define write_decoded0       
  361. {                            
  362.    byte <<= 1 ;              
  363.    bitsleft-- ;              
  364.    if (bitsleft==0)          
  365.    {                         
  366.       putc(byte, stdout) ;   
  367.       bitsleft = 8 ;         
  368.    }                         
  369. }
  370. /* Write a one bit out to the output file */
  371. #define write_decoded1       
  372. {                            
  373.    byte = (byte << 1) | 0x1; 
  374.    bitsleft-- ;              
  375.    if (bitsleft==0)          
  376.    {                         
  377.       putc(byte, stdout) ;   
  378.       bitsleft = 8 ;         
  379.    }                         
  380. }
  381. #ifdef UNIX
  382. float start_time,total_time;
  383. /*
  384.  * get_time()
  385.  *
  386.  * return amount of CPU time in seconds used since starting
  387.  */
  388. float get_time()
  389. {
  390.         struct rusage rusage;
  391. getrusage(RUSAGE_SELF,&rusage);
  392.         return(rusage.ru_utime.tv_sec +
  393.        rusage.ru_utime.tv_usec/1000000.0 +
  394.        rusage.ru_stime.tv_sec +
  395.        rusage.ru_stime.tv_usec/1000000.0) ;
  396. }
  397. #endif
  398. *****************************************************
  399. ****                                             ****
  400. ****   Arithdec.i                                ****
  401. ****                                             ****
  402. *****************************************************
  403. /*************************************************************************
  404.    This program is shareware. If you use it and find it useful please
  405.    send ($25 is suggested) or whatever you think it is worth to :
  406.  Raymond P. Wilson
  407.  38 Paremata St.
  408.  Atawhai
  409.  Nelson
  410.  New Zealand
  411.    If you wish to use this program or parts of this program in a
  412. commercial the authors permission is required.
  413. Copyright Raymond P. Wilson 1989
  414. **************************************************************************/
  415. /* arithmetic coding routines */
  416. /* Most of the functions here have been converted to macro definitions
  417.    to speed them up and have been customised for a binary alphabet */
  418. #define codevaluebits 16
  419. typedef long codevalue ;
  420. #define topvalue (((long)1<<codevaluebits)-1)
  421. #define firstqtr (topvalue/4+1)
  422. #define half     (2*firstqtr)
  423. #define thirdqtr (3*firstqtr)
  424. codevalue S_value=0 ;
  425. int S_buffer=0;
  426. /* Macro definition for call to get number in range when decoding files */
  427. #define arithmetic_decode_target(totl)
  428.        (  (((long)(S_value-S_low)+1)*(totl)-1)/ ((long)(S_high -S_low)+1)  )
  429. /*==================================*/
  430. #define addnextinputbit(v) 
  431.   { S_bitstogo--;
  432.     if (S_bitstogo<0) 
  433.       { S_buffer = getc(stdin) ;
  434.         S_bitstogo = 7 ; 
  435.       } 
  436.     v += (S_buffer & 1) ; 
  437.     S_buffer >>= 1 ; 
  438.   } 
  439. /*==================================*/
  440. #define arithmetic_decode_zero(hbnd, totl) 
  441. {
  442.    S_high = S_low  +  (((long)(S_high-S_low)+1) * hbnd)/totl - 1 ;
  443.    
  444.    for (;;)
  445.      { if (S_high<H) 
  446.          { /* nothing */
  447.          }
  448.        else
  449.        if (S_low>=H) 
  450.          { S_value -= H ;
  451.            S_low -= H ;
  452.            S_high -= H ;
  453.          }
  454.        else
  455.        if (S_low>=firstqtr && S_high<thirdqtr)
  456.          { S_value -= firstqtr ;
  457.            S_low -= firstqtr ;
  458.            S_high -= firstqtr ;
  459.          }
  460.        else break ;
  461.        S_low <<= 1;
  462.        S_high = (S_high << 1) | 1;
  463.        S_value <<= 1 ;
  464.        addnextinputbit(S_value) ;
  465.     }
  466.  }
  467. /*======================================================================*/
  468. #define arithmetic_decode_one(lbnd, totl)  
  469.    S_low  +=  (((long)(S_high-S_low)+1)*lbnd)/totl ; 
  470.    for (;;) 
  471.    { if (S_high<H)  
  472.        { /* nothing */ 
  473.        } 
  474.      else 
  475.        if (S_low>=H)  
  476.          { S_value -= H ; 
  477.            S_low -= H ; 
  478.            S_high -= H ; 
  479.          } 
  480.        else 
  481.        if (S_low>=firstqtr && S_high<thirdqtr) 
  482.          { S_value -= firstqtr ; 
  483.            S_low -= firstqtr ; 
  484.            S_high -= firstqtr ; 
  485.          } 
  486.        else break ; 
  487.        S_low <<= 1; 
  488.        S_high = (S_high << 1) | 1; 
  489.        S_value <<= 1; 
  490.        addnextinputbit(S_value) ; 
  491.     } 
  492.  }
  493. /*==================================*/
  494. #define startdecoding()
  495.   { register int i ;
  496.     S_value = 0 ;
  497.     for (i=1; i<=codevaluebits; i++)
  498.       { S_value += S_value ;
  499.         addnextinputbit(S_value) ;
  500.       }
  501.     S_low = 0 ;
  502.     S_high = topvalue ;
  503.   }
  504. #define startinputingbits()
  505. S_bitstogo = 0 ;
  506. *****************************************************
  507. ****                                             ****
  508. ****   ArithCod.i                                ****
  509. ****                                             ****
  510. *****************************************************
  511. /*************************************************************************
  512.    This program is shareware. If you use it and find it useful please
  513.    send ($25 is suggested) or whatever you think it is worth to :
  514.  Raymond P. Wilson
  515.  38 Paremata St.
  516.  Atawhai
  517.  Nelson
  518.  New Zealand
  519.    If you wish to use this program or parts of this program in a
  520. commercial the authors permission is required.
  521. Copyright Raymond P. Wilson 1989
  522. **************************************************************************/
  523. /* arithmetic coding routines */
  524. /* Most of the functions here have been converted to macro definitions
  525.    to speed them up and customised bor a binary alphabet  */
  526. #define codevaluebits 16
  527. typedef long codevalue ;
  528. #define topvalue (((long)1<<codevaluebits)-1)
  529. #define firstqtr (topvalue/4+1)
  530. #define half     (2*firstqtr)
  531. #define thirdqtr (3*firstqtr)
  532. long S_bitstofollow=0 ;
  533. int S_buffer=0;
  534. /*==================================*/
  535. #define bitplusfollow0            
  536.     { outputbit0 ;                
  537.       while (S_bitstofollow>0)    
  538.         { outputbit1 ;            
  539.           S_bitstofollow--;       
  540.         }                         
  541.     }
  542. #define bitplusfollow1            
  543.     { outputbit1 ;                
  544.       while (S_bitstofollow>0)    
  545.         { outputbit0 ;            
  546.           S_bitstofollow--;       
  547.         }                         
  548.     }
  549. #define outputbit0                
  550.     { S_buffer >>= 1;   
  551.       S_bitstogo--;               
  552.       if (S_bitstogo==0)          
  553.         { putc(S_buffer, stdout) ;
  554.           S_bitstogo = 8 ;        
  555.           cmpbytes++ ;            
  556.         }                         
  557.     }
  558. #define outputbit1                
  559.     { S_buffer = (S_buffer >> 1) | 0x80;            
  560.       S_bitstogo--;               
  561.       if (S_bitstogo==0)          
  562.         { putc(S_buffer, stdout) ;
  563.           S_bitstogo = 8 ;        
  564.           cmpbytes++ ;            
  565.         }                         
  566.     }
  567. /*==================================*/
  568. #define arithmetic_encode_zero(hbnd, totl)
  569. {
  570.    S_high = S_low  +  (((long)(S_high-S_low)+1) * hbnd)/totl - 1 ;
  571.    for (;;)
  572.      { if (S_high<H) 
  573.          { bitplusfollow0 ;
  574.          }
  575.        else
  576.        if (S_low>=H) 
  577.          { bitplusfollow1 ;
  578.            S_low -= H ;
  579.            S_high -= H ;
  580.          }
  581.        else
  582.        if (S_low>=firstqtr && S_high<thirdqtr)
  583.          { S_bitstofollow++ ;
  584.            S_low -= firstqtr ;
  585.            S_high -= firstqtr ;
  586.          }
  587.        else break ;
  588.        S_low <<= 1;
  589.        S_high = (S_high << 1) | 1;
  590.      }
  591.   }
  592. /*=====================================================================*/
  593. #define arithmetic_encode_one(lbnd, totl)
  594. {
  595.    S_low  += ((((long)(S_high-S_low)+1) * lbnd)/totl) ;
  596.    for (;;)
  597.      { if (S_high<H) 
  598.          { bitplusfollow0 ;
  599.          }
  600.        else
  601.        if (S_low>=H) 
  602.          { bitplusfollow1 ;
  603.            S_low -= H ;
  604.            S_high -= H ;
  605.          }
  606.        else
  607.        if (S_low>=firstqtr && S_high<thirdqtr)
  608.          { S_bitstofollow++ ;
  609.            S_low -= firstqtr ;
  610.            S_high -= firstqtr ;
  611.          }
  612.        else break ;
  613.        S_low <<= 1; ;
  614.        S_high = (S_high << 1) | 1;
  615.      }
  616.   }
  617. /*==================================*/
  618. #define startencoding() 
  619.     S_high = topvalue ;
  620. #define doneencoding()
  621.   { 
  622.     S_bitstofollow++;
  623.     if (S_low<firstqtr)
  624. {       bitplusfollow0;}
  625.     else
  626. {       bitplusfollow1; }
  627.   }
  628. #define startoutputingbits()
  629.     S_bitstogo = 8 ;
  630. #define doneoutputingbits()
  631.   { putc(S_buffer>>S_bitstogo, stdout) ;
  632.     cmpbytes++;
  633.   }