Commit 24d7049d authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Recording geo-tagged float Tiff

parent ff164bbf
Loading
Loading
Loading
Loading
+28 −3
Original line number Original line Diff line number Diff line
@@ -487,10 +487,10 @@ public class CLTParameters {
	public int []     gmap_tex_pals =        {0,1,2};
	public int []     gmap_tex_pals =        {0,1,2};
	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_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 TIFF  
	
	
	
	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
	public boolean    debug_filters    = false;// show intermediate results of filtering
	public boolean    debug_filters    = false;// show intermediate results of filtering
@@ -1635,6 +1635,11 @@ public class CLTParameters {
		properties.setProperty(prefix+"gmap_crop_extra",            this.gmap_crop_extra+"");            // int     
		properties.setProperty(prefix+"gmap_crop_extra",            this.gmap_crop_extra+"");            // int     
		properties.setProperty(prefix+"gmap_tex_pals",              CLTParameters.arr_to_str(this.gmap_tex_pals)); // int[]
		properties.setProperty(prefix+"gmap_tex_pals",              CLTParameters.arr_to_str(this.gmap_tex_pals)); // int[]
		
		
		properties.setProperty(prefix+"gmap_save_alt",              this.gmap_save_alt+"");              // boolean 
		properties.setProperty(prefix+"gmap_save_tiff32",           this.gmap_save_tiff32+"");           // 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+"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+"");
@@ -2654,6 +2659,11 @@ public class CLTParameters {
		if (properties.getProperty(prefix+"gmap_crop_extra")!=null)      this.gmap_crop_extra=Integer.parseInt(properties.getProperty(prefix+       "gmap_crop_extra"));// int     
		if (properties.getProperty(prefix+"gmap_crop_extra")!=null)      this.gmap_crop_extra=Integer.parseInt(properties.getProperty(prefix+       "gmap_crop_extra"));// int     
		if (properties.getProperty(prefix+"gmap_tex_pals")!=null)        this.gmap_tex_pals=CLTParameters.str_to_iarr(properties.getProperty(prefix+"gmap_tex_pals"));
		if (properties.getProperty(prefix+"gmap_tex_pals")!=null)        this.gmap_tex_pals=CLTParameters.str_to_iarr(properties.getProperty(prefix+"gmap_tex_pals"));
   		if (properties.getProperty(prefix+"gmap_save_alt")!=null)        this.gmap_save_alt=Boolean.parseBoolean(properties.getProperty(prefix+     "gmap_save_alt"));
   		if (properties.getProperty(prefix+"gmap_save_tiff32")!=null)     this.gmap_save_tiff32=Boolean.parseBoolean(properties.getProperty(prefix+  "gmap_save_tiff32"));
   		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+"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"));
@@ -3923,6 +3933,15 @@ public class CLTParameters {
		gd.addStringField ("LWIR palettes to render the maps",     CLTParameters.arr_to_str(this.gmap_tex_pals), 40,
		gd.addStringField ("LWIR palettes to render the maps",     CLTParameters.arr_to_str(this.gmap_tex_pals), 40,
				"Enter space-separated list of the palette numbers, such as, such as '0 1 2'");
				"Enter space-separated list of the palette numbers, such as, such as '0 1 2'");
		gd.addCheckbox ("Save height map (meters ASL)",            this.gmap_save_alt, // true; // enable change FG pixel to opaque from transparent
				"Save height map (meters Above Seal Level) as a floating-point single-slice TIFF (NAN for transparency).");
		gd.addCheckbox ("Save float Tiff with transparency and Geo",this.gmap_save_tiff32, // true; // enable change FG pixel to opaque from transparent
				"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
				"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
				"LWIR palette for Geo/transparency TIFF output.");
		
		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);
@@ -5138,6 +5157,12 @@ public class CLTParameters {
		this.gmap_crop_empty=       gd.getNextBoolean();
		this.gmap_crop_empty=       gd.getNextBoolean();
		this.gmap_crop_extra= (int) gd.getNextNumber();
		this.gmap_crop_extra= (int) gd.getNextNumber();
		this.gmap_tex_pals =        CLTParameters.str_to_iarr(gd.getNextString());
		this.gmap_tex_pals =        CLTParameters.str_to_iarr(gd.getNextString());
		
		this.gmap_save_alt=         gd.getNextBoolean();
		this.gmap_save_tiff32=        gd.getNextBoolean();
		this.gmap_save_tiff=        gd.getNextBoolean();
		this.gmap_tiff_pal=   (int) 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();
+1 −1
Original line number Original line Diff line number Diff line
@@ -114,7 +114,7 @@ public class DumpImageMetadata
		System.out.println(">");
		System.out.println(">");
	}
	}
	
	
	private static void dumpMetadata(IIOMetadata metadata)
	static void dumpMetadata(IIOMetadata metadata)
	{
	{
		String[] names = metadata.getMetadataFormatNames();
		String[] names = metadata.getMetadataFormatNames();
		int length = names.length;
		int length = names.length;
+106 −12
Original line number Original line Diff line number Diff line
@@ -23,11 +23,18 @@
 */
 */
package com.elphel.imagej.readers;
package com.elphel.imagej.readers;


import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferFloat;
import java.awt.image.Raster;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import java.awt.image.PixelInterleavedSampleModel;
import java.io.File;
import java.io.File;
import java.io.IOException;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
@@ -68,7 +75,7 @@ public class ElphelTiffWriter {
	public static String TIFF_FIELD_DESCRIPTION_ATTRIBUTE = "description";
	public static String TIFF_FIELD_DESCRIPTION_ATTRIBUTE = "description";
	
	
	
	
	public static void saveTiffARGB32(
	public static void saveTiffARGBOrGray32(
			ImagePlus     imp,
			ImagePlus     imp,
			String        path, // full path to save image
			String        path, // full path to save image
			double []     lla,  // latitude, longitude, altitude (or null)
			double []     lla,  // latitude, longitude, altitude (or null)
@@ -87,19 +94,30 @@ public class ElphelTiffWriter {
// https://docs.oracle.com/en/java/javase/17/docs/api/java.desktop/javax/imageio/metadata/doc-files/tiff_metadata.html	    
// https://docs.oracle.com/en/java/javase/17/docs/api/java.desktop/javax/imageio/metadata/doc-files/tiff_metadata.html	    
//	    tiffWriteParam.setCompressionType("Exif JPEG");
//	    tiffWriteParam.setCompressionType("Exif JPEG");
	    tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);
	    tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);
	    BufferedImage bufferedImageAlpha;
    	BufferedImage bufferedImage = (BufferedImage) imp.getImage(); // properties=null
	    if (imp.getType()==ImagePlus.COLOR_RGB) {
	    	/* ImagePlus image removes alpha, so we need to create a new ARGB BufferedImage
	    	/* ImagePlus image removes alpha, so we need to create a new ARGB BufferedImage
	    	 * and copy data (it is correct in imp.getImage() */
	    	 * and copy data (it is correct in imp.getImage() */
	    BufferedImage   bufferedImage = (BufferedImage) imp.getImage(); // properties=null
	    	bufferedImageAlpha = new BufferedImage(
	    BufferedImage bufferedImageAlpha = new BufferedImage(
	    			bufferedImage.getWidth(),
	    			bufferedImage.getWidth(),
	    			bufferedImage.getHeight(),
	    			bufferedImage.getHeight(),
	    			BufferedImage.TYPE_INT_ARGB);
	    			BufferedImage.TYPE_INT_ARGB);
	    	int [] ipixels = (int[])imp.getProcessor().getPixels();
	    	int [] ipixels = (int[])imp.getProcessor().getPixels();
	    	final int[] bia_as_arr = ( (DataBufferInt) bufferedImageAlpha.getRaster().getDataBuffer() ).getData();
	    	final int[] bia_as_arr = ( (DataBufferInt) bufferedImageAlpha.getRaster().getDataBuffer() ).getData();
	    	System.arraycopy(ipixels, 0, bia_as_arr, 0, bia_as_arr.length);
	    	System.arraycopy(ipixels, 0, bia_as_arr, 0, bia_as_arr.length);
	    
	    } else {
	    	bufferedImageAlpha = createFloatBufferedImage(
	    			bufferedImage.getWidth(),
	    			bufferedImage.getHeight()
	    			);
	    	float [] pixels = (float[]) imp.getProcessor().getPixels();
	    	final float[] bia_as_arr = ( (DataBufferFloat) bufferedImageAlpha.getRaster().getDataBuffer() ).getData();
	    	System.arraycopy(pixels, 0, bia_as_arr, 0, bia_as_arr.length);
	    }
	    ImageTypeSpecifier imageType = ImageTypeSpecifier.createFromRenderedImage(bufferedImageAlpha);            
	    ImageTypeSpecifier imageType = ImageTypeSpecifier.createFromRenderedImage(bufferedImageAlpha);            
	    IIOMetadata imageMetadata = tiffWriter.getDefaultImageMetadata(imageType, tiffWriteParam);
	    IIOMetadata imageMetadata = tiffWriter.getDefaultImageMetadata(imageType, tiffWriteParam);
	    if (debugLevel > 0) {System.out.println("\n=== imageMetadata ===:");DumpImageMetadata.dumpMetadata(imageMetadata);}
// just for testing:
// just for testing:
	    int cm_dig_after = 9;
	    int cm_dig_after = 9;
	    // Here is a way adding tag sets through TIFFDirectory
	    // Here is a way adding tag sets through TIFFDirectory
@@ -166,6 +184,82 @@ public class ElphelTiffWriter {
	    System.out.println();
	    System.out.println();
	}
	}
	
	
	private static BufferedImage createFloatBufferedImage(
			int width,
			int height
			) {
		//https://stackoverflow.com/questions/26766751/java-create-bufferedimage-with-float-precision/26775056#26775056	
//        int bands = 4; // 4 bands for ARGB, 3 for RGB etc
//        int[] bandOffsets = {0, 1, 2, 3}; // length == bands, 0 == R, 1 == G, 2 == B and 3 == A
        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
        // Create a TYPE_FLOAT sample model (specifying how the pixels are stored)
        SampleModel sampleModel0 = new PixelInterleavedSampleModel(
        		DataBuffer.TYPE_FLOAT,
        		width,
        		height,
        		bands,
        		width  * bands,
        		bandOffsets);

        // 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 
        // color space (3 for RGB) + 1 extra band if the color model contains alpha 
        ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY); // CS_sRGB);
//        ColorModel colorModel = new ComponentColorModel(colorSpace, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_FLOAT);
        ColorModel colorModel = new ComponentColorModel(
        		colorSpace,
        		false, // true,
        		false,
        		Transparency.TRANSLUCENT, // ?
        		DataBuffer.TYPE_FLOAT);
        SampleModel sampleModel = colorModel.createCompatibleSampleModel (width, height);       
        // ...and data buffer (where the pixels are stored)
        DataBuffer buffer = new DataBufferFloat(width * height * bands);
        // Wrap it in a writable raster
        WritableRaster raster = Raster.createWritableRaster(sampleModel, buffer, null);

        // And finally create an image with this raster
        BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
        return image;
        
		
/*
 * color space (ColorSpace.CS_GRAY) and no transparency may make more sense.
 public class FloatImage {
    public static void main(String[] args) {
        // Define dimensions and layout of the image
        int w = 300;
        int h = 200;
        int bands = 4; // 4 bands for ARGB, 3 for RGB etc
        int[] bandOffsets = {0, 1, 2, 3}; // length == bands, 0 == R, 1 == G, 2 == B and 3 == A

        // Create a TYPE_FLOAT sample model (specifying how the pixels are stored)
        SampleModel sampleModel = new PixelInterleavedSampleModel(DataBuffer.TYPE_FLOAT, w, h, bands, w  * bands, bandOffsets);
        // ...and data buffer (where the pixels are stored)
        DataBuffer buffer = new DataBufferFloat(w * h * bands);

        // Wrap it in a writable raster
        WritableRaster raster = Raster.createWritableRaster(sampleModel, buffer, null);

        // 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 
        // color space (3 for RGB) + 1 extra band if the color model contains alpha 
        ColorSpace colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
        ColorModel colorModel = new ComponentColorModel(colorSpace, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_FLOAT);

        // And finally create an image with this raster
        BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);

        System.out.println("image = " + image);
    }
}


 */
	}
	
	
	private static IIOMetadataNode createRationalDegrees(double d, int digits_after) { // 8
	private static IIOMetadataNode createRationalDegrees(double d, int digits_after) { // 8
		int denom = 1;
		int denom = 1;
		for (int i = 0; i < digits_after; i++) denom *= 10;
		for (int i = 0; i < digits_after; i++) denom *= 10;
+47 −33
Original line number Original line Diff line number Diff line
@@ -314,7 +314,7 @@ the type of pixel data in this file getPixelType()
		
		
		if (imp.getType()==ImagePlus.COLOR_RGB) { // 4*8 bit - type = 0
		if (imp.getType()==ImagePlus.COLOR_RGB) { // 4*8 bit - type = 0
			if (debugLevel>1) System.out.println("Saving 8-bit TIFF with alpha-channel: "+path); // is it possible to just add alpha to high bytes?
			if (debugLevel>1) System.out.println("Saving 8-bit TIFF with alpha-channel: "+path); // is it possible to just add alpha to high bytes?
			ElphelTiffWriter.saveTiffARGB32(
			ElphelTiffWriter.saveTiffARGBOrGray32(
					imp,
					imp,
					path,
					path,
					lla,  // double []     lla,  // latitude, longitude, altitude (or null)
					lla,  // double []     lla,  // latitude, longitude, altitude (or null)
@@ -330,6 +330,19 @@ the type of pixel data in this file getPixelType()
			return;
			return;


		} else if (imp.getType()==ImagePlus.GRAY32) {
		} else if (imp.getType()==ImagePlus.GRAY32) {
			boolean save_float = true;
			if (save_float) {
				if (debugLevel>1) System.out.println("Saving GRAY32 TIFF (NaN for transparency): "+path); // is it possible to just add alpha to high bytes?
				ElphelTiffWriter.saveTiffARGBOrGray32(
						imp,
						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
						imageJTags,
						debugLevel);

			} else {
				int            lwir_palette = 0;
				int            lwir_palette = 0;
				double []      minmax = null;
				double []      minmax = null;
				String title = imp.getTitle();
				String title = imp.getTitle();
@@ -354,7 +367,7 @@ the type of pixel data in this file getPixelType()




				if (debugLevel>1) System.out.println("Saving 8-bit RGBA TIFF with alpha-channel: "+path); // is it possible to just add alpha to high bytes?
				if (debugLevel>1) System.out.println("Saving 8-bit RGBA TIFF with alpha-channel: "+path); // is it possible to just add alpha to high bytes?
			ElphelTiffWriter.saveTiffARGB32(
				ElphelTiffWriter.saveTiffARGBOrGray32(
						imp_rgb,
						imp_rgb,
						path,
						path,
						lla,  // double []     lla,  // latitude, longitude, altitude (or null)
						lla,  // double []     lla,  // latitude, longitude, altitude (or null)
@@ -363,6 +376,7 @@ the type of pixel data in this file getPixelType()
						imageJTags,
						imageJTags,
						debugLevel);
						debugLevel);
				//			saveTiffARGB32(imp_rgb, path, imageJTags, debugLevel);
				//			saveTiffARGB32(imp_rgb, path, imageJTags, debugLevel);
			}
			return;
			return;
		}
		}
		IJ.showMessage("Not yet implemented for this image type");
		IJ.showMessage("Not yet implemented for this image type");
+1 −1
Original line number Original line Diff line number Diff line
@@ -16445,7 +16445,7 @@ public class QuadCLTCPU {
				  height, // int            height, // int tilesY,
				  height, // int            height, // int tilesY,
				  debugLevel); // int            debugLevel )
				  debugLevel); // int            debugLevel )
		  String image_path = model_dir +  Prefs.getFileSeparator() + title+".tiff";
		  String image_path = model_dir +  Prefs.getFileSeparator() + title+".tiff";
		  ElphelTiffWriter.saveTiffARGB32(
		  ElphelTiffWriter.saveTiffARGBOrGray32(
				  imp,
				  imp,
				  image_path,
				  image_path,
				  lla,           // double []     lla,  // latitude, longitude, altitude (or null)
				  lla,           // double []     lla,  // latitude, longitude, altitude (or null)
+1 −1

File changed.

Contains only whitespace changes.

Loading