about summary refs log tree commit diff
path: root/converter/other/fiasco/lib
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/lib
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/lib')
-rw-r--r--converter/other/fiasco/lib/Makefile33
-rw-r--r--converter/other/fiasco/lib/arith.c708
-rw-r--r--converter/other/fiasco/lib/arith.h122
-rw-r--r--converter/other/fiasco/lib/bit-io.c327
-rw-r--r--converter/other/fiasco/lib/bit-io.h58
-rw-r--r--converter/other/fiasco/lib/dither.c1892
-rw-r--r--converter/other/fiasco/lib/dither.h27
-rw-r--r--converter/other/fiasco/lib/error.c326
-rw-r--r--converter/other/fiasco/lib/error.h39
-rw-r--r--converter/other/fiasco/lib/image.c512
-rw-r--r--converter/other/fiasco/lib/image.h59
-rw-r--r--converter/other/fiasco/lib/list.c258
-rw-r--r--converter/other/fiasco/lib/list.h72
-rw-r--r--converter/other/fiasco/lib/macros.h70
-rw-r--r--converter/other/fiasco/lib/misc.c563
-rw-r--r--converter/other/fiasco/lib/misc.h98
-rw-r--r--converter/other/fiasco/lib/mvcode.c14
-rw-r--r--converter/other/fiasco/lib/mvcode.h6
-rw-r--r--converter/other/fiasco/lib/rpf.c223
-rw-r--r--converter/other/fiasco/lib/rpf.h47
-rw-r--r--converter/other/fiasco/lib/types.h38
21 files changed, 5492 insertions, 0 deletions
diff --git a/converter/other/fiasco/lib/Makefile b/converter/other/fiasco/lib/Makefile
new file mode 100644
index 00000000..99d7c1d7
--- /dev/null
+++ b/converter/other/fiasco/lib/Makefile
@@ -0,0 +1,33 @@
+ifeq ($(SRCDIR)x,x)
+  SRCDIR = $(CURDIR)/../../../..
+  BUILDDIR = $(SRCDIR)
+endif
+FIASCOSUBDIR = converter/other/fiasco
+SUBDIR = $(FIASCOSUBDIR)/lib
+VPATH=.:$(SRCDIR)/$(SUBDIR)
+
+include $(BUILDDIR)/Makefile.config
+
+OBJECTS = \
+  arith.o \
+  bit-io.o \
+  dither.o \
+  error.o \
+  image.o \
+  list.o \
+  misc.o \
+  rpf.o \
+  mvcode.o \
+
+MERGE_OBJECTS = $(OBJECTS)
+
+INCLUDES = -I$(SRCDIR)/$(FIASCOSUBDIR)
+
+all: libfiasco_lib.a
+
+include $(SRCDIR)/Makefile.common
+
+libfiasco_lib.a: $(OBJECTS)
+	$(AR) -rc $@ $(OBJECTS)
+	$(RANLIB) $@
+
diff --git a/converter/other/fiasco/lib/arith.c b/converter/other/fiasco/lib/arith.c
new file mode 100644
index 00000000..e3745bf7
--- /dev/null
+++ b/converter/other/fiasco/lib/arith.c
@@ -0,0 +1,708 @@
+/*
+ *  arith.c:		Adaptive arithmetic coding and decoding
+ *
+ *  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:49:37 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#include "config.h"
+
+#include "types.h"
+#include "macros.h"
+#include "error.h"
+
+#include "bit-io.h"
+#include "misc.h"
+#include "arith.h"
+
+/******************************************************************************
+
+				public code
+  
+******************************************************************************/
+
+arith_t *
+alloc_encoder (bitfile_t *output)
+/*
+ *  Arithmetic coder constructor:
+ *  Initialize the arithmetic coder.
+ *  
+ *  Return value:
+ *	A pointer to the new coder structure
+ */
+{
+   arith_t *arith = Calloc (1, sizeof (arith_t));
+
+   assert (output);
+   
+   arith->low       = LOW;
+   arith->high      = HIGH;
+   arith->underflow = 0;
+   arith->file 	    = output;
+
+   return arith;
+}
+
+void
+free_encoder (arith_t *arith)
+/*
+ *  Arithmetic encoder destructor.
+ *  Flush the arithmetic coder. Append all remaining bits to the
+ *  output stream. Append zero bits to get the output file byte aligned.
+ *  
+ *  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 */
+   bitfile_t *output;
+   
+   assert (arith);
+
+   low       = arith->low;
+   high      = arith->high;
+   underflow = arith->underflow;
+   output    = arith->file;
+   
+   low = high;
+
+   RESCALE_OUTPUT_INTERVAL;
+
+   OUTPUT_BYTE_ALIGN (output);
+
+   Free (arith);
+}
+
+real_t
+encode_symbol (unsigned symbol, arith_t *arith, model_t *model)
+/*
+ *  Encode the given 'symbol' using the given probability 'model'.
+ *  The current state of the arithmetic coder is given by 'arith'.
+ *  Output bits are appended to the stream 'output'.
+ *
+ *  The model is updated after encoding the symbol (if neccessary the
+ *  symbol counts are rescaled).
+ *  
+ *  Return value:
+ *	information content of the encoded symbol.
+ *
+ *  Side effects:
+ *	'model' is updated (probability distribution)
+ *	'arith' is updated (coder state)
+ */
+{
+   u_word_t   low_count;		/* lower bound of 'symbol' interval */
+   u_word_t   high_count;		/* upper bound of 'symbol' interval */
+   u_word_t   scale;			/* range of all 'm' symbol intervals */
+   unsigned   range;			/* range of current interval */
+   unsigned   index;			/* index of probability model */
+   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 */
+   bitfile_t *output;			/* output file */
+   
+   assert (model && arith);
+
+   /*
+    * Get interval values
+    */
+   low       = arith->low;
+   high      = arith->high;
+   underflow = arith->underflow;
+   output    = arith->file;
+
+   assert (high > low);
+   
+   if (model->order > 0)		/* order-'n' model*/
+   {
+      unsigned power;			/* multiplicator */
+      unsigned i;
+
+      /*
+       *  Compute index of the probability model to use.
+       *  See init_model() for more details.
+       */
+      power = 1;			/* multiplicator */
+      index = 0;			/* address of prob. model */
+	 
+      for (i = 0; i < model->order; i++) /* genarate a M-nary number */
+      {
+	 index += model->context [i] * power;	
+	 power *= model->symbols;
+      }
+
+      index *= model->symbols + 1;	/* we need space for M + 1 elements */
+
+      for (i = 0; i < model->order - 1; i++)
+	 model->context [i] = model->context [i + 1];
+      model->context [i] = symbol;
+   }
+   else
+      index = 0;
+
+   scale      = model->totals [index + model->symbols];
+   low_count  = model->totals [index + symbol];
+   high_count = model->totals [index + symbol + 1];
+
+   /*
+    *  Compute the new interval depending on the input 'symbol'.
+    */
+   range = (high - low) + 1;
+   high  = low + (u_word_t) ((range * high_count) / scale - 1);
+   low   = low + (u_word_t) ((range * low_count) / scale);
+   
+   RESCALE_OUTPUT_INTERVAL;
+   
+   if (model->scale > 0)		/* adaptive model */
+   {
+      unsigned i;
+
+      /*
+       *  Update probability model
+       */
+      for (i = symbol + 1; i <= model->symbols; i++)
+	 model->totals [index + i]++;
+      if (model->totals [index + model->symbols] > model->scale) /* scaling */
+      {
+	 for (i = 1; i <= model->symbols; i++)
+	 {
+	    model->totals [index + i] >>= 1;
+	    if (model->totals [index + i] <= model->totals [index + i - 1])
+	       model->totals [index + i] = model->totals [index + i - 1] + 1;
+	 }
+      }
+   }
+
+   /*
+    *  Store interval values
+    */
+   arith->low  	    = low;
+   arith->high 	    = high;
+   arith->underflow = underflow;
+   
+   return - log2 ((high_count - low_count) / (real_t) scale);
+}
+
+void
+encode_array (bitfile_t *output, const unsigned *data, const unsigned *context,
+	      const unsigned *c_symbols, unsigned n_context, unsigned n_data,
+	      unsigned scaling)
+/*
+ *  Arithmetic coding of #'n_data' symbols given in the array 'data'.
+ *  If 'n_context' > 1 then a number (context [n]) is assigned to every
+ *  data element n, specifying which context (i.e. number of symbols given by
+ *  c_symbols [context [n]] and adaptive probability model) must be used.
+ *  Rescale probability models if range > 'scaling'.
+ *
+ *  No return value.
+ */
+{
+   u_word_t **totals;			/* probability model */
+
+   if (!n_context)
+      n_context = 1;			/* always use one context */
+
+   assert (output && c_symbols && data);
+   assert (n_context == 1 || context);
+   
+   /*
+    *  Allocate probability models, start with uniform distribution
+    */
+   totals = Calloc (n_context, sizeof (u_word_t *));
+   {
+      unsigned c;
+      
+      for (c = 0; c < n_context; c++)
+      {
+	 unsigned i;
+      
+	 totals [c]    = Calloc (c_symbols [c] + 1, sizeof (u_word_t));
+	 totals [c][0] = 0;
+      
+	 for (i = 0; i < c_symbols [c]; i++)
+	    totals [c][i + 1] = totals [c][i] + 1;
+      }
+   }
+
+   /*
+    *  Encode array elements
+    */
+   {
+      u_word_t low  	 = 0;		/* Start of the current code range */
+      u_word_t high 	 = 0xffff;	/* End of the current code range */
+      u_word_t underflow = 0;		/* Number of underflow bits pending */
+      unsigned n;
+      
+      for (n = 0; n < n_data; n++)
+      {
+	 u_word_t low_count;		/* lower bound of 'symbol' interval */
+	 u_word_t high_count;		/* upper bound of 'symbol' interval */
+	 u_word_t scale;		/* range of all 'm' symbol intervals */
+	 unsigned range;		/* current range */
+	 int	  d;			/* current data symbol */
+	 int	  c;			/* context of current data symbol */
+
+	 d = data [n];
+	 c = n_context > 1 ? context [n] : 0; 
+      
+	 scale	    = totals [c][c_symbols [c]];
+	 low_count  = totals [c][d];
+	 high_count = totals [c][d + 1];
+
+	 /*
+	  * Rescale high and low for the new symbol.
+	  */
+	 range = (high - low) + 1;
+	 high  = low + (u_word_t) ((range * high_count) / scale - 1);
+	 low   = low + (u_word_t) ((range * low_count) / scale);
+	 RESCALE_OUTPUT_INTERVAL;
+      
+	 /*
+	  *  Update probability models
+	  */
+	 {
+	    unsigned i;
+
+	    for (i = d + 1; i < c_symbols [c] + 1; i++)
+	       totals [c][i]++;
+	 
+	    if (totals [c][c_symbols [c]] > scaling) /* scaling */
+	       for (i = 1; i < c_symbols [c] + 1; i++)
+	       {
+		  totals [c][i] >>= 1;
+		  if (totals [c][i] <= totals [c][i - 1])
+		     totals [c][i] = totals [c][i - 1] + 1;
+	       }
+	 }
+      }
+      /*
+       *  Flush arithmetic encoder
+       */
+      low = high;
+      RESCALE_OUTPUT_INTERVAL;
+      OUTPUT_BYTE_ALIGN (output);
+   }
+   
+   /*
+    *  Cleanup ...
+    */
+   {
+      unsigned c;
+      for (c = 0; c < n_context; c++)
+	 Free (totals [c]);
+      Free (totals);
+   }
+}
+
+arith_t *
+alloc_decoder (bitfile_t *input)
+/*
+ *  Arithmetic decoder constructor:
+ *  Initialize the arithmetic decoder with the first
+ *  16 input bits from the stream 'input'.
+ *  
+ *  Return value:
+ *	A pointer to the new decoder structure
+ */
+
+{
+   arith_t *arith = Calloc (1, sizeof (arith_t));
+   
+   assert (input);
+   
+   arith->low  = LOW;
+   arith->high = HIGH;
+   arith->code = get_bits (input, 16);
+   arith->file = input;
+
+   return arith;
+}
+
+void
+free_decoder (arith_t *arith)
+/*
+ *  Arithmetic decoder destructor:
+ *  Flush the arithmetic decoder, i.e., read bits to get the input
+ *  file byte aligned. 
+ *  
+ *  No return value.
+ *
+ *  Side effects:
+ *	structure 'arith' is discarded.
+ */
+{
+   assert (arith);
+
+   INPUT_BYTE_ALIGN (arith->file);
+
+   Free (arith);
+}
+
+unsigned
+decode_symbol (arith_t *arith, model_t *model)
+/*
+ *  Decode the next symbol - the state of the arithmetic decoder
+ *  is given in 'arith'. Read refinement bits from the stream 'input'
+ *  and use the given probability 'model'. Update the probability model after
+ *  deconding the symbol (if neccessary also rescale the symbol counts).
+ *  
+ *  Return value:
+ *	decoded symbol
+ *
+ *  Side effects:
+ *	'model' is updated (probability distribution)
+ *	'arith' is updated (decoder state)
+ */
+{
+   unsigned   range;			/* range of current interval */
+   unsigned   count;			/* value in the current interval */
+   unsigned   index;			/* index of probability model */
+   unsigned   symbol;			/* decoded symbol */
+   u_word_t   scale;			/* range of all 'm' symbol intervals */
+   u_word_t   low;			/* start of the current code range  */
+   u_word_t   high;			/* end of the current code range    */
+   u_word_t   code;			/* the present input code value */
+   bitfile_t *input;			/* input file */
+
+   assert (arith && model);
+   
+   /*
+    * Get interval values
+    */
+   low   = arith->low;
+   high  = arith->high;
+   code  = arith->code;
+   input = arith->file;
+
+   assert (high > low);
+   
+   if (model->order > 0)		/* order-'n' model */
+   {
+      unsigned power;			/* multiplicator */
+      unsigned i;
+      
+      /*
+       *  Compute index of the probability model to use.
+       *  See init_model() for more details.
+       */
+      power = 1;			/* multiplicator */
+      index = 0;			/* address of prob. model */
+	 
+      for (i = 0; i < model->order; i++) /* genarate a m-nary number */
+      {
+	 index += model->context[i] * power;	
+	 power *= model->symbols;
+      }
+
+      index *= model->symbols + 1;	/* we need space for m + 1 elements */
+   }
+   else
+      index = 0;
+
+   scale = model->totals [index + model->symbols];
+   range = (high - low) + 1;
+   count = ((code - low + 1) * scale - 1) / range;
+
+   for (symbol = model->symbols; count < model->totals [index + symbol];
+	symbol--)
+      ;
+
+   if (model->order > 0)		/* order-'n' model */
+   {
+      unsigned i;
+      
+      for (i = 0; i < model->order - 1; i++)
+	 model->context [i] = model->context [i + 1];
+      model->context [i] = symbol;
+   }
+
+   /*
+    *  Compute interval boundaries
+    */
+   {
+      u_word_t low_count;		/* lower bound of 'symbol' interval */
+      u_word_t high_count;		/* upper bound of 'symbol' interval */
+      
+      low_count  = model->totals [index + symbol];
+      high_count = model->totals [index + symbol + 1];
+      high       = low + (u_word_t) ((range * high_count) / scale - 1 );
+      low        = low + (u_word_t) ((range * low_count) / scale );
+   }
+   
+   RESCALE_INPUT_INTERVAL;
+   
+   if (model->scale > 0)		/* adaptive model */
+   {
+      unsigned i;
+
+      /*
+       *  Update probability model
+       */
+      for (i = symbol + 1; i <= model->symbols; i++)
+	 model->totals [index + i]++;
+      if (model->totals [index + model->symbols] > model->scale) /* scaling */
+      {
+	 for (i = 1; i <= model->symbols; i++)
+	 {
+	    model->totals [index + i] >>= 1;
+	    if (model->totals [index + i] <= model->totals [index + i - 1])
+	       model->totals [index + i] = model->totals [index + i - 1] + 1;
+	 }
+      }
+   }
+   
+   /*
+    *  Store interval values
+    */
+   arith->low  = low;
+   arith->high = high;
+   arith->code = code;
+
+   return symbol;
+}
+
+unsigned *
+decode_array (bitfile_t *input, const unsigned *context,
+	      const unsigned *c_symbols, unsigned n_context,
+	      unsigned n_data, unsigned scaling)
+/*
+ *  Arithmetic decoding of #'n_data' symbols.
+ *  If 'n_context' > 1 then a number (context [n]) is assigned to every
+ *  data element n, specifying which context (i.e. number of symbols given by
+ *  c_symbols [context [n]] and adaptive probability model) must be used.
+ *  Rescale probability models if range > 'scaling'.
+ *
+ *  Return value:
+ *	pointer to array containing the decoded symbols
+ */
+{
+   unsigned  *data;			/* array to store decoded symbols */
+   u_word_t **totals;			/* probability model */
+   
+   if (n_context < 1)
+      n_context = 1;			/* always use one context */
+   assert (input && c_symbols);
+   assert (n_context == 1 || context);
+
+   data = Calloc (n_data, sizeof (unsigned));
+   
+   /*
+    *  Allocate probability models, start with uniform distribution
+    */
+   totals = Calloc (n_context, sizeof (u_word_t *));
+   {
+      unsigned c;
+      
+      for (c = 0; c < n_context; c++)
+      {
+	 unsigned i;
+      
+	 totals [c]    = Calloc (c_symbols [c] + 1, sizeof (u_word_t));
+	 totals [c][0] = 0;
+      
+	 for (i = 0; i < c_symbols [c]; i++)
+	    totals [c][i + 1] = totals [c][i] + 1;
+      }
+   }
+
+   /*
+    *  Fill array 'data' with decoded values
+    */
+   {
+      u_word_t code = get_bits (input, 16); /* The present input code value */
+      u_word_t low  = 0;		/* Start of the current code range */
+      u_word_t high = 0xffff;		/* End of the current code range */
+      unsigned n;
+      
+      for (n = 0; n < n_data; n++) 
+      {
+	 u_word_t scale;		/* range of all 'm' symbol intervals */
+	 u_word_t low_count;		/* lower bound of 'symbol' interval */
+	 u_word_t high_count;		/* upper bound of 'symbol' interval */
+	 unsigned count;		/* value in the current interval */
+	 unsigned range;		/* current interval range */
+	 unsigned d;			/* current data symbol */
+	 unsigned c;			/* context of current data symbol */
+
+	 c = n_context > 1 ? context [n] : 0; 
+
+	 assert (high > low);
+	 scale = totals [c][c_symbols [c]];
+	 range = (high - low) + 1;
+	 count = (((code - low) + 1 ) * scale - 1) / range;
+      
+	 for (d = c_symbols [c]; count < totals [c][d]; d--) /* next symbol */
+	    ;
+	 low_count  = totals [c][d];
+	 high_count = totals [c][d + 1];
+
+	 high = low + (u_word_t) ((range * high_count) / scale - 1 );
+	 low  = low + (u_word_t) ((range * low_count) / scale );
+	 RESCALE_INPUT_INTERVAL;
+
+	 /*
+	  *  Updata probability models
+	  */
+	 {
+	    unsigned i;
+
+	    for (i = d + 1; i < c_symbols [c] + 1; i++)
+	       totals [c][i]++;
+	 
+	    if (totals [c][c_symbols [c]] > scaling) /* scaling */
+	       for (i = 1; i < c_symbols [c] + 1; i++)
+	       {
+		  totals [c][i] >>= 1;
+		  if (totals [c][i] <= totals [c][i - 1])
+		     totals [c][i] = totals [c][i - 1] + 1;
+	       }
+	 }
+	 data [n] = d;
+      }
+      INPUT_BYTE_ALIGN (input);
+   }
+
+   /*
+    *  Cleanup ...
+    */
+   {
+      unsigned c;
+      
+      for (c = 0; c < n_context; c++)
+	 Free (totals [c]);
+      Free (totals);
+   }
+   
+   return data;
+}
+
+model_t *
+alloc_model (unsigned m, unsigned scale, unsigned n, unsigned *totals)
+/*
+ *  Model constructor:
+ *  allocate and initialize an order-'n' probability model.
+ *  The size of the source alphabet is 'm'. Rescale the symbol counts after
+ *  'scale' symbols are encoded/decoded. The initial probability of every
+ *  symbol is 1/m.
+ *  If 'scale' = 0 then use static modeling (p = 1/n).
+ *  If 'totals' is not NULL then use this array of 'm' values to set
+ *  the initial counts.
+ *
+ *  Return value:
+ *	a pointer to the new probability model structure.
+ *  
+ *  Note: We recommend a small size of the alphabet because no escape codes
+ *  are used to encode/decode previously unseen symbols.
+ *  
+ */
+{
+   model_t  *model;			/* new probability model */
+   unsigned  num;			/* number of contexts to allocate */
+   bool_t    cont;			/* continue flag */
+   bool_t    dec;			/* next order flag */
+   unsigned  i;
+
+   /*
+    *  Allocate memory for the structure
+    */
+   model          = Calloc (1, sizeof (model_t));
+   model->symbols = m;
+   model->scale   = scale;
+   model->order   = n;
+   model->context = n > 0 ? Calloc (n, sizeof (unsigned)) : NULL;
+   /*
+    *  Allocate memory for the probabilty model.
+    *  Each of the m^n different contexts requires its own probability model.
+    */
+   for (num = 1, i = 0; i < model->order; i++)
+      num *= model->symbols;
+
+   model->totals = Calloc (num * (model->symbols + 1), sizeof (unsigned));
+
+   for (i = 0; i < model->order; i++)
+      model->context[i] = 0;		/* start with context 0,0, .. ,0 */
+   cont = YES;
+   while (cont)				/* repeat while context != M ... M */
+   {
+      int	power;			/* multiplicator */
+      int	index;			/* index of probability model */
+      /*
+       *  There are m^n different contexts:
+       *  Let "context_1 context_2 ... context_n symbol" be the current input
+       *  stream then the index of the probability model is given by:
+       *  index = context_1 * M^0 + context_2 * M^1 + ... + context_n * M^(n-1)
+       */
+      power = 1;			/* multiplicator */
+      index = 0;			/* address of prob. model */
+	 
+      for (i = 0; i < model->order; i++)	/* genarate a m-nary number */
+      {
+	 index += model->context[i] * power;	
+	 power *= model->symbols;
+      }
+
+      index *= model->symbols + 1;	/* size of each model is m + 1 */
+
+      model->totals [index + 0] = 0;	/* always zero */
+	 
+      for (i = 1; i <= model->symbols; i++) /* prob of each symbol is 1/m or
+					       as given in totals */
+	 model->totals[index + i] = model->totals [index + i - 1]
+				    + (totals ? totals [i - 1] : 1);
+
+      if (model->order == 0)		/* order-0 model */
+	 cont = NO;
+      else				/* try next context */
+	 for (i = model->order - 1, dec = YES; dec; i--)
+	 {
+	    dec = NO;
+	    model->context[i]++;
+	    if (model->context[i] >= model->symbols) 
+	    {
+	       /* change previous context */
+	       model->context[i] = 0;
+	       if (i > 0)		/* there's still a context remaining */
+		  dec = YES;
+	       else
+		  cont = NO;		/* all context models initilized */
+	    }
+	 }
+   }
+   for (i = 0; i < model->order; i++)
+      model->context[i] = 0;		/* start with context 0,0, .. ,0 */
+
+   return model;
+}
+
+void
+free_model (model_t *model)
+/*
+ *  Model destructor:
+ *  Free memory allocated by the arithmetic 'model'.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *	struct 'model' is discarded
+ */
+{
+   if (model != NULL)
+   {
+      if (model->context != NULL)
+	 Free (model->context);
+      Free (model->totals);
+      Free (model);
+   }
+   else
+      warning ("Can't free model <NULL>.");
+}
diff --git a/converter/other/fiasco/lib/arith.h b/converter/other/fiasco/lib/arith.h
new file mode 100644
index 00000000..744eb9d7
--- /dev/null
+++ b/converter/other/fiasco/lib/arith.h
@@ -0,0 +1,122 @@
+/*
+ *  arith.h
+ *
+ *  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:49:37 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#ifndef _ARITH_H
+#define _ARITH_H
+
+#include "types.h"
+#include "bit-io.h"
+
+typedef struct model
+{
+   unsigned  symbols;			/* number of symbols in the alphabet */
+   unsigned  scale;			/* if totals > scale rescale totals */
+   unsigned  order;			/* order of the probability model */
+   unsigned *context;			/* context of the model */
+   unsigned *totals;			/* the totals */
+} model_t;
+
+typedef struct arith
+{
+   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   code;			/* the present input code value */
+   bitfile_t *file;			/* I/O stream */
+} arith_t;
+
+enum interval {LOW = 0x0000, FIRST_QUARTER = 0x4000, HALF = 0x8000,
+	       THIRD_QUARTER = 0xc000, HIGH = 0xffff};
+
+arith_t *
+alloc_encoder (bitfile_t *file);
+void
+free_encoder (arith_t *arith);
+real_t
+encode_symbol (unsigned symbol, arith_t *arith, model_t *model);
+void
+encode_array (bitfile_t *output, const unsigned *data, const unsigned *context,
+	      const unsigned *c_symbols, unsigned n_context, unsigned n_data,
+	      unsigned scaling);
+arith_t *
+alloc_decoder (bitfile_t *input);
+void
+free_decoder (arith_t *arith);
+unsigned
+decode_symbol (arith_t *arith, model_t *model);
+unsigned *
+decode_array (bitfile_t *input, const unsigned *context,
+	      const unsigned *c_symbols, unsigned n_context,
+	      unsigned n_data, unsigned scaling);
+model_t *
+alloc_model (unsigned m, unsigned scale, unsigned n, unsigned *totals);
+void
+free_model (model_t *model);
+
+#define RESCALE_INPUT_INTERVAL  for (;;)                                      \
+                                   if ((high >= HALF) && (low < HALF) &&      \
+                                      ((low & FIRST_QUARTER) != FIRST_QUARTER \
+				       || (high & FIRST_QUARTER) != 0))       \
+                                   {                                          \
+                                      break;                                  \
+                                   }                                          \
+                                   else if ((high < HALF) || (low >= HALF))   \
+                                   {                                          \
+                                      low  <<= 1;                             \
+                                      high <<= 1;                             \
+                                      high  |= 1;                             \
+                                      code <<= 1;                             \
+                                      code  += get_bit (input);               \
+                                   }                                          \
+                                   else                                       \
+                                   {                                          \
+                                      code  ^= FIRST_QUARTER;                 \
+                                      low   &= FIRST_QUARTER - 1;             \
+                                      low  <<= 1;                             \
+                                      high <<= 1;                             \
+                                      high  |= HALF + 1;                      \
+                                      code <<= 1;                             \
+                                      code  += get_bit (input);               \
+                                   }                                          
+        								   
+#define RESCALE_OUTPUT_INTERVAL  for (;;)                                     \
+                                 {                                            \
+                                    if (high < HALF)                          \
+                                    {                                         \
+                                       put_bit (output, 0);                   \
+                                       for (; underflow; underflow--)         \
+                                          put_bit (output, 1);                \
+                                    }                                         \
+                                    else if (low >= HALF)                     \
+                                    {                                         \
+                                       put_bit (output, 1);                   \
+                                       for (; underflow; underflow--)         \
+                                          put_bit (output, 0);                \
+                                    }                                         \
+                                    else if (high < THIRD_QUARTER &&          \
+                                             low >= FIRST_QUARTER)            \
+                                    {                                         \
+                                       underflow++;                           \
+                                       high |= FIRST_QUARTER;                 \
+                                       low  &= FIRST_QUARTER - 1;             \
+                                    }                                         \
+                                    else                                      \
+                                       break;                                 \
+                                    high <<= 1;                               \
+                                    high  |= 1;                               \
+                                    low  <<= 1;                               \
+                                 }                                             
+					 
+#endif /* not _ARITH_H */
+
diff --git a/converter/other/fiasco/lib/bit-io.c b/converter/other/fiasco/lib/bit-io.c
new file mode 100644
index 00000000..364a1c05
--- /dev/null
+++ b/converter/other/fiasco/lib/bit-io.c
@@ -0,0 +1,327 @@
+/*
+ *  bit-io.c:       Buffered and bit oriented file I/O 
+ *
+ *  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:49:37 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#define _BSD_SOURCE 1   /* Make sure strdup() is in string.h */
+#define _XOPEN_SOURCE 500  /* Make sure strdup() is in string.h */
+
+#include "config.h"
+
+#include <string.h>
+#if STDC_HEADERS
+#   include <stdlib.h>
+#endif /* not STDC_HEADERS */
+
+#include "macros.h"
+#include "types.h"
+#include "error.h"
+
+#include "misc.h"
+#include "bit-io.h"
+
+/*****************************************************************************
+
+                 local constants
+  
+*****************************************************************************/
+
+static const unsigned BUFFER_SIZE = 16350;
+
+static const unsigned mask[] = {0x0001, 0x0002, 0x0004, 0x0008,
+                                0x0010, 0x0020, 0x0040, 0x0080,
+                                0x0100, 0x0200, 0x0400, 0x0800,
+                                0x1000, 0x2000, 0x4000, 0x8000};
+
+/*****************************************************************************
+
+                public code
+  
+*****************************************************************************/
+
+FILE *
+open_file (const char *filename, const char *env_var, openmode_e mode)
+/*
+ *  Try to open file 'filename' with mode 'mode' (READ_ACCESS, WRITE_ACCESS).
+ *  Scan the current directory first and then cycle through the
+ *  path given in the environment variable 'env_var', if set.
+ * 
+ *  Return value:
+ *  Pointer to open file on success, else NULL.
+ */
+{
+    char       *path;        /* current path */
+    FILE       *fp;      /* file pointer of I/O stream */
+    char       *ext_filename = NULL; /* full path of file */
+    char       *env_path     = NULL; /* path given by 'env_var' */
+    char const * const PATH_SEP     = " ;:,"; /* path separation characters */
+    char const * const DEFAULT_PATH = "."; /* default for output files */
+    const char * const read_mode  = "rb";
+    const char * const write_mode = "wb";
+
+
+    assert (mode == READ_ACCESS || mode == WRITE_ACCESS);
+
+    /*
+     *  First check for stdin or stdout
+     */
+    if (filename == NULL || streq (filename, "-"))
+    {
+        if (mode == READ_ACCESS)
+            return stdin;
+        else 
+            return stdout;
+    }
+   
+    /*
+     *  Try to open 'readonly' file in the current directory
+     */
+    if (mode == READ_ACCESS && (fp = fopen (filename, read_mode)))
+        return fp; 
+
+    if (mode == WRITE_ACCESS && strchr (filename, '/')) /* contains path */
+        return fopen (filename, write_mode);
+   
+    /*
+     *  Get value of environment variable 'env_var', if set
+     *  else use DEFAULT_PATH ("./")
+     */
+    if (env_var != NULL)
+        env_path = getenv (env_var);
+    if (env_path == NULL) 
+        env_path = strdup (DEFAULT_PATH);
+    else
+        env_path = strdup (env_path);
+   
+    /*
+     *  Try to open file in the directory given by the environment
+     *  variable env_var - individual path components are separated by PATH_SEP 
+     */
+    path = strtok (env_path, PATH_SEP);
+    do 
+    {
+        if (ext_filename) 
+            Free (ext_filename);
+        ext_filename =  Calloc (strlen (path) + strlen (filename) + 2,
+                                sizeof (char));
+        strcpy (ext_filename, path); 
+        if (*(ext_filename + strlen (ext_filename) - 1) != '/')
+            strcat (ext_filename, "/");
+        strcat (ext_filename, filename);
+        fp = fopen (ext_filename, mode == READ_ACCESS ? read_mode : write_mode);
+    }
+    while (fp == NULL && (path = strtok (NULL, PATH_SEP)) != NULL);
+
+    Free (env_path);
+   
+    return fp;
+}
+
+bitfile_t *
+open_bitfile (const char *filename, const char *env_var, openmode_e mode)
+/*
+ *  Bitfile constructor:
+ *  Try to open file 'filename' for buffered bit oriented access with mode
+ *  'mode'. Scan the current directory first and then cycle through the path
+ *  given in the environment variable 'env_var', if set.
+ *
+ *  Return value:
+ *  Pointer to open bitfile on success,
+ *      otherwise the program is terminated.
+ */
+{
+    bitfile_t *bitfile = Calloc (1, sizeof (bitfile_t));
+   
+    bitfile->file = open_file (filename, env_var, mode);
+
+    if (bitfile->file == NULL)
+        file_error (filename);
+
+    if (mode == READ_ACCESS)
+    {
+        bitfile->bytepos  = 0;
+        bitfile->bitpos   = 0;
+        bitfile->mode     = mode;
+        bitfile->filename = filename ? strdup (filename) : strdup ("(stdin)");
+    }
+    else if (mode == WRITE_ACCESS)
+    {
+        bitfile->bytepos  = BUFFER_SIZE - 1;
+        bitfile->bitpos   = 8;
+        bitfile->mode     = mode;
+        bitfile->filename = filename ? strdup (filename) : strdup ("(stdout)");
+    }
+    else
+        error ("Unknow file access mode '%d'.", mode);
+   
+    bitfile->bits_processed = 0;
+    bitfile->buffer         = Calloc (BUFFER_SIZE, sizeof (byte_t));
+    bitfile->ptr            = bitfile->buffer;
+
+    return bitfile;
+}
+
+bool_t
+get_bit (bitfile_t *bitfile)
+/*
+ *  Get one bit from the given stream 'bitfile'.
+ *
+ *  Return value:
+ *   1  H bit
+ *   0  L bit
+ *
+ *  Side effects:
+ *  Buffer of 'bitfile' is modified accordingly.
+ */
+{
+    assert (bitfile);
+   
+    if (!bitfile->bitpos--)      /* use next byte ? */
+    {
+        bitfile->ptr++;
+        if (!bitfile->bytepos--)      /* no more bytes left in the buffer? */
+        {
+            /*
+             *  Fill buffer with new data
+             */
+            int bytes = fread (bitfile->buffer, sizeof (byte_t),
+                               BUFFER_SIZE, bitfile->file) - 1;
+            if (bytes < 0)         /* Error or EOF */
+                error ("Can't read next bit from bitfile %s.", bitfile->filename);
+            else
+                bitfile->bytepos = bytes;
+
+            bitfile->ptr = bitfile->buffer;
+        }
+        bitfile->bitpos = 7;
+    }
+
+    bitfile->bits_processed++;
+
+    return *bitfile->ptr & mask [bitfile->bitpos] ? 1 : 0;
+}
+
+unsigned int
+get_bits (bitfile_t *bitfile, unsigned bits)
+/*
+ *  Get #'bits' bits from the given stream 'bitfile'.
+ *
+ *  Return value:
+ *  composed integer value
+ *
+ *  Side effects:
+ *  Buffer of 'bitfile' is modified.
+ */
+{
+    unsigned value = 0;          /* input value */
+   
+    while (bits--)
+        value = (unsigned) (value << 1) | get_bit (bitfile);
+
+    return value;
+}
+
+void
+put_bit (bitfile_t *bitfile, unsigned value)
+/*     
+ *  Put the bit 'value' to the bitfile buffer.
+ *  The buffer is written to the file 'bitfile->file' if the number of
+ *  buffer bytes exceeds 'BUFFER_SIZE'.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *  Buffer of 'bitfile' is modified.
+ */
+{
+    assert (bitfile);
+   
+    if (!bitfile->bitpos--)      /* use next byte ? */
+    {
+        bitfile->ptr++;
+        if (!bitfile->bytepos--)      /* no more bytes left ? */
+        {
+            /*
+             *  Write buffer to disk and fill buffer with zeros
+             */
+            if (fwrite (bitfile->buffer, sizeof (byte_t),
+                        BUFFER_SIZE, bitfile->file) != BUFFER_SIZE)
+                error ("Can't write next bit of bitfile %s!", bitfile->filename);
+            memset (bitfile->buffer, 0, BUFFER_SIZE);
+            bitfile->bytepos = BUFFER_SIZE - 1;
+            bitfile->ptr     = bitfile->buffer;
+        }
+        bitfile->bitpos = 7;
+    }
+   
+    if (value)
+        *bitfile->ptr |= mask [bitfile->bitpos];
+
+    bitfile->bits_processed++;
+}
+
+void
+put_bits (bitfile_t *bitfile, unsigned value, unsigned bits)
+/*     
+ *  Put #'bits' bits of integer 'value' to the bitfile buffer 'bitfile'.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *  Buffer of 'bitfile' is modified.
+ */
+{
+    while (bits--)
+        put_bit (bitfile, value & mask [bits]);
+}
+
+void
+close_bitfile (bitfile_t *bitfile)
+/*
+ *  Bitfile destructor:
+ *  Close 'bitfile', if 'bitfile->mode' == WRITE_ACCESS write bit buffer
+ *  to disk. 
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *  Structure 'bitfile' is discarded.
+ */
+{
+    assert (bitfile);
+   
+    if (bitfile->mode == WRITE_ACCESS)
+    {
+        unsigned bytes = fwrite (bitfile->buffer, sizeof (byte_t),
+                                 BUFFER_SIZE - bitfile->bytepos, bitfile->file);
+        if (bytes != BUFFER_SIZE - bitfile->bytepos)
+            error ("Can't write remaining %d bytes of bitfile "
+                   "(only %d bytes written)!",
+                   BUFFER_SIZE - bitfile->bytepos, bytes);
+    }
+    fclose (bitfile->file);
+    Free (bitfile->buffer);
+    Free (bitfile->filename);
+    Free (bitfile);
+}
+
+unsigned
+bits_processed (const bitfile_t *bitfile)
+/*
+ *  Return value:
+ *  Number of bits processed up to now
+ */
+{
+    return bitfile->bits_processed;
+}
diff --git a/converter/other/fiasco/lib/bit-io.h b/converter/other/fiasco/lib/bit-io.h
new file mode 100644
index 00000000..d37cc47c
--- /dev/null
+++ b/converter/other/fiasco/lib/bit-io.h
@@ -0,0 +1,58 @@
+/*
+ *  bit-io.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:49:37 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#ifndef _BIT_IO_H
+#define _BIT_IO_H
+
+#include <stdio.h>
+#include "types.h"
+
+#define OUTPUT_BYTE_ALIGN(bfile) while ((bfile)->bitpos) put_bit (bfile, 0);
+#define INPUT_BYTE_ALIGN(bfile)  while ((bfile)->bitpos) get_bit (bfile);
+
+typedef enum {READ_ACCESS, WRITE_ACCESS} openmode_e;
+
+typedef struct bitfile
+{
+   FILE	      *file;			/* associated filepointer */
+   char	      *filename;		/* corresponding filename */
+   byte_t     *buffer;			/* stream buffer */
+   byte_t     *ptr;			/* pointer to current buffer pos */
+   unsigned    bytepos;			/* current I/O byte */
+   unsigned    bitpos;			/* current I/O bit */
+   unsigned    bits_processed;		/* number of bits already processed */
+   openmode_e  mode;			/* access mode */
+} bitfile_t;
+
+FILE *
+open_file (const char *filename, const char *env_var, openmode_e mode);
+bitfile_t *
+open_bitfile (const char *filename, const char *env_var, openmode_e mode);
+void
+put_bit (bitfile_t *bitfile, unsigned value);
+void
+put_bits (bitfile_t *bitfile, unsigned value, unsigned bits);
+bool_t
+get_bit (bitfile_t *bitfile);
+unsigned 
+get_bits (bitfile_t *bitfile, unsigned bits);
+void
+close_bitfile (bitfile_t *bitfile);
+unsigned
+bits_processed (const bitfile_t *bitfile);
+
+#endif /* not _BIT_IO_H */
+
diff --git a/converter/other/fiasco/lib/dither.c b/converter/other/fiasco/lib/dither.c
new file mode 100644
index 00000000..c7f9ebab
--- /dev/null
+++ b/converter/other/fiasco/lib/dither.c
@@ -0,0 +1,1892 @@
+/*
+ *  dither.c:		Various dithering routines 	
+ *
+ *  Adapted 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>
+ */
+
+/*
+ * Copyright (c) 1995 Erik Corry
+ * All rights reserved.
+ * 
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ * 
+ * IN NO EVENT SHALL ERIK CORRY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+ * SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
+ * THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF ERIK CORRY HAS BEEN ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * ERIK CORRY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
+ * BASIS, AND ERIK CORRY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
+ * UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+/*
+ *  $Date: 2000/11/27 20:22:51 $
+ *  $Author: hafner $
+ *  $Revision: 5.3 $
+ *  $State: Exp $
+ */
+
+#include "config.h"
+
+#if HAVE_STRING_H
+#	include <string.h>
+#else /* not HAVE_STRING_H */
+#	include <strings.h>
+#endif /* not HAVE_STRING_H */
+#if STDC_HEADERS
+#	include <stdlib.h>
+#endif /* not STDC_HEADERS */
+
+#include "types.h"
+#include "macros.h"
+#include "error.h"
+
+#include "fiasco.h"
+#include "image.h"
+#include "misc.h"
+#include "dither.h"
+
+/*****************************************************************************
+
+				prototypes
+  
+*****************************************************************************/
+
+static int 
+display_16_bit (const struct fiasco_renderer *this, unsigned char *ximage,
+		const fiasco_image_t *fiasco_image);
+static int 
+display_24_bit_bgr (const struct fiasco_renderer *this, unsigned char *ximage,
+		    const fiasco_image_t *fiasco_image);
+static int 
+display_24_bit_rgb (const struct fiasco_renderer *this, unsigned char *ximage,
+		    const fiasco_image_t *fiasco_image);
+static int 
+display_32_bit (const struct fiasco_renderer *this, unsigned char *ximage,
+		const fiasco_image_t *fiasco_image);
+static int
+free_bits_at_bottom (unsigned long a);
+static int
+free_bits_at_top (unsigned long a);
+static int
+number_of_bits_set (unsigned long a);
+
+/*****************************************************************************
+
+				public code
+  
+*****************************************************************************/
+
+fiasco_renderer_t *
+fiasco_renderer_new (unsigned long red_mask, unsigned long green_mask,
+		     unsigned long blue_mask, unsigned bpp,
+		     int double_resolution)
+/*
+ *  FIASCO renderer constructor.
+ *  Allocate memory for the FIASCO renderer structure and
+ *  initialize values.
+ *  `red_mask', `green_mask', and `blue_mask' are the corresponding masks
+ *  of the X11R6 XImage structure. 
+ *  `bpp' gives the depth of the image in bits per pixel (16, 24, or 32).
+ *  If `double_resolution' is not 0 the the image width and height is doubled.
+ *  (fast pixel doubling, no interpolation!)
+ *
+ *  Return value:
+ *	pointer to the new structure or NULL on error
+ */
+{
+   if (bpp != 16 && bpp != 24 && bpp !=32)
+   {
+      set_error (_("Rendering depth of XImage must be 16, 24, or 32 bpp."));
+      return NULL;
+   }
+   else
+   {
+      fiasco_renderer_t  *render    = calloc (1, sizeof (fiasco_renderer_t));
+      renderer_private_t *private   = calloc (1, sizeof (renderer_private_t));
+      bool_t 	       	  twopixels = (bpp == 16 && double_resolution);
+      int 		  crval, cbval, i; /* counter */
+
+      if (!render || !private)
+      {
+	 set_error (_("Out of memory."));
+	 return NULL;
+      }
+      switch (bpp)
+      {
+	 case 16:
+	    render->render = display_16_bit;
+	    break;
+	 case 24:
+	    if (red_mask > green_mask)
+	       render->render = display_24_bit_rgb;
+	    else
+	       render->render = display_24_bit_bgr;
+	    break;
+	 case 32:
+	    render->render = display_32_bit;
+	    break;
+	 default:
+	    break;			/* does not happen */
+      }
+      render->private = private;
+      render->delete  = fiasco_renderer_delete;
+
+      private->double_resolution = double_resolution;
+      private->Cr_r_tab = calloc (256 + 2 * 1024, sizeof (int));
+      private->Cr_g_tab = calloc (256 + 2 * 1024, sizeof (int));
+      private->Cb_g_tab = calloc (256 + 2 * 1024, sizeof (int));
+      private->Cb_b_tab = calloc (256 + 2 * 1024, sizeof (int));
+
+      if (!private->Cr_r_tab || !private->Cr_g_tab
+	  || !private->Cb_b_tab || !private->Cb_g_tab)
+      {
+	 set_error (_("Out of memory."));
+	 return NULL;
+      }
+      
+      for (i = 1024; i < 1024 + 256; i++)
+      {
+	 cbval = crval  = i - 128 - 1024;
+
+	 private->Cr_r_tab [i] =  1.4022 * crval + 0.5;
+	 private->Cr_g_tab [i] = -0.7145 * crval + 0.5;
+	 private->Cb_g_tab [i] = -0.3456 * cbval + 0.5; 
+	 private->Cb_b_tab [i] =  1.7710 * cbval + 0.5;
+      }
+      for (i = 0; i < 1024; i++)
+      {
+	 private->Cr_r_tab [i] = private->Cr_r_tab [1024];
+	 private->Cr_g_tab [i] = private->Cr_g_tab [1024];
+	 private->Cb_g_tab [i] = private->Cb_g_tab [1024]; 
+	 private->Cb_b_tab [i] = private->Cb_b_tab [1024];
+      }
+      for (i = 1024 + 256; i < 2048 + 256; i++)
+      {
+	 private->Cr_r_tab [i] = private->Cr_r_tab [1024 + 255];
+	 private->Cr_g_tab [i] = private->Cr_g_tab [1024 + 255];
+	 private->Cb_g_tab [i] = private->Cb_g_tab [1024 + 255]; 
+	 private->Cb_b_tab [i] = private->Cb_b_tab [1024 + 255];
+      }
+
+      private->Cr_r_tab += 1024 + 128;
+      private->Cr_g_tab += 1024 + 128;
+      private->Cb_g_tab += 1024 + 128;
+      private->Cb_b_tab += 1024 + 128;
+   
+      /* 
+       *  Set up entries 0-255 in rgb-to-pixel value tables.
+       */
+      private->r_table = calloc (256 + 2 * 1024, sizeof (unsigned int));
+      private->g_table = calloc (256 + 2 * 1024, sizeof (unsigned int));
+      private->b_table = calloc (256 + 2 * 1024, sizeof (unsigned int));
+      private->y_table = calloc (256 + 2 * 1024, sizeof (unsigned int));
+
+      if (!private->r_table || !private->g_table
+	  || !private->b_table || !private->y_table)
+      {
+	 set_error (_("Out of memory."));
+	 return NULL;
+      }
+      
+      for (i = 0; i < 256; i++)
+      {
+	 private->r_table [i + 1024]
+	    = i >> (8 - number_of_bits_set(red_mask));
+	 private->r_table [i + 1024]
+	    <<= free_bits_at_bottom (red_mask);
+	 private->g_table [i + 1024]
+	    = i >> (8 - number_of_bits_set (green_mask));
+	 private->g_table [i + 1024]
+	    <<= free_bits_at_bottom (green_mask);
+	 private->b_table [i + 1024]
+	    <<= free_bits_at_bottom (blue_mask);
+	 private->b_table [i + 1024]
+	    = i >> (8 - number_of_bits_set (blue_mask));
+	 if (twopixels)
+	 {
+	    private->r_table [i + 1024] = ((private->r_table [i + 1024] << 16)
+					   | private->r_table [i + 1024]);
+	    private->g_table [i + 1024] = ((private->g_table [i + 1024] << 16)
+					   | private->g_table [i + 1024]);
+	    private->b_table [i + 1024] = ((private->b_table [i + 1024] << 16)
+					   | private->b_table [i + 1024]);
+	 }
+	 private->y_table [i + 1024] = (private->r_table [i + 1024]
+					| private->g_table [i + 1024]
+					| private->b_table [i + 1024]);
+      }
+
+      /*
+       * Spread out the values we have to the rest of the array so that
+       * we do not need to check for overflow.
+       */
+      for (i = 0; i < 1024; i++)
+      {
+	 private->r_table [i]              = private->r_table [1024];
+	 private->r_table [i + 1024 + 256] = private->r_table [1024 + 255];
+	 private->g_table [i]              = private->g_table [1024];
+	 private->g_table [i + 1024 + 256] = private->g_table [1024 + 255];
+	 private->b_table [i]              = private->b_table [1024];
+	 private->b_table [i + 1024 + 256] = private->b_table [1024 + 255];
+	 private->y_table [i]              = private->y_table [1024];
+	 private->y_table [i + 1024 + 256] = private->y_table [1024 + 255];
+      }
+
+      private->r_table += 1024;
+      private->g_table += 1024;
+      private->b_table += 1024;
+      private->y_table += 1024 + 128;
+
+      return render;
+   }
+   
+}
+
+void
+fiasco_renderer_delete (fiasco_renderer_t *renderer)
+/*
+ *  FIASCO renderer destructor:
+ *  Free memory of 'renderer' structure.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *	structure 'renderer' is discarded.
+ */
+{
+   if (!renderer)
+      return;
+   else
+   {
+      renderer_private_t *private = (renderer_private_t *) renderer->private;
+
+      Free (private->Cr_g_tab - (1024 + 128));
+      Free (private->Cr_r_tab - (1024 + 128));
+      Free (private->Cb_g_tab - (1024 + 128));
+      Free (private->Cb_b_tab - (1024 + 128));
+      Free (private->r_table - 1024);
+      Free (private->g_table - 1024);
+      Free (private->b_table - 1024);
+      Free (private->y_table - (1024 + 128));
+
+      Free (private);
+      Free (renderer);
+   }
+}
+
+int
+fiasco_renderer_render (const fiasco_renderer_t *renderer,
+			unsigned char *ximage,
+			const fiasco_image_t *fiasco_image)
+{
+   if (!renderer)
+   {
+      set_error (_("Parameter `%s' not defined (NULL)."), "renderer");
+      return 0;
+   }
+   else
+      return renderer->render (renderer, ximage, fiasco_image);
+}
+
+/*****************************************************************************
+
+				private code
+  
+*****************************************************************************/
+
+/*
+ *  Erik Corry's multi-byte dither routines.
+ *
+ *  The basic idea is that the Init generates all the necessary
+ *  tables.  The tables incorporate the information about the layout
+ *  of pixels in the XImage, so that it should be able to cope with
+ *  16-bit 24-bit (non-packed) and 32-bit (10-11 bits per
+ *  color!) screens.  At present it cannot cope with 24-bit packed
+ *  mode, since this involves getting down to byte level again. It is
+ *  assumed that the bits for each color are contiguous in the
+ *  longword.
+ * 
+ *  Writing to memory is done in shorts or ints. (Unfortunately, short
+ *  is not very fast on Alpha, so there is room for improvement
+ *  here). There is no dither time check for overflow - instead the
+ *  tables have slack at each end. This is likely to be faster than an
+ *  'if' test as many modern architectures are really bad at
+ *  ifs. Potentially, each '&&' causes a pipeline flush!
+ *
+ *  There is no shifting and fixed point arithmetic, as I really doubt
+ *  you can see the difference, and it costs. This may be just my
+ *  bias, since I heard that Intel is really bad at shifting.
+ */
+
+static int
+number_of_bits_set (unsigned long a)
+/*
+ *  How many 1 bits are there in the longword.
+ *  Low performance, do not call often.
+ */
+{
+   if (!a)
+      return 0;
+   if (a & 1)
+      return 1 + number_of_bits_set (a >> 1);
+   else
+      return (number_of_bits_set (a >> 1));
+}
+
+static int
+free_bits_at_top (unsigned long a)
+/*
+ *  How many 0 bits are there at most significant end of longword.
+ *  Low performance, do not call often.
+ */
+{
+   if(!a)				/* assume char is 8 bits */
+      return sizeof (unsigned long) * 8;
+   else if (((long) a) < 0l)		/* assume twos complement */
+      return 0;
+   else
+      return 1 + free_bits_at_top ( a << 1);
+}
+
+static int
+free_bits_at_bottom (unsigned long a)
+/*
+ *  How many 0 bits are there at least significant end of longword.
+ *  Low performance, do not call often.
+ */
+{
+   /* assume char is 8 bits */
+   if (!a)
+      return sizeof (unsigned long) * 8;
+   else if(((long) a) & 1l)
+      return 0;
+   else
+      return 1 + free_bits_at_bottom ( a >> 1);
+}
+
+static int 
+display_16_bit (const struct fiasco_renderer *this, unsigned char *ximage,
+		const fiasco_image_t *fiasco_image)
+/*
+ *  Convert 'image' to 16 bit color bitmap.
+ *  If 'double_resolution' is true then double image size in both directions.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *	'out[]'	is filled with dithered image
+ */
+{
+   const image_t      *image;
+   renderer_private_t *private;
+   byte_t	      *out;
+   
+   if (!this)
+   {
+      set_error (_("Parameter `%s' not defined (NULL)."), "this");
+      return 0;
+   }
+   if (!ximage)
+   {
+      set_error (_("Parameter `%s' not defined (NULL)."), "ximage");
+      return 0;
+   }
+   if (!fiasco_image)
+   {
+      set_error (_("Parameter `%s' not defined (NULL)."), "fiasco_image");
+      return 0;
+   }
+
+   out 	   = (byte_t *) ximage;
+   image   = cast_image ((fiasco_image_t *) fiasco_image);
+   if (!image)
+      return 0;
+   private = (renderer_private_t *) this->private;
+   
+   if (image->color)
+   {
+      word_t 	   *cbptr, *crptr;	/* pointer to chroma bands */
+      word_t 	   *yptr;		/* pointers to lumincance band */
+      int     	    yval, crval, cbval;	/* pixel value in YCbCr color space */
+      int     	    R, G, B;		/* pixel value in RGB color space */
+      int     	    n;			/* pixel counter */
+      int     	    x, y;		/* pixel coordinates */
+      int 	   *Cr_r_tab, *Cr_g_tab, *Cb_g_tab, *Cb_b_tab;
+      unsigned int *r_table, *g_table, *b_table;
+
+      Cr_g_tab = private->Cr_g_tab;
+      Cr_r_tab = private->Cr_r_tab;
+      Cb_b_tab = private->Cb_b_tab;
+      Cb_g_tab = private->Cb_g_tab;
+      r_table  = private->r_table;
+      g_table  = private->g_table;
+      b_table  = private->b_table;
+      yptr     = image->pixels [Y];
+      cbptr    = image->pixels [Cb];
+      crptr    = image->pixels [Cr];
+
+      if (image->format == FORMAT_4_2_0)
+      {
+	 u_word_t *dst, *dst2;		/* pointers to dithered pixels */
+	 word_t	  *yptr2;		/* pointers to lumincance band */
+
+	 if (private->double_resolution)
+	 {
+	    yptr2 = yptr + image->width;
+	    dst   = (u_word_t *) out;
+	    dst2  = dst + 4 * image->width;
+	    for (y = image->height / 2; y; y--)
+	    {
+	       for (x = image->width / 2; x; x--)
+	       {
+#ifdef HAVE_SIGNED_SHIFT
+		  crval = *crptr++ >> 4;
+		  cbval = *cbptr++ >> 4;
+		  yval  = (*yptr++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  crval = *crptr++ / 16;
+		  cbval = *cbptr++ / 16;
+		  yval  = *yptr++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+	       
+#ifdef HAVE_SIGNED_SHIFT
+		  yval  = (*yptr++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval  = *yptr++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+
+#ifdef HAVE_SIGNED_SHIFT
+		  yval  = (*yptr2++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval  = *yptr2++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst2++ = r_table [R] | g_table [G] | b_table [B];
+		  *dst2++ = r_table [R] | g_table [G] | b_table [B];
+
+#ifdef HAVE_SIGNED_SHIFT
+		  yval  = (*yptr2++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval  = *yptr2++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst2++ = r_table [R] | g_table [G] | b_table [B];
+		  *dst2++ = r_table [R] | g_table [G] | b_table [B];
+	       }
+	       memcpy (dst, dst - 2 * image->width,
+		       2 * image->width * sizeof (u_word_t));
+	       memcpy (dst2, dst2 - 2 * image->width,
+		       2 * image->width * sizeof (u_word_t));
+	       yptr  += image->width;
+	       yptr2 += image->width;
+	       dst   += 3 * image->width * 2;
+	       dst2  += 3 * image->width * 2;
+	    }
+	 }
+	 else
+	 {
+	    yptr2 = yptr + image->width;
+	    dst  = (u_word_t *) out;
+	    dst2 = dst + image->width;
+	    
+	    for (y = image->height / 2; y; y--)
+	    {
+	       for (x = image->width / 2; x; x--)
+	       {
+#ifdef HAVE_SIGNED_SHIFT
+		  crval = *crptr++ >> 4;
+		  cbval = *cbptr++ >> 4;
+		  yval  = (*yptr++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  crval = *crptr++ / 16;
+		  cbval = *cbptr++ / 16;
+		  yval  = *yptr++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+	       
+#ifdef HAVE_SIGNED_SHIFT
+		  yval  = (*yptr++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval  = *yptr++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+
+#ifdef HAVE_SIGNED_SHIFT
+		  yval  = (*yptr2++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval  = *yptr2++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst2++ = r_table [R] | g_table [G] | b_table [B];
+
+#ifdef HAVE_SIGNED_SHIFT
+		  yval  = (*yptr2++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval  = *yptr2++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst2++ = r_table [R] | g_table [G] | b_table [B];
+	       }
+	       yptr  += image->width;
+	       yptr2 += image->width;
+	       dst   += image->width;
+	       dst2  += image->width;
+	    }
+	 }
+      }
+      else				/* 4:4:4 format */
+      {
+	 if (private->double_resolution)
+	 {
+	    unsigned int *dst;		/* pointer to dithered pixels */
+	    
+	    dst  = (unsigned int *) out;
+	    
+	    for (y = image->height; y; y--)
+	    {
+	       for (x = image->width; x; x--)
+	       {
+#ifdef HAVE_SIGNED_SHIFT
+		  crval = *crptr++ >> 4;
+		  cbval = *cbptr++ >> 4;
+		  yval  = (*yptr++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  crval = *crptr++ / 16;
+		  cbval = *cbptr++ / 16;
+		  yval  = *yptr++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+	       }
+	       memcpy (dst, dst - image->width,
+		       image->width * sizeof (unsigned int));
+	       dst += image->width;
+	    }
+	 }
+	 else
+	 {
+	    u_word_t *dst;		/* pointer to dithered pixels */
+
+	    dst  = (u_word_t *) out;
+	    
+	    for (n = image->width * image->height; n; n--)
+	    {
+#ifdef HAVE_SIGNED_SHIFT
+	       crval = *crptr++ >> 4;
+	       cbval = *cbptr++ >> 4;
+	       yval  = (*yptr++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+	       crval = *crptr++ / 16;
+	       cbval = *cbptr++ / 16;
+	       yval  = *yptr++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+	       R = yval + Cr_r_tab [crval];
+	       G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+	       B = yval + Cb_b_tab [cbval];
+
+	       *dst++ = r_table [R] | g_table [G] | b_table [B];
+	    }
+	 }
+      }
+   }
+   else
+   {
+      unsigned int *dst;		/* pointer to dithered pixels */
+      word_t	   *src;		/* current pixel of frame */
+      unsigned int *y_table;
+
+      y_table = private->y_table;
+      dst     = (unsigned int *) out;
+      src     = image->pixels [GRAY];
+      
+      if (private->double_resolution)
+      {
+	 int x, y;			/* pixel coordinates */
+  	    
+	 for (y = image->height; y; y--)
+	 {
+	    for (x = image->width; x; x--)
+	    {
+	       int value;
+	       
+#ifdef HAVE_SIGNED_SHIFT
+	       value = y_table [*src++ >> 4];
+#else /* not HAVE_SIGNED_SHIFT */
+	       value = y_table [*src++ / 16];
+#endif /* not HAVE_SIGNED_SHIFT */
+	       *dst++ = (value << 16) | value;
+	    }
+	    
+	    memcpy (dst, dst - image->width,
+		    image->width * sizeof (unsigned int));
+	    dst += image->width;
+	 }
+      }
+      else
+      {
+	 int n;				/* pixel counter */
+	 
+	 for (n = image->width * image->height / 2; n; n--, src += 2)
+#ifdef HAVE_SIGNED_SHIFT
+#	ifndef WORDS_BIGENDIAN
+	    *dst++ = (y_table [src [1] >> 4] << 16) | y_table [src [0] >> 4];
+#	else /* not WORDS_BIGENDIAN  */
+	    *dst++ = (y_table [src [0] >> 4] << 16) | y_table [src [1] >> 4];
+#	endif
+#else /* not HAVE_SIGNED_SHIFT */
+#	ifndef WORDS_BIGENDIAN
+	    *dst++ = (y_table [src [1] / 16] << 16) | y_table [src [0] / 16];
+#	else /* not WORDS_BIGENDIAN  */
+	    *dst++ = (y_table [src [0] / 16] << 16) | y_table [src [1] / 16];
+#	endif
+#endif /* not HAVE_SIGNED_SHIFT */
+      }
+   }
+
+   return 1;
+}
+
+static int 
+display_24_bit_bgr (const struct fiasco_renderer *this, unsigned char *ximage,
+		    const fiasco_image_t *fiasco_image)
+/*
+ *  Convert 'image' to 16 bit color bitmap.
+ *  If 'double_resolution' is true then double image size in both directions.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *	'out[]'	is filled with dithered image
+ */
+{
+   unsigned 	      *gray_clip = init_clipping ();
+   const image_t      *image;
+   renderer_private_t *private;
+   byte_t	      *out;
+
+   if (!gray_clip)
+      return 0;
+   if (!this)
+   {
+      set_error (_("Parameter `%s' not defined (NULL)."), "this");
+      return 0;
+   }
+   if (!ximage)
+   {
+      set_error (_("Parameter `%s' not defined (NULL)."), "ximage");
+      return 0;
+   }
+   if (!fiasco_image)
+   {
+      set_error (_("Parameter `%s' not defined (NULL)."), "fiasco_image");
+      return 0;
+   }
+
+   out 	   = (byte_t *) ximage;
+   image   = cast_image ((fiasco_image_t *) fiasco_image);
+   if (!image)
+      return 0;
+   private = (renderer_private_t *) this->private;
+   
+   if (image->color)
+   {
+      word_t 	   *cbptr, *crptr;	/* pointer to chroma bands */
+      word_t 	   *yptr;		/* pointers to lumincance band */
+      int 	   *Cr_r_tab, *Cr_g_tab, *Cb_g_tab, *Cb_b_tab;
+      unsigned int *r_table, *g_table, *b_table;
+
+      Cr_g_tab = private->Cr_g_tab;
+      Cr_r_tab = private->Cr_r_tab;
+      Cb_b_tab = private->Cb_b_tab;
+      Cb_g_tab = private->Cb_g_tab;
+      r_table  = private->r_table;
+      g_table  = private->g_table;
+      b_table  = private->b_table;
+      yptr     = image->pixels [Y];
+      cbptr    = image->pixels [Cb];
+      crptr    = image->pixels [Cr];
+
+      if (image->format == FORMAT_4_2_0)
+      {
+	 if (private->double_resolution)
+	 {
+	    int		  yval1;	/* lumincance pixel */
+	    int 	  crval1, cbval1; /* chroma pixels */
+	    int		  yval2;	/* pixel in YCbCr color space */
+	    unsigned int  R1, G1, B1;	/* pixel in RGB color space */
+	    unsigned int  R2, G2, B2;	/* pixel in RGB color space */
+	    int		  x, y;		/* pixel counter */
+	    unsigned int *dst;		/* pointer to dithered pixels */
+	    unsigned int *dst2;		/* pointers to dithered pixels */
+	    word_t	 *yptr2;	/* pointers to lumincance band */
+	    
+	    dst   = (unsigned int *) out;
+	    dst2  = dst + (image->width >> 1) * 3 * 2;
+	    yptr2 = yptr + image->width;
+	    
+	    for (y = image->height >> 1; y; y--)
+	    {
+	       for (x = image->width >> 1; x; x--)
+	       {
+#ifdef HAVE_SIGNED_SHIFT
+		  yval1  = (*yptr++ >> 4) + 128;
+		  yval2  = (*yptr++ >> 4) + 128;
+		  crval1 = *crptr++ >> 4;
+		  cbval1 = *cbptr++ >> 4;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval1  = *yptr++  / 16 + 128;
+		  yval2  = *yptr++  / 16 + 128;
+		  crval1 = *crptr++ / 16;
+		  cbval1 = *cbptr++ / 16;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+		  R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+		  G1 = gray_clip [yval1 + Cr_g_tab [crval1]
+				 + Cb_g_tab [cbval1]];
+		  B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+		  R2 = gray_clip [yval2 + Cr_r_tab [crval1]];
+		  G2 = gray_clip [yval2 + Cr_g_tab [crval1]
+				 + Cb_g_tab [cbval1]];
+		  B2 = gray_clip [yval2 + Cb_b_tab [cbval1]];
+
+		  *dst++ = B1 | (G1 << 8) | (R1 << 16) | (B1 << 24);
+		  *dst++ = G1 | (R1 << 8) | (B2 << 16) | (G2 << 24);
+		  *dst++ = R2 | (B2 << 8) | (G2 << 16) | (R2 << 24);
+
+#ifdef HAVE_SIGNED_SHIFT
+		  yval1  = (*yptr2++ >> 4) + 128;
+		  yval2  = (*yptr2++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval1  = *yptr2++  / 16 + 128;
+		  yval2  = *yptr2++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+		  R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+		  G1 = gray_clip [yval1 + Cr_g_tab [crval1]
+				 + Cb_g_tab [cbval1]];
+		  B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+		  R2 = gray_clip [yval2 + Cr_r_tab [crval1]];
+		  G2 = gray_clip [yval2 + Cr_g_tab [crval1]
+				 + Cb_g_tab [cbval1]];
+		  B2 = gray_clip [yval2 + Cb_b_tab [cbval1]];
+
+		  *dst2++ = B1 | (G1 << 8) | (R1 << 16) | (B1 << 24);
+		  *dst2++ = G1 | (R1 << 8) | (B2 << 16) | (G2 << 24);
+		  *dst2++ = R2 | (B2 << 8) | (G2 << 16) | (R2 << 24);
+	       }
+	       memcpy (dst, dst - (image->width >> 1) * 3,
+		       (image->width >> 1) * 3 * sizeof (unsigned int));
+	       memcpy (dst2, dst2 - (image->width >> 1) * 3, 
+		       (image->width >> 1) * 3 * sizeof (unsigned int));
+	       dst   += (image->width >> 1) * 3 * 3;
+	       dst2  += (image->width >> 1) * 3 * 3;
+	       yptr  += image->width;
+	       yptr2 += image->width;
+	    }
+	 }
+	 else
+	 {
+	    int		  yval1;	/* lumincance pixel */
+	    int 	  crval1, cbval1; /* chroma pixels */
+	    int		  yval2;	/* pixel in YCbCr color space */
+	    unsigned int  R1, G1, B1;	/* pixel in RGB color space */
+	    unsigned int  R2, G2, B2;	/* pixel in RGB color space */
+	    int		  x, y;		/* pixel counter */
+	    unsigned int *dst;		/* pointer to dithered pixels */
+	    unsigned int *dst2;		/* pointers to dithered pixels */
+	    word_t	 *yptr2;	/* pointers to lumincance band */
+	    
+	    dst   = (unsigned int *) out;
+	    dst2  = dst + (image->width >> 2) * 3;
+	    yptr2 = yptr + image->width;
+	    
+	    for (y = image->height >> 1; y; y--)
+	    {
+	       for (x = image->width >> 2; x; x--)
+	       {
+#ifdef HAVE_SIGNED_SHIFT
+		  yval1  = (*yptr++ >> 4) + 128;
+		  yval2  = (*yptr++ >> 4) + 128;
+		  crval1 = *crptr++ >> 4;
+		  cbval1 = *cbptr++ >> 4;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval1  = *yptr++  / 16 + 128;
+		  yval2  = *yptr++  / 16 + 128;
+		  crval1 = *crptr++ / 16;
+		  cbval1 = *cbptr++ / 16;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+		  R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+		  G1 = gray_clip [yval1 + Cr_g_tab [crval1]
+				 + Cb_g_tab [cbval1]];
+		  B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+		  R2 = gray_clip [yval2 + Cr_r_tab [crval1]];
+		  G2 = gray_clip [yval2 + Cr_g_tab [crval1]
+				 + Cb_g_tab [cbval1]];
+		  B2 = gray_clip [yval2 + Cb_b_tab [cbval1]];
+
+		  *dst++ = B1 | (G1 << 8) | (R1 << 16) | (B2 << 24);
+		  *dst   = G2 | (R2 << 8);
+
+#ifdef HAVE_SIGNED_SHIFT
+		  yval1  = (*yptr2++ >> 4) + 128;
+		  yval2  = (*yptr2++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval1  = *yptr2++  / 16 + 128;
+		  yval2  = *yptr2++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+		  R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+		  G1 = gray_clip [yval1 + Cr_g_tab [crval1]
+				 + Cb_g_tab [cbval1]];
+		  B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+		  R2 = gray_clip [yval2 + Cr_r_tab [crval1]];
+		  G2 = gray_clip [yval2 + Cr_g_tab [crval1]
+				 + Cb_g_tab [cbval1]];
+		  B2 = gray_clip [yval2 + Cb_b_tab [cbval1]];
+
+		  *dst2++ = B1 | (G1 << 8) | (R1 << 16) | (B2 << 24);
+		  *dst2   = G2 | (R2 << 8);
+	       
+#ifdef HAVE_SIGNED_SHIFT
+		  yval1  = (*yptr++ >> 4) + 128;
+		  yval2  = (*yptr++ >> 4) + 128;
+		  crval1 = *crptr++ >> 4;
+		  cbval1 = *cbptr++ >> 4;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval1  = *yptr++  / 16 + 128;
+		  yval2  = *yptr++  / 16 + 128;
+		  crval1 = *crptr++ / 16;
+		  crval2 = *crptr++ / 16;
+		  cbval1 = *cbptr++ / 16;
+		  cbval2 = *cbptr++ / 16;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+		  R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+		  G1 = gray_clip [yval1 + Cr_g_tab [crval1]
+				 + Cb_g_tab [cbval1]];
+		  B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+		  R2 = gray_clip [yval2 + Cr_r_tab [crval1]];
+		  G2 = gray_clip [yval2 + Cr_g_tab [crval1]
+				 + Cb_g_tab [cbval1]];
+		  B2 = gray_clip [yval2 + Cb_b_tab [cbval1]];
+
+		  *dst++ |= (B1 << 16) | (G1 << 24);
+		  *dst++ = R1 | (B2 << 8) | (G2 << 16) | (R2 << 24);
+
+#ifdef HAVE_SIGNED_SHIFT
+		  yval1  = (*yptr2++ >> 4) + 128;
+		  yval2  = (*yptr2++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval1  = *yptr2++  / 16 + 128;
+		  yval2  = *yptr2++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+		  R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+		  G1 = gray_clip [yval1 + Cr_g_tab [crval1]
+				 + Cb_g_tab [cbval1]];
+		  B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+		  R2 = gray_clip [yval2 + Cr_r_tab [crval1]];
+		  G2 = gray_clip [yval2 + Cr_g_tab [crval1]
+				 + Cb_g_tab [cbval1]];
+		  B2 = gray_clip [yval2 + Cb_b_tab [cbval1]];
+
+		  *dst2++ |= (B1 << 16) | (G1 << 24);
+		  *dst2++ = R1 | (B2 << 8) | (G2 << 16) | (R2 << 24);
+	       }
+	       dst   += (image->width >> 2) * 3;
+	       dst2  += (image->width >> 2) * 3;
+	       yptr  += image->width;
+	       yptr2 += image->width;
+	    }
+	 }
+      }
+      else				/* 4:4:4 format */
+      {
+	 if (private->double_resolution)
+	 {
+	    unsigned int R1, G1, B1;		/* pixel1 in RGB color space */
+	    unsigned int R2, G2, B2;		/* pixel2 in RGB color space */
+	    int		 yval1, crval1, cbval1;	/* pixel1 in YCbCr space */
+	    int		 yval2, crval2, cbval2;	/* pixel2 in YCbCr space */
+	    int		 x, y;			/* pixel counter */
+	    unsigned int *dst;		        /* dithered pixel pointer */
+	    
+	    dst = (unsigned int *) out;
+	    
+	    for (y = image->height; y; y--)
+	    {
+	       for (x = image->width >> 1; x; x--)
+	       {
+#ifdef HAVE_SIGNED_SHIFT
+		  yval1  = (*yptr++ >> 4) + 128;
+		  yval2  = (*yptr++ >> 4) + 128;
+		  crval1 = *crptr++ >> 4;
+		  crval2 = *crptr++ >> 4;
+		  cbval1 = *cbptr++ >> 4;
+		  cbval2 = *cbptr++ >> 4;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval1  = *yptr++  / 16 + 128;
+		  yval2  = *yptr++  / 16 + 128;
+		  crval1 = *crptr++ / 16;
+		  crval2 = *crptr++ / 16;
+		  cbval1 = *cbptr++ / 16;
+		  cbval2 = *cbptr++ / 16;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  
+		  R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+		  G1 = gray_clip [yval1 + Cr_g_tab [crval1]
+				 + Cb_g_tab [cbval1]];
+		  B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+		  R2 = gray_clip [yval2 + Cr_r_tab [crval2]];
+		  G2 = gray_clip [yval2 + Cr_g_tab [crval2]
+				 + Cb_g_tab [cbval2]];
+		  B2 = gray_clip [yval2 + Cb_b_tab [cbval2]];
+
+		  *dst++ = B1 | (G1 << 8) | (R1 << 16) | (B1 << 24);
+		  *dst++ = G1 | (R1 << 8) | (B2 << 16) | (G2 << 24);
+		  *dst++ = R2 | (B2 << 8) | (G2 << 16) | (R2 << 24);
+	       }
+	       memcpy (dst, dst - 3 * (image->width >> 1),
+		       3 * (image->width >> 1) * sizeof (unsigned int));
+	       dst += 3 * (image->width >> 1);
+	    }
+	 }
+	 else
+	 {
+	    unsigned int R1, G1, B1;		/* pixel in RGB color space */
+	    unsigned int R2, G2, B2;		/* pixel in RGB color space */
+	    int		 yval1, crval1, cbval1;	/* pixel1 in YCbCr space */
+	    int		 yval2, crval2, cbval2;	/* pixel2 in YCbCr space */
+	    int		 n;			/* pixel counter */
+	    unsigned int *dst;		        /* dithered pixel pointer */
+	    
+	    dst = (unsigned int *) out;
+	    
+	    for (n = (image->width * image->height) >> 2; n; n--)
+	    {
+#ifdef HAVE_SIGNED_SHIFT
+	       yval1  = (*yptr++ >> 4) + 128;
+	       yval2  = (*yptr++ >> 4) + 128;
+	       crval1 = *crptr++ >> 4;
+	       crval2 = *crptr++ >> 4;
+	       cbval1 = *cbptr++ >> 4;
+	       cbval2 = *cbptr++ >> 4;
+#else /* not HAVE_SIGNED_SHIFT */
+	       yval1  = *yptr++  / 16 + 128;
+	       yval2  = *yptr++  / 16 + 128;
+	       crval1 = *crptr++ / 16;
+	       crval2 = *crptr++ / 16;
+	       cbval1 = *cbptr++ / 16;
+	       cbval2 = *cbptr++ / 16;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+	       R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+	       G1 = gray_clip [yval1 + Cr_g_tab [crval1] + Cb_g_tab [cbval1]];
+	       B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+	       R2 = gray_clip [yval2 + Cr_r_tab [crval2]];
+	       G2 = gray_clip [yval2 + Cr_g_tab [crval2] + Cb_g_tab [cbval2]];
+	       B2 = gray_clip [yval2 + Cb_b_tab [cbval2]];
+
+	       *dst++ = B1 | (G1 << 8) | (R1 << 16) | (B2 << 24);
+	       *dst   = G2 | (R2 << 8);
+
+#ifdef HAVE_SIGNED_SHIFT
+	       yval1  = (*yptr++ >> 4) + 128;
+	       yval2  = (*yptr++ >> 4) + 128;
+	       crval1 = *crptr++ >> 4;
+	       crval2 = *crptr++ >> 4;
+	       cbval1 = *cbptr++ >> 4;
+	       cbval2 = *cbptr++ >> 4;
+#else /* not HAVE_SIGNED_SHIFT */
+	       yval1  = *yptr++  / 16 + 128;
+	       yval2  = *yptr++  / 16 + 128;
+	       crval1 = *crptr++ / 16;
+	       crval2 = *crptr++ / 16;
+	       cbval1 = *cbptr++ / 16;
+	       cbval2 = *cbptr++ / 16;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+	       R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+	       G1 = gray_clip [yval1 + Cr_g_tab [crval1] + Cb_g_tab [cbval1]];
+	       B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+	       R2 = gray_clip [yval2 + Cr_r_tab [crval2]];
+	       G2 = gray_clip [yval2 + Cr_g_tab [crval2] + Cb_g_tab [cbval2]];
+	       B2 = gray_clip [yval2 + Cb_b_tab [cbval2]];
+
+	       *dst++ |= (B1 << 16) | (G1 << 24);
+	       *dst++ = R1 | (B2 << 8) | (G2 << 16) | (R2 << 24);
+	    }
+	 }
+      }
+   }
+   else
+   {
+      unsigned int *dst;		/* pointer to dithered pixels */
+      word_t	   *src;		/* current pixel of frame */
+      unsigned int *y_table;
+
+      y_table = private->y_table;
+      dst     = (unsigned int *) out;
+      src     = image->pixels [GRAY];
+
+      if (private->double_resolution)
+      {
+	 int	   x, y;		/* pixel counter */
+	 unsigned *shift_clipping = gray_clip + 128;
+
+	 for (y = image->height; y; y--)
+	 {
+	    for (x = image->width >> 1; x; x--)
+	    {
+	       unsigned int val1, val2;
+#ifdef HAVE_SIGNED_SHIFT
+	       val1 = shift_clipping [*src++ >> 4];
+	       val2 = shift_clipping [*src++ >> 4];
+#else /* not HAVE_SIGNED_SHIFT */
+	       val1 = shift_clipping [*src++ / 16];
+	       val2 = shift_clipping [*src++ / 16];
+#endif /* not HAVE_SIGNED_SHIFT */
+
+	       *dst++ = val1 | (val1 << 8) | (val1 << 16) | (val1 << 24);
+	       *dst++ = val1 | (val1 << 8) | (val2 << 16) | (val2 << 24); 
+	       *dst++ = val2 | (val2 << 8) | (val2 << 16) | (val2 << 24);
+	    }
+
+	    memcpy (dst, dst - 3 * (image->width >> 1),
+		    3 * (image->width >> 1) * sizeof (unsigned int));
+	    dst += 3 * (image->width >> 1);
+	 }
+      }
+      else
+      {
+	 int	   n;			/* pixel counter */
+	 unsigned *shift_clipping = gray_clip + 128;
+
+	 for (n = (image->width * image->height) >> 2; n; n--)
+	 {
+	    unsigned int val1, val2;
+
+#ifdef HAVE_SIGNED_SHIFT
+	    val1 = shift_clipping [*src++ >> 4];
+	    val2 = shift_clipping [*src++ >> 4];
+#else /* not HAVE_SIGNED_SHIFT */
+	    val1 = shift_clipping [*src++ / 16];
+	    val2 = shift_clipping [*src++ / 16];
+#endif /* not HAVE_SIGNED_SHIFT */
+
+	    *dst++ = val1 | (val1 << 8)
+		     | (val1 << 16) | (val2 << 24);  /* RGBR */
+	    *dst   = val2 | (val2 << 8);             /* GB-- */
+
+#ifdef HAVE_SIGNED_SHIFT
+	    val1 = shift_clipping [*src++ >> 4];
+	    val2 = shift_clipping [*src++ >> 4];
+#else /* not HAVE_SIGNED_SHIFT */
+	    val1 = shift_clipping [*src++ / 16];
+	    val2 = shift_clipping [*src++ / 16];
+#endif /* not HAVE_SIGNED_SHIFT */
+	    
+	    *dst++ |= (val1 << 16) | (val1 << 24);   /* --RG */
+	    *dst++  = val1 | (val2 << 8)
+		      | (val2 << 16) | (val2 << 24); /* BRGB */
+	 }
+      }
+   }
+   
+   return 1;
+}
+
+static int 
+display_24_bit_rgb (const struct fiasco_renderer *this, unsigned char *ximage,
+		    const fiasco_image_t *fiasco_image)
+/*
+ *  Convert 'image' to 16 bit color bitmap.
+ *  If 'double_resolution' is true then double image size in both directions.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *	'out[]'	is filled with dithered image
+ */
+{
+   unsigned 	      *gray_clip = init_clipping ();
+   const image_t      *image;
+   renderer_private_t *private;
+   byte_t	      *out;
+
+   if (!gray_clip)
+      return 0;
+   if (!this)
+   {
+      set_error (_("Parameter `%s' not defined (NULL)."), "this");
+      return 0;
+   }
+   if (!ximage)
+   {
+      set_error (_("Parameter `%s' not defined (NULL)."), "ximage");
+      return 0;
+   }
+   if (!fiasco_image)
+   {
+      set_error (_("Parameter `%s' not defined (NULL)."), "fiasco_image");
+      return 0;
+   }
+
+   out 	   = (byte_t *) ximage;
+   image   = cast_image ((fiasco_image_t *) fiasco_image);
+   if (!image)
+      return 0;
+   private = (renderer_private_t *) this->private;
+   
+   if (image->color)
+   {
+      word_t 	   *cbptr, *crptr;	/* pointer to chroma bands */
+      word_t 	   *yptr;		/* pointers to lumincance band */
+      int 	   *Cr_r_tab, *Cr_g_tab, *Cb_g_tab, *Cb_b_tab;
+      unsigned int *r_table, *g_table, *b_table;
+
+      Cr_g_tab = private->Cr_g_tab;
+      Cr_r_tab = private->Cr_r_tab;
+      Cb_b_tab = private->Cb_b_tab;
+      Cb_g_tab = private->Cb_g_tab;
+      r_table  = private->r_table;
+      g_table  = private->g_table;
+      b_table  = private->b_table;
+      yptr     = image->pixels [Y];
+      cbptr    = image->pixels [Cb];
+      crptr    = image->pixels [Cr];
+
+      if (image->format == FORMAT_4_2_0)
+      {
+	 if (private->double_resolution)
+	 {
+	    int		  yval1;	/* lumincance pixel */
+	    int 	  crval1, cbval1; /* chroma pixels */
+	    int		  yval2;	/* pixel in YCbCr color space */
+	    unsigned int  R1, G1, B1;	/* pixel in RGB color space */
+	    unsigned int  R2, G2, B2;	/* pixel in RGB color space */
+	    int		  x, y;		/* pixel counter */
+	    unsigned int *dst;		/* pointer to dithered pixels */
+	    unsigned int *dst2;		/* pointers to dithered pixels */
+	    word_t	 *yptr2;	/* pointers to lumincance band */
+	    
+	    dst   = (unsigned int *) out;
+	    dst2  = dst + (image->width >> 1) * 3 * 2;
+	    yptr2 = yptr + image->width;
+	    
+	    for (y = image->height >> 1; y; y--)
+	    {
+	       for (x = image->width >> 1; x; x--)
+	       {
+#ifdef HAVE_SIGNED_SHIFT
+		  yval1  = (*yptr++ >> 4) + 128;
+		  yval2  = (*yptr++ >> 4) + 128;
+		  crval1 = *crptr++ >> 4;
+		  cbval1 = *cbptr++ >> 4;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval1  = *yptr++  / 16 + 128;
+		  yval2  = *yptr++  / 16 + 128;
+		  crval1 = *crptr++ / 16;
+		  cbval1 = *cbptr++ / 16;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+		  R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+		  G1 = gray_clip [yval1 + Cr_g_tab [crval1]
+				  + Cb_g_tab [cbval1]];
+		  B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+		  R2 = gray_clip [yval2 + Cr_r_tab [crval1]];
+		  G2 = gray_clip [yval2 + Cr_g_tab [crval1]
+				  + Cb_g_tab [cbval1]];
+		  B2 = gray_clip [yval2 + Cb_b_tab [cbval1]];
+
+		  *dst++ = R1 | (G1 << 8) | (B1 << 16) | (R1 << 24);
+		  *dst++ = G1 | (B1 << 8) | (R2 << 16) | (G2 << 24);
+		  *dst++ = B2 | (R2 << 8) | (G2 << 16) | (B2 << 24);
+
+#ifdef HAVE_SIGNED_SHIFT
+		  yval1  = (*yptr2++ >> 4) + 128;
+		  yval2  = (*yptr2++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval1  = *yptr2++  / 16 + 128;
+		  yval2  = *yptr2++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+		  R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+		  G1 = gray_clip [yval1 + Cr_g_tab [crval1]
+				  + Cb_g_tab [cbval1]];
+		  B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+		  R2 = gray_clip [yval2 + Cr_r_tab [crval1]];
+		  G2 = gray_clip [yval2 + Cr_g_tab [crval1]
+				  + Cb_g_tab [cbval1]];
+		  B2 = gray_clip [yval2 + Cb_b_tab [cbval1]];
+
+		  *dst2++ = R1 | (G1 << 8) | (B1 << 16) | (R1 << 24);
+		  *dst2++ = G1 | (B1 << 8) | (R2 << 16) | (G2 << 24);
+		  *dst2++ = B2 | (R2 << 8) | (G2 << 16) | (B2 << 24);
+	       }
+	       memcpy (dst, dst - (image->width >> 1) * 3,
+		       (image->width >> 1) * 3 * sizeof (unsigned int));
+	       memcpy (dst2, dst2 - (image->width >> 1) * 3, 
+		       (image->width >> 1) * 3 * sizeof (unsigned int));
+	       dst   += (image->width >> 1) * 3 * 3;
+	       dst2  += (image->width >> 1) * 3 * 3;
+	       yptr  += image->width;
+	       yptr2 += image->width;
+	    }
+	 }
+	 else
+	 {
+	    int		  yval1;	/* lumincance pixel */
+	    int 	  crval1, cbval1; /* chroma pixels */
+	    int		  yval2;	/* pixel in YCbCr color space */
+	    unsigned int  R1, G1, B1;	/* pixel in RGB color space */
+	    unsigned int  R2, G2, B2;	/* pixel in RGB color space */
+	    int		  x, y;		/* pixel counter */
+	    unsigned int *dst;		/* pointer to dithered pixels */
+	    unsigned int *dst2;		/* pointers to dithered pixels */
+	    word_t	 *yptr2;	/* pointers to lumincance band */
+	    
+	    dst   = (unsigned int *) out;
+	    dst2  = dst + (image->width >> 2) * 3;
+	    yptr2 = yptr + image->width;
+	    
+	    for (y = image->height >> 1; y; y--)
+	    {
+	       for (x = image->width >> 2; x; x--)
+	       {
+#ifdef HAVE_SIGNED_SHIFT
+		  yval1  = (*yptr++ >> 4) + 128;
+		  yval2  = (*yptr++ >> 4) + 128;
+		  crval1 = *crptr++ >> 4;
+		  cbval1 = *cbptr++ >> 4;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval1  = *yptr++  / 16 + 128;
+		  yval2  = *yptr++  / 16 + 128;
+		  crval1 = *crptr++ / 16;
+		  cbval1 = *cbptr++ / 16;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+		  R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+		  G1 = gray_clip [yval1 + Cr_g_tab [crval1]
+				  + Cb_g_tab [cbval1]];
+		  B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+		  R2 = gray_clip [yval2 + Cr_r_tab [crval1]];
+		  G2 = gray_clip [yval2 + Cr_g_tab [crval1]
+				  + Cb_g_tab [cbval1]];
+		  B2 = gray_clip [yval2 + Cb_b_tab [cbval1]];
+
+		  *dst++ = R1 | (G1 << 8) | (B1 << 16) | (R2 << 24);
+		  *dst   = G2 | (B2 << 8);
+
+#ifdef HAVE_SIGNED_SHIFT
+		  yval1  = (*yptr2++ >> 4) + 128;
+		  yval2  = (*yptr2++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval1  = *yptr2++  / 16 + 128;
+		  yval2  = *yptr2++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+		  R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+		  G1 = gray_clip [yval1 + Cr_g_tab [crval1]
+				  + Cb_g_tab [cbval1]];
+		  B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+		  R2 = gray_clip [yval2 + Cr_r_tab [crval1]];
+		  G2 = gray_clip [yval2 + Cr_g_tab [crval1]
+				  + Cb_g_tab [cbval1]];
+		  B2 = gray_clip [yval2 + Cb_b_tab [cbval1]];
+
+		  *dst2++ = R1 | (G1 << 8) | (B1 << 16) | (R2 << 24);
+		  *dst2   = G2 | (B2 << 8);
+	       
+#ifdef HAVE_SIGNED_SHIFT
+		  yval1  = (*yptr++ >> 4) + 128;
+		  yval2  = (*yptr++ >> 4) + 128;
+		  crval1 = *crptr++ >> 4;
+		  cbval1 = *cbptr++ >> 4;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval1  = *yptr++  / 16 + 128;
+		  yval2  = *yptr++  / 16 + 128;
+		  crval1 = *crptr++ / 16;
+		  crval2 = *crptr++ / 16;
+		  cbval1 = *cbptr++ / 16;
+		  cbval2 = *cbptr++ / 16;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+		  R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+		  G1 = gray_clip [yval1 + Cr_g_tab [crval1]
+				  + Cb_g_tab [cbval1]];
+		  B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+		  R2 = gray_clip [yval2 + Cr_r_tab [crval1]];
+		  G2 = gray_clip [yval2 + Cr_g_tab [crval1]
+				  + Cb_g_tab [cbval1]];
+		  B2 = gray_clip [yval2 + Cb_b_tab [cbval1]];
+
+		  *dst++ |= (R1 << 16) | (G1 << 24);
+		  *dst++ = B1 | (R2 << 8) | (G2 << 16) | (B2 << 24);
+
+#ifdef HAVE_SIGNED_SHIFT
+		  yval1  = (*yptr2++ >> 4) + 128;
+		  yval2  = (*yptr2++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval1  = *yptr2++  / 16 + 128;
+		  yval2  = *yptr2++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+		  R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+		  G1 = gray_clip [yval1 + Cr_g_tab [crval1]
+				  + Cb_g_tab [cbval1]];
+		  B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+		  R2 = gray_clip [yval2 + Cr_r_tab [crval1]];
+		  G2 = gray_clip [yval2 + Cr_g_tab [crval1]
+				  + Cb_g_tab [cbval1]];
+		  B2 = gray_clip [yval2 + Cb_b_tab [cbval1]];
+
+		  *dst2++ |= (R1 << 16) | (G1 << 24);
+		  *dst2++ = B1 | (R2 << 8) | (G2 << 16) | (B2 << 24);
+	       }
+	       dst   += (image->width >> 2) * 3;
+	       dst2  += (image->width >> 2) * 3;
+	       yptr  += image->width;
+	       yptr2 += image->width;
+	    }
+	 }
+      }
+      else				/* 4:4:4 format */
+      {
+	 if (private->double_resolution)
+	 {
+	    unsigned int R1, G1, B1;		/* pixel1 in RGB color space */
+	    unsigned int R2, G2, B2;		/* pixel2 in RGB color space */
+	    int		 yval1, crval1, cbval1;	/* pixel1 in YCbCr space */
+	    int		 yval2, crval2, cbval2;	/* pixel2 in YCbCr space */
+	    int		 x, y;			/* pixel counter */
+	    unsigned int *dst;		        /* dithered pixel pointer */
+	    
+	    dst = (unsigned int *) out;
+	    
+	    for (y = image->height; y; y--)
+	    {
+	       for (x = image->width >> 1; x; x--)
+	       {
+#ifdef HAVE_SIGNED_SHIFT
+		  yval1  = (*yptr++ >> 4) + 128;
+		  yval2  = (*yptr++ >> 4) + 128;
+		  crval1 = *crptr++ >> 4;
+		  crval2 = *crptr++ >> 4;
+		  cbval1 = *cbptr++ >> 4;
+		  cbval2 = *cbptr++ >> 4;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval1  = *yptr++  / 16 + 128;
+		  yval2  = *yptr++  / 16 + 128;
+		  crval1 = *crptr++ / 16;
+		  crval2 = *crptr++ / 16;
+		  cbval1 = *cbptr++ / 16;
+		  cbval2 = *cbptr++ / 16;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  
+		  R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+		  G1 = gray_clip [yval1 + Cr_g_tab [crval1]
+				  + Cb_g_tab [cbval1]];
+		  B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+		  R2 = gray_clip [yval2 + Cr_r_tab [crval2]];
+		  G2 = gray_clip [yval2 + Cr_g_tab [crval2]
+				  + Cb_g_tab [cbval2]];
+		  B2 = gray_clip [yval2 + Cb_b_tab [cbval2]];
+
+		  *dst++ = R1 | (G1 << 8) | (B1 << 16) | (R1 << 24);
+		  *dst++ = G1 | (B1 << 8) | (R2 << 16) | (G2 << 24);
+		  *dst++ = B2 | (R2 << 8) | (G2 << 16) | (B2 << 24);
+	       }
+	       memcpy (dst, dst - 3 * (image->width >> 1),
+		       3 * (image->width >> 1) * sizeof (unsigned int));
+	       dst += 3 * (image->width >> 1);
+	    }
+	 }
+	 else
+	 {
+	    unsigned int R1, G1, B1;		/* pixel in RGB color space */
+	    unsigned int R2, G2, B2;		/* pixel in RGB color space */
+	    int		 yval1, crval1, cbval1;	/* pixel1 in YCbCr space */
+	    int		 yval2, crval2, cbval2;	/* pixel2 in YCbCr space */
+	    int		 n;			/* pixel counter */
+	    unsigned int *dst;		        /* dithered pixel pointer */
+	    
+	    dst = (unsigned int *) out;
+	    
+	    for (n = (image->width * image->height) >> 2; n; n--)
+	    {
+#ifdef HAVE_SIGNED_SHIFT
+	       yval1  = (*yptr++ >> 4) + 128;
+	       yval2  = (*yptr++ >> 4) + 128;
+	       crval1 = *crptr++ >> 4;
+	       crval2 = *crptr++ >> 4;
+	       cbval1 = *cbptr++ >> 4;
+	       cbval2 = *cbptr++ >> 4;
+#else /* not HAVE_SIGNED_SHIFT */
+	       yval1  = *yptr++  / 16 + 128;
+	       yval2  = *yptr++  / 16 + 128;
+	       crval1 = *crptr++ / 16;
+	       crval2 = *crptr++ / 16;
+	       cbval1 = *cbptr++ / 16;
+	       cbval2 = *cbptr++ / 16;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+	       R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+	       G1 = gray_clip [yval1 + Cr_g_tab [crval1] + Cb_g_tab [cbval1]];
+	       B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+	       R2 = gray_clip [yval2 + Cr_r_tab [crval2]];
+	       G2 = gray_clip [yval2 + Cr_g_tab [crval2] + Cb_g_tab [cbval2]];
+	       B2 = gray_clip [yval2 + Cb_b_tab [cbval2]];
+
+	       *dst++ = R1 | (G1 << 8) | (B1 << 16) | (R2 << 24);
+	       *dst   = G2 | (B2 << 8);
+
+#ifdef HAVE_SIGNED_SHIFT
+	       yval1  = (*yptr++ >> 4) + 128;
+	       yval2  = (*yptr++ >> 4) + 128;
+	       crval1 = *crptr++ >> 4;
+	       crval2 = *crptr++ >> 4;
+	       cbval1 = *cbptr++ >> 4;
+	       cbval2 = *cbptr++ >> 4;
+#else /* not HAVE_SIGNED_SHIFT */
+	       yval1  = *yptr++  / 16 + 128;
+	       yval2  = *yptr++  / 16 + 128;
+	       crval1 = *crptr++ / 16;
+	       crval2 = *crptr++ / 16;
+	       cbval1 = *cbptr++ / 16;
+	       cbval2 = *cbptr++ / 16;
+#endif /* not HAVE_SIGNED_SHIFT */
+
+	       R1 = gray_clip [yval1 + Cr_r_tab [crval1]];
+	       G1 = gray_clip [yval1 + Cr_g_tab [crval1] + Cb_g_tab [cbval1]];
+	       B1 = gray_clip [yval1 + Cb_b_tab [cbval1]];
+	       R2 = gray_clip [yval2 + Cr_r_tab [crval2]];
+	       G2 = gray_clip [yval2 + Cr_g_tab [crval2] + Cb_g_tab [cbval2]];
+	       B2 = gray_clip [yval2 + Cb_b_tab [cbval2]];
+
+	       *dst++ |= (R1 << 16) | (G1 << 24);
+	       *dst++ = B1 | (R2 << 8) | (G2 << 16) | (B2 << 24);
+	    }
+	 }
+      }
+   }
+   else
+   {
+      unsigned int *dst;		/* pointer to dithered pixels */
+      word_t	   *src;		/* current pixel of frame */
+      unsigned int *y_table;
+
+      y_table = private->y_table;
+      dst     = (unsigned int *) out;
+      src     = image->pixels [GRAY];
+
+      if (private->double_resolution)
+      {
+	 int	   x, y;		/* pixel counter */
+	 unsigned *shift_clipping = gray_clip + 128;
+
+	 for (y = image->height; y; y--)
+	 {
+	    for (x = image->width >> 1; x; x--)
+	    {
+	       unsigned int val1, val2;
+#ifdef HAVE_SIGNED_SHIFT
+	       val1 = shift_clipping [*src++ >> 4];
+	       val2 = shift_clipping [*src++ >> 4];
+#else /* not HAVE_SIGNED_SHIFT */
+	       val1 = shift_clipping [*src++ / 16];
+	       val2 = shift_clipping [*src++ / 16];
+#endif /* not HAVE_SIGNED_SHIFT */
+
+	       *dst++ = val1 | (val1 << 8) | (val1 << 16) | (val1 << 24);
+	       *dst++ = val1 | (val1 << 8) | (val2 << 16) | (val2 << 24); 
+	       *dst++ = val2 | (val2 << 8) | (val2 << 16) | (val2 << 24);
+	    }
+
+	    memcpy (dst, dst - 3 * (image->width >> 1),
+		    3 * (image->width >> 1) * sizeof (unsigned int));
+	    dst += 3 * (image->width >> 1);
+	 }
+      }
+      else
+      {
+	 int	   n;			/* pixel counter */
+	 unsigned *shift_clipping = gray_clip + 128;
+
+	 for (n = (image->width * image->height) >> 2; n; n--)
+	 {
+	    unsigned int val1, val2;
+
+#ifdef HAVE_SIGNED_SHIFT
+	    val1 = shift_clipping [*src++ >> 4];
+	    val2 = shift_clipping [*src++ >> 4];
+#else /* not HAVE_SIGNED_SHIFT */
+	    val1 = shift_clipping [*src++ / 16];
+	    val2 = shift_clipping [*src++ / 16];
+#endif /* not HAVE_SIGNED_SHIFT */
+
+	    *dst++ = val1 | (val1 << 8)
+		     | (val1 << 16) | (val2 << 24);  /* RGBR */
+	    *dst   = val2 | (val2 << 8);             /* GB-- */
+
+#ifdef HAVE_SIGNED_SHIFT
+	    val1 = shift_clipping [*src++ >> 4];
+	    val2 = shift_clipping [*src++ >> 4];
+#else /* not HAVE_SIGNED_SHIFT */
+	    val1 = shift_clipping [*src++ / 16];
+	    val2 = shift_clipping [*src++ / 16];
+#endif /* not HAVE_SIGNED_SHIFT */
+	    
+	    *dst++ |= (val1 << 16) | (val1 << 24);   /* --RG */
+	    *dst++  = val1 | (val2 << 8)
+		      | (val2 << 16) | (val2 << 24); /* BRGB */
+	 }
+      }
+   }
+   
+   return 1;
+}
+
+static int 
+display_32_bit (const struct fiasco_renderer *this, unsigned char *ximage,
+		const fiasco_image_t *fiasco_image)
+/*
+ *  Convert 'image' to 16 bit color bitmap.
+ *  If 'double_resolution' is true then double image size in both directions.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *	'out[]'	is filled with dithered image
+ */
+{
+   const image_t      *image;
+   renderer_private_t *private;
+   byte_t	      *out;
+   
+   if (!this)
+   {
+      set_error (_("Parameter `%s' not defined (NULL)."), "this");
+      return 0;
+   }
+   if (!ximage)
+   {
+      set_error (_("Parameter `%s' not defined (NULL)."), "ximage");
+      return 0;
+   }
+   if (!fiasco_image)
+   {
+      set_error (_("Parameter `%s' not defined (NULL)."), "fiasco_image");
+      return 0;
+   }
+
+   out 	   = (byte_t *) ximage;
+   private = (renderer_private_t *) this->private;
+   image   = cast_image ((fiasco_image_t *) fiasco_image);
+   if (!image)
+      return 0;
+   
+   if (image->color)
+   {
+      word_t 	   *cbptr, *crptr;	/* pointer to chroma bands */
+      word_t 	   *yptr;		/* pointers to lumincance band */
+      int     	    yval, crval, cbval;	/* pixel value in YCbCr color space */
+      int     	    R, G, B;		/* pixel value in RGB color space */
+      int     	    n;			/* pixel counter */
+      int     	    x, y;		/* pixel coordinates */
+      int 	   *Cr_r_tab, *Cr_g_tab, *Cb_g_tab, *Cb_b_tab;
+      unsigned int *r_table, *g_table, *b_table;
+
+      Cr_g_tab = private->Cr_g_tab;
+      Cr_r_tab = private->Cr_r_tab;
+      Cb_b_tab = private->Cb_b_tab;
+      Cb_g_tab = private->Cb_g_tab;
+      r_table  = private->r_table;
+      g_table  = private->g_table;
+      b_table  = private->b_table;
+      yptr  = image->pixels [Y];
+      cbptr = image->pixels [Cb];
+      crptr = image->pixels [Cr];
+
+      if (image->format == FORMAT_4_2_0)
+      {
+	 unsigned int	*dst, *dst2;	/* pointers to dithered pixels */
+	 word_t		*yptr2;		/* pointers to lumincance band */
+
+	 if (private->double_resolution)
+	 {
+	    yptr2 = yptr + image->width;
+	    dst  = (unsigned int *) out;
+	    dst2 = dst + 4 * image->width;
+	    for (y = image->height / 2; y; y--)
+	    {
+	       for (x = image->width / 2; x; x--)
+	       {
+#ifdef HAVE_SIGNED_SHIFT
+		  crval = *crptr++ >> 4;
+		  cbval = *cbptr++ >> 4;
+		  yval  = (*yptr++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  crval = *crptr++ / 16;
+		  cbval = *cbptr++ / 16;
+		  yval  = *yptr++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+	       
+#ifdef HAVE_SIGNED_SHIFT
+		  yval  = (*yptr++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval  = *yptr++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+
+#ifdef HAVE_SIGNED_SHIFT
+		  yval  = (*yptr2++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval  = *yptr2++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst2++ = r_table [R] | g_table [G] | b_table [B];
+		  *dst2++ = r_table [R] | g_table [G] | b_table [B];
+
+#ifdef HAVE_SIGNED_SHIFT
+		  yval  = (*yptr2++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval  = *yptr2++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst2++ = r_table [R] | g_table [G] | b_table [B];
+		  *dst2++ = r_table [R] | g_table [G] | b_table [B];
+	       }
+	       memcpy (dst, dst - 2 * image->width,
+		       2 * image->width * sizeof (unsigned int));
+	       memcpy (dst2, dst2 - 2 * image->width,
+		       2 * image->width * sizeof (unsigned int));
+	       yptr  += image->width;
+	       yptr2 += image->width;
+	       dst   += 3 * image->width * 2;
+	       dst2  += 3 * image->width * 2;
+	    }
+	 }
+	 else
+	 {
+	    yptr2 = yptr + image->width;
+	    dst   = (unsigned int *) out;
+	    dst2  = dst + image->width;
+	    
+	    for (y = image->height / 2; y; y--)
+	    {
+	       for (x = image->width / 2; x; x--)
+	       {
+#ifdef HAVE_SIGNED_SHIFT
+		  crval = *crptr++ >> 4;
+		  cbval = *cbptr++ >> 4;
+		  yval  = (*yptr++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  crval = *crptr++ / 16;
+		  cbval = *cbptr++ / 16;
+		  yval  = *yptr++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+	       
+#ifdef HAVE_SIGNED_SHIFT
+		  yval  = (*yptr++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval  = *yptr++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+
+#ifdef HAVE_SIGNED_SHIFT
+		  yval  = (*yptr2++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval  = *yptr2++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst2++ = r_table [R] | g_table [G] | b_table [B];
+
+#ifdef HAVE_SIGNED_SHIFT
+		  yval  = (*yptr2++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  yval  = *yptr2++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  *dst2++ = r_table [R] | g_table [G] | b_table [B];
+	       }
+	       yptr  += image->width;
+	       yptr2 += image->width;
+	       dst   += image->width;
+	       dst2  += image->width;
+	    }
+	 }
+      }
+      else				/* 4:4:4 format */
+      {
+	 if (private->double_resolution)
+	 {
+	    unsigned int *dst;		/* pointer to dithered pixels */
+	    
+	    dst = (unsigned int *) out;
+	    
+	    for (y = image->height; y; y--)
+	    {
+	       for (x = image->width; x; x--)
+	       {
+#ifdef HAVE_SIGNED_SHIFT
+		  crval = *crptr++ >> 4;
+		  cbval = *cbptr++ >> 4;
+		  yval  = (*yptr++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+		  crval = *crptr++ / 16;
+		  cbval = *cbptr++ / 16;
+		  yval  = *yptr++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+		  R = yval + Cr_r_tab [crval];
+		  G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+		  B = yval + Cb_b_tab [cbval];
+		  
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+		  *dst++ = r_table [R] | g_table [G] | b_table [B];
+	       }
+	       memcpy (dst, dst - 2 * image->width,
+		       2 * image->width * sizeof (unsigned int));
+	       dst += image->width * 2;
+	    }
+	 }
+	 else
+	 {
+	    unsigned int *dst;		/* pointer to dithered pixels */
+
+	    dst  = (unsigned int *) out;
+	    
+	    for (n = image->width * image->height; n; n--)
+	    {
+#ifdef HAVE_SIGNED_SHIFT
+	       crval = *crptr++ >> 4;
+	       cbval = *cbptr++ >> 4;
+	       yval  = (*yptr++ >> 4) + 128;
+#else /* not HAVE_SIGNED_SHIFT */
+	       crval = *crptr++ / 16;
+	       cbval = *cbptr++ / 16;
+	       yval  = *yptr++  / 16 + 128;
+#endif /* not HAVE_SIGNED_SHIFT */
+	       R = yval + Cr_r_tab [crval];
+	       G = yval + Cr_g_tab [crval] + Cb_g_tab [cbval];
+	       B = yval + Cb_b_tab [cbval];
+
+	       *dst++ = r_table [R] | g_table [G] | b_table [B];
+	    }
+	 }
+      }
+   }
+   else
+   {
+      unsigned int *dst;		/* pointer to dithered pixels */
+      word_t	   *src;		/* current pixel of frame */
+      unsigned int *y_table;
+
+      y_table = private->y_table;
+      dst     = (unsigned int *) out;
+      src     = image->pixels [GRAY];
+      
+      if (private->double_resolution)
+      {
+	 int x, y;			/* pixel coordinates */
+	 
+	 for (y = image->height; y; y--)
+	 {
+	    for (x = image->width; x; x--)
+	    {
+	       int value;
+
+#ifdef HAVE_SIGNED_SHIFT
+	       value = y_table [*src++ >> 4];
+#else /* not HAVE_SIGNED_SHIFT */
+	       value = y_table [*src++ / 16];
+#endif /* not HAVE_SIGNED_SHIFT */
+	       *dst++ = value;
+	       *dst++ = value;
+	    }
+
+	    memcpy (dst, dst - 2 * image->width,
+		    2 * image->width * sizeof (unsigned int));
+	    dst += 2 * image->width;
+	 }
+      }
+      else
+      {
+	 int n;				/* pixel counter */
+	 
+	 for (n = image->width * image->height; n; n--)
+#ifdef HAVE_SIGNED_SHIFT
+	    *dst++ = y_table [*src++ >> 4];
+#else /* not HAVE_SIGNED_SHIFT */
+	    *dst++ = y_table [*src++ / 16];
+#endif /* not HAVE_SIGNED_SHIFT */
+      }
+   }
+   
+   return 1;
+}
+
+
+ 
diff --git a/converter/other/fiasco/lib/dither.h b/converter/other/fiasco/lib/dither.h
new file mode 100644
index 00000000..71f9d3c3
--- /dev/null
+++ b/converter/other/fiasco/lib/dither.h
@@ -0,0 +1,27 @@
+/*
+ *  dither.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:49:37 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#ifndef _DITHER_H
+#define _DITHER_H
+
+typedef struct renderer_private
+{
+   int 	       	*Cr_r_tab, *Cr_g_tab, *Cb_g_tab, *Cb_b_tab;
+   unsigned int *r_table, *g_table, *b_table, *y_table;
+   bool_t	double_resolution;
+} renderer_private_t;
+
+#endif /* _DITHER_H */
diff --git a/converter/other/fiasco/lib/error.c b/converter/other/fiasco/lib/error.c
new file mode 100644
index 00000000..b858badf
--- /dev/null
+++ b/converter/other/fiasco/lib/error.c
@@ -0,0 +1,326 @@
+/*
+ *  error.c:		Error handling
+ *
+ *  Written by:		Stefan Frank
+ *			Ullrich Hafner
+ *  
+ *  Credits:	Modelled after variable argument routines from Jef
+ *		Poskanzer's pbmplus package. 
+ *
+ *  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>
+
+    "int dummy = " change to int dummy; dummy =" for Netpbm to avoid 
+    unused variable warning.
+
+ */
+
+/*
+ *  $Date: 2000/06/14 20:49:37 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#define _ERROR_C
+
+#include "config.h"
+
+#include <stdio.h>
+#include <errno.h>
+
+#if STDC_HEADERS
+#	include <stdarg.h>
+#	define VA_START(args, lastarg) va_start(args, lastarg)
+#else  /* not STDC_HEADERS */
+#	include <varargs.h>
+#	define VA_START(args, lastarg) va_start(args)
+#endif /* not STDC_HEADERS */
+#if HAVE_STRING_H
+#	include <string.h>
+#else /* not HAVE_STRING_H */
+#	include <strings.h>
+#endif /* not HAVE_STRING_H */
+
+#if HAVE_SETJMP_H
+#	include <setjmp.h>
+#endif /* HAVE_SETJMP_H */
+
+#include "types.h"
+#include "macros.h"
+#include "error.h"
+
+#include "misc.h"
+#include "fiasco.h"
+
+/*****************************************************************************
+
+			     local variables
+  
+*****************************************************************************/
+
+static fiasco_verbosity_e  verboselevel  = FIASCO_SOME_VERBOSITY;
+static char 	      	  *error_message = NULL;
+
+#if HAVE_SETJMP_H
+jmp_buf env;
+#endif /* HAVE_SETJMP_H */
+
+/*****************************************************************************
+
+			       public code
+  
+*****************************************************************************/
+
+void
+set_error (const char *format, ...)
+/*
+ *  Set error text to given string.
+ */
+{
+   va_list     args;
+   unsigned    len = 0;
+   const char *str = format;
+   
+   VA_START (args, format);
+
+   len = strlen (format);
+   while ((str = strchr (str, '%')))
+   {
+      str++;
+      if (*str == 's')
+      {
+	 char *vstring = va_arg (args, char *);
+	 len += strlen (vstring);
+      }
+      else if (*str == 'd')
+      {
+	 int dummy;
+     dummy = va_arg (args, int);
+	 len += 10;
+      }
+      else if (*str == 'c')
+      {
+	 int dummy;
+     dummy = va_arg (args, int);
+	 len += 1;
+      }
+      else
+	 return;
+      str++;
+   }
+   va_end(args);
+
+   VA_START (args, format);
+
+   if (error_message)
+      Free (error_message);
+   error_message = Calloc (len, sizeof (char));
+   
+#if HAVE_VPRINTF
+   vsprintf (error_message, format, args);
+#elif HAVE_DOPRNT
+   _doprnt (format, args, stderr);
+#endif /* HAVE_DOPRNT */
+
+   va_end (args);
+}
+
+void
+error (const char *format, ...)
+/*
+ *  Set error text to given string.
+ */
+{
+   va_list     args;
+   unsigned    len = 0;
+   const char *str = format;
+   
+   VA_START (args, format);
+
+   len = strlen (format);
+   while ((str = strchr (str, '%')))
+   {
+      str++;
+      if (*str == 's')
+      {
+	 char *vstring = va_arg (args, char *);
+	 len += strlen (vstring);
+      }
+      else if (*str == 'd')
+      {
+	 int dummy;
+     dummy = va_arg (args, int);
+	 len += 10;
+      }
+      else if (*str == 'c')
+      {
+	 int dummy;
+     dummy = va_arg (args, int);
+	 len += 1;
+      }
+      else
+      {
+#if HAVE_SETJMP_H
+	 longjmp (env, 1);
+#else /* not HAVE_SETJMP_H */
+	 exit (1);
+#endif /* HAVE_SETJMP_H */
+      };
+      
+      str++;
+   }
+   va_end(args);
+
+   VA_START (args, format);
+
+   if (error_message)
+      Free (error_message);
+   error_message = Calloc (len, sizeof (char));
+   
+#if HAVE_VPRINTF
+   vsprintf (error_message, format, args);
+#elif HAVE_DOPRNT
+   _doprnt (format, args, stderr);
+#endif /* HAVE_DOPRNT */
+
+   va_end (args);
+   
+#if HAVE_SETJMP_H
+   longjmp (env, 1);
+#else /* not HAVE_SETJMP_H */
+   exit (1);
+#endif /* HAVE_SETJMP_H */
+}
+
+const char *
+fiasco_get_error_message (void)
+/*
+ *  Return value:
+ *	Last error message of FIASCO library.
+ */
+{
+   return error_message ? error_message : "";
+}
+
+const char *
+get_system_error (void)
+{
+   return strerror (errno);
+}
+
+void
+file_error (const char *filename)
+/*
+ *  Print file error message and exit.
+ *
+ *  No return value.
+ */
+{
+   error ("File `%s': I/O Error - %s.", filename, get_system_error ());
+}
+
+void 
+warning (const char *format, ...)
+/*
+ *  Issue a warning and continue execution.
+ *
+ *  No return value.
+ */
+{
+   va_list	args;
+
+   VA_START (args, format);
+
+   if (verboselevel == FIASCO_NO_VERBOSITY)
+      return;
+	
+   fprintf (stderr, "Warning: ");
+#if HAVE_VPRINTF
+   vfprintf (stderr, format, args);
+#elif HAVE_DOPRNT
+   _doprnt (format, args, stderr);
+#endif /* HAVE_DOPRNT */
+   fputc ('\n', stderr);
+
+   va_end (args);
+}
+
+void 
+message (const char *format, ...)
+/*
+ *  Print a message to stderr.
+ */
+{
+   va_list args;
+
+   VA_START (args, format);
+
+   if (verboselevel == FIASCO_NO_VERBOSITY)
+      return;
+
+#if HAVE_VPRINTF
+   vfprintf (stderr, format, args);
+#elif HAVE_DOPRNT
+   _doprnt (format, args, stderr);
+#endif /* HAVE_DOPRNT */
+   fputc ('\n', stderr);
+   va_end (args);
+}
+
+void 
+debug_message (const char *format, ...)
+/*
+ *  Print a message to stderr.
+ */
+{
+   va_list args;
+
+   VA_START (args, format);
+
+   if (verboselevel < FIASCO_ULTIMATE_VERBOSITY)
+      return;
+
+   fprintf (stderr, "*** ");
+#if HAVE_VPRINTF
+   vfprintf (stderr, format, args);
+#elif HAVE_DOPRNT
+   _doprnt (format, args, stderr);
+#endif /* HAVE_DOPRNT */
+   fputc ('\n', stderr);
+   va_end (args);
+}
+
+void
+info (const char *format, ...)
+/*
+ *  Print a message to stderr. Do not append a newline.
+ */
+{
+   va_list args;
+
+   VA_START (args, format);
+
+   if (verboselevel == FIASCO_NO_VERBOSITY)
+      return;
+
+#if HAVE_VPRINTF
+   vfprintf (stderr, format, args);
+#elif HAVE_DOPRNT
+   _doprnt (format, args, stderr);
+#endif /* HAVE_DOPRNT */
+   fflush (stderr);
+   va_end (args);
+}
+
+void
+fiasco_set_verbosity (fiasco_verbosity_e level)
+{
+   verboselevel = level;
+}
+
+fiasco_verbosity_e
+fiasco_get_verbosity (void)
+{
+   return verboselevel;
+}
diff --git a/converter/other/fiasco/lib/error.h b/converter/other/fiasco/lib/error.h
new file mode 100644
index 00000000..288b25f4
--- /dev/null
+++ b/converter/other/fiasco/lib/error.h
@@ -0,0 +1,39 @@
+/*
+ *  error.h
+ *  
+ *  Written by:     Stefan Frank
+ *          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>
+ */
+
+#ifndef ERROR_H_INCLUDED
+#define ERROR_H_INCLUDED
+
+void
+set_error (const char *format, ...);
+void
+error (const char *format, ...);
+void
+file_error (const char *filename);
+void
+message (const char *format, ...);
+void 
+debug_message (const char *format, ...);
+void
+warning (const char *format, ...);
+void 
+info (const char *format, ...);
+const char *
+get_system_error (void);
+
+#include <setjmp.h>
+extern jmp_buf env;
+
+#define try         if (setjmp (env) == 0)
+#define catch           else
+
+#include <assert.h>
+
+#endif
diff --git a/converter/other/fiasco/lib/image.c b/converter/other/fiasco/lib/image.c
new file mode 100644
index 00000000..019ba03c
--- /dev/null
+++ b/converter/other/fiasco/lib/image.c
@@ -0,0 +1,512 @@
+/*
+ *  image.c:		Input and output of PNM images.
+ *
+ *  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/15 17:21:30 $
+ *  $Author: hafner $
+ *  $Revision: 5.2 $
+ *  $State: Exp $
+ */
+
+#include "pnm.h"
+
+#include <string.h>
+
+#include "types.h"
+#include "macros.h"
+#include "error.h"
+
+#include "fiasco.h"
+#include "misc.h"
+#include "image.h"
+
+/*****************************************************************************
+
+				prototypes
+  
+*****************************************************************************/
+
+static void
+init_chroma_tables (void);
+
+/*****************************************************************************
+
+				local variables
+  
+*****************************************************************************/
+static int *Cr_r_tab = NULL;
+static int *Cr_g_tab = NULL;
+static int *Cb_g_tab = NULL;
+static int *Cb_b_tab = NULL;
+
+/*****************************************************************************
+
+				public code
+  
+*****************************************************************************/
+
+fiasco_image_t *
+fiasco_image_new (const char *filename)
+/*
+ *  FIASCO image constructor.
+ *  Allocate memory for the FIASCO image structure and
+ *  load the specified image `filename'. The image has to be in
+ *  raw pgm or ppm format.
+ *
+ *  Return value:
+ *	pointer to the new image structure
+ *	or NULL in case of an error
+ */
+{
+   try
+   {
+      fiasco_image_t *image = Calloc (1, sizeof (fiasco_image_t));
+
+      image->private 	= read_image (filename);
+      image->delete  	= fiasco_image_delete;
+      image->get_width  = fiasco_image_get_width;
+      image->get_height = fiasco_image_get_height;
+      image->is_color  	= fiasco_image_is_color;
+
+      return image;
+   }
+   catch
+   {
+      return NULL;
+   }
+}
+
+void
+fiasco_image_delete (fiasco_image_t *image)
+/*
+ *  FIASCO image destructor.
+ *  Free memory of FIASCO image struct.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *	structure 'image' is discarded.
+ */
+{
+   image_t *this = cast_image (image);
+
+   if (!this)
+      return;
+
+   try
+   {
+      free_image (this);
+   }
+   catch
+   {
+      return;
+   }
+}
+
+unsigned
+fiasco_image_get_width (fiasco_image_t *image)
+{
+   image_t *this = cast_image (image);
+
+   if (!this)
+      return 0;
+   else
+      return this->width;
+}
+
+unsigned
+fiasco_image_get_height (fiasco_image_t *image)
+{
+   image_t *this = cast_image (image);
+
+   if (!this)
+      return 0;
+   else
+      return this->width;
+}
+
+int
+fiasco_image_is_color (fiasco_image_t *image)
+{
+   image_t *this = cast_image (image);
+
+   if (!this)
+      return 0;
+   else
+      return this->color;
+}
+
+image_t *
+cast_image (fiasco_image_t *image)
+/*
+ *  Cast pointer `image' to type image_t.
+ *  Check whether `image' is a valid object of type image_t.
+ *
+ *  Return value:
+ *	pointer to dfiasco_t struct on success
+ *      NULL otherwise
+ */
+{
+   image_t *this = (image_t *) image->private;
+   if (this)
+   {
+      if (!streq (this->id, "IFIASCO"))
+      {
+	 set_error (_("Parameter `image' doesn't match required type."));
+	 return NULL;
+      }
+   }
+   else
+   {
+      set_error (_("Parameter `%s' not defined (NULL)."), "image");
+   }
+
+   return this;
+}
+
+image_t *
+alloc_image (unsigned width, unsigned height, bool_t color, format_e format)
+/*
+ *  Image constructor:
+ *  Allocate memory for the image_t structure.
+ *  Image size is given by 'width' and 'height'.
+ *  If 'color' == YES then allocate memory for three color bands (Y, Cb, Cr).
+ *  otherwise just allocate memory for a grayscale image.
+ *  'format' specifies whether image pixels of color images
+ *  are stored in 4:4:4 or 4:2:0 format.
+ *
+ *  Return value:
+ *	pointer to the new image structure.
+ */
+{
+   image_t *image;
+   color_e band;
+
+   if ((width & 1) || (height & 1))
+      error ("Width and height of images must be even numbers.");
+   if (!color)
+      format = FORMAT_4_4_4;
+
+   image         	  = Calloc (1, sizeof (image_t));
+   image->width  	  = width;
+   image->height 	  = height;
+   image->color  	  = color;
+   image->format 	  = format;
+   image->reference_count = 1;
+   
+   strcpy (image->id, "IFIASCO");
+
+   for (band = first_band (color); band <= last_band (color); band++)
+      if (format == FORMAT_4_2_0 && band != Y)
+	 image->pixels [band] = Calloc ((width * height) >> 2,
+					sizeof (word_t));
+      else
+	 image->pixels [band] = Calloc (width * height, sizeof (word_t));
+   
+   return image;
+}
+
+image_t *
+clone_image (image_t *image)
+/*
+ *  Copy constructor:
+ *  Construct new image by copying the given `image'.
+ *
+ *  Return value:
+ *	pointer to the new image structure.
+ */
+{
+   image_t *new = alloc_image (image->width, image->height, image->color,
+			       image->format);
+   color_e band;
+   
+   for (band = first_band (new->color); band <= last_band (new->color); band++)
+      if (new->format == FORMAT_4_2_0 && band != Y)
+      {
+	 memcpy (new->pixels [band], image->pixels [band],
+		 ((new->width * new->height) >> 2) * sizeof (word_t));
+      }
+      else
+      {
+	 memcpy (new->pixels [band], image->pixels [band],
+		 new->width * new->height * sizeof (word_t));
+      }
+
+   return new;
+}
+
+void
+free_image (image_t *image)
+/*
+ *  Image destructor:
+ *  Free memory of 'image' struct and pixel data.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *	structure 'image' is discarded.
+ */
+{
+   if (image != NULL)
+   {
+      if (--image->reference_count)
+	 return;			/* image is still referenced */
+      else
+      {
+	 color_e band;
+
+	 for (band  = first_band (image->color);
+	      band <= last_band (image->color); band++)
+	    if (image->pixels [band])
+	       Free (image->pixels [band]);
+	 Free (image);
+      }
+   }
+   else
+      warning ("Can't free image <NULL>.");
+}
+
+
+static void 
+read_image_data(image_t * const image, FILE *input, const bool_t color,
+                const int width, const int height, const xelval maxval,
+                const int format) {
+   int row;
+   int i;      /* Cursor into image->pixels arrays */
+   xel * xelrow;
+   /* The following are just the normal rgb -> YCbCr conversion matrix,
+      except normalization to maxval 4095 (12 bit color) is built in
+      */
+   const double coeff_lu_r = +0.2989 / maxval * 4095;
+   const double coeff_lu_g = +0.5866 / maxval * 4095;
+   const double coeff_lu_b = +0.1145 / maxval * 4095;
+   const double coeff_cb_r = -0.1687 / maxval * 4095;
+   const double coeff_cb_g = -0.3312 / maxval * 4095;
+   const double coeff_cb_b = +0.5000 / maxval * 4095;
+   const double coeff_cr_r = +0.5000 / maxval * 4095;
+   const double coeff_cr_g = -0.4183 / maxval * 4095;
+   const double coeff_cr_b = -0.0816 / maxval * 4095;
+
+   xelrow = pnm_allocrow(width);
+
+   i = 0; 
+   for (row = 0; row < height; row++) {
+       int col;
+       pnm_readpnmrow(input, xelrow, width, maxval, format);
+       for (col = 0; col < width; col++) {
+           if (color) {
+               image->pixels[Y][i] = 
+                   coeff_lu_r * PPM_GETR(xelrow[col]) 
+                   + coeff_lu_g * PPM_GETG(xelrow[col])
+                   + coeff_lu_b * PPM_GETB(xelrow[col]) - 2048;
+               image->pixels[Cb][i] = 
+                   coeff_cb_r * PPM_GETR(xelrow[col]) 
+                   + coeff_cb_g * PPM_GETG(xelrow[col])
+                   + coeff_cb_b * PPM_GETB(xelrow[col]);
+               image->pixels[Cr][i] = 
+                   coeff_cr_r * PPM_GETR(xelrow[col]) 
+                   + coeff_cr_g * PPM_GETG(xelrow[col])
+                   + coeff_cr_b * PPM_GETB(xelrow[col]);
+
+               i++;
+           } else 
+               image->pixels[GRAY][i++] =
+                   PNM_GET1(xelrow[col]) * 4095 / maxval - 2048;
+       }
+   }
+
+   free(xelrow);
+}
+
+
+
+image_t *
+read_image (const char *image_name)
+/*
+ *  Read image 'image_name'.
+ *  
+ *  Return value:
+ *	pointer to the image structure.
+ */
+{
+   FILE	    *input;			/* input stream */
+   image_t  *image;			/* pointer to new image structure */
+   int  width, height;		/* image size */
+   xelval   maxval;         /* Maxval of image */
+   int format;              /* Image's format code */
+   bool_t    color;			/* color image ? (YES/NO) */
+
+   if (image_name == NULL)
+       input = stdin;
+   else
+       input = pm_openr((char*)image_name);
+
+   pnm_readpnminit(input, &width, &height, &maxval, &format);
+
+   if (PNM_FORMAT_TYPE(format) == PPM_FORMAT)
+       color = YES;
+   else
+       color = NO;
+
+   if (width < 32)
+       pm_error("Image must have a width of at least 32 pixels.");
+
+   if (height < 32)
+       pm_error("Image must have a height of at least 32 pixels.");
+
+   image = alloc_image (width, height, color, FORMAT_4_4_4);
+
+   read_image_data(image, input, color, width, height, maxval, format);
+
+   pm_close(input);
+   
+   return image;
+}   
+
+void
+write_image (const char *image_name, const image_t *image)
+/*
+ *  Write given 'image' data to the file 'image_name'.
+ *  
+ *  No return value.
+ */
+{
+   FILE	*output;			/* output stream */
+   int format;
+   int row;
+   int i;     /* Cursor into image->pixel arrays */
+   xel * xelrow;
+   unsigned *gray_clip;			/* clipping table */
+
+   assert (image && image_name);
+   
+   if (image->format == FORMAT_4_2_0)
+   {
+      warning ("Writing of images in 4:2:0 format not supported.");
+      return;
+   }
+   
+   if (image_name == NULL)
+       output = stdout;
+   else if (strcmp(image_name, "-") == 0)
+       output = stdout;
+   else
+       output = pm_openw((char*)image_name);
+
+   gray_clip  = init_clipping ();	/* mapping of int -> unsigned */
+   if (!gray_clip)
+      error (fiasco_get_error_message ());
+   init_chroma_tables ();
+
+   format = image->color ? PPM_TYPE : PGM_TYPE;
+   
+   pnm_writepnminit(output, image->width, image->height, 255, format, 0);
+
+   xelrow = pnm_allocrow(image->width);
+   i = 0;
+   for (row = 0; row < image->height; row++) {
+       int col;
+       for (col = 0; col < image->width; col++) {
+           if (image->color) {
+               word_t yval, cbval, crval;
+
+               yval  = image->pixels[Y][i]  / 16 + 128;
+               cbval = image->pixels[Cb][i] / 16;
+               crval = image->pixels[Cr][i] / 16;
+
+               PPM_ASSIGN(xelrow[col], 
+                          gray_clip[yval + Cr_r_tab[crval]],
+                          gray_clip[yval + Cr_g_tab[crval] + Cb_g_tab [cbval]],
+                          gray_clip[yval + Cb_b_tab[cbval]]);
+
+           } else
+               /* The 16 below should be 4095/255 = 16.0588 */
+               PNM_ASSIGN1(xelrow[col], 
+                           gray_clip[image->pixels[GRAY][i]/16+128]);
+           i++;
+       }
+       pnm_writepnmrow(output, xelrow, 
+                       image->width, 255, format, 0);
+   }
+   pnm_freerow(xelrow);
+
+   pm_close(output);
+}
+
+bool_t
+same_image_type (const image_t *img1, const image_t *img2)
+/*
+ *  Check whether the given images 'img1' and `img2' are of the same type.
+ *
+ *  Return value:
+ *	YES	if images 'img1' and `img2' are of the same type
+ *	NO	otherwise.
+ */
+{
+   assert (img1 && img2);
+   
+   return ((img1->width == img2->width)
+	   && (img1->height == img2->height)
+	   && (img1->color == img2->color)
+	   && (img1->format == img2->format));
+}
+
+/*****************************************************************************
+
+				private code
+  
+*****************************************************************************/
+
+static void
+init_chroma_tables (void)
+/*
+ *  Chroma tables are used to perform fast YCbCr->RGB color space conversion.
+ */
+{
+   int crval, cbval, i;
+
+   if (Cr_r_tab != NULL || Cr_g_tab != NULL ||
+       Cb_g_tab != NULL || Cb_b_tab != NULL)
+      return;
+
+   Cr_r_tab = Calloc (768, sizeof (int));
+   Cr_g_tab = Calloc (768, sizeof (int));
+   Cb_g_tab = Calloc (768, sizeof (int));
+   Cb_b_tab = Calloc (768, sizeof (int));
+
+   for (i = 256; i < 512; i++)
+   {
+      cbval = crval  = i - 128 - 256;
+
+      Cr_r_tab[i] =  1.4022 * crval + 0.5;
+      Cr_g_tab[i] = -0.7145 * crval + 0.5;
+      Cb_g_tab[i] = -0.3456 * cbval + 0.5; 
+      Cb_b_tab[i] =  1.7710 * cbval + 0.5;
+   }
+   for (i = 0; i < 256; i++)
+   {
+      Cr_r_tab[i] = Cr_r_tab[256];
+      Cr_g_tab[i] = Cr_g_tab[256];
+      Cb_g_tab[i] = Cb_g_tab[256]; 
+      Cb_b_tab[i] = Cb_b_tab[256];
+   }
+   for (i = 512; i < 768; i++)
+   {
+      Cr_r_tab[i] = Cr_r_tab[511];
+      Cr_g_tab[i] = Cr_g_tab[511];
+      Cb_g_tab[i] = Cb_g_tab[511]; 
+      Cb_b_tab[i] = Cb_b_tab[511];
+   }
+
+   Cr_r_tab += 256 + 128;
+   Cr_g_tab += 256 + 128;
+   Cb_g_tab += 256 + 128;
+   Cb_b_tab += 256 + 128;
+}
+
diff --git a/converter/other/fiasco/lib/image.h b/converter/other/fiasco/lib/image.h
new file mode 100644
index 00000000..958049f6
--- /dev/null
+++ b/converter/other/fiasco/lib/image.h
@@ -0,0 +1,59 @@
+/*
+ *  image.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/10/22 10:43:56 $
+ *  $Author: hafner $
+ *  $Revision: 5.3 $
+ *  $State: Exp $
+ */
+
+#ifndef _IMAGE_H
+#define _IMAGE_H
+
+#include <stdio.h>
+#include "types.h"
+#include "fiasco.h"
+
+typedef enum {FORMAT_4_4_4, FORMAT_4_2_0} format_e;
+
+typedef struct image
+/*
+ *  Image data
+ */
+{
+   char      id [7];
+   unsigned  reference_count;
+   unsigned  width;			/* Width of the image */
+   unsigned  height;			/* Height of the image */
+   bool_t    color;			/* Color or grayscale image */
+   format_e  format;			/* Pixel format 4:4:4 or 4:2:0 */
+   word_t   *pixels [3];		/* Pixels in short format */
+} image_t;
+
+image_t *
+cast_image (fiasco_image_t *image);
+image_t *
+alloc_image (unsigned width, unsigned height, bool_t color, format_e format);
+image_t *
+clone_image (image_t *image);
+void
+free_image (image_t *image);
+FILE *
+read_pnmheader (const char *image_name, unsigned *width, unsigned *height,
+		bool_t *color);
+image_t *
+read_image (const char *image_name);
+void
+write_image (const char *image_name, const image_t *image);
+bool_t
+same_image_type (const image_t *img1, const image_t *img2);
+
+#endif /* not _IMAGE_H */
+
diff --git a/converter/other/fiasco/lib/list.c b/converter/other/fiasco/lib/list.c
new file mode 100644
index 00000000..9f516c2e
--- /dev/null
+++ b/converter/other/fiasco/lib/list.c
@@ -0,0 +1,258 @@
+/*
+ *  list.c:		List operations	
+ *
+ *  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:49:37 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#include "config.h"
+
+#if HAVE_STRING_H
+#	include <string.h>
+#else /* not HAVE_STRING_H */
+#	include <strings.h>
+#endif /* not HAVE_STRING_H */
+
+#include "types.h"
+#include "macros.h"
+#include "error.h"
+
+#include "misc.h"
+#include "list.h"
+
+/*****************************************************************************
+
+				public code
+  
+*****************************************************************************/
+
+list_t *
+alloc_list (size_t size_of_element)
+/*
+ *  List constructor:
+ *  Allocate a new list.
+ *  Size of list element values is given by 'size_of_element'.
+ *
+ *  Return value:
+ *	pointer to an empty list
+ */
+{
+   list_t *new_list = Calloc (1, sizeof (list_t));
+
+   assert (size_of_element > 0);
+
+   new_list->head 	     = NULL;
+   new_list->tail 	     = NULL;
+   new_list->size_of_element = size_of_element;
+
+   return new_list;
+}
+
+void
+free_list (list_t *list)
+/*
+ *  List destructor:
+ *  Discard list and its elements.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *	struct 'list' is discarded
+ */
+{
+   assert (list);
+   
+   while (list_remove (list, HEAD, NULL))
+      ;
+   Free (list);
+}
+
+void
+list_insert (list_t *list, pos_e pos, const void *data)
+/*
+ *  Insert a new 'list' element at head ('pos' = HEAD) or
+ *  tail ('pos' = TAIL) of 'list'. 
+ *  'data' is a pointer to a memory segment of size
+ *  'list'->size_of_element containing the value to store.
+ *  The value is directly copied - no references are stored.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *	lists current tail or head is replaced by the new element
+ */
+{
+   node_t *element;
+
+   assert (list && data);
+
+   element 	  = Calloc (1, sizeof (node_t));
+   element->value = Calloc (1, list->size_of_element);
+   memcpy (element->value, data, list->size_of_element);
+
+   if (pos == TAIL)
+   {
+      element->next = NULL;
+      element->prev = list->tail;
+      if (list->tail)
+	 list->tail->next = element;
+      list->tail = element;
+      if (!list->head)
+	 list->head = element;
+   }
+   else					/* pos == HEAD */
+   {
+      element->prev = NULL;
+      element->next = list->head;
+      if (list->head)
+	 list->head->prev = element;
+      list->head = element;
+      if (!list->tail)
+	 list->tail = element;
+   }
+}
+
+bool_t
+list_remove (list_t *list, pos_e pos, void *data)
+/*
+ *  Remove 'list' element from head or tail of 'list'.
+ *
+ *  Return value:
+ *	TRUE on success,
+ *	FALSE if list is empty or
+ *	      if list value data is NULL
+ *
+ *  Side effects:
+ *	lists current head or tail is removed
+ *	value of the removed list element (if not NULL) is copied to
+ *      'data' (if 'data' is not NULL)
+ */
+{
+   node_t *element;
+   void	  *valueptr;
+
+   assert (list);
+   
+   if (pos == TAIL)
+   {
+      element = list->tail;
+      if (element)
+      {
+	 list->tail = element->prev;
+	 valueptr   = element->value;
+	 Free (element);
+      }
+      else
+	 valueptr = NULL;
+      if (!list->tail)			/* 'element' was last node */
+	 list->head = NULL;
+   }
+   else					/* pos == HEAD */
+   {
+      element = list->head;
+      if (element)
+      {
+	 list->head = element->next;
+	 valueptr   = element->value;
+	 Free (element);
+      }
+      else
+	 valueptr = NULL;
+      if (!list->head)			/* 'element' was last node */
+	 list->tail = NULL;
+   }
+
+   if (valueptr)			/* copy value of node */
+   {
+      if (data)				
+	 memcpy (data, valueptr, list->size_of_element);
+      Free (valueptr);
+   }
+   
+   return valueptr ? TRUE : FALSE;
+}
+
+bool_t
+list_element_n (const list_t *list, pos_e pos, unsigned n, void *data)
+/*
+ *  Get value of 'list' element number 'n'.
+ *  (First element is list head if 'pos' == HEAD
+ *                 or list tail if 'pos' == TAIL.
+ *   Accordingly, traverse the list in ascending or descending order).
+ *  
+ *  Return value:
+ *	TRUE on success, FALSE if there is no element 'n'
+ *
+ *  Side effects:
+ *	value of list element 'n' is copied to 'data' 
+ */
+{
+   node_t *element;
+
+   assert (list && data);
+   
+   if (pos == HEAD)
+      for (element = list->head; element != NULL && n;
+	   element = element->next, n--)
+	 ;
+   else
+      for (element = list->tail; element != NULL && n;
+	   element = element->prev, n--)
+	 ;
+      
+   if (element)
+   {
+      memcpy (data, element->value, list->size_of_element);
+      return TRUE;
+   }
+   else
+      return FALSE;
+}
+
+unsigned
+list_sizeof (const list_t *list)
+/*
+ *  Count number of 'list' elements.
+ *
+ *  Return value:
+ *	number of 'list' elements.
+ */
+{
+   node_t   *element;
+   unsigned  n = 0;
+
+   assert (list);
+   
+   for (element = list->head; element != NULL; element = element->next)
+      n++;
+
+   return n;
+}
+
+void
+list_foreach (const list_t *list, void (*function)(void *, void *), void *data)
+/*
+ *  Call 'function' for each element of the 'list'.
+ *  Parameters given to 'function' are a pointer to the value of the
+ *  current 'list' element and the user pointer 'data'.
+ *
+ *  No return value.
+ */
+{
+   node_t *element;
+
+   assert (list && function && data);
+   
+   for (element = list->head; element; element = element->next)
+      function (element->value, data);
+}
+
diff --git a/converter/other/fiasco/lib/list.h b/converter/other/fiasco/lib/list.h
new file mode 100644
index 00000000..db7c08b2
--- /dev/null
+++ b/converter/other/fiasco/lib/list.h
@@ -0,0 +1,72 @@
+/*
+ *  list.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:49:37 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#ifndef _LIST_H
+#define _LIST_H
+
+#include <stdio.h>
+#include <stddef.h>
+
+typedef struct node
+{
+   struct node *prev;			/* pointer to prev list element */
+   struct node *next;			/* pointer to next list element */
+   void	       *value;			/* pointer to value of node */
+} node_t;
+
+typedef struct list
+{
+   node_t *head;
+   node_t *tail;
+   size_t  size_of_element;		/* number of bytes to store value */
+} list_t;
+
+typedef enum {TAIL, HEAD} pos_e;
+
+/*
+ *  Alias definitions for queue and stack
+ */
+
+typedef list_t lqueue_t ;
+#define alloc_queue		alloc_list
+#define free_queue		free_list		
+#define queue_append(q, d)	(list_insert ((q), TAIL, (d)))
+#define queue_remove(q, d)	(list_remove ((q), HEAD, (d)))
+
+typedef list_t lstack_t ;
+#define alloc_stack		alloc_list
+#define free_stack		free_list
+#define stack_push(q, d)	(list_insert ((q), TAIL, (d)))
+#define stack_pop(q, d)		(list_remove ((q), TAIL, (d)))
+
+list_t *
+alloc_list (size_t size_of_element);
+void 
+free_list (list_t *list);
+bool_t
+list_element_n (const list_t *list, pos_e pos, unsigned n, void *data);
+void
+list_foreach (const list_t *list, void (*function)(void *, void *),
+	      void *data);
+void
+list_insert (list_t *list, pos_e pos, const void *data);
+bool_t
+list_remove (list_t *list, pos_e pos, void *data);
+unsigned
+list_sizeof (const list_t *list);
+
+#endif /* not _LIST_H */
+
diff --git a/converter/other/fiasco/lib/macros.h b/converter/other/fiasco/lib/macros.h
new file mode 100644
index 00000000..877abeea
--- /dev/null
+++ b/converter/other/fiasco/lib/macros.h
@@ -0,0 +1,70 @@
+/*
+ *  macros.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:49:37 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#ifndef _MACROS_H
+#define _MACROS_H
+
+#include <string.h>
+/*******************************************************************************
+
+			  System configuration section
+  
+*******************************************************************************/
+
+#ifndef SEEK_CUR
+#   define SEEK_CUR	1
+#endif /* not SEEK_CUR */
+
+#ifdef WIN32
+#undef max
+#undef min
+#endif /* not WIN32 */
+
+/*****************************************************************************
+
+				Various macros
+  
+*****************************************************************************/
+
+#define streq(str1, str2)	(strcmp ((str1), (str2)) == 0)
+#define strneq(str1, str2)	(strcmp ((str1), (str2)) != 0)
+#define square(x)		((x) * (x))
+#define first_band(color)	((unsigned) ((color) ? Y  : GRAY))
+#define last_band(color)        ((unsigned) ((color) ? Cr : GRAY))
+#define width_of_level(l)	((unsigned) (1 << ((l) >> 1)))
+#define height_of_level(l)	((unsigned) (1 << (((l) + 1) >> 1)))
+#define size_of_level(l)	((unsigned) (1 << (l)))
+#define address_of_level(l)	((unsigned) (size_of_level (l) - 1))
+#define size_of_tree(l)		((unsigned) (address_of_level ((l) + 1)))
+#define is_odd(n)		(abs (n) % 2)
+#ifndef max
+#define max(a,b)		((a) < (b) ? (b) : (a))
+#endif
+#ifndef min
+#define min(a,b)	        ((a) > (b) ? (b) : (a))
+#endif
+#define _(x) (x) 
+
+
+#define	MAXSTRLEN 1024
+#define	MAXSTRLEN_SCANF "%1024s"
+
+typedef enum color {GRAY = 0, Y = 0, Cb = 1, Cr = 2} color_e;
+
+#endif /* _MACROS_H */
+
+
+
diff --git a/converter/other/fiasco/lib/misc.c b/converter/other/fiasco/lib/misc.c
new file mode 100644
index 00000000..02a1314f
--- /dev/null
+++ b/converter/other/fiasco/lib/misc.c
@@ -0,0 +1,563 @@
+/*
+ *  misc.c:		Some usefull functions, that don't fit in one of 
+ *			the other files and that are needed by at least
+ *			two modules. 
+ *
+ *  Written by:		Stefan Frank
+ *			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:49:37 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <ctype.h>
+
+#ifdef TIME_WITH_SYS_TIME
+#	include <sys/time.h>
+#	include <time.h>
+#else  /* not TIME_WITH_SYS_TIME */
+#	if HAVE_SYS_TIME_H
+#		include <sys/time.h>
+#	else /* not HAVE_SYS_TIME_H */
+#		include <time.h>
+#	endif /* not HAVE_SYS_TIME_H */
+#endif /* not TIME_WITH_SYS_TIME */
+
+#if STDC_HEADERS
+#	include <stdlib.h>
+#endif /* not STDC_HEADERS */
+
+#if HAVE_STRING_H
+#	include <string.h>
+#else /* not HAVE_STRING_H */
+#	include <strings.h>
+#endif /* not HAVE_STRING_H */
+
+#include "types.h"
+#include "macros.h"
+#include "error.h"
+
+#include "bit-io.h"
+#include "misc.h"
+
+/*****************************************************************************
+
+				prototypes
+  
+*****************************************************************************/
+
+static void
+remove_comments (FILE *file);
+
+/*****************************************************************************
+
+				public code
+  
+*****************************************************************************/
+
+void *
+Calloc (size_t n, size_t size)
+/*
+ *  Allocate memory like calloc ().
+ *
+ *  Return value: Pointer to the new block of memory on success,
+ *		  otherwise the program is terminated.
+ */
+{
+   void	*ptr;				/* pointer to the new memory block */
+
+   if (n <= 0 || size <= 0)
+      error ("Can't allocate memory for %d items of size %d",
+	     (int) n, (int) size);
+
+   ptr = calloc (n, size);
+   if (!ptr)
+      error ("Out of memory!");
+
+   return ptr;
+}
+
+void
+Free (void *memory)
+/*
+ *  Free memory given by the pointer 'memory'
+ *
+ *  No return value.
+ */
+{
+   if (memory != NULL)
+      free (memory);
+   else
+      warning ("Can't free memory block <NULL>.");
+}
+
+unsigned
+prg_timer (clock_t *last_timer, enum action_e action)
+/*
+ *  If 'action' == START then store current value of system timer.
+ *  If 'action' == STOP	 then compute number of elapsed micro seconds since
+ *			 the last time 'prg_timer' was called
+ *			 with 'action' == START.
+ *
+ *  Return value:
+ *	Number of elapsed micro seconds if 'action' == STOP
+ *	0				if 'action' == START
+ *
+ *  Side effects:
+ *	last_timer is set to current timer if action == START
+ */
+{
+   assert (last_timer);
+   
+   if (action == START)
+   {
+      *last_timer = clock ();
+      return 0;
+   }
+   else
+      return (clock () - *last_timer) / (CLOCKS_PER_SEC / 1000.0);
+}
+
+real_t 
+read_real (FILE *infile)
+/* 
+ *  Read one real value from the given input stream 'infile'.
+ *  
+ *  Return value:
+ *	real value on success
+ */
+{
+   float input;
+
+   assert (infile);
+   
+   remove_comments (infile);
+   if (fscanf(infile, "%f", &input) != 1)
+      error("Can't read float value!");
+
+   return (real_t) input;
+}
+
+int 
+read_int (FILE *infile)
+/* 
+ *  Read one integer value from the given input stream 'infile'.
+ *
+ *  Return value:
+ *	integer value on success
+ */
+{
+   int input;				/* integer */
+
+   assert (infile);
+   
+   remove_comments (infile);
+   if (fscanf(infile, "%d", &input) != 1)
+      error("Can't read integer value!");
+
+   return input;
+}
+   
+static void
+remove_comments (FILE *file)
+/*
+ *  Remove shell/pgm style comments (#) from the input 'file'
+ *
+ *  No return value.
+ */
+{
+   int c;				/* current character */
+   
+   assert (file);
+   
+   do
+   {
+      while (isspace(c = getc (file)))
+	 ;
+      if (c == EOF)
+	 error ("EOF reached, input seems to be truncated!");
+      if (c == '#')
+      {
+	 int dummy;
+	 
+	 while (((dummy = getc (file)) != '\n') && dummy != EOF)
+	    ;
+	 if (dummy == EOF)
+	    error ("EOF reached, input seems to be truncated!");
+      }
+      else 
+	 ungetc (c, file);
+   } while (c == '#');
+}
+
+void
+write_rice_code (unsigned value, unsigned rice_k, bitfile_t *output)
+/*
+ *  Write 'value' to the stream 'output' using Rice coding with base 'rice_k'.
+ *
+ *  No return value.
+ */
+{
+   unsigned unary;			/* unary part of Rice Code */
+
+   assert (output);
+   
+   for (unary = value >> rice_k; unary; unary--)
+      put_bit (output, 1);
+   put_bit (output, 0);
+   put_bits (output, value & ((1 << rice_k) - 1), rice_k);
+}
+
+unsigned
+read_rice_code (unsigned rice_k, bitfile_t *input)
+/*
+ *  Read a Rice encoded integer (base 'rice_k') from the stream 'input'.
+ *
+ *  Return value:
+ *	decoded integer
+ */
+{
+   unsigned unary;			/* unary part of Rice code */
+   
+   assert (input);
+   
+   for (unary = 0; get_bit (input); unary++) /* unary part */
+      ;
+
+   return (unary << rice_k) | get_bits (input, rice_k);
+}
+
+void
+write_bin_code (unsigned value, unsigned maxval, bitfile_t *output)
+/*
+ *  Write 'value' to the stream 'output' using an adjusted binary code
+ *  based on given 'maxval'.
+ *
+ *  No return value.
+ */
+{
+   unsigned k;
+   unsigned r;
+   
+   assert (output && maxval && value <= maxval);
+
+   k = log2 (maxval + 1);
+   r = (maxval + 1) % (1 << k);
+
+   if (value < maxval + 1 - 2 * r)	/* 0, ... , maxval - 2r */
+      put_bits (output, value, k);
+   else					/* maxval - 2r + 1, ..., maxval */
+      put_bits (output, value + maxval + 1 - 2 * r, k + 1);
+}
+
+unsigned
+read_bin_code (unsigned maxval, bitfile_t *input)
+/*
+ *  Read a bincode encoded integer from the stream 'input'.
+ *
+ *  Return value:
+ *	decoded integer
+ */
+{
+   unsigned k;
+   unsigned r;
+   unsigned value;
+   
+   assert (input);
+
+   k = log2 (maxval + 1);
+   r = (maxval + 1) % (1 << k);
+
+   value = get_bits (input, k);
+   if (value < maxval + 1 - 2 * r)
+      return value;
+   else
+   {
+      value <<= 1;
+      if (get_bit (input))
+	 value++;
+      return value - maxval - 1 + 2 * r;
+   }
+}
+
+unsigned
+bits_rice_code (unsigned value, unsigned rice_k)
+/*
+ *  Compute number of bits needed for coding integer 'value'
+ *  with given Rice code 'rice_k'.
+ *
+ *  Return value:
+ *	number of bits
+ */
+{
+   unsigned unary;
+   unsigned bits = 0;
+   
+   for (unary = value >> rice_k; unary; unary--)
+      bits++;
+   bits += rice_k + 1;
+
+   return bits;
+}
+
+unsigned
+bits_bin_code (unsigned value, unsigned maxval)
+/*
+ *  Compute number of bits needed for coding integer 'value'
+ *  with adjusted binary code of given maximum value 'maxval'.
+ *
+ *  Return value:
+ *	number of bits
+ */
+{
+   unsigned k;
+   unsigned r;
+
+   assert (maxval && value <= maxval);
+
+   k = log2 (maxval + 1);
+   r = (maxval + 1) % (1 << k);
+
+   return value < maxval + 1 - 2 * r ? k : k + 1;
+}
+
+unsigned *
+init_clipping (void)
+/*
+ *  Initialize the clipping tables
+ *
+ *  Return value:
+ *	pointer to clipping table
+ */
+{
+   static unsigned *gray_clip = NULL;	/* clipping array */
+
+   if (gray_clip == NULL)		/* initialize clipping table */
+   {
+      int i;				/* counter */
+
+      gray_clip  = calloc (256 * 3, sizeof (unsigned));
+      if (!gray_clip)
+      {
+	 set_error (_("Out of memory."));
+	 return NULL;
+      }
+      gray_clip += 256;
+
+      for (i = -256; i < 512; i++)
+	 if (i < 0)
+	    gray_clip [i] = 0;
+	 else if (i > 255)
+	    gray_clip [i] = 255;
+	 else
+	    gray_clip [i] = i;
+   }
+
+   return gray_clip;
+}
+
+#ifndef HAVE_MEMMOVE
+void *
+memmove (void *v_dst, const void *v_src, size_t n)
+/*
+ *  Copy 'n' bytes from memory area 'src' to memory area 'dest'.
+ *  The memory areas may overlap.
+ *
+ *  Return value:
+ *	pointer 'dest'
+ */
+{
+   byte_t	*to, *dst = (byte_t *) v_dst;
+   const byte_t	*from, *src = (byte_t *) v_src;
+   
+   assert (v_dst && v_src);
+   
+   if (dst <= src)
+   {
+      from = src;
+      to   = dst;
+      for (; n; n--)
+	 *to++ = *from++;
+   }
+   else
+   { 
+      from = src + (n - 1);
+      to   = dst + (n - 1);
+      for (; n; n--)
+	 *to-- = *from--;
+   }
+   
+   return v_dst;
+}
+#endif /* not HAVE_MEMMOVE */
+
+#ifndef HAVE_STRDUP
+char *
+strdup (const char *s)
+/*
+ *  Duplicate given string 's'.
+ *
+ *  Return value:
+ *	pointer to new string value
+ */
+{
+   assert (s);
+   
+   return strcpy (Calloc (strlen (s) + 1, sizeof (char)), s);
+}
+#endif /* not HAVE_STRDUP */
+
+/* Note that some systems have a "log2()" in the math library and some
+   have a "log2" macro.  So we name ours Log2.  But to avoid lots of
+   differences from the original fiasco source code, we define a
+   macro log2 in config.h to expand to Log2.
+   */
+double
+Log2 (double x)
+/*
+ *  Return value:
+ *	base-2 logarithm of 'x'
+ */
+{
+   return log (x) / 0.69314718;
+}
+
+#ifndef HAVE_STRCASECMP
+bool_t
+strcaseeq (const char *s1, const char *s2)
+/*
+ *  Compare strings 's1' and 's2', ignoring  the  case of the characters.
+ *
+ *  Return value:
+ *	TRUE if strings match, else FALSE
+ */
+{
+   bool_t  matched;
+   char	  *ls1, *ls2, *ptr;
+
+   assert (s1 && s2);
+   
+   ls1 = strdup (s1);
+   ls2 = strdup (s2);
+   
+   for (ptr = ls1; *ptr; ptr++)
+      *ptr = tolower (*ptr);
+   for (ptr = ls2; *ptr; ptr++)
+      *ptr = tolower (*ptr);
+
+   matched = streq (ls1, ls2) ? YES : NO;
+
+   Free (ls1);
+   Free (ls2);
+   
+   return matched;
+}
+#endif /* not HAVE_STRCASECMP */
+
+real_t
+variance (const word_t *pixels, unsigned x0, unsigned y0,
+	  unsigned width, unsigned height, unsigned cols)
+/*
+ *  Compute variance of subimage ('x0', y0', 'width', 'height') of 
+ *  the image data given by 'pixels' ('cols' is the number of pixels
+ *  in one row of the image).
+ *
+ *  Return value:
+ *	variance
+ */
+{
+   real_t   average;			/* average of pixel values */
+   real_t   variance;			/* variance of pixel values */
+   unsigned x, y;			/* pixel counter */
+   unsigned n;				/* number of pixels */
+
+   assert (pixels);
+   
+   for (average = 0, n = 0, y = y0; y < y0 + height; y++)
+      for (x = x0; x < min (x0 + width, cols); x++, n++)
+	 average += pixels [y * cols + x] / 16;
+
+   average /= n;
+
+   for (variance = 0, y = y0; y < y0 + height; y++)
+      for (x = x0; x < min (x0 + width, cols); x++)
+	 variance += square ((pixels [y * cols + x] / 16) - average);
+
+   return variance;
+}
+
+int
+sort_asc_word (const void *value1, const void *value2)
+/*
+ *  Sorting function for quicksort.
+ *  Smallest values come first.
+ */
+{
+   if (* (word_t *) value1 < * (word_t *) value2)
+      return -1;
+   else if (* (word_t *) value1 > * (word_t *) value2)
+      return +1;
+   else
+      return 0;
+}
+
+int
+sort_desc_word (const void *value1, const void *value2)
+/*
+ *  Sorting function for quicksort.
+ *  Largest values come first.
+ */
+{
+   if (* (word_t *) value1 > * (word_t *) value2)
+      return -1;
+   else if (* (word_t *) value1 < * (word_t *) value2)
+      return +1;
+   else
+      return 0;
+}
+
+int
+sort_asc_pair (const void *value1, const void *value2)
+/*
+ *  Sorting function for quicksort.
+ *  Smallest values come first.
+ */
+{
+   word_t v1 = ((pair_t *) value1)->key;
+   word_t v2 = ((pair_t *) value2)->key;
+   
+   if (v1 < v2)
+      return -1;
+   else if (v1 > v2)
+      return +1;
+   else
+      return 0;
+}
+
+int
+sort_desc_pair (const void *value1, const void *value2)
+/*
+ *  Sorting function for quicksort.
+ *  Largest values come first.
+ */
+{
+   word_t v1 = ((pair_t *) value1)->key;
+   word_t v2 = ((pair_t *) value2)->key;
+
+   if (v1 > v2)
+      return -1;
+   else if (v1 < v2)
+      return +1;
+   else
+      return 0;
+}
diff --git a/converter/other/fiasco/lib/misc.h b/converter/other/fiasco/lib/misc.h
new file mode 100644
index 00000000..29456590
--- /dev/null
+++ b/converter/other/fiasco/lib/misc.h
@@ -0,0 +1,98 @@
+/*
+ *  misc.h
+ *
+ *  Written by:		Stefan Frank
+ *			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:49:37 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#ifndef _MISC_H
+#define _MISC_H
+
+#include "config.h"
+
+#if TIME_WITH_SYS_TIME
+#	include <sys/time.h>
+#	include <time.h>
+#else  /* not TIME_WITH_SYS_TIME */
+#	if HAVE_SYS_TIME_H
+#		include <sys/time.h>
+#	else /* not HAVE_SYS_TIME_H */
+#		include <time.h>
+#	endif /* not HAVE_SYS_TIME_H */
+#endif /* not TIME_WITH_SYS_TIME */
+
+#include <stdio.h>
+#include "types.h"
+#include "bit-io.h"
+
+enum action_e {START, STOP};
+
+void *
+Calloc (size_t n, size_t size);
+void
+Free (void *memory);
+unsigned
+prg_timer (clock_t *ptimer, enum action_e action);
+int 
+read_int(FILE *infile);
+real_t 
+read_real(FILE *infile);
+unsigned
+read_rice_code (unsigned rice_k, bitfile_t *input);
+void
+write_rice_code (unsigned value, unsigned rice_k, bitfile_t *output);
+void
+write_bin_code (unsigned value, unsigned maxval, bitfile_t *output);
+unsigned
+bits_bin_code (unsigned value, unsigned maxval);
+unsigned
+bits_rice_code (unsigned value, unsigned rice_k);
+unsigned
+read_bin_code (unsigned maxval, bitfile_t *input);
+unsigned *
+init_clipping (void);
+real_t
+variance (const word_t *pixels, unsigned x0, unsigned y0,
+	  unsigned width, unsigned height, unsigned cols);
+
+#ifndef HAVE_MEMMOVE
+void *
+memmove(void *dest, const void *src, size_t n);
+#endif /* not HAVE_MEMMOVE */
+
+double
+Log2 (double x);
+#ifndef HAVE_STRDUP
+char *
+strdup (const char *s);
+#endif
+#ifndef HAVE_STRCASECMP
+bool_t
+strcaseeq (const char *s1, const char *s2);
+#else  /* HAVE_STRCASECMP */
+int
+strcasecmp (const char *s1, const char *s2);
+#define strcaseeq(s1, s2) (strcasecmp ((s1), (s2)) == 0)
+#endif /* HAVE_STRCASECMP */
+
+int
+sort_asc_word (const void *value1, const void *value2);
+int
+sort_desc_word (const void *value1, const void *value2);
+int
+sort_asc_pair (const void *value1, const void *value2);
+int
+sort_desc_pair (const void *value1, const void *value2);
+
+#endif /* not _MISC_H */
+
diff --git a/converter/other/fiasco/lib/mvcode.c b/converter/other/fiasco/lib/mvcode.c
new file mode 100644
index 00000000..d9ce91e2
--- /dev/null
+++ b/converter/other/fiasco/lib/mvcode.c
@@ -0,0 +1,14 @@
+#include "mvcode.h"
+
+unsigned mv_code_table [33][2] =
+/*
+ *  MPEG's huffman code for vector components. Format: code_value, length
+ */
+{
+   {0x19, 11}, {0x1b, 11}, {0x1d, 11}, {0x1f, 11}, {0x21, 11}, {0x23, 11},
+   {0x13, 10}, {0x15, 10}, {0x17, 10}, {0x7, 8}, {0x9, 8}, {0xb, 8}, {0x7, 7},
+   {0x3, 5}, {0x3, 4}, {0x3, 3}, {0x1, 1}, {0x2, 3}, {0x2, 4}, {0x2, 5},
+   {0x6, 7}, {0xa, 8}, {0x8, 8}, {0x6, 8}, {0x16, 10}, {0x14, 10}, {0x12, 10}, 
+   {0x22, 11}, {0x20, 11}, {0x1e, 11}, {0x1c, 11}, {0x1a, 11}, {0x18, 11}
+};
+
diff --git a/converter/other/fiasco/lib/mvcode.h b/converter/other/fiasco/lib/mvcode.h
new file mode 100644
index 00000000..f43f2081
--- /dev/null
+++ b/converter/other/fiasco/lib/mvcode.h
@@ -0,0 +1,6 @@
+#ifndef MVCODE_H_INCLUDED
+#define MVCODE_H_INCLUDED
+
+extern unsigned mv_code_table [33][2];
+
+#endif
diff --git a/converter/other/fiasco/lib/rpf.c b/converter/other/fiasco/lib/rpf.c
new file mode 100644
index 00000000..ac7d48ca
--- /dev/null
+++ b/converter/other/fiasco/lib/rpf.c
@@ -0,0 +1,223 @@
+/*
+ *  rpf.c:		Conversion of float to reduced precision format values
+ *
+ *  Written by:		Stefan Frank
+ *			Richard Krampfl
+ *			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:49:37 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#include "config.h"
+
+#include "types.h"
+#include "macros.h"
+#include "error.h"
+
+#include "misc.h"
+#include "rpf.h"
+
+/* 
+ * CAUTION: The IEEE float format must be used by your compiler,
+ *          or all following code is void!
+ */
+
+#ifdef WORDS_BIGENDIAN
+/*
+ *  Big-Endian Architecture (e.g. SUN, Motorola)
+ *  Memory representation of integer 0x00112233 is 00,11,22,33
+ */
+
+enum real_bytes {BYTE_0, BYTE_1, BYTE_2, BYTE_3};
+
+#else  /* not WORDS_BIGENDIAN */
+/*
+ *  Little-Endian Architecture (e.g. Intel, VAX, Alpha)
+ *  Memory representation of integer 0x00112233 is 33,22,11,00
+ */
+
+enum real_bytes {BYTE_3, BYTE_2, BYTE_1, BYTE_0};
+
+#endif /* not WORDS_BIGENDIAN */
+
+const int RPF_ZERO = -1;
+
+/*****************************************************************************
+
+			       private code
+  
+*****************************************************************************/
+
+int
+rtob (real_t f, const rpf_t *rpf)
+/*
+ *  Convert real number 'f' into fixed point format.
+ *  The real number in [-'range'; +'range'] is scaled to [-1 ; +1].
+ *  Sign and the first 'precision' - 1 bits of the mantissa are
+ *  packed into one integer.  
+ *
+ *  Return value:
+ *	real value in reduced precision format
+ */
+{  
+   unsigned int	mantissa;
+   int		exponent, sign;
+   union
+   {
+      float f;
+      unsigned char c[4];
+   } v;					/* conversion dummy */
+
+   f  /= rpf->range;			/* scale f to [-1,+1] */	
+   v.f = f;
+
+   /*
+    *  Extract mantissa (23 Bits), exponent (8 Bits) and sign (1 Bit)
+    */
+
+   mantissa = ((((v.c[BYTE_1] & 127) << 8 ) | v.c[BYTE_2]) << 8) | v.c[BYTE_3];
+   exponent = (((v.c[BYTE_0] & 127) << 1) | (v.c[BYTE_1] & 128 ? 1 : 0)) - 126;
+   sign     = v.c[BYTE_0] & 128 ? 1 : 0;
+		
+   /*
+    *  Generate reduced precision mantissa.
+    */
+   mantissa >>= 1;				/* shift 1 into from left */
+   mantissa  |= (1 << 22);
+   if (exponent > 0) 
+      mantissa <<= exponent;
+   else
+      mantissa >>= -exponent;  
+   
+   mantissa >>= (23 - rpf->mantissa_bits - 1);
+
+   mantissa +=  1;			/* Round last bit. */
+   mantissa >>= 1;
+   
+   if (mantissa == 0)			/* close to zero */
+      return RPF_ZERO;
+   else if (mantissa >= (1U << rpf->mantissa_bits)) /* overflow */
+      return sign;
+   else
+      return ((mantissa & ((1U << rpf->mantissa_bits) - 1)) << 1) | sign;
+}
+
+float
+btor (int binary, const rpf_t *rpf)
+/*
+ *  Convert value 'binary' in reduced precision format to a real value.
+ *  For more information refer to function lin_rtob() above.
+ *
+ *  Return value:
+ *	converted value
+ */
+{
+   unsigned int	mantissa;
+   int		sign, exponent;
+   union
+   {
+      float f;
+      unsigned char c[4];
+   } value;
+
+   if (binary == RPF_ZERO)
+      return 0;
+
+   if (binary < 0 || binary >= 1 << (rpf->mantissa_bits + 1))
+      error ("Reduced precision format: value %d out of range.", binary);
+
+   /*
+    *  Restore IEEE float format:
+    *  mantissa (23 Bits), exponent (8 Bits) and sign (1 Bit)
+    */
+   
+   sign       = binary & 1;
+   mantissa   = (binary & ((1 << (rpf->mantissa_bits + 1)) - 1)) >> 1; 
+   mantissa <<= (23 - rpf->mantissa_bits);
+   exponent   = 0;
+
+   if (mantissa == 0)
+   {
+      value.f = (sign ? -1.0 : 1.0);
+   }
+   else
+   {
+      while (!(mantissa & (1 << 22)))	/* normalize mantissa */
+      {
+	 exponent--;
+	 mantissa <<= 1;
+      }
+      mantissa <<= 1;
+
+      value.c[BYTE_0] = (sign << 7) | ((exponent + 126) >> 1);
+      value.c[BYTE_1] = (((exponent + 126) & 1) << 7)
+			| ((mantissa  >> 16) & 127);
+      value.c[BYTE_2] = (mantissa >> 8) & 255;
+      value.c[BYTE_3] = mantissa & 255;
+   }
+   
+   return value.f * rpf->range;		/* expand [ -1 ; +1 ] to
+					   [ -range ; +range ] */
+}
+
+rpf_t *
+alloc_rpf (unsigned mantissa, fiasco_rpf_range_e range)
+/*
+ *  Reduced precision format constructor.
+ *  Allocate memory for the rpf_t structure.
+ *  Number of mantissa bits is given by `mantissa'.
+ *  The range of the real values is in the interval [-`range', +`range'].
+ *  In case of invalid parameters, a structure with default values is
+ *  returned. 
+ *
+ *  Return value
+ *	pointer to the new rpf structure
+ */
+{
+   rpf_t *rpf = Calloc (1, sizeof (rpf_t));
+   
+   if (mantissa < 2)
+   {
+      warning (_("Size of RPF mantissa has to be in the interval [2,8]. "
+		 "Using minimum value 2.\n"));
+      mantissa = 2;
+   }
+   else if (mantissa > 8)
+   {
+      warning (_("Size of RPF mantissa has to be in the interval [2,8]. "
+		 "Using maximum value 8.\n"));
+      mantissa = 2;
+   }
+
+   rpf->mantissa_bits = mantissa;
+   rpf->range_e       = range;
+   switch (range)
+   {
+      case FIASCO_RPF_RANGE_0_75:
+	 rpf->range = 0.75;
+	 break;
+      case FIASCO_RPF_RANGE_1_50:
+	 rpf->range = 1.50;
+	 break;
+      case FIASCO_RPF_RANGE_2_00:
+	 rpf->range = 2.00;
+	 break;
+      case FIASCO_RPF_RANGE_1_00:
+	 rpf->range = 1.00;
+	 break;
+      default:
+	 warning (_("Invalid RPF range specified. Using default value 1.0."));
+	 rpf->range   = 1.00;
+	 rpf->range_e = FIASCO_RPF_RANGE_1_00;
+	 break;
+   }
+   return rpf;
+}
diff --git a/converter/other/fiasco/lib/rpf.h b/converter/other/fiasco/lib/rpf.h
new file mode 100644
index 00000000..ba3ff6be
--- /dev/null
+++ b/converter/other/fiasco/lib/rpf.h
@@ -0,0 +1,47 @@
+/*
+ *  rpf.h
+ *
+ *  Written by:		Stefan Frank
+ *			Richard Krampfl
+ *			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:49:37 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#ifndef _RPF_H
+#define _RPF_H
+
+#include "types.h"
+#include "fiasco.h"
+
+typedef struct rpf
+{
+   unsigned    	      mantissa_bits;	/* number of bits used for mantissa */
+   real_t      	      range;		/* scale value to [-range, +range] */
+   fiasco_rpf_range_e range_e;
+} rpf_t;
+
+int
+rtob (real_t real, const rpf_t *rpf);
+real_t 
+btor (int b, const rpf_t *rpf);
+rpf_t *
+alloc_rpf (unsigned mantissa, fiasco_rpf_range_e range);
+
+extern const int RPF_ZERO;
+
+#endif /* not _RPF_H */
+
+
+
+
+
+
diff --git a/converter/other/fiasco/lib/types.h b/converter/other/fiasco/lib/types.h
new file mode 100644
index 00000000..16d8028c
--- /dev/null
+++ b/converter/other/fiasco/lib/types.h
@@ -0,0 +1,38 @@
+/*
+ *  types.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:49:37 $
+ *  $Author: hafner $
+ *  $Revision: 5.1 $
+ *  $State: Exp $
+ */
+
+#ifndef _FIASCO_TYPES_H
+#define _FIASCO_TYPES_H
+
+#undef FALSE
+#undef NO
+#undef TRUE
+#undef YES
+
+enum fiasco_boolean { NO = 0, FALSE = 0, YES = 1, TRUE = 1};
+
+typedef float                real_t;
+typedef enum fiasco_boolean  bool_t;
+typedef unsigned char        byte_t;
+typedef short                word_t;
+typedef unsigned short       u_word_t;
+typedef struct pair
+{
+   word_t key;
+   word_t value;
+} pair_t;
+
+#endif