Commit a47aabbe authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Linear output for GRAY32 GEO output, UM for ARGB (slow fillNaNs)

parent 24d7049d
Loading
Loading
Loading
Loading
+47 −3
Original line number Original line Diff line number Diff line
@@ -489,7 +489,14 @@ public class CLTParameters {
	public boolean    gmap_save_alt =        true;  // save height map (meters ASL)  
	public boolean    gmap_save_alt =        true;  // save height map (meters ASL)  
	public boolean    gmap_save_tiff32 =     true;  // save float TIFF (NaN for transparency) with geo metadata (top left corner)
	public boolean    gmap_save_tiff32 =     true;  // save float TIFF (NaN for transparency) with geo metadata (top left corner)
	public boolean    gmap_save_tiff =       true;  // save transparent TIFF with geo metadata (top left corner)
	public boolean    gmap_save_tiff =       true;  // save transparent TIFF with geo metadata (top left corner)
	public int        gmap_tiff_pal =        0;     // LWIR palette for TIFF  
	public int        gmap_tiff_pal =        0;     // LWIR palette for ARGB TIFF
	
	public boolean    gmap_um =              true;  // Use unsharp mask filter for ARGB TIFF maps  
	public double     gmap_um_sigma =        0.4;   // Unsharp mask sigma for  ARGB TIFF maps (in meters)
	public double     gmap_um_weight =       0.8;   // Unsharp mask weight for ARGB TIFF maps
	public boolean    gmap_lwir_autorange =  true;  // Autorange LWIR textures for ARGB TIFF maps
	public boolean    gmap_um_fixed =        false; // Use fixed range after unsharp mask instead of autorange  for ARGB TIFF maps
	public double     gmap_um_range =        500;   // Full range after unsharp mask for ARGB TIFF maps  
	
	
	public boolean    generate_bg =      true;  // Generate background image for 3dmodels
	public boolean    generate_bg =      true;  // Generate background image for 3dmodels
	public boolean    show_textures    = true;  // show generated textures
	public boolean    show_textures    = true;  // show generated textures
@@ -1640,6 +1647,13 @@ public class CLTParameters {
		properties.setProperty(prefix+"gmap_save_tiff",             this.gmap_save_tiff+"");             // boolean 
		properties.setProperty(prefix+"gmap_save_tiff",             this.gmap_save_tiff+"");             // boolean 
		properties.setProperty(prefix+"gmap_tiff_pal",              this.gmap_tiff_pal+"");              // int     
		properties.setProperty(prefix+"gmap_tiff_pal",              this.gmap_tiff_pal+"");              // int     
		properties.setProperty(prefix+"gmap_um",                     this.gmap_um+"");                   // boolean
		properties.setProperty(prefix+"gmap_um_sigma",               this.gmap_um_sigma+"");             // double
		properties.setProperty(prefix+"gmap_um_weight",              this.gmap_um_weight+"");            // double
		properties.setProperty(prefix+"gmap_lwir_autorange",         this.gmap_lwir_autorange+"");       // boolean
		properties.setProperty(prefix+"gmap_um_fixed",               this.gmap_um_fixed+"");             // boolean
		properties.setProperty(prefix+"gmap_um_range",               this.gmap_um_range+"");             // double
		
		properties.setProperty(prefix+"generate_bg",                this.generate_bg+"");
		properties.setProperty(prefix+"generate_bg",                this.generate_bg+"");
		properties.setProperty(prefix+"show_textures",              this.show_textures+"");
		properties.setProperty(prefix+"show_textures",              this.show_textures+"");
		properties.setProperty(prefix+"debug_filters",              this.debug_filters+"");
		properties.setProperty(prefix+"debug_filters",              this.debug_filters+"");
@@ -2664,6 +2678,13 @@ public class CLTParameters {
   		if (properties.getProperty(prefix+"gmap_save_tiff")!=null)       this.gmap_save_tiff=Boolean.parseBoolean(properties.getProperty(prefix+    "gmap_save_tiff"));
   		if (properties.getProperty(prefix+"gmap_save_tiff")!=null)       this.gmap_save_tiff=Boolean.parseBoolean(properties.getProperty(prefix+    "gmap_save_tiff"));
		if (properties.getProperty(prefix+"gmap_tiff_pal")!=null)        this.gmap_tiff_pal=Integer.parseInt(properties.getProperty(prefix+         "gmap_tiff_pal"));// int     
		if (properties.getProperty(prefix+"gmap_tiff_pal")!=null)        this.gmap_tiff_pal=Integer.parseInt(properties.getProperty(prefix+         "gmap_tiff_pal"));// int     
		if (properties.getProperty(prefix+"gmap_um")!=null)              this.gmap_um=Boolean.parseBoolean(properties.getProperty(prefix+"gmap_um"));		
		if (properties.getProperty(prefix+"gmap_um_sigma")!=null)        this.gmap_um_sigma=Double.parseDouble(properties.getProperty(prefix+"gmap_um_sigma"));
		if (properties.getProperty(prefix+"gmap_um_weight")!=null)       this.gmap_um_weight=Double.parseDouble(properties.getProperty(prefix+"gmap_um_weight"));
		if (properties.getProperty(prefix+"gmap_lwir_autorange")!=null)  this.gmap_lwir_autorange=Boolean.parseBoolean(properties.getProperty(prefix+"gmap_lwir_autorange"));		
		if (properties.getProperty(prefix+"gmap_um_fixed")!=null)        this.gmap_um_fixed=Boolean.parseBoolean(properties.getProperty(prefix+"gmap_um_fixed"));		
		if (properties.getProperty(prefix+"gmap_um_range")!=null)        this.gmap_um_range=Double.parseDouble(properties.getProperty(prefix+"gmap_um_range"));
		
		if (properties.getProperty(prefix+"generate_bg")!=null)                   this.generate_bg=Boolean.parseBoolean(properties.getProperty(prefix+"generate_bg"));
		if (properties.getProperty(prefix+"generate_bg")!=null)                   this.generate_bg=Boolean.parseBoolean(properties.getProperty(prefix+"generate_bg"));
		if (properties.getProperty(prefix+"show_textures")!=null)                 this.show_textures=Boolean.parseBoolean(properties.getProperty(prefix+"show_textures"));
		if (properties.getProperty(prefix+"show_textures")!=null)                 this.show_textures=Boolean.parseBoolean(properties.getProperty(prefix+"show_textures"));
		if (properties.getProperty(prefix+"debug_filters")!=null)                 this.debug_filters=Boolean.parseBoolean(properties.getProperty(prefix+"debug_filters"));
		if (properties.getProperty(prefix+"debug_filters")!=null)                 this.debug_filters=Boolean.parseBoolean(properties.getProperty(prefix+"debug_filters"));
@@ -3939,9 +3960,25 @@ public class CLTParameters {
				"Save float (32-bit) TIFF with geo and resolution metadata (coordinates correspond to the top left image corner), NAN for transparency.");
				"Save float (32-bit) TIFF with geo and resolution metadata (coordinates correspond to the top left image corner), NAN for transparency.");
		gd.addCheckbox ("Save ARGB Tiff with transparency and Geo",this.gmap_save_tiff, // true; // enable change FG pixel to opaque from transparent
		gd.addCheckbox ("Save ARGB Tiff with transparency and Geo",this.gmap_save_tiff, // true; // enable change FG pixel to opaque from transparent
				"Save transparent TIFF with geo and resolution metadata (coordinates correspond to the top left image corner).");
				"Save transparent TIFF with geo and resolution metadata (coordinates correspond to the top left image corner).");
		gd.addNumericField("Crop maps extra",                      this.gmap_tiff_pal, 0,3,"",  // minimal neighbors to keep alpha
		gd.addNumericField("LWIR palette for Geo",                 this.gmap_tiff_pal, 0,3,"",  // minimal neighbors to keep alpha
				"LWIR palette for Geo/transparency TIFF output.");
				"LWIR palette for Geo/transparency TIFF output.");
		gd.addMessage     ("Unsharp mask parameters for ARGB render of the ground maps");		
		gd.addCheckbox ("Apply unsharp mask to ARGB render",       this.gmap_um,
		        "Use unsharp mask filter for texture.");
		gd.addNumericField("Unsharp mask sigma",                   this.gmap_um_sigma, 5,7,"m",
		        "Unsharp mask sigma for ARGB ground map render in meters.");
		gd.addNumericField("Unsharp mask weight",                  this.gmap_um_weight, 5,7,"",
		        "Unsharp mask weight for ARGB ground map render.");
		gd.addCheckbox ("Autorange LWIR textures",                 this.gmap_lwir_autorange,
		        "Autorange LWIR ARGB ground map render (after unsharp mask).");
		gd.addCheckbox ("Fixed range (after unsharp only)",        this.gmap_um_fixed,
		        "Use fixed range after unsharp mask for ARGB ground map instead of autorange.");
		gd.addNumericField("Full range for ARGB ground map render",this.gmap_um_range, 5,7,"counts",
				"Full range after unsharp mask when fixed range is selected.");
		
		
		
		gd.addMessage     ("Earlier 3D generation parameters");
		gd.addMessage     ("Earlier 3D generation parameters");
		gd.addCheckbox    ("Generate background (infinity) image for 3D (not needed for view down)",                 this.generate_bg);
		gd.addCheckbox    ("Generate background (infinity) image for 3D (not needed for view down)",                 this.generate_bg);
		gd.addCheckbox    ("Show generated textures",                                                                this.show_textures);
		gd.addCheckbox    ("Show generated textures",                                                                this.show_textures);
@@ -5163,6 +5200,13 @@ public class CLTParameters {
		this.gmap_save_tiff=        gd.getNextBoolean();
		this.gmap_save_tiff=        gd.getNextBoolean();
		this.gmap_tiff_pal=   (int) gd.getNextNumber();
		this.gmap_tiff_pal=   (int) gd.getNextNumber();
		
		
		this.gmap_um =              gd.getNextBoolean();
		this.gmap_um_sigma =        gd.getNextNumber();
		this.gmap_um_weight =       gd.getNextNumber();
		this.gmap_lwir_autorange =  gd.getNextBoolean();
		this.gmap_um_fixed =        gd.getNextBoolean();
		this.gmap_um_range =        gd.getNextNumber();
		
		this.generate_bg=           gd.getNextBoolean();
		this.generate_bg=           gd.getNextBoolean();
		this.show_textures=         gd.getNextBoolean();
		this.show_textures=         gd.getNextBoolean();
		this.debug_filters=         gd.getNextBoolean();
		this.debug_filters=         gd.getNextBoolean();
+7 −7
Original line number Original line Diff line number Diff line
@@ -194,13 +194,13 @@ public class ElphelTiffWriter {
        int bands = 1; // 4 bands for ARGB, 3 for RGB etc
        int bands = 1; // 4 bands for ARGB, 3 for RGB etc
        int[] bandOffsets = {0}; // length == bands, 0 == R, 1 == G, 2 == B and 3 == A
        int[] bandOffsets = {0}; // length == bands, 0 == R, 1 == G, 2 == B and 3 == A
        // Create a TYPE_FLOAT sample model (specifying how the pixels are stored)
        // Create a TYPE_FLOAT sample model (specifying how the pixels are stored)
        SampleModel sampleModel0 = new PixelInterleavedSampleModel(
//        SampleModel sampleModel0 = new PixelInterleavedSampleModel(
        		DataBuffer.TYPE_FLOAT,
//        		DataBuffer.TYPE_FLOAT,
        		width,
//        		width,
        		height,
//        		height,
        		bands,
//        		bands,
        		width  * bands,
//        		width  * bands,
        		bandOffsets);
//        		bandOffsets);


        // Create a color model compatible with this sample model/raster (TYPE_FLOAT)
        // Create a color model compatible with this sample model/raster (TYPE_FLOAT)
        // Note that the number of bands must equal the number of color components in the 
        // Note that the number of bands must equal the number of color components in the 
+47 −1
Original line number Original line Diff line number Diff line
@@ -8668,7 +8668,7 @@ public class QuadCLTCPU {
			  double [][][] textures //  [nslices][nchn][i]
			  double [][][] textures //  [nslices][nchn][i]
			  ) {
			  ) {
		  if ((textures == null) || (textures.length==0)) {
		  if ((textures == null) || (textures.length==0)) {
			  throw new IllegalArgumentException ("umTextures(): Empty textures");
			  throw new IllegalArgumentException ("getMinMaxTextures(): Empty textures");
		  }
		  }
		  final boolean is_mono = textures[0].length <= 2;
		  final boolean is_mono = textures[0].length <= 2;
		  final int alpha_chn = is_mono? 1 : 3;
		  final int alpha_chn = is_mono? 1 : 3;
@@ -16456,6 +16456,52 @@ public class QuadCLTCPU {
		  return true;
		  return true;
	  }
	  }
	  
	  
	  // Currently only a single-slice 32-bit file (with NaN for tranparency)
	  public boolean writeLwirGeoTiff32(
			  final CLTParameters  clt_parameters,
			  double []            data,
			  double []            lla,  // latitude, longitude, altitude (or null)
			  LocalDateTime        dt,   // local date/time or null
			  double               pix_in_meters,
			  int                  width,
			  QuadCLT              scene,
			  String               suffix, // include "-geo"
			  int                  debugLevel) {
		  if (scene == null) {
			  scene = (QuadCLT) this;
		  }
		  int height = data.length/width;
		  String set_name = getImageName();
		  if (set_name == null ) {
			  QuadCLTCPU.SetChannels [] set_channels = setChannels(debugLevel);
			  set_name = set_channels[0].set_name;
		  }
		  String model_dir= correctionsParameters.selectX3dDirectory(
				  set_name, // quad timestamp. Will be ignored if correctionsParameters.use_x3d_subdirs is false
				  null,
				  true,  // smart,
				  true);  //newAllowed, // save\
		  String title = getImageName()+suffix;
		  ImagePlus imp = ShowDoubleFloatArrays.makeArrays(
				  data, // double[] pixels,
				  width, // int width,
				  height, // int height,
				  title); // String title);
		  String image_path = model_dir +  Prefs.getFileSeparator() + title+".tiff";
		  ElphelTiffWriter.saveTiffARGBOrGray32(
				  imp,
				  image_path,
				  lla,           // double []     lla,  // latitude, longitude, altitude (or null)
				  dt,            // LocalDateTime dt,   // local date/time or null
				  pix_in_meters, //double        pix_in_meters, // resolution or Double.NaN
				  false,         // imageJTags,
				  debugLevel);
		  return true;
	  }
	  
	  
	  
	  
	  
	/** broke  
	/** broke  
	  public boolean writeRatingFile( // USED in lwir
	  public boolean writeRatingFile( // USED in lwir
+137 −76
Original line number Original line Diff line number Diff line
@@ -2471,9 +2471,15 @@ public class TexturedModel {
		final int       crop_extra =      clt_parameters.gmap_crop_extra ; //20;
		final int       crop_extra =      clt_parameters.gmap_crop_extra ; //20;
		final int []    tex_pals =        clt_parameters.gmap_tex_pals ; //{0,1,2};
		final int []    tex_pals =        clt_parameters.gmap_tex_pals ; //{0,1,2};
		final boolean   gmap_save_alt =   clt_parameters.gmap_save_alt;  // true;  // save height map (meters ASL)  
		final boolean   gmap_save_alt =   clt_parameters.gmap_save_alt;  // true;  // save height map (meters ASL)  
		final boolean   gmap_save_tiff32= clt_parameters.gmap_save_tiff32; // save float TIFF (NaN for transparency) with geo metadata (top left corner)
		final boolean   gmap_save_tiff =  clt_parameters.gmap_save_tiff; // true;  // save transparent TIFF with geo metadata (top left corner)
		final boolean   gmap_save_tiff =  clt_parameters.gmap_save_tiff; // true;  // save transparent TIFF with geo metadata (top left corner)
		final int       gmap_tiff_pal =   clt_parameters.gmap_tiff_pal;  // 0;     // LWIR palette for TIFF  
		final int       gmap_tiff_pal =   clt_parameters.gmap_tiff_pal;  // 0;     // LWIR palette for TIFF  
		
		final boolean   gmap_um =         clt_parameters.gmap_um;            // true;  // Use unsharp mask filter for ARGB TIFF maps  
		final double    gmap_um_sigma =   clt_parameters.gmap_um_sigma;      // 0.4;   // Unsharp mask sigma for  ARGB TIFF maps (in meters)
		final double    gmap_um_weight =  clt_parameters.gmap_um_weight;     // 0.8;   // Unsharp mask weight for ARGB TIFF maps
		final boolean   gmap_lwir_autorange = clt_parameters.gmap_lwir_autorange;// true;  // Autorange LWIR textures for ARGB TIFF maps
		final boolean   gmap_um_fixed =   clt_parameters.gmap_um_fixed;      // false; // Use fixed range after unsharp mask instead of autorange  for ARGB TIFF maps
		final double    gmap_um_range =   clt_parameters.gmap_um_range;      // 500;   // Full range after unsharp mask for ARGB TIFF maps  
		
		
		final double  range_disparity_offset = clt_parameters.imp.range_disparity_offset;// double  range_disparity_offset
		final double  range_disparity_offset = clt_parameters.imp.range_disparity_offset;// double  range_disparity_offset
		final boolean batch_mode =        clt_parameters.multiseq_run; // batch_run;
		final boolean batch_mode =        clt_parameters.multiseq_run; // batch_run;
@@ -3068,9 +3074,6 @@ public class TexturedModel {
					}
					}
					//			String model_name = ref_scene.correctionsParameters.getModelName(ref_scene.getImageName());
					//			String model_name = ref_scene.correctionsParameters.getModelName(ref_scene.getImageName());
					String suffix ="-RECT"; 
					String suffix ="-RECT"; 
					if (clt_parameters.tex_um) {
						suffix+="-UM"+(clt_parameters.tex_um_sigma)+"_"+(clt_parameters.tex_um_weight);
					} 
					suffix +="-PIX"+pix_size * hdr_whs[2];
					suffix +="-PIX"+pix_size * hdr_whs[2];
					scenes[ref_index].saveDoubleArrayInModelDirectory(
					scenes[ref_index].saveDoubleArrayInModelDirectory(
							suffix+"-FULL", // String      suffix,
							suffix+"-FULL", // String      suffix,
@@ -3136,18 +3139,75 @@ public class TexturedModel {
							}
							}
						}
						}
						double avg_z = sum_z/num_pix;
						double avg_z = sum_z/num_pix;
						LocalDateTime dt = scenes[ref_index].getLocalDateTime(); 
						top_left_lla[2] = avg_z; // average altitude. Maybe keep drone altitude?
						top_left_lla[2] = avg_z; // average altitude. Maybe keep drone altitude?
						if (gmap_save_alt) {
						if (gmap_save_alt) {
							/*
							scenes[ref_index].saveDoubleArrayInTopModelDirectory( // save with Z
							scenes[ref_index].saveDoubleArrayInTopModelDirectory( // save with Z
									suffix+"-ALT", // String      suffix,
									suffix+"-ALT", // String      suffix,
									null,          // String []   labels, // or null
									null,          // String []   labels, // or null
									new double[][] {cropped_z[0]},    // double [][] data,
									new double[][] {cropped_z[0]},    // double [][] data,
									hdr_whs[0],    // int            width, // int tilesX,
									hdr_whs[0],    // int            width, // int tilesX,
									hdr_whs[1]);   // int            height, // int tilesY,
									hdr_whs[1]);   // int            height, // int tilesY,
							*/
							scenes[ref_index].writeLwirGeoTiff32(
									clt_parameters,                     // final CLTParameters  clt_parameters,
									cropped_z[0],                       // double []            data,
									top_left_lla,                       // double []            lla,  // latitude, longitude, altitude (or null)
									dt,                                 // LocalDateTime        dt,   // local date/time or null
									scaled_pixel_size,                  // double               pix_in_meters,
									hdr_whs[0],                         // int     width,
									null,                               // QuadCLT              scene,
									suffix+"-GEO-ALT",                  // String               suffix,
									debugLevel);                        // int                  debugLevel)
						}
						}
						double [] minmax =  tex_um_fixed ? (new double[] {-tex_um_range/2, tex_um_range/2}): null;				
						if (gmap_save_tiff32) {
							scenes[ref_index].writeLwirGeoTiff32(
									clt_parameters,                     // final CLTParameters  clt_parameters,
									img_cropped[0],                       // double []            data,
									top_left_lla,                       // double []            lla,  // latitude, longitude, altitude (or null)
									dt,                                 // LocalDateTime        dt,   // local date/time or null
									scaled_pixel_size,                  // double               pix_in_meters,
									hdr_whs[0],                         // int     width,
									null,                               // QuadCLT              scene,
									suffix+"-GEO",                      // String               suffix,
									debugLevel);                        // int                  debugLevel)
						}
						if ((gmap_save_tiff && (gmap_tiff_pal >=0)) || (tex_pals.length > 0)) {
							// TODO: Move UM here, save 32-bit GEO w/o UM
							if (gmap_um) {
								double um_sigma = gmap_um_sigma / scaled_pixel_size;
								int grow_pix = (int) (4 * um_sigma); // experimentally - UM grows by 4*sigma;
								// it is needed before Gaussian blur which extends NaN								
								double [] um_data = TileProcessor.fillNaNs(
										img_cropped[0], // final double [] data,
										null,                     // final boolean [] prohibit,
										hdr_whs[0],        // int       width,
										// CAREFUL ! Remaining NaN is grown by unsharp mask filter ************* !
										2*grow_pix, // 2*width, // 16,           // final int grow,
										0.7,          // double    diagonal_weight, // relative to ortho
										100,          // int       num_passes,
										0.03,         // final double     max_rchange, //  = 0.01 - does not need to be accurate
										THREADS_MAX); // final int threadsMax)      // maximal number of threads to launch
								double [][][] um_data3 = {{um_data}};
								QuadCLTCPU.umTextures(
										um_data3,                // final double [][][] textures, //  [nslices][nchn][i]
										hdr_whs[0], // tilesX * transform_size, // final int    width,
										false,                   // um_ignore_alpha,         // final boolean ignore_alpha,
										um_sigma,                // final double um_sigma,
										gmap_um_weight);         // final double um_weight)
								for (int i = 0; i < um_data.length; i++) {
									if (Double.isNaN(img_cropped[0][i])) {
										um_data[i] = Double.NaN;
									}
								}
								img_cropped[0] = um_data; // replaced with UM
								suffix+="-UM"+(clt_parameters.tex_um_sigma)+"_"+(clt_parameters.tex_um_weight);
								
							}
							
							double [] minmax =  gmap_um_fixed ? (new double[] {-gmap_um_range/2, gmap_um_range/2}): null;				
							if (gmap_save_tiff && (gmap_tiff_pal >=0)) {
							if (gmap_save_tiff && (gmap_tiff_pal >=0)) {
							LocalDateTime dt = scenes[ref_index].getLocalDateTime(); 
								scenes[ref_index].writeLwirGeoTiffARGB(
								scenes[ref_index].writeLwirGeoTiffARGB(
										clt_parameters,                     // final CLTParameters  clt_parameters,
										clt_parameters,                     // final CLTParameters  clt_parameters,
										img_cropped[0],                     // double []            data,
										img_cropped[0],                     // double []            data,
@@ -3176,6 +3236,7 @@ public class TexturedModel {
										debugLevel); // int                  debugLevel)
										debugLevel); // int                  debugLevel)
							}
							}
						}
						}
					}


				}
				}
			}
			}
