about summary refs log tree commit diff
path: root/converter/other/fiasco/codec/subdivide.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/other/fiasco/codec/subdivide.c')
-rw-r--r--converter/other/fiasco/codec/subdivide.c650
1 files changed, 650 insertions, 0 deletions
diff --git a/converter/other/fiasco/codec/subdivide.c b/converter/other/fiasco/codec/subdivide.c
new file mode 100644
index 00000000..b7982716
--- /dev/null
+++ b/converter/other/fiasco/codec/subdivide.c
@@ -0,0 +1,650 @@
+/*
+ *  subdivide.c:	Recursive subdivision of range 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/07/15 17:59:31 $
+ *  $Author: hafner $
+ *  $Revision: 5.4 $
+ *  $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 "image.h"
+#include "cwfa.h"
+#include "approx.h"
+#include "ip.h"
+#include "bintree.h"
+#include "control.h"
+#include "prediction.h"
+#include "domain-pool.h"
+#include "mwfa.h"
+#include "misc.h"
+#include "subdivide.h"
+#include "list.h"
+#include "coeff.h"
+#include "wfalib.h"
+
+/*****************************************************************************
+
+				prototypes
+
+*****************************************************************************/
+
+static void
+init_new_state (bool_t auxiliary_state, bool_t delta, range_t *range,
+		const range_t *child, const int *y_state,
+		wfa_t *wfa, coding_t *c);
+static void
+init_range (range_t *range, const image_t *image, unsigned band,
+	    const wfa_t *wfa, coding_t *c);
+
+/*****************************************************************************
+
+				public code
+  
+*****************************************************************************/
+
+real_t 
+subdivide (real_t max_costs, unsigned band, int y_state, range_t *range,
+	   wfa_t *wfa, coding_t *c, bool_t prediction, bool_t delta)
+/*
+ *  Subdivide the current 'range' recursively and decide whether
+ *  a linear combination, a recursive subdivision, or a prediction is
+ *  the best choice of approximation.
+ *  'band' is the current color band, 'y_state' is the corresponding
+ *  state of the Y color component (color image compression only).
+ *  If 'prediction' is TRUE then also test motion compensation or
+ *  nondeterministic approximation.
+ *  If 'delta' is TRUE then current range is already predicted.
+ *  
+ *  Return value:
+ *	costs of the best approximation or MAXCOSTS if costs exceed 'max_costs'
+ *
+ *  Side effects:
+ *	'range'	factors and costs of linear combination are modified
+ *      'wfa'	new transitions and prediction coefficients are added
+ *	'c'	pixels and inner products are updated
+ */
+{
+   real_t    subdivide_costs;        /* Costs arising from approx. the current
+				       range with two childs */
+   real_t    lincomb_costs;          /* Costs arising from approx. the current
+				       range with a linear combination */
+   int	     new_y_state [MAXLABELS];	/* Corresponding state of Y */
+   real_t    price;			/* Approximation costs multiplier */
+   bool_t    try_mc;			/* YES: try MC prediction */
+   bool_t    try_nd;			/* YES: try ND prediction */
+   unsigned  states;			/* Number of states before the
+					   recursive subdivision starts */
+   void     *domain_model;		/* copy of domain pool model */      
+   void     *d_domain_model;		/* copy of delta domain pool model */
+   void     *lc_domain_model;		/* copy of domain pool model */
+   void     *lc_d_domain_model;		/* copy of delta domain pool model */
+   void	    *coeff_model;	        /* copy of coefficients model */
+   void	    *d_coeff_model;		/* copy of delta coefficients model */
+   void	    *lc_coeff_model;	        /* copy of coefficients model */
+   void	    *lc_d_coeff_model;		/* copy of delta coefficients model */
+   tree_t    tree_model;		/* copy of tree model */
+   tree_t    p_tree_model;		/* copy of pred. tree model */
+   range_t   lrange;			/* range of lin. comb. approx. */
+   range_t   rrange;			/* range of recursive approx. */
+   range_t   child [MAXLABELS];		/* new childs of the current range */
+   static unsigned percent = 0;		/* status of progress meter */
+
+   if (wfa->wfainfo->level == range->level)
+      percent = 0;
+   
+   range->into [0] = NO_EDGE;		/* default approximation: empty */
+   range->tree     = RANGE;
+
+   if (range->level < 3)		/* Don't process small ranges */
+      return MAXCOSTS;	
+
+   /*
+    *  If image permutation (tiling) is performed and the tiling level
+    *  is reached then get coordinates of the new block.
+    */
+   if (c->tiling->exponent
+       && range->level == wfa->wfainfo->level - c->tiling->exponent)
+   {
+      unsigned width, height;		/* size of range (dummies)*/
+      
+      if (c->tiling->vorder [range->global_address] < 0)
+	 return 0;			/* nothing to do */
+      else
+	 locate_subimage (wfa->wfainfo->level, range->level,
+			  c->tiling->vorder [range->global_address],
+			  &range->x, &range->y, &width, &height);
+   }
+
+   if (range->x >= c->mt->original->width ||
+       range->y >= c->mt->original->height)
+      return 0;				/* range is not visible */
+
+   /*
+    *  Check whether prediction is allowed or not
+    *  mc == motion compensation, nd == nondeterminism
+    */
+   try_mc = (prediction && c->mt->frame_type != I_FRAME			
+	     && range->level >= wfa->wfainfo->p_min_level
+	     && range->level <= wfa->wfainfo->p_max_level
+	     && (range->x + width_of_level (range->level)
+		 <= c->mt->original->width)
+	     && (range->y + height_of_level (range->level)
+		 <= c->mt->original->height));
+
+   try_nd = (prediction && c->mt->frame_type == I_FRAME
+	     && range->level >= wfa->wfainfo->p_min_level
+	     && range->level <= wfa->wfainfo->p_max_level);
+
+   if (try_mc)
+      clear_norms_table (range->level, wfa->wfainfo, c->mt);
+
+   
+   /*
+    *  Check if current range must be initialized. I.e. range pixels must
+    *  be copied from entire image to bintree pixel buffer. Moreover,
+    *  all inner products tables must be initialized.
+    */
+   if (range->level == c->options.lc_max_level)	
+      init_range (range, c->mt->original, band, wfa, c);
+   
+   price = c->price;
+   if (band != Y)			
+      price *= c->options.chroma_decrease; /* less quality for chroma bands */
+
+   /*
+    *  Compute childs of corresponding state in Y band
+    */
+   if (band != Y)			/* Cb and Cr bands only */
+   {
+      unsigned label;
+
+      for (label = 0; label < MAXLABELS; label++)
+	 if (ischild (y_state))
+	    new_y_state [label] = wfa->tree [y_state][label];
+	 else
+	    new_y_state [label] = RANGE;
+   }
+   else
+      new_y_state [0] = new_y_state [1] = RANGE;
+   
+   /*
+    *  Store contents of all models that may get modified during recursion
+    */
+   domain_model   = c->domain_pool->model_duplicate (c->domain_pool->model);
+   d_domain_model = c->d_domain_pool->model_duplicate (c->d_domain_pool->model);
+   coeff_model    = c->coeff->model_duplicate (c->coeff, c->coeff->model);
+   d_coeff_model  = c->d_coeff->model_duplicate (c->d_coeff, c->d_coeff->model);
+   tree_model     = c->tree;
+   p_tree_model   = c->p_tree;
+   states         = wfa->states;	
+   
+   /*
+    *  First alternative of range approximation:
+    *  Compute costs of linear combination.
+    */
+   if (range->level <= c->options.lc_max_level) /* range is small enough */
+   {
+      lrange                 = *range;
+      lrange.tree            = RANGE;
+      lrange.tree_bits       = tree_bits (LEAF, lrange.level, &c->tree);
+      lrange.matrix_bits     = 0;
+      lrange.weights_bits    = 0;
+      lrange.mv_tree_bits    = try_mc ? 1 : 0; /* mc allowed but not used */
+      lrange.mv_coord_bits   = 0;
+      lrange.nd_tree_bits    = 0;	
+      lrange.nd_weights_bits = 0;	
+      lrange.prediction	     = NO;
+      
+      lincomb_costs
+	 = approximate_range (max_costs, price, c->options.max_elements,
+			      y_state, &lrange,
+			      (delta ? c->d_domain_pool : c->domain_pool),
+			      (delta ? c->d_coeff : c->coeff), wfa, c);
+   }
+   else
+      lincomb_costs = MAXCOSTS;		
+
+   /*
+    *  Store contents of models that have been modified
+    *  by approximate_range () above ...
+    */
+   lc_domain_model   = c->domain_pool->model;
+   lc_d_domain_model = c->d_domain_pool->model;
+   lc_coeff_model    = c->coeff->model;
+   lc_d_coeff_model  = c->d_coeff->model;
+   /*
+    *  ... and restore them with values before lc
+    */
+   c->domain_pool->model   = c->domain_pool->model_duplicate (domain_model);
+   c->d_domain_pool->model = c->d_domain_pool->model_duplicate (d_domain_model);
+   c->coeff->model         = c->coeff->model_duplicate (c->coeff, coeff_model);
+   c->d_coeff->model       = c->d_coeff->model_duplicate (c->d_coeff,
+							  d_coeff_model);
+   
+   /*
+    *  Second alternative of range approximation:
+    *  Compute costs of recursive subdivision.
+    */
+   if (range->level > c->options.lc_min_level) /* range is large enough */
+   {
+      unsigned label;
+      
+      memset (&child [0], 0, 2 * sizeof (range_t)); /* initialize childs */
+
+      /*
+       *  Initialize a new range for recursive approximation
+       */
+      rrange                 = *range;
+      rrange.tree_bits       = tree_bits (CHILD, rrange.level, &c->tree);
+      rrange.matrix_bits     = 0;
+      rrange.weights_bits    = 0;
+      rrange.err             = 0;
+      rrange.mv_tree_bits    = try_mc ? 1 : 0;	/* mc allowed but not used */
+      rrange.mv_coord_bits   = 0;
+      rrange.nd_tree_bits    = try_nd ?
+			       tree_bits (CHILD, lrange.level, &c->p_tree): 0;
+      rrange.nd_weights_bits = 0;	
+      rrange.prediction	     = NO;
+
+      /*
+       *  Initialize the cost function and subdivide the current range.
+       *  Every child is approximated by a recursive call of subdivide()
+       */
+      subdivide_costs = (rrange.tree_bits + rrange.weights_bits
+			 + rrange.matrix_bits + rrange.mv_tree_bits
+			 + rrange.mv_coord_bits + rrange.nd_tree_bits
+			 + rrange.nd_weights_bits) * price;
+      
+      for (label = 0; label < MAXLABELS; label++) 
+      {
+	 real_t remaining_costs;	/* upper limit for next recursion */
+	 
+	 child[label].image          = rrange.image * MAXLABELS + label + 1;
+	 child[label].address        = rrange.address * MAXLABELS + label;
+	 child[label].global_address = rrange.global_address * MAXLABELS
+				       + label;
+	 child[label].level          = rrange.level - 1;
+	 child[label].x	= rrange.level & 1
+			  ? rrange.x
+			  : (rrange.x
+			     + label * width_of_level (rrange.level - 1));
+	 child[label].y = rrange.level & 1
+			  ? (rrange.y
+			     + label * height_of_level (rrange.level - 1))
+			  : rrange.y;
+	 
+	 /* 
+	  *  If neccessary compute the inner products of the new states
+	  *  (generated during the recursive approximation of child [0])
+	  */
+	 if (label && rrange.level <= c->options.lc_max_level)
+	    compute_ip_images_state (child[label].image, child[label].address,
+				     child[label].level, 1, states, wfa, c);
+	 /*
+	  *  Call subdivide() for both childs. 
+	  *  Abort the recursion if 'subdivide_costs' exceed 'lincomb_costs'
+	  *  or 'max_costs'.
+	  */
+	 remaining_costs = min (lincomb_costs, max_costs) - subdivide_costs;
+
+	 if (remaining_costs > 0)	/* still a way for improvement */
+	 {
+	    subdivide_costs += subdivide (remaining_costs, band,
+					  new_y_state [label], &child [label],
+					  wfa, c, prediction, delta);
+	 }
+	 else if (try_mc && child[label].level >= wfa->wfainfo->p_min_level)
+	 {
+	    fill_norms_table (child[label].x, child[label].y,
+			      child[label].level, wfa->wfainfo, c->mt);
+	 }
+	 
+	 if (try_mc)
+	    update_norms_table (rrange.level, wfa->wfainfo, c->mt);
+	 
+	 /*
+	  *  Update of progress meter
+	  */
+	 if (c->options.progress_meter != FIASCO_PROGRESS_NONE)
+	 {
+	    if (c->options.progress_meter == FIASCO_PROGRESS_PERCENT)
+	    {
+	       unsigned	new_percent; 	/* new status of progress meter */
+	 
+	       new_percent = (child[label].global_address + 1) * 100.0
+			     / (1 << (wfa->wfainfo->level - child[label].level));
+	       if (new_percent > percent)
+	       {
+		  percent = new_percent;
+		  info ("%3d%%  \r", percent);
+	       }
+	    }
+	    else if (c->options.progress_meter == FIASCO_PROGRESS_BAR)
+	    {
+	       unsigned	new_percent;	/* new status of progress meter */
+	 
+	       new_percent = (child[label].global_address + 1) * 50.0
+			     / (1 << (wfa->wfainfo->level
+				      - child[label].level));
+	       for (; new_percent > percent; percent++)
+	       {
+		  info ("#");
+	       }
+	    }
+	 }
+   
+	 /*
+	  *  If costs of subdivision exceed costs of linear combination 
+	  *  then abort recursion.
+	  */
+	 if (subdivide_costs >= min (lincomb_costs, max_costs)) 
+	 {
+	    subdivide_costs = MAXCOSTS;
+	    break; 
+	 }
+	 rrange.err             += child [label].err;
+	 rrange.tree_bits       += child [label].tree_bits;
+	 rrange.matrix_bits     += child [label].matrix_bits;
+	 rrange.weights_bits    += child [label].weights_bits;
+	 rrange.mv_tree_bits    += child [label].mv_tree_bits;
+	 rrange.mv_coord_bits   += child [label].mv_coord_bits;
+	 rrange.nd_weights_bits += child [label].nd_weights_bits;
+	 rrange.nd_tree_bits    += child [label].nd_tree_bits;
+
+	 tree_update (ischild (child [label].tree) ? CHILD : LEAF,
+		      child [label].level, &c->tree);
+	 tree_update (child [label].prediction ? LEAF : CHILD,
+		      child [label].level, &c->p_tree);
+      }
+   }
+   else
+      subdivide_costs = MAXCOSTS;
+
+   /*
+    *  Third alternative of range approximation:
+    *  Predict range via motion compensation or nondeterminism and 
+    *  approximate delta image. 
+    */
+   if (try_mc || try_nd)		/* try prediction */
+   {
+      real_t prediction_costs;	/* Costs arising from approx. the current
+				   range with prediction */
+
+      prediction_costs
+	 = predict_range (min (min (lincomb_costs, subdivide_costs),
+			       max_costs),
+			  price, range, wfa, c, band, y_state, states,
+			  &tree_model, &p_tree_model, domain_model,
+			  d_domain_model, coeff_model, d_coeff_model);
+      if (prediction_costs < MAXCOSTS)	/* prediction has smallest costs */
+      {
+	 c->domain_pool->model_free (domain_model);
+	 c->d_domain_pool->model_free (d_domain_model);
+	 c->domain_pool->model_free (lc_domain_model);
+	 c->d_domain_pool->model_free (lc_d_domain_model);
+	 c->coeff->model_free (coeff_model);
+	 c->d_coeff->model_free (d_coeff_model);
+	 c->coeff->model_free (lc_coeff_model);
+	 c->d_coeff->model_free (lc_d_coeff_model);
+	 
+	 return prediction_costs;
+      }
+   }
+
+   if (lincomb_costs >= MAXCOSTS && subdivide_costs >= MAXCOSTS)
+   {
+      /*
+       *  Return MAXCOSTS if neither a linear combination nor a recursive
+       *  subdivision yield costs less than 'max_costs'
+       */
+      c->domain_pool->model_free (c->domain_pool->model);
+      c->d_domain_pool->model_free (c->d_domain_pool->model);
+      c->domain_pool->model_free (lc_domain_model);
+      c->d_domain_pool->model_free (lc_d_domain_model);
+
+      c->coeff->model_free (c->coeff->model);
+      c->d_coeff->model_free (c->d_coeff->model);
+      c->coeff->model_free (lc_coeff_model);
+      c->d_coeff->model_free (lc_d_coeff_model);
+	 
+      c->domain_pool->model   = domain_model;
+      c->d_domain_pool->model = d_domain_model;
+      c->coeff->model	      = coeff_model;
+      c->d_coeff->model	      = d_coeff_model;
+      c->tree                 = tree_model;
+      c->p_tree               = p_tree_model;
+      
+      if (wfa->states != states)
+	 remove_states (states, wfa);
+
+      return MAXCOSTS;
+   }
+   else if (lincomb_costs < subdivide_costs) 
+   {
+      /*
+       *  Use the linear combination: The factors of the linear combination
+       *  are stored already in 'range', so revert the probability models
+       *  only. 
+       */
+      c->domain_pool->model_free (c->domain_pool->model);
+      c->d_domain_pool->model_free (c->d_domain_pool->model);
+      c->domain_pool->model_free (domain_model);
+      c->d_domain_pool->model_free (d_domain_model);
+
+      c->coeff->model_free (c->coeff->model);
+      c->d_coeff->model_free (c->d_coeff->model);
+      c->coeff->model_free (coeff_model);
+      c->d_coeff->model_free (d_coeff_model);
+      
+      c->domain_pool->model   = lc_domain_model;
+      c->d_domain_pool->model = lc_d_domain_model;
+      c->coeff->model	      = lc_coeff_model;
+      c->d_coeff->model	      = lc_d_coeff_model;
+      c->tree                 = tree_model;
+      c->p_tree               = p_tree_model;
+
+      *range = lrange;
+      
+      if (wfa->states != states)
+	 remove_states (states, wfa);
+
+      return lincomb_costs;
+   }
+   else
+   {
+      /*
+       *  Use the recursive subdivision: Generate a new state with transitions
+       *  given in child[].
+       *  Don't use state in linear combinations in any of the following cases:
+       *  - if color component is Cb or Cr
+       *  - if level of state > tiling level 
+       *  - if state is (partially) outside image geometry 
+       */
+      if (band > Y
+	  || (c->tiling->exponent
+	      && rrange.level > wfa->wfainfo->level - c->tiling->exponent)
+	  || (range->x + width_of_level (range->level)
+	      > c->mt->original->width)
+	  || (range->y + height_of_level (range->level)
+	      > c->mt->original->height))
+	 init_new_state (YES, delta, &rrange, child, new_y_state, wfa, c);
+      else
+	 init_new_state (NO, delta, &rrange, child, new_y_state, wfa, c);
+
+      *range = rrange;
+
+      c->domain_pool->model_free (domain_model);
+      c->d_domain_pool->model_free (d_domain_model);
+      c->domain_pool->model_free (lc_domain_model);
+      c->d_domain_pool->model_free (lc_d_domain_model);
+      c->coeff->model_free (coeff_model);
+      c->d_coeff->model_free (d_coeff_model);
+      c->coeff->model_free (lc_coeff_model);
+      c->d_coeff->model_free (lc_d_coeff_model);
+
+      return subdivide_costs;
+   }
+}
+
+void
+cut_to_bintree (real_t *dst, const word_t *src,
+		unsigned src_width, unsigned src_height,
+		unsigned x0, unsigned y0, unsigned width, unsigned height)
+/*
+ *  Cut region ('x0', 'y0', 'width', 'height') of the pixel array 'src'.
+ *  Size of image is given by 'src_width' x 'src_height'.
+ *  'dst' pixels are converted to bintree order and real format.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *	'dst []' is filled with corresponding region.
+ */
+{
+   const unsigned mask01      = 0x555555; /* binary ...010101010101 */
+   const unsigned mask10      = 0xaaaaaa; /* binary ...101010101010 */
+   const unsigned mask01plus1 = mask01 + 1; /* binary ...010101010110 */
+   const unsigned mask10plus1 = mask10 + 1; /* binary ...101010101011 */
+   unsigned  	  x, y;			/* pixel coordinates */
+   unsigned  	  xmask, ymask;		/* address conversion */
+
+   if (width != height && width != (height >> 1))
+      error ("Bintree cutting requires special type of images.");
+
+   ymask = 0;
+   for (y = y0; y < y0 + height; y++, ymask = (ymask + mask10plus1) & mask01)
+   {
+      xmask = 0;
+      for (x = x0; x < x0 + width; x++, xmask = (xmask + mask01plus1) & mask10)
+      {
+	 if (y >= src_height || x >= src_width)
+	    dst [xmask | ymask] = 0;
+	 else
+	    dst [xmask | ymask] = src [y * src_width + x] / 16;
+      }
+   }
+}
+
+/*****************************************************************************
+
+				private code
+  
+*****************************************************************************/
+
+static void
+init_new_state (bool_t auxiliary_state, bool_t delta, range_t *range,
+		const range_t *child, const int *y_state,
+		wfa_t *wfa, coding_t *c)
+/*
+ *  Initializes a new state with all parameters needed for the encoding step.
+ *  If flag 'auxiliary_state' is set then don't insert state into domain pools.
+ *  If flag 'delta' is set then state represents a delta image (prediction via
+ *  nondeterminism or motion compensation).
+ *  'range' the current range image,
+ *   'child []' the left and right childs of 'range'.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *	New state is appended to 'wfa' (and also its inner products and images
+ *      are computed and stored in 'c')
+ */
+{
+   unsigned label;
+   bool_t   state_is_domain = NO;
+
+   if (!auxiliary_state)
+   {
+      if (!delta || c->options.delta_domains)
+	 state_is_domain = c->domain_pool->append (wfa->states, range->level,
+						   wfa, c->domain_pool->model);
+      if (delta || c->options.normal_domains)
+	 state_is_domain = c->d_domain_pool->append (wfa->states, range->level,
+						     wfa,
+						     c->d_domain_pool->model)
+			   || state_is_domain;
+   }
+   else
+      state_is_domain = NO;
+   
+   range->into [0] = NO_EDGE;
+   range->tree     = wfa->states;
+   
+   for (label = 0; label < MAXLABELS; label++) 
+   {
+      wfa->tree [wfa->states][label]       = child [label].tree;
+      wfa->y_state [wfa->states][label]    = y_state [label];
+      wfa->mv_tree [wfa->states][label]    = child [label].mv;
+      wfa->x [wfa->states][label]          = child [label].x;
+      wfa->y [wfa->states][label]          = child [label].y;
+      wfa->prediction [wfa->states][label] = child [label].prediction;
+
+      append_transitions (wfa->states, label, child [label].weight,
+			  child [label].into, wfa);
+   }
+   wfa->delta_state [wfa->states] = delta;
+
+   if (range->err < 0)
+      warning ("Negative image norm: %f, %f", child [0].err, child [1].err);
+
+/*    state_is_domain = YES; */
+   
+   append_state (!state_is_domain,
+		 compute_final_distribution (wfa->states, wfa),
+		 range->level, wfa, c);
+}
+
+static void
+init_range (range_t *range, const image_t *image, unsigned band,
+	    const wfa_t *wfa, coding_t *c)
+/*
+ *  Read a new 'range' of the image 'image_name' (current color component
+ *  is 'band') and compute the new inner product arrays.
+ *
+ *  No return value.
+ *
+ *  Side effects:
+ *	'c->pixels' are filled with pixel values of image block 
+ *	'c->ip_images_state' are computed with respect to new image block 
+ *	'range->address' and 'range->image' are initialized with zero
+ */
+{
+   unsigned state;
+   
+   /*
+    *  Clear already computed products
+    */
+   for (state = 0; state < wfa->states; state++)
+      if (need_image (state, wfa))
+	 memset (c->ip_images_state[state], 0,
+		 size_of_tree (c->products_level) * sizeof(real_t));
+
+   cut_to_bintree (c->pixels, image->pixels [band],
+		   image->width, image->height,
+		   range->x, range->y, width_of_level (range->level),
+		   height_of_level (range->level));
+   
+   range->address = range->image = 0;
+   compute_ip_images_state (0, 0, range->level, 1, 0, wfa, c);
+}
+
+