about summary refs log tree commit diff
path: root/converter/other/fiasco/output
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-19 03:12:28 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-19 03:12:28 +0000
commit1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch)
tree64c8c96cf54d8718847339a403e5e67b922e8c3f /converter/other/fiasco/output
downloadnetpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz
netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz
netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/other/fiasco/output')
-rw-r--r--converter/other/fiasco/output/Makefile26
-rw-r--r--converter/other/fiasco/output/matrices.c547
-rw-r--r--converter/other/fiasco/output/matrices.h28
-rw-r--r--converter/other/fiasco/output/mc.c250
-rw-r--r--converter/other/fiasco/output/mc.h28
-rw-r--r--converter/other/fiasco/output/nd.c244
-rw-r--r--converter/other/fiasco/output/nd.h27
-rw-r--r--converter/other/fiasco/output/tree.c176
-rw-r--r--converter/other/fiasco/output/tree.h27
-rw-r--r--converter/other/fiasco/output/weights.c200
-rw-r--r--converter/other/fiasco/output/weights.h27
-rw-r--r--converter/other/fiasco/output/write.c250
-rw-r--r--converter/other/fiasco/output/write.h28
13 files changed, 1858 insertions, 0 deletions
diff --git a/converter/other/fiasco/output/Makefile b/converter/other/fiasco/output/Makefile
new file mode 100644
index 00000000..3bdc4635
--- /dev/null
+++ b/converter/other/fiasco/output/Makefile
@@ -0,0 +1,26 @@
+ifeq ($(SRCDIR)x,x)
+  SRCDIR = $(CURDIR)/../../../..
+  BUILDDIR = $(SRCDIR)
+endif
+FIASCOSUBDIR = converter/other/fiasco
+SUBDIR = $(FIASCOSUBDIR)/output
+VPATH=.:$(SRCDIR)/$(SUBDIR)
+
+include $(BUILDDIR)/Makefile.config
+
+OBJECTS =  matrices.o mc.o nd.o tree.o weights.o write.o
+
+MERGE_OBJECTS = $(OBJECTS)
+
+INCLUDES = -I$(SRCDIR)/$(FIASCOSUBDIR) \
+	   -I$(SRCDIR)/$(FIASCOSUBDIR)/lib \
+	   -I$(SRCDIR)/$(FIASCOSUBDIR)/codec 
+
+all: libfiasco_output.a
+
+include $(SRCDIR)/Makefile.common
+
+libfiasco_output.a: $(OBJECTS)
+	$(AR) -rc $@ $(OBJECTS)
+	$(RANLIB) $@
+
diff --git a/converter/other/fiasco/output/matrices.c b/converter/other/fiasco/output/matrices.c
new file mode 100644
index 00000000..fd8d31e2
--- /dev/null
+++ b/converter/other/fiasco/output/matrices.c
@@ -0,0 +1,547 @@
+/*
+ *  matrices.c:		Output of transitions matrices
+ *
+ *  Written by:		Ullrich Hafner
+ *		
+ *  This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec)
+ *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
+ */
+
+/* NETPBM: When you call delta_encoding() with last_domain < 4, it
+   crashes.  And we have seen it happen.
+*/
+
+/*
+ *  $Date: 2000/06/14 20:50:31 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#include "config.h"
+
+#if STDC_HEADERS
+#	include <stdlib.h>
+#endif /* not STDC_HEADERS */
+
+#include "types.h"
+#include "macros.h"
+#include "error.h"
+
+#include "wfa.h"
+#include "bit-io.h"
+#include "arith.h"
+#include "misc.h"
+#include "wfalib.h"
+
+#include "matrices.h"
+
+/*****************************************************************************
+
+				prototypes
+  
+*****************************************************************************/
+
+static unsigned
+delta_encoding (bool_t use_normal_domains, bool_t use_delta_domains,
+		const wfa_t *wfa, unsigned last_domain, bitfile_t *output);
+static unsigned
+column_0_encoding (const wfa_t *wfa, unsigned last_row, bitfile_t *output);
+static unsigned
+chroma_encoding (const wfa_t *wfa, bitfile_t *output);
+
+/*****************************************************************************
+
+				public code
+  
+*****************************************************************************/
+
+unsigned
+write_matrices (bool_t use_normal_domains, bool_t use_delta_domains,
+		const wfa_t *wfa, bitfile_t *output)
+/*
+ *  Write transition matrices of 'wfa' to stream 'output'.
+ *
+ *  Return value:
+ *	number of transitions encoded
+ */
+{
+   unsigned root_state;			/* root of luminance */
+   unsigned total = 0;			/* number of transitions */
+   
+   root_state = wfa->wfainfo->color
+		? wfa->tree [wfa->tree [wfa->root_state][0]][0]
+		: wfa->root_state;
+   
+   total  = column_0_encoding (wfa, root_state, output);
+
+   total += delta_encoding (use_normal_domains, use_delta_domains,
+			    wfa, root_state, output);
+   
+   if (wfa->wfainfo->color)
+      total += chroma_encoding (wfa, output);
+   
+   return total;
+}
+
+/*****************************************************************************
+
+				private code
+  
+*****************************************************************************/
+
+static unsigned
+delta_encoding (bool_t use_normal_domains, bool_t use_delta_domains,
+		const wfa_t *wfa, unsigned last_domain, bitfile_t *output)
+/*
+ *  Write transition matrices with delta coding to stream 'input'.
+ *  'last_domain' is the maximum state number used as domain image.
+ *
+ *  Return value:
+ *	number of non-zero matrix elements (WFA edges)
+ */
+{
+   range_sort_t	rs;			/* ranges are sorted as in the coder */
+   unsigned	max_domain;		/* dummy used for recursion */
+   unsigned	total = 0;
+      
+   /*
+    *  Generate a list of range blocks.
+    *  The order is the same as in the coder.
+    */
+   rs.range_state      = Calloc ((last_domain + 1) * MAXLABELS,
+				 sizeof (u_word_t));
+   rs.range_label      = Calloc ((last_domain + 1) * MAXLABELS,
+				 sizeof (byte_t));
+   rs.range_max_domain = Calloc ((last_domain + 1) * MAXLABELS,
+				 sizeof (u_word_t));
+   rs.range_subdivided = Calloc ((last_domain + 1) * MAXLABELS,
+				 sizeof (bool_t));
+   rs.range_no	       = 0;
+   max_domain 	       = wfa->basis_states - 1;
+   sort_ranges (last_domain, &max_domain, &rs, wfa);
+   
+   /*
+    *  Compute and write distribution of #edges
+    */
+   {
+      unsigned state, label;
+      unsigned edge;
+      unsigned count [MAXEDGES + 1];
+      unsigned n;
+      unsigned edges = 0;
+      unsigned M     = 0;
+      unsigned bits  = bits_processed (output);
+      
+      for (n = 0; n < MAXEDGES + 1; n++)
+	 count [n] = 0;
+      
+      for (state = wfa->basis_states; state <= last_domain; state++)
+	 for (label = 0; label < MAXLABELS; label++)
+	    if (isrange (wfa->tree [state][label]))
+	    {
+	       for (edge = 0; isedge (wfa->into [state][label][edge]); edge++)
+		  ;
+	       count [edge]++;
+	       edges++;
+	       M = max (edge, M);
+	    }
+      write_rice_code (M, 3, output);
+      for (n = 0; n <= M; n++)
+/* NETPBM: The following causes a crash when last_domain < 4, because
+   it requests writing of a negative number of bits.  And we have seen
+   last_domain = 3.  But we have no clue what last_domain means, or 
+   even what a rice code is, so we don't know where the error lies.
+   -Bryan 2001.02.09 
+*/
+	 write_rice_code (count [n], (int) log2 (last_domain) - 2, output);
+
+      /*
+       * Arithmetic coding of values */
+      {
+	 unsigned  range;
+	 model_t  *elements = alloc_model (M + 1, 0, 0, count);
+	 arith_t  *encoder  = alloc_encoder (output);
+	       
+	 for (range = 0; range < rs.range_no; range++)
+	    if (!rs.range_subdivided [range])
+	    {
+	       state = rs.range_state [range];
+	       label = rs.range_label [range];
+	       for (edge = 0; isedge (wfa->into [state][label][edge]); edge++)
+		  ;
+	       
+	       encode_symbol (edge, encoder, elements);
+	    }
+	 free_encoder (encoder);
+	 free_model (elements);
+      }
+      debug_message ("delta-#edges: %5d bits. (%5d symbols => %5.2f bps)",
+		     bits_processed (output) - bits, edges,
+		     edges > 0 ? ((bits_processed (output) - bits) /
+				  (double) edges) : 0);
+   }
+
+   /*
+    *  Write matrix elements
+    */
+   {
+      unsigned	bits  	 = bits_processed (output);
+      u_word_t *mapping1 = Calloc (wfa->states, sizeof (u_word_t));
+      u_word_t *mapping2 = Calloc (wfa->states, sizeof (u_word_t));
+      unsigned	range;
+
+      put_bit (output, use_normal_domains);
+      put_bit (output, use_delta_domains);
+      
+      /*
+       *  Generate array of states which are admitted domains.
+       *  When coding intra frames 'mapping1' == 'mapping2' otherwise
+       *  'mapping1' is a list of 'normal' domains which are admitted for 
+       *             coding intra blocks
+       *  'mapping2' is a list of 'delta' domains which are admitted for
+       *             coding the motion compensated prediction error 
+       */
+      {
+	 unsigned n1, n2, state;
+	 
+	 for (n1 = n2 = state = 0; state < wfa->states; state++)
+	 {
+	    mapping1 [state] = n1;
+	    if (usedomain (state, wfa)
+		&& (state < wfa->basis_states || use_delta_domains
+		    || !wfa->delta_state [state]))
+	       n1++;
+	    
+	    mapping2 [state] = n2;
+	    if (usedomain (state, wfa)
+		&& (state < wfa->basis_states || use_normal_domains
+		    || wfa->delta_state [state]))
+	       n2++;
+	 }
+	 debug_message ("# normal states = %d, # delta states = %d,"
+			" # WFA states = %d", n1, n2, wfa->states);
+      }
+      
+      for (range = 0; range < rs.range_no; range++)
+	 if (!rs.range_subdivided [range])
+	 {
+	    unsigned  state = rs.range_state [range];
+	    unsigned  label = rs.range_label [range];
+	    unsigned  last  = 1;
+	    u_word_t *mapping;
+	    unsigned  max_value;
+	    unsigned  edge;
+	    word_t    domain;
+
+	    if (wfa->delta_state [state] ||
+		wfa->mv_tree [state][label].type != NONE)
+	       mapping = mapping2;
+	    else
+	       mapping = mapping1;
+	    
+	    max_value = mapping [rs.range_max_domain [range]];
+	    
+	    for (edge = 0; isedge (domain = wfa->into [state][label][edge]);
+		 edge++)
+	       if (domain > 0)
+	       {
+		  total++;
+		  if (max_value - last)
+		  {
+		     write_bin_code (mapping [domain] - last,
+				     max_value - last, output);
+		     last = mapping [domain] + 1;
+		  }
+	       }
+	 }
+
+      debug_message ("delta-index:  %5d bits. (%5d symbols => %5.2f bps)",
+		     bits_processed (output) - bits, total,
+		     total > 0 ? ((bits_processed (output) - bits) /
+				  (double) total) : 0);
+      Free (mapping1);
+      Free (mapping2);
+   }
+   
+   Free (rs.range_state);
+   Free (rs.range_label);
+   Free (rs.range_max_domain);
+   Free (rs.range_subdivided);
+
+   return total;
+}
+
+static unsigned
+column_0_encoding (const wfa_t *wfa, unsigned last_row, bitfile_t *output)
+/*
+ *  Write column 0 of the transition matrices of the 'wfa' to stream 'output'
+ *  with quasi arithmetic coding.
+ *  All rows from 'wfa->basis_states' up to 'last_row' are decoded.
+ *
+ *  Return value:
+ *	number of non-zero matrix elements (WFA edges)
+ */
+{
+   u_word_t  high;			/* Start of the current code range */
+   u_word_t  low;			/* End of the current code range */
+   unsigned *prob;			/* probability array */
+   unsigned  row;			/* current matrix row */
+   unsigned  label;			/* current matrix label */
+   unsigned  underflow;			/* Underflow bits */
+   unsigned  index;			/* probability index */
+   unsigned  total = 0;			/* Number of '1' elements */
+   unsigned  bits  = bits_processed (output);
+
+   /*
+    *  Compute the probability array:
+    *  prob[] = { 1/2, 1/2, 1/4, 1/4, 1/4, 1/4,
+    *             1/8, ... , 1/16, ..., 1/(MAXPROB+1)}
+    */
+   {
+      unsigned n;
+      unsigned exp;			/* current exponent */
+      
+      prob = Calloc (1 << (MAX_PROB + 1), sizeof (unsigned));
+   
+      for (index = 0, n = MIN_PROB; n <= MAX_PROB; n++)
+	 for (exp = 0; exp < 1U << n; exp++, index++)
+	    prob [index] = n;
+   }
+   
+   high      = HIGH;			/* 1.0 */
+   low       = LOW;			/* 0.0 */
+   underflow = 0;			/* no underflow bits */
+
+   index = 0;
+
+   /*
+    *  Encode column 0 with a quasi arithmetic coder (QAC).
+    *  Advantage of this QAC with respect to a binary AC:
+    *  Instead of using time consuming multiplications and divisions
+    *  to compute the probability of the most probable symbol (MPS) and
+    *  the range of the interval, a table look up procedure linked
+    *  with a shift operation is used for both computations.
+    */
+   for (row = wfa->basis_states; row <= last_row; row++)
+      for (label = 0; label < MAXLABELS; label++)
+	 if (isrange (wfa->tree [row][label]))
+	 {
+	    if (wfa->into [row][label][0] != 0)
+	    {
+	       /*
+		*  encode the MPS '0'
+		*/
+	       high = high - ((high - low) >> prob [index]) - 1;
+	       RESCALE_OUTPUT_INTERVAL;
+	       
+	       if (index < 1020)
+		  index++;
+	    }
+	    else
+	    {
+	       /*
+		*  encode the LPS '1'
+		*/
+	       low = high - ((high - low) >> prob [index]);
+
+	       RESCALE_OUTPUT_INTERVAL;
+	       
+	       total++;
+	       index >>= 1;
+	    }
+	 }
+   /*
+    *  Flush the quasi-arithmetic encoder
+    */
+   low = high;
+
+   RESCALE_OUTPUT_INTERVAL;
+   
+   OUTPUT_BYTE_ALIGN (output);
+
+   Free (prob);
+
+   debug_message ("delta-state0: %5d bits. (%5d symbols => %5.2f bps)",
+		  bits_processed (output) - bits, total,
+		  total > 0 ? ((bits_processed (output) - bits) /
+			       (double) total) : 0);
+
+   return total;
+}   
+
+static unsigned
+chroma_encoding (const wfa_t *wfa, bitfile_t *output)
+/*
+ *  Write transition matrices of 'wfa' states which are part of the
+ *  chroma channels Cb and Cr to stream 'output'.
+ *
+ *  Return value:
+ *	number of non-zero matrix elements (WFA edges)
+ */
+{
+
+   unsigned  domain;			/* current domain, counter */
+   unsigned  label;			/* current label */
+   unsigned  total = 0;			/* number of '1' elements */
+   u_word_t  high;			/* Start of the current code range */
+   u_word_t  low;			/* End of the current code range */
+   unsigned  underflow;			/* underflow bits */
+   unsigned *prob;			/* probability array */
+   unsigned  index;			/* probability index, counter */
+   unsigned  next_index;		/* probability of last domain */
+   unsigned  row;			/* current matrix row */
+   word_t   *y_domains;
+   unsigned  count = 0;			/* number of transitions for part 1 */
+   unsigned  bits  = bits_processed (output);
+   
+   /*
+    *  Compute the asymmetric probability array
+    *  prob[] = { 1/2, 1/2, 1/4, 1/4, 1/4, 1/4,
+    *                     1/8, ... , 1/16, ..., 1/(MAXPROB+1)}
+    */
+   {
+      unsigned n;
+      unsigned exp;			/* current exponent */
+      
+      prob = Calloc (1 << (MAX_PROB + 1), sizeof (unsigned));
+   
+      for (index = 0, n = MIN_PROB; n <= MAX_PROB; n++)
+	 for (exp = 0; exp < 1U << n; exp++, index++)
+	    prob [index] = n;
+   }
+   
+   high      = HIGH;			/* 1.0 */
+   low       = LOW;			/* 0.0 */
+   underflow = 0;			/* no underflow bits */
+
+   next_index = index = 0;
+
+   y_domains = compute_hits (wfa->basis_states,
+			     wfa->tree [wfa->tree [wfa->root_state][0]][0],
+			     wfa->wfainfo->chroma_max_states, wfa);
+
+   /*
+    *  First of all, read all matrix columns given in the list 'y_domains'
+    *  which note all admitted domains.
+    *  These matrix elements are stored with QAC (see column_0_encoding ()).
+    */
+   for (domain = 0; y_domains [domain] != -1; domain++)
+   {
+      bool_t save_index = YES;		/* YES: store current prob. index */
+      
+      row   = wfa->tree [wfa->tree [wfa->root_state][0]][0] + 1;
+      index = next_index;
+	 
+      for (; row < wfa->states; row++)
+      {
+	 for (label = 0; label < MAXLABELS; label++)
+	    if (isrange (wfa->tree [row][label]))
+	    {
+	       unsigned	edge;
+	       int	into;
+	       bool_t    match;		/* approx with current domain found */
+	       
+	       for (match = NO, edge = 0;
+		    isedge (into = wfa->into [row][label][edge])
+			    && (unsigned) into < row;
+		    edge++)
+		  if (into == y_domains [domain]
+		      && into != wfa->y_state [row][label])
+		     match = YES;
+	       if (!match)
+	       {
+		  /*
+		   *  encode the MPS '0'
+		   */
+		  high = high - ((high - low) >> prob [index]) - 1;
+
+		  RESCALE_OUTPUT_INTERVAL;
+		     
+		  if (index < 1020)
+		     index++;
+	       }
+	       else
+	       {
+		  /*
+		   *  encode the LPS '1'
+		   */
+		  low = high - ((high - low) >> prob [index]);
+
+		  RESCALE_OUTPUT_INTERVAL;
+		     
+		  total++;
+		  index >>= 1;
+	       }
+	    }
+	 if (save_index)
+	 {
+	    next_index = index;
+	    save_index = NO;
+	 }
+      }
+   }
+
+   debug_message ("CbCr_matrix:  %5d bits. (%5d symbols => %5.2f bps)",
+		  bits_processed (output) - bits, total,
+		  total > 0 ? ((bits_processed (output) - bits) /
+			       (double) total) : 0);
+   count = total;
+   bits  = bits_processed (output);
+   
+   /*
+    *  Encode the additional column which indicates whether there
+    *  are transitions to a state with same spatial coordinates
+    *  in the Y component.
+    *
+    *  Again, quasi arithmetic coding is used for this task.
+    */
+
+   next_index = index = 0;
+
+   for (row = wfa->tree [wfa->tree [wfa->root_state][0]][0] + 1;
+	row < wfa->states; row++)
+      for (label = 0; label < MAXLABELS; label++)
+	 if (!wfa->y_column [row][label])
+	 {
+	    /*
+	     *  encode the MPS '0'
+	     */
+	    high = high - ((high - low) >> prob [index]) - 1;
+
+	    RESCALE_OUTPUT_INTERVAL;
+	    
+	    if (index < 1020)
+	       index++;
+	 }
+	 else
+	 {
+	    /*
+	     *  encode the LPS '1'
+	     */
+	    low = high - ((high - low) >> prob [index]);
+
+	    RESCALE_OUTPUT_INTERVAL;
+
+	    index >>= 1;
+	    total++;
+	 }
+
+   /*
+    *  Flush the quasi-arithmetic encoder
+    */
+   low = high;
+
+   RESCALE_OUTPUT_INTERVAL;
+   OUTPUT_BYTE_ALIGN (output);
+
+   debug_message ("Yreferences:  %5d bits. (%5d symbols => %5.2f bps)",
+		  bits_processed (output) - bits, total - count,
+		  total - count > 0 ? ((bits_processed (output) - bits) /
+				       (double) (total - count)) : 0);
+
+   Free (prob);
+   Free (y_domains);
+   
+   return total;
+}
diff --git a/converter/other/fiasco/output/matrices.h b/converter/other/fiasco/output/matrices.h
new file mode 100644
index 00000000..f880fef8
--- /dev/null
+++ b/converter/other/fiasco/output/matrices.h
@@ -0,0 +1,28 @@
+/*
+ *  matrices.h
+ *
+ *  Written by:		Ullrich Hafner
+ *		
+ *  This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec)
+ *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
+ */
+
+/*
+ *  $Date: 2000/06/14 20:50:31 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#ifndef _MATRICES_H
+#define _MATRICES_H
+
+#include "wfa.h"
+#include "bit-io.h"
+
+unsigned
+write_matrices (bool_t use_normal_domains, bool_t use_delta_domains,
+		const wfa_t *wfa, bitfile_t *output);
+
+#endif /* _MATRICES_H */
+
diff --git a/converter/other/fiasco/output/mc.c b/converter/other/fiasco/output/mc.c
new file mode 100644
index 00000000..afff586b
--- /dev/null
+++ b/converter/other/fiasco/output/mc.c
@@ -0,0 +1,250 @@
+/*
+ *  mc.c:		Output of motion compensation	
+ *
+ *  Written by:		Michael Unger
+ *			Ullrich Hafner
+ *		
+ *  This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec)
+ *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
+ */
+
+/*
+ *  $Date: 2000/06/14 20:50:31 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#include "config.h"
+
+#include "types.h"
+#include "macros.h"
+#include "error.h"
+
+#include "wfa.h"
+#include "bit-io.h"
+#include "mvcode.h"
+
+#include "mc.h"
+
+/*****************************************************************************
+
+			     local variables
+  
+*****************************************************************************/
+
+static unsigned p_frame_codes [4][2] =
+/*
+ *  Code values and bits for P-frame prediction
+ *  NONE,  FORWARD
+ */
+{
+   {1, 1}, {0, 1}, {0, 0}, {0, 0} 
+};
+
+static unsigned b_frame_codes [4][2] =
+/*
+ *  Code values and bits for B-frame prediction
+ *  NONE,  FORWARD,  BACKWARD, INTERPOLATED
+ */
+{
+   {1, 1}, {000, 3}, {001, 3}, {01, 2} 
+};
+
+enum vlc_e {CODE = 0, BITS = 1};
+
+/*****************************************************************************
+
+				prototypes
+  
+*****************************************************************************/
+
+static void
+encode_mc_tree (unsigned max_state, frame_type_e frame_type, const wfa_t *wfa,
+	       bitfile_t *output);
+static void
+encode_mc_coords (unsigned max_state, const wfa_t *wfa, bitfile_t *output);
+
+/*****************************************************************************
+
+				public code
+  
+*****************************************************************************/
+
+void
+write_mc (frame_type_e frame_type, const wfa_t *wfa, bitfile_t *output)
+{
+   unsigned max_state = wfa->wfainfo->color
+			? wfa->tree[wfa->tree[wfa->root_state][0]][0]
+			: wfa->states;
+
+   encode_mc_tree (max_state, frame_type, wfa, output);
+   encode_mc_coords (max_state, wfa, output);
+}
+
+/*****************************************************************************
+
+				private code
+  
+*****************************************************************************/
+
+static void
+encode_mc_tree (unsigned max_state, frame_type_e frame_type, const wfa_t *wfa,
+		bitfile_t *output)
+/*
+ *  Write tree of motion compensation decisions to the 'output' stream.
+ *  Depending on 'frame_type' different decoding methods are used.
+ *  'max_state' is the last state with motion compensation infos.
+ *
+ *  No return value.
+ */
+{
+   unsigned  label;			/* current label */
+   unsigned  state;			/* current state */
+   unsigned  total = 0;			/* number of motion tree decisions */
+   unsigned  queue [MAXSTATES];		/* state numbers in BFO */
+   unsigned  current;			/* current node to process */
+   unsigned  last;			/* last node (update every new node) */
+   mc_type_e type;			/* type of motion compensation */
+   unsigned	     (*mc_tree_codes)[2]; /* pointer to VLC table */
+   unsigned  bits  = bits_processed (output); /* number of bits used */
+   
+   if (frame_type == P_FRAME)
+      mc_tree_codes = p_frame_codes;	/* binary code */
+   else 
+      mc_tree_codes = b_frame_codes;	/* variable length code */
+   
+   /*
+    *  Traverse tree in breadth first order (starting at
+    *  level 'wfa->p_max_level'). Use a queue to store the childs
+    *  of each node ('last' is the next free queue element).  
+    */
+
+   for (last = 0, state = wfa->basis_states; state < max_state; state++)
+      if (wfa->level_of_state [state] - 1 == (int) wfa->wfainfo->p_max_level)
+	 queue [last++] = state;	/* init level = 'mc_max_level' */
+   
+   for (current = 0; current < last; current++)
+      for (label = 0; label < MAXLABELS; label++)
+      {
+	 state = queue [current];
+	 type  = wfa->mv_tree [state][label].type;
+	 if (wfa->x [state][label]
+	     + width_of_level (wfa->level_of_state [state] - 1)
+	     <= wfa->wfainfo->width
+	     &&
+	     wfa->y [state][label]
+	     + height_of_level (wfa->level_of_state [state] - 1)
+	     <= wfa->wfainfo->height)
+	 {
+	    put_bits (output, mc_tree_codes [type][CODE],
+		      mc_tree_codes [type][BITS]);
+	    total++;
+	 }
+	 if (type == NONE && !isrange (wfa->tree [state][label]) &&
+	     wfa->level_of_state [state] - 1 >=
+	     (int) wfa->wfainfo->p_min_level)
+	    queue [last++] = wfa->tree [state][label]; /* append child */
+	 
+      }
+
+   OUTPUT_BYTE_ALIGN (output);
+   debug_message ("mc-tree:      %5d bits. (%5d symbols => %5.2f bps)",
+		  bits_processed (output) - bits, total,
+		  total > 0 ? ((bits_processed (output) - bits) /
+			       (double) total) : 0);
+}
+
+static void
+encode_mc_coords (unsigned max_state, const wfa_t *wfa, bitfile_t *output)
+/*
+ *  Write motion vector coordinates to the 'output' stream. They are stored
+ *  with the static Huffman code of the MPEG and H.263 standards.
+ *  'max_state' is the last state with motion compensation infos.
+ *
+ *  No return value.
+ */
+{
+   unsigned  state;			/* current state */
+   unsigned  label;			/* current label */
+   unsigned  level_count [MAXLEVEL];	/* number of mv per level */
+   unsigned  level;			/* counter */
+   unsigned  ftotal = 0;		/* #forward motion tree decisions */
+   unsigned  btotal = 0;		/* #backward decisions */
+   unsigned  itotal = 0;		/* #interpolated decisions */
+   unsigned  bits   = bits_processed (output); /* number of bits used */
+   unsigned  sr     = wfa->wfainfo->search_range; /* search range */
+   
+   for (level = wfa->wfainfo->p_max_level;
+	level >= wfa->wfainfo->p_min_level; level--)
+      level_count [level] = 0;
+   
+   for (state = wfa->basis_states; state < max_state; state++)
+      for (label = 0; label < MAXLABELS; label++)
+      {
+	 mv_t *mv = &wfa->mv_tree[state][label]; /* motion vector info */
+	 
+	 if (mv->type != NONE)
+	 {
+	    level_count [wfa->level_of_state [state] - 1]++;
+	    switch (mv->type)
+	    {
+	       case FORWARD:
+		  put_bits (output,
+			    mv_code_table[(mv->fx + sr)][CODE],
+			    mv_code_table[(mv->fx + sr)][BITS]);
+		  put_bits (output,
+			    mv_code_table[(mv->fy + sr)][CODE],
+			    mv_code_table[(mv->fy + sr)][BITS]);
+		  ftotal++;
+		  break;
+	       case BACKWARD:
+		  put_bits (output,
+			    mv_code_table[(mv->bx + sr)][CODE],
+			    mv_code_table[(mv->bx + sr)][BITS]);
+		  put_bits (output,
+			    mv_code_table[(mv->by + sr)][CODE],
+			    mv_code_table[(mv->by + sr)][BITS]);
+		  btotal++;
+		  break;
+	       case INTERPOLATED:
+		  put_bits (output,
+			    mv_code_table[(mv->fx + sr)][CODE],
+			    mv_code_table[(mv->fx + sr)][BITS]);
+		  put_bits (output,
+			    mv_code_table[(mv->fy + sr)][CODE],
+			    mv_code_table[(mv->fy + sr)][BITS]);
+		  put_bits (output,
+			    mv_code_table[(mv->bx + sr)][CODE],
+			    mv_code_table[(mv->bx + sr)][BITS]);
+		  put_bits (output,
+			    mv_code_table[(mv->by + sr)][CODE],
+			    mv_code_table[(mv->by + sr)][BITS]);
+		  itotal++;
+		  break;
+	       default:
+		  break;
+	    }
+	 }
+      }
+
+   OUTPUT_BYTE_ALIGN (output);
+   
+   debug_message ("Motion compensation: %d forward, %d backward, "
+		  "%d interpolated", ftotal, btotal, itotal);
+
+   for (level = wfa->wfainfo->p_max_level;
+	level >= wfa->wfainfo->p_min_level; level--)
+      debug_message ("Level %d: %d motion vectors", level, level_count[level]);
+   
+   {
+      unsigned  total = ftotal * 2 + btotal * 2 + itotal * 4;
+
+      debug_message ("mv-coord:     %5d bits. (%5d symbols => %5.2f bps)",
+		     bits_processed (output) - bits, total,
+		     total > 0 ? ((bits_processed (output) - bits) /
+				  (double) total) : 0);
+   }
+
+   return;
+}
diff --git a/converter/other/fiasco/output/mc.h b/converter/other/fiasco/output/mc.h
new file mode 100644
index 00000000..b7843fd8
--- /dev/null
+++ b/converter/other/fiasco/output/mc.h
@@ -0,0 +1,28 @@
+/*
+ *  mc.h
+ *
+ *  Written by:		Michael Unger
+ *			Ullrich Hafner
+ *		
+ *  This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec)
+ *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
+ */
+
+/*
+ *  $Date: 2000/06/14 20:50:31 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#ifndef _MC_H
+#define _MC_H
+
+#include "wfa.h"
+#include "bit-io.h"
+
+void
+write_mc (frame_type_e frame_type, const wfa_t *wfa, bitfile_t *output);
+
+#endif /* not _MC_H */
+
diff --git a/converter/other/fiasco/output/nd.c b/converter/other/fiasco/output/nd.c
new file mode 100644
index 00000000..a09ff762
--- /dev/null
+++ b/converter/other/fiasco/output/nd.c
@@ -0,0 +1,244 @@
+/*
+ *  nd.c:		Output of prediction tree	
+ *
+ *  Written by:		Ullrich Hafner
+ *		
+ *  This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec)
+ *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
+ */
+
+/*
+ *  $Date: 2000/06/14 20:50:31 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#include "config.h"
+
+#include "types.h"
+#include "macros.h"
+#include "error.h"
+
+#include "wfa.h"
+#include "arith.h"
+#include "misc.h"
+#include "bit-io.h"
+#include "rpf.h"
+#include "list.h"
+
+#include "nd.h"
+
+/*****************************************************************************
+
+				prototypes
+  
+*****************************************************************************/
+
+static unsigned
+encode_nd_tree (const wfa_t *wfa, bitfile_t *output);
+static void
+encode_nd_coefficients (unsigned total, const wfa_t *wfa, bitfile_t *output);
+
+/*****************************************************************************
+
+				public code
+  
+*****************************************************************************/
+
+void
+write_nd (const wfa_t *wfa, bitfile_t *output)
+/*
+ *  Write prediction information of 'wfa' to given stream 'output'.
+ *  Coefficients are quantized with model 'p_rpf'.
+ *
+ *  No return value.
+ */
+{
+   unsigned total = encode_nd_tree (wfa, output);
+   
+   if (total > 0)
+      encode_nd_coefficients (total, wfa, output);
+}
+
+/*****************************************************************************
+
+				private code
+  
+*****************************************************************************/
+
+static unsigned
+encode_nd_tree (const wfa_t *wfa, bitfile_t *output)
+/*
+ *  Write prediction tree of 'wfa' to given stream 'output'. 
+ *
+ *  No return value.
+ */
+{
+   lqueue_t *queue;			/* queue of states */
+   int	     state, next;		/* state and its current child */
+   unsigned  used, not_used;		/* counter ND used/not used */
+   u_word_t  low;			/* Start of the current code range */
+   u_word_t  high;			/* End of the current code range */
+   u_word_t  underflow;			/* Number of underflow bits pending */
+   u_word_t  sum0, sum1;		/* Probability model */
+   unsigned  bits = bits_processed (output);
+
+   used = not_used = 0;
+   
+   /*
+    *  Initialize arithmetic coder
+    */
+   low       = 0;
+   high      = 0xffff;
+   underflow = 0;
+   sum0      = 1;
+   sum1      = 11;
+   
+   queue = alloc_queue (sizeof (int));
+   state = wfa->root_state;
+   queue_append (queue, &state);
+   
+   /*
+    *  Traverse the WFA tree in breadth first order (using a queue).
+    */
+   while (queue_remove (queue, &next))
+   {
+      unsigned label;
+      
+      if (wfa->level_of_state [next] > wfa->wfainfo->p_max_level + 1)
+      {
+	 /*
+	  *  Nondetermismn is not allowed at levels larger than
+	  *  'wfa->wfainfo->p_max_level'.
+	  */
+	 for (label = 0; label < MAXLABELS; label++)
+	    if (ischild (state = wfa->tree [next][label]))
+	       queue_append (queue, &state); /* continue with childs */
+      }
+      else if (wfa->level_of_state [next] > wfa->wfainfo->p_min_level)
+      {
+	 for (label = 0; label < MAXLABELS; label++)
+	    if (ischild (state = wfa->tree [next][label]))
+	    {
+	       unsigned range;		/* Current interval range */
+
+	       if (isedge (wfa->into [next][label][0])) /* prediction used */
+	       {
+		  used++;
+		  
+		  /*
+		   *  Encode a '1' symbol
+		   */
+		  range =  (high - low) + 1;
+		  low   = low + (u_word_t) ((range * sum0) / sum1);
+		  RESCALE_OUTPUT_INTERVAL;
+	       }
+	       else			/* no predict., continue with childs */
+	       {
+		  not_used++;
+		  if (wfa->level_of_state [state] > wfa->wfainfo->p_min_level)
+		     queue_append (queue, &state);
+		  
+		  /*
+		   *  Encode a '0' symbol
+		   */
+		  range =  (high - low) + 1;
+		  high  = low + (u_word_t) ((range * sum0) / sum1 - 1);
+		  RESCALE_OUTPUT_INTERVAL;
+		  sum0++;
+	       }
+	       /*
+		*  Update the frequency counts
+		*/
+	       sum1++;
+	       if (sum1 > 50)		/* Scale the symbol frequencies */
+	       {
+		  sum0 >>= 1;
+		  sum1 >>= 1;
+		  if (!sum0)
+		     sum0 = 1;
+		  if (sum0 >= sum1)
+		     sum1 = sum0 + 1;
+	       }
+	    }
+	 
+      }
+   }
+   free_queue (queue);
+
+   /*
+    *  Flush the quasi-arithmetic encoder
+    */
+   low = high;
+   RESCALE_OUTPUT_INTERVAL;
+   OUTPUT_BYTE_ALIGN (output);
+
+   debug_message ("%d nd fields: %d used nd, %d used not nd", used + not_used,
+		  used, not_used);
+   {
+      unsigned total = used + not_used;
+      
+      debug_message ("nd-tree:      %5d bits. (%5d symbols => %5.2f bps)",
+		     bits_processed (output) - bits, total,
+		     total > 0 ? ((bits_processed (output) - bits) /
+				  (double) total) : 0);
+   }
+
+   return used;
+}
+
+static void
+encode_nd_coefficients (unsigned total, const wfa_t *wfa, bitfile_t *output)
+/*
+ *  Write #'total' weights of nondeterministic part of 'wfa' to given 'output'
+ *  stream. Coefficients are stored with arithmetic coding (the model is
+ *  given by 'p_rpf').
+ *
+ *  No return value.
+ */
+{
+   unsigned bits = bits_processed (output);
+
+   {
+      unsigned *coefficients;		/* array of factors to encode */
+      unsigned *ptr;			/* pointer to current factor */
+      unsigned	state, label, edge;
+      word_t	domain;
+      
+      ptr = coefficients  = Calloc (total, sizeof (unsigned));
+
+      for (state = wfa->basis_states; state < wfa->states; state++)
+	 for (label = 0; label < MAXLABELS; label++)
+	    if (ischild (wfa->tree [state][label])
+		&& isedge (wfa->into [state][label][0]))
+	       for (edge = 0; isedge (domain = wfa->into [state][label][edge]);
+		    edge++)
+	       {
+		  if (ptr - coefficients >= (int) total)
+		     error ("Can't write more than %d coefficients.", total);
+
+		  *ptr++ = rtob (wfa->weight [state][label][edge],
+				 wfa->wfainfo->dc_rpf);
+	       }
+
+      /*
+       *  Encode array of coefficients with arithmetic coding
+       */
+      {
+	 const int scaling = 50;	/* scaling factor of prob. model */
+	 unsigned  c_symbols = 1 << (wfa->wfainfo->dc_rpf->mantissa_bits + 1);
+
+	 encode_array (output, coefficients, NULL, &c_symbols, 1,
+		       total, scaling);
+      }
+      
+      debug_message ("nd-factors:   %5d bits. (%5d symbols => %5.2f bps)",
+		     bits_processed (output) - bits, total,
+		     total ? ((bits_processed (output) - bits)
+			      / (double) total) : 0);
+      Free (coefficients);
+   }
+}
+
+
diff --git a/converter/other/fiasco/output/nd.h b/converter/other/fiasco/output/nd.h
new file mode 100644
index 00000000..600b3d73
--- /dev/null
+++ b/converter/other/fiasco/output/nd.h
@@ -0,0 +1,27 @@
+/*
+ *  nd.h
+ *
+ *  Written by:		Ullrich Hafner
+ *		
+ *  This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec)
+ *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
+ */
+
+/*
+ *  $Date: 2000/06/14 20:50:31 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#ifndef _ND_H
+#define _ND_H
+
+#include "wfa.h"
+#include "bit-io.h"
+
+void
+write_nd (const wfa_t *wfa, bitfile_t *output);
+
+#endif /* not _ND_H */
+
diff --git a/converter/other/fiasco/output/tree.c b/converter/other/fiasco/output/tree.c
new file mode 100644
index 00000000..0056d7dd
--- /dev/null
+++ b/converter/other/fiasco/output/tree.c
@@ -0,0 +1,176 @@
+/*
+ *  tree.c:		Output of bintree partitioning
+ *
+ *  Written by:		Ullrich Hafner
+ *		
+ *  This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec)
+ *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
+ */
+
+/*
+ *  $Date: 2000/06/14 20:50:31 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#include "config.h"
+
+#include "types.h"
+#include "macros.h"
+#include "error.h"
+
+#include "wfa.h"
+#include "bit-io.h"
+#include "arith.h"
+#include "misc.h"
+
+#include "tree.h"
+
+/*****************************************************************************
+
+				prototypes
+  
+*****************************************************************************/
+
+static void
+encode_tree (bitfile_t *output, const byte_t *data, unsigned n_data,
+	     unsigned scaling, u_word_t sum0, u_word_t sum1);
+
+/*****************************************************************************
+
+				public code
+  
+*****************************************************************************/
+
+void
+write_tree (const wfa_t *wfa, bitfile_t *output)
+/*
+ *  Write bintree to stream 'output'.
+ *  Traverse tree in breadth first order and save a '1' for each child
+ *  and a '0' for each range image.
+ *
+ *  No return value.
+ */
+{
+   unsigned  queue [MAXSTATES];		/* state numbers in BFO */
+   unsigned  current;			/* current node to process */
+   unsigned  last;			/* last node (update every new node) */
+   unsigned  label;			/* current label */
+   int	     into;			/* next child */
+   byte_t   *tree_string;		/* bitstring to encode */
+   unsigned  total = 0;			/* number of ranges */
+   unsigned  bits  = bits_processed (output); /* number of bits */
+
+   /*
+    *  Traverse tree in breadth first order. Use a queue to store
+    *  the childs of each node ('last' is the next free queue element).
+    *  The first element ('current') of this queue will get the new parent
+    *  node. 
+    */
+   tree_string = Calloc (MAXSTATES * MAXLABELS, sizeof (byte_t));
+   queue [0] = wfa->root_state;
+   for (last = 1, current = 0; current < last; current++)
+      for (label = 0; label < MAXLABELS; label++)
+	 if (!isrange (into = wfa->tree [queue[current]][label])) /* child ? */
+	 {
+	    queue [last++]        = into;
+	    tree_string [total++] = 1;
+	 }
+	 else				/* or range ? */
+	    tree_string [total++] = 0;
+
+   if (total != (wfa->states - wfa->basis_states) * MAXLABELS)
+      error ("total [%d] != (states - basis_states) * 2 [%d]", total,
+	     (wfa->states - wfa->basis_states) * MAXLABELS);
+   
+   {
+      unsigned scale = total / 20 ;
+
+      encode_tree (output, tree_string, total, scale, 1, 11);
+   }
+
+   Free (tree_string);
+   
+   debug_message ("tree:         %5d bits. (%5d symbols => %5.2f bps)",
+		  bits_processed (output) - bits, total,
+		  total > 0 ? ((bits_processed (output) - bits)
+			       / (double) total) : 0);
+}
+
+/*****************************************************************************
+
+				private code
+  
+*****************************************************************************/
+
+static void
+encode_tree (bitfile_t *output, const byte_t *data, unsigned n_data,
+	     unsigned scaling, u_word_t sum0, u_word_t sum1)
+/*
+ *  Encode bintree data with adaptive binary arithmetic coding.
+ *  Write 'n_data' output symbols stored in 'data' to stream 'output'.
+ *  Rescale probability model after every 'scaling' symbols.
+ *  Initial counts are given by 'sum0' and 'sum1'.
+ *
+ *  No return value.
+ */
+{
+   u_word_t low;			/* Start of the current code range */
+   u_word_t high;			/* End of the current code range */
+   u_word_t underflow;			/* Number of underflow bits pending */
+   unsigned n;				/* Data counter */
+
+   low       = 0;
+   high      = 0xffff;
+   underflow = 0;
+
+   for (n = n_data; n; n--)
+   {
+      unsigned range;			/* Current interval range */
+      
+      if (!*data++)
+      {
+	 /*
+	  *  encode a '0'
+	  */
+	 range =  (high - low) + 1;
+	 high  = low + (u_word_t) ((range * sum0) / sum1 - 1);
+
+	 RESCALE_OUTPUT_INTERVAL;
+
+	 sum0++;
+      }
+      else
+      {
+	 /*
+	  *  encode a '1'
+	  */
+	 range =  (high - low) + 1;
+	 low   = low + (u_word_t) ((range * sum0) / sum1);
+
+	 RESCALE_OUTPUT_INTERVAL;
+      }
+      /*
+       *  Update the frequency counts
+       */
+      sum1++;
+      if (sum1 > scaling) /* Scale the symbol frequencies */
+      {
+	 sum0 >>= 1;
+	 sum1 >>= 1;
+	 if (!sum0)
+	    sum0 = 1;
+	 if (sum0 >= sum1)
+	    sum1 = sum0 + 1;
+      }
+   }
+   /*
+    *  Flush the quasi-arithmetic encoder
+    */
+   low = high;
+
+   RESCALE_OUTPUT_INTERVAL;
+
+   OUTPUT_BYTE_ALIGN (output);
+}
diff --git a/converter/other/fiasco/output/tree.h b/converter/other/fiasco/output/tree.h
new file mode 100644
index 00000000..6f8a3800
--- /dev/null
+++ b/converter/other/fiasco/output/tree.h
@@ -0,0 +1,27 @@
+/*
+ *  tree.h
+ *
+ *  Written by:		Ullrich Hafner
+ *		
+ *  This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec)
+ *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
+ */
+
+/*
+ *  $Date: 2000/06/14 20:50:31 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#ifndef _TREE_H
+#define _TREE_H
+
+#include "wfa.h"
+#include "bit-io.h"
+
+void
+write_tree (const wfa_t *wfa, bitfile_t *output);
+
+#endif /* not _TREE_H */
+
diff --git a/converter/other/fiasco/output/weights.c b/converter/other/fiasco/output/weights.c
new file mode 100644
index 00000000..085a1f00
--- /dev/null
+++ b/converter/other/fiasco/output/weights.c
@@ -0,0 +1,200 @@
+/*
+ *  weights.c:		Output of weights
+ *
+ *  Written by:		Ullrich Hafner
+ *		
+ *  This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec)
+ *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
+ */
+
+/*
+ *  $Date: 2000/06/14 20:50:31 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#include "config.h"
+
+#include "types.h"
+#include "macros.h"
+#include "error.h"
+
+#include "wfa.h"
+#include "misc.h"
+#include "bit-io.h"
+#include "arith.h"
+#include "wfalib.h"
+
+#include "weights.h"
+
+/*****************************************************************************
+
+				public code
+  
+*****************************************************************************/
+
+void
+write_weights (unsigned total, const wfa_t *wfa, bitfile_t *output)
+/*
+ *  Traverse the transition matrices of the 'wfa' and write #'total'
+ *  weights != 0 to stream 'output'.
+ *
+ *  No return value.
+ */
+{
+   unsigned  state, label;		/* current label */
+   unsigned  offset1, offset2;		/* model offsets. */
+   unsigned  offset3, offset4;		/* model offsets. */
+   unsigned *weights_array;		/* array of weights to encode */
+   unsigned *wptr;			/* pointer to current weight */
+   unsigned *level_array;		/* array of corresponding levels */
+   unsigned *lptr;			/* pointer to current corr. level */
+   int	     min_level, max_level;	/* min and max range level */
+   int	     d_min_level, d_max_level; 	/* min and max delta range level */
+   bool_t    dc, d_dc;			/* true if dc or delta dc are used */
+   bool_t    delta_approx = NO;		/* true if delta has been used */
+   unsigned  delta_count  = 0;		/* number of delta ranges */
+   unsigned  bits 	  = bits_processed (output);
+   
+   /*
+    *  Check whether delta approximation has been used
+    */
+   for (state = wfa->basis_states; state < wfa->states; state++)
+      if (wfa->delta_state [state])
+      {
+	 delta_approx = YES;
+	 break;
+      }
+   
+   /*
+    *  Generate array of corresponding levels (context of probability model)
+    */
+   min_level = d_min_level = MAXLEVEL;
+   max_level = d_max_level = 0;
+   dc 	     = d_dc	   = NO;
+   
+   for (state = wfa->basis_states; state < wfa->states; state++)
+      for (label = 0; label < MAXLABELS; label++)
+         if (isrange (wfa->tree [state][label]))
+	 {
+	    if (delta_approx && wfa->delta_state [state]) /* delta approx. */
+	    {
+	       d_min_level = min (d_min_level,
+				  wfa->level_of_state [state] - 1);
+	       d_max_level = max (d_max_level,
+				  wfa->level_of_state [state] - 1);
+	       if (wfa->into [state][label][0] == 0)
+		  d_dc = YES;
+	    }
+	    else
+	    {
+	       min_level = min (min_level, wfa->level_of_state [state] - 1);
+	       max_level = max (max_level, wfa->level_of_state [state] - 1);
+	       if (wfa->into [state][label][0] == 0)
+		  dc = YES;
+	    }
+	 }
+   if (min_level > max_level)		/* no lc found */
+      max_level = min_level - 1;
+   if (d_min_level > d_max_level)
+      d_max_level = d_min_level - 1;
+
+   /*
+    *  Context model:
+    *		0		DC weight
+    *		1		Delta DC weight
+    *		2-k		normal weights per level
+    *		k+1 - m		Delta weights per level
+    */
+
+   offset1 = dc ? 1 : 0;
+   offset2 = offset1 + (d_dc ? 1 : 0);
+   offset3 = offset2 + (max_level - min_level + 1);
+   offset4 = offset3 + (d_max_level - d_min_level + 1);
+   
+   /*
+    *  Weights are encoded as follows:
+    *  all weights of state n
+    *     sorted by label
+    *        sorted by domain number
+    */
+
+   wptr = weights_array = Calloc (total, sizeof (unsigned));
+   lptr = level_array   = Calloc (total, sizeof (unsigned));
+
+   for (state = wfa->basis_states; state < wfa->states; state++)
+      for (label = 0; label < MAXLABELS; label++)
+         if (isrange (wfa->tree [state][label]))
+	 {
+	    int	edge;			/* current edge */
+	    int	domain;			/* current domain (context of model) */
+	    
+            for (edge = 0; isedge (domain = wfa->into [state][label][edge]);
+		 edge++)
+            {
+	       if (wptr - weights_array >= (int) total)
+		  error ("Can't write more than %d weights.", total);
+	       if (domain)		/* not DC component */
+	       {
+		  if (delta_approx && wfa->delta_state [state]) /* delta */
+		  {
+		     *wptr++ = rtob (wfa->weight [state][label][edge],
+				     wfa->wfainfo->d_rpf);
+		     *lptr++ = offset3
+			       + wfa->level_of_state [state] - 1 - d_min_level;
+		     delta_count++;
+		  }
+		  else
+		  {
+		     *wptr++ = rtob (wfa->weight [state][label][edge],
+				     wfa->wfainfo->rpf);
+		     *lptr++ = offset2
+			       + wfa->level_of_state [state] - 1 - min_level;
+		  }
+	       }
+	       else			/* DC component */
+	       {
+		  if (delta_approx && wfa->delta_state [state]) /* delta */
+		  {
+		     *wptr++ = rtob (wfa->weight [state][label][edge],
+				     wfa->wfainfo->d_dc_rpf);
+		     *lptr++ = offset1;
+		  }
+		  else
+		  {
+		     *wptr++ = rtob (wfa->weight [state][label][edge],
+				     wfa->wfainfo->dc_rpf);
+		     *lptr++ = 0;
+		  }
+	       }
+            }
+	 }
+
+   {
+      unsigned	 i;
+      unsigned	*c_symbols = Calloc (offset4, sizeof (int));
+      const int	 scale 	   = 500;	/* scaling of probability model */
+
+      c_symbols [0] = 1 << (wfa->wfainfo->dc_rpf->mantissa_bits + 1);
+      if (offset1 != offset2)
+	 c_symbols [offset1] = 1 << (wfa->wfainfo->d_dc_rpf->mantissa_bits
+				     + 1);
+      for (i = offset2; i < offset3; i++)
+	 c_symbols [i] = 1 << (wfa->wfainfo->rpf->mantissa_bits + 1);
+      for (; i < offset4; i++)
+	 c_symbols [i] = 1 << (wfa->wfainfo->d_rpf->mantissa_bits + 1);
+      
+      encode_array (output, weights_array, level_array, c_symbols, offset4,
+		    total, scale);
+      Free (c_symbols);
+   }
+   
+   debug_message ("%d delta weights out of %d.", delta_count, total);
+   debug_message ("weights:      %5d bits. (%5d symbols => %5.2f bps)",
+		  bits_processed (output) - bits, total,
+		  (bits_processed (output) - bits) / (double) total);
+
+   Free (weights_array);
+   Free (level_array);
+}
diff --git a/converter/other/fiasco/output/weights.h b/converter/other/fiasco/output/weights.h
new file mode 100644
index 00000000..271203ad
--- /dev/null
+++ b/converter/other/fiasco/output/weights.h
@@ -0,0 +1,27 @@
+/*
+ *  weights.h
+ *
+ *  Written by:		Ullrich Hafner
+ *		
+ *  This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec)
+ *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
+ */
+
+/*
+ *  $Date: 2000/06/14 20:50:31 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#ifndef _WEIGHTS_H
+#define _WEIGHTS_H
+
+#include "wfa.h"
+#include "bit-io.h"
+
+void
+write_weights (unsigned total, const wfa_t *wfa, bitfile_t *output);
+
+#endif /* not _WEIGHTS_H */
+
diff --git a/converter/other/fiasco/output/write.c b/converter/other/fiasco/output/write.c
new file mode 100644
index 00000000..e6185ad3
--- /dev/null
+++ b/converter/other/fiasco/output/write.c
@@ -0,0 +1,250 @@
+/*
+ *  write.c:        Output of WFA files
+ *
+ *  Written by:     Ullrich Hafner
+ *      
+ *  This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec)
+ *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
+ */
+
+/*
+ *  $Date: 2000/07/18 15:44:59 $
+ *  $Author: hafner $
+ *  $Revision: 5.3 $
+ *  $State: Exp $
+ */
+
+#include "config.h"
+
+#include "types.h"
+#include "macros.h"
+#include "error.h"
+
+#include "cwfa.h"
+#include "image.h"
+#include "misc.h"
+#include "bit-io.h"
+#include "rpf.h"
+
+#include "tree.h"
+#include "matrices.h"
+#include "weights.h"
+#include "mc.h"
+#include "nd.h"
+#include "write.h"
+ 
+/*****************************************************************************
+
+                prototypes
+  
+*****************************************************************************/
+
+static void
+write_tiling (const tiling_t *tiling, bitfile_t *output);
+
+/*****************************************************************************
+
+                public code
+
+                
+*****************************************************************************/
+
+
+void
+write_next_wfa (const wfa_t *wfa, const coding_t *c, bitfile_t *output)
+/*
+ *  Write 'wfa' to stream 'output'. If the first frame should be written
+ *  then also store the header information of the coding struct 'c'.
+ *
+ *  No return value.
+ */
+{
+   unsigned edges = 0;          /* number of transitions */
+   unsigned bits;
+   
+   debug_message ("--------------------------------------"
+          "--------------------------------------");
+
+   if (c->mt->number == 0)              /* first WFA */
+      write_header (wfa->wfainfo, output);
+  
+   bits = bits_processed (output);
+   
+   /*
+    *  Frame header information
+    */
+   {
+      const int rice_k = 8;     /* parameter of Rice Code */
+
+      write_rice_code (wfa->states, rice_k, output);      
+      write_rice_code (c->mt->frame_type, rice_k, output); 
+      write_rice_code (c->mt->number, rice_k, output);     
+   }
+   
+   OUTPUT_BYTE_ALIGN (output);
+
+   debug_message ("frame-header: %5d bits.", bits_processed (output) - bits);
+
+   if (c->tiling->exponent)     /* write tiling permutation */
+   {
+      put_bit (output, 1);
+      write_tiling (c->tiling, output);
+   }
+   else
+      put_bit (output, 0);
+
+   OUTPUT_BYTE_ALIGN (output);
+
+   write_tree (wfa, output);
+
+   if (c->options.prediction)       /* write nondeterministic approx. */
+   {
+      put_bit (output, 1); 
+      write_nd (wfa, output);
+   }
+   else
+      put_bit (output, 0);
+
+   if (c->mt->frame_type != I_FRAME)    /* write motion compensation info */
+      write_mc (c->mt->frame_type, wfa, output);
+   
+   edges = write_matrices (c->options.normal_domains,
+               c->options.delta_domains, wfa, output);
+
+   if (edges)               /* found at least one approximation */
+      write_weights (edges, wfa, output);
+
+   debug_message ("--------------------------------------"
+          "--------------------------------------");
+}
+
+void
+write_header (const wfa_info_t *wi, bitfile_t *output)
+/*
+ *  Write the header information describing the type of 'wfa'
+ *  to stream 'output'.
+ *
+ *  No return value.
+ */
+{
+   const unsigned rice_k = 8;       /* parameter of Rice Code */
+   unsigned   bits   = bits_processed (output);
+   const char *text;            /* next character to write */
+
+   /*
+    *  Write magic number and name of initial basis
+    */
+   for (text = FIASCO_MAGIC; *text; text++)
+      put_bits (output, *text, 8);
+   put_bits (output, '\n', 8);
+   for (text = wi->basis_name; *text; text++)
+      put_bits (output, *text, 8);
+   put_bits (output, *text, 8);
+   
+   write_rice_code (FIASCO_BINFILE_RELEASE, rice_k, output);
+
+   write_rice_code (HEADER_TITLE, rice_k, output);
+   for (text = wi->title;
+    text && *text && text - wi->title < MAXSTRLEN - 2;
+    text++)
+      put_bits (output, *text, 8);
+   put_bits (output, 0, 8);
+   
+   write_rice_code (HEADER_COMMENT, rice_k, output);
+   for (text = wi->comment;
+    text && *text && text - wi->comment < MAXSTRLEN - 2;
+    text++)
+      put_bits (output, *text, 8);
+   put_bits (output, 0, 8);
+   
+   write_rice_code (HEADER_END, rice_k, output);
+   
+   write_rice_code (wi->max_states, rice_k, output); 
+   put_bit (output, wi->color ? 1 : 0); 
+   write_rice_code (wi->width, rice_k, output);
+   write_rice_code (wi->height, rice_k, output);
+   if (wi->color)
+      write_rice_code (wi->chroma_max_states, rice_k, output); 
+   write_rice_code (wi->p_min_level, rice_k, output); 
+   write_rice_code (wi->p_max_level, rice_k, output); 
+   write_rice_code (wi->frames, rice_k, output);
+   write_rice_code (wi->smoothing, rice_k, output);
+
+   put_bits (output, wi->rpf->mantissa_bits - 2, 3);
+   put_bits (output, wi->rpf->range_e, 2);
+   if (wi->rpf->mantissa_bits != wi->dc_rpf->mantissa_bits ||
+       wi->rpf->range != wi->dc_rpf->range)
+   {
+      put_bit (output, YES);
+      put_bits (output, wi->dc_rpf->mantissa_bits - 2, 3);
+      put_bits (output, wi->dc_rpf->range_e, 2);
+   }
+   else
+      put_bit (output, NO);
+   if (wi->rpf->mantissa_bits != wi->d_rpf->mantissa_bits ||
+       wi->rpf->range != wi->d_rpf->range)
+   {
+      put_bit (output, YES);
+      put_bits (output, wi->d_rpf->mantissa_bits - 2, 3);
+      put_bits (output, wi->d_rpf->range_e, 2);
+   }
+   else
+      put_bit (output, NO);
+   if (wi->dc_rpf->mantissa_bits != wi->d_dc_rpf->mantissa_bits ||
+       wi->dc_rpf->range != wi->d_dc_rpf->range)
+   {
+      put_bit (output, YES);
+      put_bits (output, wi->d_dc_rpf->mantissa_bits - 2, 3);
+      put_bits (output, wi->d_dc_rpf->range_e, 2);
+   }
+   else
+      put_bit (output, NO);
+
+   if (wi->frames > 1)          /* motion compensation stuff */
+   {
+      write_rice_code (wi->fps, rice_k, output); 
+      write_rice_code (wi->search_range, rice_k, output); 
+      put_bit (output, wi->half_pixel ? 1 : 0); 
+      put_bit (output, wi->B_as_past_ref ? 1 : 0);
+   }
+
+   OUTPUT_BYTE_ALIGN (output);
+   debug_message ("header:         %d bits.", bits_processed (output) - bits);
+}
+
+/*****************************************************************************
+
+                private code
+  
+*****************************************************************************/
+
+static void
+write_tiling (const tiling_t *tiling, bitfile_t *output)
+/*
+ *  Write image tiling information given by 'tiling' to stream 'output'.
+ *
+ *  No return value.
+ */
+{
+   const unsigned rice_k = 8;       /* parameter of Rice Code */
+   unsigned       bits   = bits_processed (output);
+   
+   write_rice_code (tiling->exponent, rice_k, output);
+   if (tiling->method == FIASCO_TILING_VARIANCE_ASC
+       || tiling->method == FIASCO_TILING_VARIANCE_DSC)
+   {
+      unsigned tile;            /* current image tile */
+
+      put_bit (output, 1);      
+      for (tile = 0; tile < 1U << tiling->exponent; tile++)
+     if (tiling->vorder [tile] != -1) /* image tile is visible */
+        put_bits (output, tiling->vorder [tile], tiling->exponent);
+   }
+   else
+   {
+      put_bit (output, 0);      
+      put_bit (output, tiling->method == FIASCO_TILING_SPIRAL_ASC);
+   }
+
+   debug_message ("tiling:        %4d bits.", bits_processed (output) - bits);
+}
diff --git a/converter/other/fiasco/output/write.h b/converter/other/fiasco/output/write.h
new file mode 100644
index 00000000..a3ede1f4
--- /dev/null
+++ b/converter/other/fiasco/output/write.h
@@ -0,0 +1,28 @@
+/*
+ *  write.h
+ *
+ *  Written by:		Ullrich Hafner
+ *		
+ *  This file is part of FIASCO («F»ractal «I»mage «A»nd «S»equence «CO»dec)
+ *  Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de>
+ */
+
+/*
+ *  $Date: 2000/07/15 17:27:30 $
+ *  $Author: hafner $
+ *  $Revision: 5.2 $
+ *  $State: Exp $
+ */
+
+#ifndef _WRITE_H
+#define _WRITE_H
+
+#include "cwfa.h"
+#include "bit-io.h"
+
+void
+write_next_wfa (const wfa_t *wfa, const coding_t *c, bitfile_t *output);
+void
+write_header (const wfa_info_t *wi, bitfile_t *output);
+
+#endif /* not _WRITE_H */