code: public static void transformN(WaveletDescription<WlCoef_F32> desc ,
  								  GrayF32 input , GrayF32 output ,
  								  GrayF32 storage ,
  								  int numLevels )
  	{
  		if( numLevels == 1 ) {
  			transform1(desc,input,output, storage);
  			return;
  		}
  
  		UtilWavelet.checkShape(desc.getForward(),input,output,numLevels);
  		storage = InputSanityCheck.checkDeclare(output, storage);
  		// modify the shape of a temporary image not the original
  		storage = storage.subimage(0,0,output.width,output.height, null);
  		storage.subImage = false;
  
  		transform1(desc,input,output, storage);
  
  		for( int i = 2; i <= numLevels; i++ ) {
  			int width = output.width/2;
  			int height = output.height/2;
  			width += width%2;
  			height += height%2;
  
  			input = input.subimage(0,0,width,height, null);
  			output = output.subimage(0,0,width,height, null);
  			input.setTo(output);
  
  			// transform the scaling image and save the results in the output image
  			storage.reshape(width,height);
  			transform1(desc,input,output,storage);
  		}
  	}
docs: <p>
  Performs a level N wavelet transform using the fast wavelet transform (FWT).
  </p>
  
  <p>To save memory the input image is used to store intermediate results and is modified.</p>
  
  @param desc Description of the wavelet.
  @param input Input image and is used as internal workspace. Modified.
  @param output Where the multilevel wavelet transform is written to. Modified.
  @param storage Optional storage image.  Should be the same size as output image. If null then
  an image is declared internally.
  @param numLevels Number of levels which should be computed in the transform.