TIFF_TO_JP2_MIE.sml

  Download

More scripts: Import & Export

Syntax Highlighing:

comments, key words, predefined symbols, class members & methods, functions & classes
            
# TIFF_TO_JP2_MIE.sml
# Sample script for tutorial Writing Scripts with SML
# Links to one or more input GeoTIFF files and exports each to a GeoJP2 file
# with selected compression settings.  GeoTIFF files may contain composite
#  or separate bands. Script creates a custom dialog window to manage user inputs.
# version 8 December 2009. 
#################  Global Variables  #########################
class STRING outputDir$;					# path to output directory
class STRINGLIST filepathlist;			# list of filepaths of the TIFF files selected
numeric numfiles; 							# number of TIFF files selected
numeric err;									# value returned for error checking
class GUI_DLG dlgwin;						# the dialog window created by script
class GUI_CTRL_LISTBOX filelistbox;		# handle for file listbox on the dialog
class GUI_CTRL_PUSHBUTTON dirBtn, runBtn;	# handles for pushbuttons
numeric ratioEnabled = 1;		# flag for tracking whether compression ratio field has been enabled
class RVC_OBJITEM objItemList[]; # hash of objItems for the component rasters to be created
																				# from a single multiband GeoTIFF file
#################  User-Defined Procedures  ##########################
# procedure called when the dialog window opens; use to get class handles for controls
proc OnOpen()
	{
	filelistbox = dlgwin.GetCtrlByID("filelistbox");
	dirBtn = dlgwin.GetCtrlByID("dirBtn");
	runBtn = dlgwin.GetCtrlByID("runBtn");
	}
# Procedure called by the Select TIFF Files button on the dialog.
# Gets a stringlist with the filepath strings for the selected files, 
# writes the filepath strings to the file listbox on the dialog, and
# enables the Get Directory button
proc GetInputFiles() 
	{
	local numeric i;
	dlgwin.SetCtrlValueStr("msgText", "");
	# clear previous input file list if any
	if (filepathlist.GetNumItems() > 0 ) then filepathlist.Clear();
	if (filelistbox.GetCount() > 0 ) then filelistbox.DeleteAllItems();
	# get input GeoTIFF files
	numfiles = GetInputFileNames(_context.ScriptDir, "Select TIFF file(s) for conversion to JP2:", "tif", filepathlist);
	printf("numfiles = %d\n", numfiles);
	for i = 1 to numfiles
		{
		filelistbox.AddItem( filepathlist[i-1] );			# add filepath string to the listbox
		}
	dirBtn.SetEnabled(1);		# enable the button to select output directory
	# if an output directory has already been selected in a previous run, enable the Run button
	if (outputDir$ <> "") then runBtn.SetEnabled(1);
	}
# Procedure called by the Select Output Directory button on the dialog
# Gets the output directory path and enables the Run Jobs and Save Jobs buttons
proc GetOutputDirectory()
	{
	outputDir$ = GetDirectory("", "Choose directory for JP2 files:");
	if (outputDir$ == "") then
		PopupMessage("No directory selected.  Please choose an output directory.");
	else {
		outputDir$ = outputDir$ + "/";
		dlgwin.SetCtrlValueStr("outDirText", outputDir$);		# write directory name to the dialog
		runBtn.SetEnabled(1);			# enable the Run button
		}
	}
# procedure called by the Close button on the dialog
proc OnClose()
	{
	dlgwin.Close(0);
	Exit();
	}
# Procedure called when JPEG2000 compression option is selected.
# Changes the state of associated controls on the dialog
proc OnCompSelected()
	{
	if (dlgwin.GetCtrlByID("jp2compOptions").GetValueStr() == "LossyRatio")		# user-defined compression is set
		{
		if (ratioEnabled <> 1)		# if ratio label and field are currently disabled, enable them
			{
			dlgwin.GetCtrlByID("ratioLabel").SetEnabled(1);
			dlgwin.GetCtrlByID("compRatioNum").SetEnabled(1);
			ratioEnabled = 1;
			}
		}
	else		#  compression option = lossless or best quality
		{
		if (ratioEnabled == 1)		# if ratio label and field are enabled, disable them
			{
			dlgwin.GetCtrlByID("ratioLabel").SetEnabled(0);
			dlgwin.GetCtrlByID("compRatioNum").SetEnabled(0);
			ratioEnabled = 0;
			}
		}
	}