@@ -7593,18 +7654,7 @@ public class TexturedModel {
					tilesX * transform_size, // int            width, // int tilesX,
					tilesX * transform_size, // int            width, // int tilesX,
					tilesY * transform_size); // int            height, // int tilesY,
					tilesY * transform_size); // int            height, // int tilesY,
		}		
		}		

		// save linear textures before applying UM
		// Optionally apply UM (before auto/manual range)
		final boolean um_ignore_alpha =     true;
		final boolean hist_ignore_alpha =   true; 
		if (tex_um) {
			QuadCLTCPU.umTextures(
					faded_textures,          // final double [][][] textures, //  [nslices][nchn][i]
					tilesX * transform_size, // final int    width,
					um_ignore_alpha,         // final boolean ignore_alpha,
					tex_um_sigma,            // final double um_sigma,
					tex_um_weight);          // final double um_weight)
		}
		if (lin_textures != null) {
		if (lin_textures != null) {
			// duplicate texture before normalization
			// duplicate texture before normalization
			lin_textures[0] = new double [faded_textures.length][][];
			lin_textures[0] = new double [faded_textures.length][][];
@@ -7619,6 +7669,17 @@ public class TexturedModel {
				}
				}
			}
			}
		}
		}
		// Optionally apply UM (before auto/manual range)
		final boolean um_ignore_alpha =     true;
		final boolean hist_ignore_alpha =   true; 
		if (tex_um) {
			QuadCLTCPU.umTextures(
					faded_textures,          // final double [][][] textures, //  [nslices][nchn][i]
					tilesX * transform_size, // final int    width,
					um_ignore_alpha,         // final boolean ignore_alpha,
					tex_um_sigma,            // final double um_sigma,
					tex_um_weight);          // final double um_weight)
		}
		if (save_interm_textures || save_um_texture0) {
		if (save_interm_textures || save_um_texture0) {
			double [][] dbg_textures = new double [faded_textures.length * faded_textures[0].length][faded_textures[0][0].length];
			double [][] dbg_textures = new double [faded_textures.length * faded_textures[0].length][faded_textures[0][0].length];
			String [] dbg_titles = new String[dbg_textures.length];
			String [] dbg_titles = new String[dbg_textures.length];