1 /*
2  *  subdivide.c:	Recursive subdivision of range images
3  *
4  *  Written by:		Ullrich Hafner
5  *
6  *  This file is part of FIASCO (Fractal Image And Sequence COdec)
7  *  Copyright (C) 1994-2000 Ullrich Hafner
8  */
9 
10 /*
11  *  $Date: 2000/07/15 17:59:31 $
12  *  $Author: hafner $
13  *  $Revision: 5.4 $
14  *  $State: Exp $
15  */
16 
17 #include "config.h"
18 
19 #include <string.h>
20 
21 #include "pm_c_util.h"
22 
23 #include "types.h"
24 #include "macros.h"
25 #include "error.h"
26 
27 #include "image.h"
28 #include "cwfa.h"
29 #include "approx.h"
30 #include "ip.h"
31 #include "bintree.h"
32 #include "control.h"
33 #include "prediction.h"
34 #include "domain-pool.h"
35 #include "mwfa.h"
36 #include "misc.h"
37 #include "subdivide.h"
38 #include "list.h"
39 #include "coeff.h"
40 #include "wfalib.h"
41 
42 /*****************************************************************************
43 
44 				prototypes
45 
46 *****************************************************************************/
47 
48 static void
49 init_new_state (bool_t auxiliary_state, bool_t delta, range_t *range,
50 		const range_t *child, const int *y_state,
51 		wfa_t *wfa, coding_t *c);
52 static void
53 init_range (range_t *range, const image_t *image, unsigned band,
54 	    const wfa_t *wfa, coding_t *c);
55 
56 /*****************************************************************************
57 
58 				public code
59 
60 *****************************************************************************/
61 
62 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)63 subdivide (real_t max_costs, unsigned band, int y_state, range_t *range,
64 	   wfa_t *wfa, coding_t *c, bool_t prediction, bool_t delta)
65 /*
66  *  Subdivide the current 'range' recursively and decide whether
67  *  a linear combination, a recursive subdivision, or a prediction is
68  *  the best choice of approximation.
69  *  'band' is the current color band, 'y_state' is the corresponding
70  *  state of the Y color component (color image compression only).
71  *  If 'prediction' is TRUE then also test motion compensation or
72  *  nondeterministic approximation.
73  *  If 'delta' is TRUE then current range is already predicted.
74  *
75  *  Return value:
76  *	costs of the best approximation or MAXCOSTS if costs exceed 'max_costs'
77  *
78  *  Side effects:
79  *	'range'	factors and costs of linear combination are modified
80  *      'wfa'	new transitions and prediction coefficients are added
81  *	'c'	pixels and inner products are updated
82  */
83 {
84    real_t    subdivide_costs;        /* Costs arising from approx. the current
85 				       range with two children */
86    real_t    lincomb_costs;          /* Costs arising from approx. the current
87 				       range with a linear combination */
88    int	     new_y_state [MAXLABELS];	/* Corresponding state of Y */
89    real_t    price;			/* Approximation costs multiplier */
90    bool_t    try_mc;			/* YES: try MC prediction */
91    bool_t    try_nd;			/* YES: try ND prediction */
92    unsigned  states;			/* Number of states before the
93 					   recursive subdivision starts */
94    void     *domain_model;		/* copy of domain pool model */
95    void     *d_domain_model;		/* copy of delta domain pool model */
96    void     *lc_domain_model;		/* copy of domain pool model */
97    void     *lc_d_domain_model;		/* copy of delta domain pool model */
98    void	    *coeff_model;	        /* copy of coefficients model */
99    void	    *d_coeff_model;		/* copy of delta coefficients model */
100    void	    *lc_coeff_model;	        /* copy of coefficients model */
101    void	    *lc_d_coeff_model;		/* copy of delta coefficients model */
102    tree_t    tree_model;		/* copy of tree model */
103    tree_t    p_tree_model;		/* copy of pred. tree model */
104    range_t   lrange;			/* range of lin. comb. approx. */
105    range_t   rrange;			/* range of recursive approx. */
106    range_t   child [MAXLABELS];		/* new children of the current range */
107    static unsigned percent = 0;		/* status of progress meter */
108 
109    if (wfa->wfainfo->level == range->level)
110       percent = 0;
111 
112    range->into [0] = NO_EDGE;		/* default approximation: empty */
113    range->tree     = RANGE;
114 
115    if (range->level < 3)		/* Don't process small ranges */
116       return MAXCOSTS;
117 
118    /*
119     *  If image permutation (tiling) is performed and the tiling level
120     *  is reached then get coordinates of the new block.
121     */
122    if (c->tiling->exponent
123        && range->level == wfa->wfainfo->level - c->tiling->exponent)
124    {
125       unsigned width, height;		/* size of range (dummies)*/
126 
127       if (c->tiling->vorder [range->global_address] < 0)
128 	 return 0;			/* nothing to do */
129       else
130 	 locate_subimage (wfa->wfainfo->level, range->level,
131 			  c->tiling->vorder [range->global_address],
132 			  &range->x, &range->y, &width, &height);
133    }
134 
135    if (range->x >= c->mt->original->width ||
136        range->y >= c->mt->original->height)
137       return 0;				/* range is not visible */
138 
139    /*
140     *  Check whether prediction is allowed or not
141     *  mc == motion compensation, nd == nondeterminism
142     */
143    try_mc = (prediction && c->mt->frame_type != I_FRAME
144 	     && range->level >= wfa->wfainfo->p_min_level
145 	     && range->level <= wfa->wfainfo->p_max_level
146 	     && (range->x + width_of_level (range->level)
147 		 <= c->mt->original->width)
148 	     && (range->y + height_of_level (range->level)
149 		 <= c->mt->original->height));
150 
151    try_nd = (prediction && c->mt->frame_type == I_FRAME
152 	     && range->level >= wfa->wfainfo->p_min_level
153 	     && range->level <= wfa->wfainfo->p_max_level);
154 
155    if (try_mc)
156       clear_norms_table (range->level, wfa->wfainfo, c->mt);
157 
158 
159    /*
160     *  Check if current range must be initialized. I.e. range pixels must
161     *  be copied from entire image to bintree pixel buffer. Moreover,
162     *  all inner products tables must be initialized.
163     */
164    if (range->level == c->options.lc_max_level)
165       init_range (range, c->mt->original, band, wfa, c);
166 
167    price = c->price;
168    if (band != Y)
169       price *= c->options.chroma_decrease; /* less quality for chroma bands */
170 
171    /*
172     *  Compute children of corresponding state in Y band
173     */
174    if (band != Y)			/* Cb and Cr bands only */
175    {
176       unsigned label;
177 
178       for (label = 0; label < MAXLABELS; label++)
179 	 if (ischild (y_state))
180 	    new_y_state [label] = wfa->tree [y_state][label];
181 	 else
182 	    new_y_state [label] = RANGE;
183    }
184    else
185       new_y_state [0] = new_y_state [1] = RANGE;
186 
187    /*
188     *  Store contents of all models that may get modified during recursion
189     */
190    domain_model   = c->domain_pool->model_duplicate (c->domain_pool->model);
191    d_domain_model = c->d_domain_pool->model_duplicate (c->d_domain_pool->model);
192    coeff_model    = c->coeff->model_duplicate (c->coeff, c->coeff->model);
193    d_coeff_model  = c->d_coeff->model_duplicate (c->d_coeff, c->d_coeff->model);
194    tree_model     = c->tree;
195    p_tree_model   = c->p_tree;
196    states         = wfa->states;
197 
198    /*
199     *  First alternative of range approximation:
200     *  Compute costs of linear combination.
201     */
202    if (range->level <= c->options.lc_max_level) /* range is small enough */
203    {
204       lrange                 = *range;
205       lrange.tree            = RANGE;
206       lrange.tree_bits       = tree_bits (LEAF, lrange.level, &c->tree);
207       lrange.matrix_bits     = 0;
208       lrange.weights_bits    = 0;
209       lrange.mv_tree_bits    = try_mc ? 1 : 0; /* mc allowed but not used */
210       lrange.mv_coord_bits   = 0;
211       lrange.nd_tree_bits    = 0;
212       lrange.nd_weights_bits = 0;
213       lrange.prediction	     = NO;
214 
215       lincomb_costs
216 	 = approximate_range (max_costs, price, c->options.max_elements,
217 			      y_state, &lrange,
218 			      (delta ? c->d_domain_pool : c->domain_pool),
219 			      (delta ? c->d_coeff : c->coeff), wfa, c);
220    }
221    else
222       lincomb_costs = MAXCOSTS;
223 
224    /*
225     *  Store contents of models that have been modified
226     *  by approximate_range () above ...
227     */
228    lc_domain_model   = c->domain_pool->model;
229    lc_d_domain_model = c->d_domain_pool->model;
230    lc_coeff_model    = c->coeff->model;
231    lc_d_coeff_model  = c->d_coeff->model;
232    /*
233     *  ... and restore them with values before lc
234     */
235    c->domain_pool->model   = c->domain_pool->model_duplicate (domain_model);
236    c->d_domain_pool->model = c->d_domain_pool->model_duplicate (d_domain_model);
237    c->coeff->model         = c->coeff->model_duplicate (c->coeff, coeff_model);
238    c->d_coeff->model       = c->d_coeff->model_duplicate (c->d_coeff,
239 							  d_coeff_model);
240 
241    /*
242     *  Second alternative of range approximation:
243     *  Compute costs of recursive subdivision.
244     */
245    if (range->level > c->options.lc_min_level) /* range is large enough */
246    {
247       unsigned label;
248 
249       memset (&child [0], 0, 2 * sizeof (range_t)); /* initialize children */
250 
251       /*
252        *  Initialize a new range for recursive approximation
253        */
254       rrange                 = *range;
255       rrange.tree_bits       = tree_bits (CHILD, rrange.level, &c->tree);
256       rrange.matrix_bits     = 0;
257       rrange.weights_bits    = 0;
258       rrange.err             = 0;
259       rrange.mv_tree_bits    = try_mc ? 1 : 0;	/* mc allowed but not used */
260       rrange.mv_coord_bits   = 0;
261       rrange.nd_tree_bits    = try_nd ?
262 			       tree_bits (CHILD, lrange.level, &c->p_tree): 0;
263       rrange.nd_weights_bits = 0;
264       rrange.prediction	     = NO;
265 
266       /*
267        *  Initialize the cost function and subdivide the current range.
268        *  Every child is approximated by a recursive call of subdivide()
269        */
270       subdivide_costs = (rrange.tree_bits + rrange.weights_bits
271 			 + rrange.matrix_bits + rrange.mv_tree_bits
272 			 + rrange.mv_coord_bits + rrange.nd_tree_bits
273 			 + rrange.nd_weights_bits) * price;
274 
275       for (label = 0; label < MAXLABELS; label++)
276       {
277 	 real_t remaining_costs;	/* upper limit for next recursion */
278 
279 	 child[label].image          = rrange.image * MAXLABELS + label + 1;
280 	 child[label].address        = rrange.address * MAXLABELS + label;
281 	 child[label].global_address = rrange.global_address * MAXLABELS
282 				       + label;
283 	 child[label].level          = rrange.level - 1;
284 	 child[label].x	= rrange.level & 1
285 			  ? rrange.x
286 			  : (rrange.x
287 			     + label * width_of_level (rrange.level - 1));
288 	 child[label].y = rrange.level & 1
289 			  ? (rrange.y
290 			     + label * height_of_level (rrange.level - 1))
291 			  : rrange.y;
292 
293 	 /*
294 	  *  If necessary compute the inner products of the new states
295 	  *  (generated during the recursive approximation of child [0])
296 	  */
297 	 if (label && rrange.level <= c->options.lc_max_level)
298 	    compute_ip_images_state (child[label].image, child[label].address,
299 				     child[label].level, 1, states, wfa, c);
300 	 /*
301 	  *  Call subdivide() for both children.
302 	  *  Abort the recursion if 'subdivide_costs' exceed 'lincomb_costs'
303 	  *  or 'max_costs'.
304 	  */
305 	 remaining_costs = MIN(lincomb_costs, max_costs) - subdivide_costs;
306 
307 	 if (remaining_costs > 0)	/* still a way for improvement */
308 	 {
309 	    subdivide_costs += subdivide (remaining_costs, band,
310 					  new_y_state [label], &child [label],
311 					  wfa, c, prediction, delta);
312 	 }
313 	 else if (try_mc && child[label].level >= wfa->wfainfo->p_min_level)
314 	 {
315 	    fill_norms_table (child[label].x, child[label].y,
316 			      child[label].level, wfa->wfainfo, c->mt);
317 	 }
318 
319 	 if (try_mc)
320 	    update_norms_table (rrange.level, wfa->wfainfo, c->mt);
321 
322 	 /*
323 	  *  Update of progress meter
324 	  */
325 	 if (c->options.progress_meter != FIASCO_PROGRESS_NONE)
326 	 {
327 	    if (c->options.progress_meter == FIASCO_PROGRESS_PERCENT)
328 	    {
329 	       unsigned	new_percent; 	/* new status of progress meter */
330 
331 	       new_percent = (child[label].global_address + 1) * 100.0
332 			     / (1 << (wfa->wfainfo->level - child[label].level));
333 	       if (new_percent > percent)
334 	       {
335 		  percent = new_percent;
336 		  info ("%3d%%  \r", percent);
337 	       }
338 	    }
339 	    else if (c->options.progress_meter == FIASCO_PROGRESS_BAR)
340 	    {
341 	       unsigned	new_percent;	/* new status of progress meter */
342 
343 	       new_percent = (child[label].global_address + 1) * 50.0
344 			     / (1 << (wfa->wfainfo->level
345 				      - child[label].level));
346 	       for (; new_percent > percent; percent++)
347 	       {
348 		  info ("#");
349 	       }
350 	    }
351 	 }
352 
353 	 /*
354 	  *  If costs of subdivision exceed costs of linear combination
355 	  *  then abort recursion.
356 	  */
357 	 if (subdivide_costs >= MIN(lincomb_costs, max_costs))
358 	 {
359 	    subdivide_costs = MAXCOSTS;
360 	    break;
361 	 }
362 	 rrange.err             += child [label].err;
363 	 rrange.tree_bits       += child [label].tree_bits;
364 	 rrange.matrix_bits     += child [label].matrix_bits;
365 	 rrange.weights_bits    += child [label].weights_bits;
366 	 rrange.mv_tree_bits    += child [label].mv_tree_bits;
367 	 rrange.mv_coord_bits   += child [label].mv_coord_bits;
368 	 rrange.nd_weights_bits += child [label].nd_weights_bits;
369 	 rrange.nd_tree_bits    += child [label].nd_tree_bits;
370 
371 	 tree_update (ischild (child [label].tree) ? CHILD : LEAF,
372 		      child [label].level, &c->tree);
373 	 tree_update (child [label].prediction ? LEAF : CHILD,
374 		      child [label].level, &c->p_tree);
375       }
376    }
377    else
378       subdivide_costs = MAXCOSTS;
379 
380    /*
381     *  Third alternative of range approximation:
382     *  Predict range via motion compensation or nondeterminism and
383     *  approximate delta image.
384     */
385    if (try_mc || try_nd)		/* try prediction */
386    {
387        real_t prediction_costs;	/* Costs arising from approx. the current
388                                    range with prediction */
389 
390        prediction_costs
391            = predict_range (MIN(MIN(lincomb_costs, subdivide_costs),
392                                 max_costs),
393                             price, range, wfa, c, band, y_state, states,
394                             &tree_model, &p_tree_model, domain_model,
395                             d_domain_model, coeff_model, d_coeff_model);
396        if (prediction_costs < MAXCOSTS)	/* prediction has smallest costs */
397        {
398            c->domain_pool->model_free (domain_model);
399            c->d_domain_pool->model_free (d_domain_model);
400            c->domain_pool->model_free (lc_domain_model);
401            c->d_domain_pool->model_free (lc_d_domain_model);
402            c->coeff->model_free (coeff_model);
403            c->d_coeff->model_free (d_coeff_model);
404            c->coeff->model_free (lc_coeff_model);
405            c->d_coeff->model_free (lc_d_coeff_model);
406 
407            return prediction_costs;
408        }
409    }
410 
411    if (lincomb_costs >= MAXCOSTS && subdivide_costs >= MAXCOSTS)
412    {
413       /*
414        *  Return MAXCOSTS if neither a linear combination nor a recursive
415        *  subdivision yield costs less than 'max_costs'
416        */
417       c->domain_pool->model_free (c->domain_pool->model);
418       c->d_domain_pool->model_free (c->d_domain_pool->model);
419       c->domain_pool->model_free (lc_domain_model);
420       c->d_domain_pool->model_free (lc_d_domain_model);
421 
422       c->coeff->model_free (c->coeff->model);
423       c->d_coeff->model_free (c->d_coeff->model);
424       c->coeff->model_free (lc_coeff_model);
425       c->d_coeff->model_free (lc_d_coeff_model);
426 
427       c->domain_pool->model   = domain_model;
428       c->d_domain_pool->model = d_domain_model;
429       c->coeff->model	      = coeff_model;
430       c->d_coeff->model	      = d_coeff_model;
431       c->tree                 = tree_model;
432       c->p_tree               = p_tree_model;
433 
434       if (wfa->states != states)
435 	 remove_states (states, wfa);
436 
437       return MAXCOSTS;
438    }
439    else if (lincomb_costs < subdivide_costs)
440    {
441       /*
442        *  Use the linear combination: The factors of the linear combination
443        *  are stored already in 'range', so revert the probability models
444        *  only.
445        */
446       c->domain_pool->model_free (c->domain_pool->model);
447       c->d_domain_pool->model_free (c->d_domain_pool->model);
448       c->domain_pool->model_free (domain_model);
449       c->d_domain_pool->model_free (d_domain_model);
450 
451       c->coeff->model_free (c->coeff->model);
452       c->d_coeff->model_free (c->d_coeff->model);
453       c->coeff->model_free (coeff_model);
454       c->d_coeff->model_free (d_coeff_model);
455 
456       c->domain_pool->model   = lc_domain_model;
457       c->d_domain_pool->model = lc_d_domain_model;
458       c->coeff->model	      = lc_coeff_model;
459       c->d_coeff->model	      = lc_d_coeff_model;
460       c->tree                 = tree_model;
461       c->p_tree               = p_tree_model;
462 
463       *range = lrange;
464 
465       if (wfa->states != states)
466 	 remove_states (states, wfa);
467 
468       return lincomb_costs;
469    }
470    else
471    {
472       /*
473        *  Use the recursive subdivision: Generate a new state with transitions
474        *  given in child[].
475        *  Don't use state in linear combinations in any of the following cases:
476        *  - if color component is Cb or Cr
477        *  - if level of state > tiling level
478        *  - if state is (partially) outside image geometry
479        */
480       if (band > Y
481 	  || (c->tiling->exponent
482 	      && rrange.level > wfa->wfainfo->level - c->tiling->exponent)
483 	  || (range->x + width_of_level (range->level)
484 	      > c->mt->original->width)
485 	  || (range->y + height_of_level (range->level)
486 	      > c->mt->original->height))
487 	 init_new_state (YES, delta, &rrange, child, new_y_state, wfa, c);
488       else
489 	 init_new_state (NO, delta, &rrange, child, new_y_state, wfa, c);
490 
491       *range = rrange;
492 
493       c->domain_pool->model_free (domain_model);
494       c->d_domain_pool->model_free (d_domain_model);
495       c->domain_pool->model_free (lc_domain_model);
496       c->d_domain_pool->model_free (lc_d_domain_model);
497       c->coeff->model_free (coeff_model);
498       c->d_coeff->model_free (d_coeff_model);
499       c->coeff->model_free (lc_coeff_model);
500       c->d_coeff->model_free (lc_d_coeff_model);
501 
502       return subdivide_costs;
503    }
504 }
505 
506 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)507 cut_to_bintree (real_t *dst, const word_t *src,
508 		unsigned src_width, unsigned src_height,
509 		unsigned x0, unsigned y0, unsigned width, unsigned height)
510 /*
511  *  Cut region ('x0', 'y0', 'width', 'height') of the pixel array 'src'.
512  *  Size of image is given by 'src_width' x 'src_height'.
513  *  'dst' pixels are converted to bintree order and real format.
514  *
515  *  No return value.
516  *
517  *  Side effects:
518  *	'dst []' is filled with corresponding region.
519  */
520 {
521    const unsigned mask01      = 0x555555; /* binary ...010101010101 */
522    const unsigned mask10      = 0xaaaaaa; /* binary ...101010101010 */
523    const unsigned mask01plus1 = mask01 + 1; /* binary ...010101010110 */
524    const unsigned mask10plus1 = mask10 + 1; /* binary ...101010101011 */
525    unsigned  	  x, y;			/* pixel coordinates */
526    unsigned  	  xmask, ymask;		/* address conversion */
527 
528    if (width != height && width != (height >> 1))
529       error ("Bintree cutting requires special type of images.");
530 
531    ymask = 0;
532    for (y = y0; y < y0 + height; y++, ymask = (ymask + mask10plus1) & mask01)
533    {
534       xmask = 0;
535       for (x = x0; x < x0 + width; x++, xmask = (xmask + mask01plus1) & mask10)
536       {
537 	 if (y >= src_height || x >= src_width)
538 	    dst [xmask | ymask] = 0;
539 	 else
540 	    dst [xmask | ymask] = src [y * src_width + x] / 16;
541       }
542    }
543 }
544 
545 /*****************************************************************************
546 
547 				private code
548 
549 *****************************************************************************/
550 
551 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)552 init_new_state (bool_t auxiliary_state, bool_t delta, range_t *range,
553 		const range_t *child, const int *y_state,
554 		wfa_t *wfa, coding_t *c)
555 /*
556  *  Initializes a new state with all parameters needed for the encoding step.
557  *  If flag 'auxiliary_state' is set then don't insert state into domain pools.
558  *  If flag 'delta' is set then state represents a delta image (prediction via
559  *  nondeterminism or motion compensation).
560  *  'range' the current range image,
561  *   'child []' the left and right children of 'range'.
562  *
563  *  No return value.
564  *
565  *  Side effects:
566  *	New state is appended to 'wfa' (and also its inner products and images
567  *      are computed and stored in 'c')
568  */
569 {
570    unsigned label;
571    bool_t   state_is_domain = NO;
572 
573    if (!auxiliary_state)
574    {
575       if (!delta || c->options.delta_domains)
576 	 state_is_domain = c->domain_pool->append (wfa->states, range->level,
577 						   wfa, c->domain_pool->model);
578       if (delta || c->options.normal_domains)
579 	 state_is_domain = c->d_domain_pool->append (wfa->states, range->level,
580 						     wfa,
581 						     c->d_domain_pool->model)
582 			   || state_is_domain;
583    }
584    else
585       state_is_domain = NO;
586 
587    range->into [0] = NO_EDGE;
588    range->tree     = wfa->states;
589 
590    for (label = 0; label < MAXLABELS; label++)
591    {
592       wfa->tree [wfa->states][label]       = child [label].tree;
593       wfa->y_state [wfa->states][label]    = y_state [label];
594       wfa->mv_tree [wfa->states][label]    = child [label].mv;
595       wfa->x [wfa->states][label]          = child [label].x;
596       wfa->y [wfa->states][label]          = child [label].y;
597       wfa->prediction [wfa->states][label] = child [label].prediction;
598 
599       append_transitions (wfa->states, label, child [label].weight,
600 			  child [label].into, wfa);
601    }
602    wfa->delta_state [wfa->states] = delta;
603 
604    if (range->err < 0)
605       warning ("Negative image norm: %f, %f", child [0].err, child [1].err);
606 
607 /*    state_is_domain = YES; */
608 
609    append_state (!state_is_domain,
610 		 compute_final_distribution (wfa->states, wfa),
611 		 range->level, wfa, c);
612 }
613 
614 static void
init_range(range_t * range,const image_t * image,unsigned band,const wfa_t * wfa,coding_t * c)615 init_range (range_t *range, const image_t *image, unsigned band,
616 	    const wfa_t *wfa, coding_t *c)
617 /*
618  *  Read a new 'range' of the image 'image_name' (current color component
619  *  is 'band') and compute the new inner product arrays.
620  *
621  *  No return value.
622  *
623  *  Side effects:
624  *	'c->pixels' are filled with pixel values of image block
625  *	'c->ip_images_state' are computed with respect to new image block
626  *	'range->address' and 'range->image' are initialized with zero
627  */
628 {
629    unsigned state;
630 
631    /*
632     *  Clear already computed products
633     */
634    for (state = 0; state < wfa->states; state++)
635       if (need_image (state, wfa))
636 	 memset (c->ip_images_state[state], 0,
637 		 size_of_tree (c->products_level) * sizeof(real_t));
638 
639    cut_to_bintree (c->pixels, image->pixels [band],
640 		   image->width, image->height,
641 		   range->x, range->y, width_of_level (range->level),
642 		   height_of_level (range->level));
643 
644    range->address = range->image = 0;
645    compute_ip_images_state (0, 0, range->level, 1, 0, wfa, c);
646 }
647 
648 
649