# Procedure called by the Run icon button
proc OnRun()
	{
	local numeric i, j;				# loop counters
	local string inputPath$;		# string with the filepath of the current input TIFF file
	local string compType$;			# type of JPEG2000 compression to set
	local numeric compRatio;		# target compression ratio for lossy compression
	local numeric numBands;			# number of bands in the GeoTIFF file
	local numeric imported;			# number of bands successfully imported
	local class STRING dest$;			# string with destination path and filename
	# get compression options from the dialog
	compType$ = dlgwin.GetCtrlValueStr("jp2compOptions");
	if (compType$ == "LossyRatio") then				# get target ratio for user-defined compression
		compRatio = dlgwin.GetCtrlValueNum("compRatioNum");
	else
		compRatio = 0;
	# loop through selected input GeoTIFF files
	for i = 1 to numfiles
		{
		local class RVC_OBJECT tempFile;		# for temporary Project File to hold bands for export
		local class MieGeoTIFF geotiff;				# for importing from or linking to GeoTIFF
		local class MieGeoJP2 geoJP2;				# for exporting to GeoJP2
		# set compression options for export to GeoJP2
		geoJP2.CompressionType = compType$;
		geoJP2.CompressionRatio = compRatio;
		dlgwin.SetCtrlValueStr("msgText", sprintf("Processing file %d of %d: Linking to GeoTIFF", i, numfiles));
		printf("Processing file %d of %d: Linking to GeoTIFF", i, numfiles);
		# get path string for current GeoTIFF file
		inputPath$ = filepathlist[ i - 1 ];
		local class FILEPATH inFilepath(inputPath$);
		# Check source file to generate an ObjItemList with the proper number of components.
		# This is the list of RVC objects that GeoTIFF bands will be link to.  The ObjItemList returned
		# is basically a template with the correct number of entries.  The actual filepath
		# to the RVC file and the object path for each RVC object need to be filled in manually
		# in a later step.
		geotiff.GetObjItemList(inputPath$, objItemList);
		numBands = objItemList.GetNumItems();
		printf("file %d, path = %s, number of bands = %d\n", i, inputPath$, numBands);
		# make temporary Project File to hold rasters imported from GeoTIFF
		tempFile.MakeTempFile(1);	# set to delete on close.
		local class FILEPATH tempFilepath;
		tempFilepath = tempFile.GetObjItem().GetFilePath();
		printf("tempFilepath = %s\n", tempFilepath);
		local class RVC_DESCRIPTOR descriptor;		# descriptor for naming temporary raster objects
		for j = 1 to numBands
			{
			# set tempfile filepath and object names for each ObjItem in inObjItemList (new raster
			# objects to be created in the temporary Project File)
			descriptor.SetName(sprintf( "Component%d", j) );
			objItemList[ j ].CreateNew(tempFile.GetObjItem(), "RASTER", descriptor);
			printf("temp filepath = %s, object path = %s\n", objItemList[ j ].GetFilePath(), objItemList[j ].GetObjectPath() ); 
			}
		# import the GeoTIFF bands to the temp file
		geotiff.DoLink = 1;
		geotiff.ImportObjects(inputPath$, objItemList);
		dlgwin.SetCtrlValueStr("msgText", sprintf("Processing file %d of %d: Exporting to GeoJP2", i, numfiles));
		printf("Processing file %d of %d: Exporting to GeoJP2", i, numfiles);
		# Reset the object paths in the ObjItemList after import to associate the ObjItems with actual inodes in the file. 
		# Check that all imported bands actually exist.
		imported = 0;
		for j = 1 to numBands
			{
			objItemList[ j ].SetObjectPath( sprintf("Component%d.RASTER", j) );
			imported += objItemList[ j ].IsExisting();		# returns 1 if object exists
			}
		printf("imported = %d\n", imported);
		if (imported == numBands)
			{
			# set path and filename for export to GeoJP2
			class STRING filename$ = inFilepath.GetNameOnly();	# name of current input GeoTIFF file 
			dest$ = outputDir$ + filename$ + ".jp2";
			printf("output file path = %s\n", dest$);
			# export the linked bands to the designated GeoJP2 file
			geoJP2.ExportObjects(objItemList, dest$);
			# change status of controls for next run
			dirBtn.SetEnabled(0);
			runBtn.SetEnabled(0);
	
			printf("Export of file %d of %d completed.\n", i, numfiles);
			}
		else
			{
			printf("GeoTIFF bands for file %d not imported, aborting export.\n", i);
			}
		# close the tempfile and clear the ObjItem hash
		tempFile.Close();
		objItemList.Clear();
		}
	dlgwin.SetCtrlValueStr("msgText", "Done.");
	}	# end OnRun()
#########################   Main Program  ###################################
clear();
# dialog specification
class STRING xml$ = '<?xml version="1.0"?>
	<!DOCTYPE root SYSTEM "smlforms.dtd">
	<root>
		<dialog id="dlg" Title="TIFF to JP2 Conversion" Buttons="" OnOpen="OnOpen()">
			<pushbutton Name=" Select TIFF Files " OnPressed="GetInputFiles()"/>
			<listbox id="filelistbox" Width="40" />
			<pushbutton id="dirBtn" Name=" Select Output Directory " Enabled="false" OnPressed="GetOutputDirectory()"/>
			<edittext id="outDirText" ReadOnly="true" Width="40"/>
			<pane Orientation="horizontal" HorizResize="Fixed">
				<label>JPEG2000 compression</label>
				<combobox id="jp2compOptions" Default="LossyRatio" OnSelection="OnCompSelected()">
					<item Name="Lossless" Value="Lossless"/>
					<item Name="Best Quality" Value="LossyBest"/>
					<item Name="User Defined" Value="LossyRatio"/>
				</combobox>
				<label id="ratioLabel" Enabled="true">Target ratio</label>
				<editnumber id="compRatioNum" Width="3" Precision="0" Default="15" Enabled="true"/>
			</pane>
			<edittext id="msgText" Width="40" ReadOnly="true"/>
			<pane Orientation="horizontal" HorizResize="Fixed" HorizAlign="Right">
				<pushbutton id="runBtn" Name=" Run " Enabled="false" OnPressed="OnRun()"/>
				<pushbutton Name=" Close " OnPressed="OnClose()"/>
			</pane>
		</dialog>
	</root>';
##############################################
### parse XML text for the dialog into memory; 
### return an error code (number < 0 ) if there are syntax errors
class XMLDOC dlgdoc;
err = dlgdoc.Parse(xml$);
if ( err < 0 ) {
	PopupError( err ); 	# Popup an error dialog. "Details" button shows syntax errors.
	Exit();
	}
################################################
# get the dialog element from the parsed XML document and
# show error message if the dialog element can't be found
class XMLNODE dlgnode;
dlgnode = dlgdoc.GetElementByID("dlg");
if ( dlgnode == 0 ) {
	PopupMessage("Could not find dialog node in XML document");
	Exit();
	}
################################################
# Set the XML dialog element as the source for the GUI_DLG class 
# instance we are using for the dialog window.
err = dlgwin.SetXMLNode(dlgnode);
if ( err < 0 ) {
	PopupError( err ); 	# Popup an error dialog. 
	Exit();
	}
dlgwin.CreateModeless();
dlgwin.Open();
WaitForExit();