Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Some constants (See TIFF Format)
- number kLittleEndianTIFF = 0x4949
- number kBigEndianTIFF = 0x4D4D
- number kMagicIDNumberTIFF = 42
- number FALSE = 0
- number TRUE = 1
- Interface I_ImportTiffWithTags
- {
- // Aux. method to simplify single value read from stream
- number ReadValueOfType( object self, string type );
- // Aux. method to strip multiple pre- and post- string occurances from a string
- string ClipText( object self, string input, string leadIn, string leadOut, number doMultiple );
- string ClipTextWhiteSpaces( object self, string input );
- // Aux. method to convert ASCII text of specific format into a TagStructure
- TagGroup CreateTagsFromString( object self, string input, string entrySep, string keyToValueSep, string GroupLeadIn, string GroupLeadOut );
- TagGroup CreateTagsFromString_FEI_Default( object self, string input );
- TagGroup CreateTagsFromString_ZEISS_Default( object self, string input );
- // Get all TIFF tags from file in path as tagGroup
- TagGroup GetTIFFTagsAsTG( object self, string path, number doTextFields, number doSingleValues, number includedSkipped );
- TagGroup GetTIFFTagsAsTG( object self, string path, number includedSkipped ); // doTextField = true, doSingleValues = true
- TagGroup GetTIFFTagsAsTG( object self, string path ); // doTextField = true, doSingleValues = true, includedSkipped = false
- // Get all ASCII TIFF tags as single string
- String GetTIFFAscii( object self, string path, number splitSeparateTags );
- String GetTIFFAscii( object self, string path); // splitSeparateTags = true
- // Import Image and append TIFF tags as TagGroup "TIFF Tags" to image
- image OpenTIFFWithTags( object self, string path );
- // Import TIFF Image stored by FEI SEMs, import info from ASCII in image, calibrate if possible
- image OpenFEI_TIFF( object self, string path, number withTiffTags );
- image OpenFEI_TIFF( object self, string path );
- // Import TIFF Image stored by ZEISS SEMs, import info from ASCII in image, calibrate if possible
- image OpenZEISS_TIFF( object self, string path, number withTiffTags );
- image OpenZEISS_TIFF( object self, string path);
- // Aux. to find calibration from the tags, format specific
- number GetCalibrationFromTags_FEI( object self, tagGroup FEItgs, number &sx, number &ox, string &ux, number &sy, number &oy, string &uy );
- number GetCalibrationFromTags_ZEISS( object self, tagGroup ZEISStags, number &sx, number &ox, string &ux, number &sy, number &oy, string &uy );
- }
- Class CImportTIFFWithTags
- {
- object fStream
- number byteOrder
- number verbose
- number kMaxTextShow
- CImportTIFFWithTags( object self )
- {
- verbose = FALSE
- kMaxTextShow = 20
- }
- number ReadValueOfType( object self, string type )
- {
- if ( !fStream.ScriptObjectIsValid() ) Throw( "Invalid file stream." )
- number val = 0
- TagGroup tg = NewTagGroup()
- if ( type == "bool" )
- {
- tg.TagGroupSetTagAsBoolean( type, 0 )
- tg.TagGroupReadTagDataFromStream( type, fstream, byteOrder )
- tg.TagGroupGetTagAsBoolean( type, val )
- }
- else if ( type == "uint8" )
- {
- string str = fStream.StreamReadAsText(0,1)
- val = asc(str)
- }
- else if ( type == "uint16" )
- {
- tg.TagGroupSetTagAsUInt16( type, 0 )
- tg.TagGroupReadTagDataFromStream( type, fstream, byteOrder )
- tg.TagGroupGetTagAsUInt16( type, val )
- }
- else if ( type == "uint32" )
- {
- tg.TagGroupSetTagAsUInt32( type, 0 )
- tg.TagGroupReadTagDataFromStream( type, fstream, byteOrder )
- tg.TagGroupGetTagAsUInt32( type, val )
- }
- else if ( type == "float" )
- {
- tg.TagGroupSetTagAsFloat( type, 0 )
- tg.TagGroupReadTagDataFromStream( type, fstream, byteOrder )
- tg.TagGroupGetTagAsFloat( type, val )
- }
- else if ( type == "double" )
- {
- tg.TagGroupSetTagAsDouble( type, 0 )
- tg.TagGroupReadTagDataFromStream( type, fstream, byteOrder )
- tg.TagGroupGetTagAsDouble( type, val )
- }
- else Throw("Invalid read-type:"+type)
- return val
- }
- string ClipText( object self, string input, string leadIn, string leadOut, number doMultiple )
- {
- string work = input
- if ( len(leadIn) <= len(work) )
- {
- while ( leadIn == left(work,len(leadIn)) )
- {
- work = right( work, len(work) - len(leadIn) )
- if ( !doMultiple ) break
- if ( len(work) < len(leadin) ) break
- }
- }
- if ( len(leadOut) <= len(work) )
- {
- while ( leadOut == right(work,len(leadout)) )
- {
- work = left( work, len(work) - len(leadOut) )
- if ( !doMultiple ) break
- if ( len(leadOut) <= len(work) ) break
- }
- }
- return work
- }
- string ClipTextWhiteSpaces( object self, string input )
- {
- return self.ClipText( input, " ", " ", TRUE );
- }
- TagGroup CreateTagsFromString( object self, string input, string entrySep, string keyToValueSep, string GroupLeadIn, string GroupLeadOut )
- {
- TagGroup tg = NewTagGroup()
- number bCheckGroup = ( len(GroupLeadIn) && len(GroupLeadOut) ) // true if groupLeads are specified
- string work = input
- string groupName = ""
- if ( "" == entrySep )
- entrySep = "\n"
- number pos = find( work, entrySep )
- number skipped = 0
- while( -1 != pos )
- {
- //OKDialog("work:"+work)
- //OKDialog("Entry:"+len(entrySep) )
- string entry = left( work, pos )
- work = right( work, len(work) - len(entry) - len(entrySep) + 1)
- number sep = find( entry, keyToValueSep )
- if( -1 < sep )
- {
- // Entry matches format "KEY=VALUE" with '=' being the defined entrySep
- string key = left( entry, sep )
- string value= right( entry, len(entry) - sep - len(keyToValueSep) )
- // Truncate trailing white spaces
- key = self.ClipTextWhiteSpaces(key)
- value = self.ClipTextWhiteSpaces(value)
- string tagPath = groupName + ( "" == groupName ? "" : ":" ) + key
- tg.TagGroupSetTagAsString( tagPath, value )
- }
- else if ( bCheckGroup )
- {
- // Entry does not match format "KEY=VALUE", check if it is a groupname
- number leadIn = find( entry, GroupLeadIn )
- number leadOut = find( entry, GroupLeadOut )
- if ( ( -1 < leadIn ) && ( -1 < leadOut ) && ( leadIn < leadOut ) ) // Is it a new group? "[GROUPNAME]"
- {
- groupName = mid( entry, leadIn + len(GroupLeadIn), leadOut - leadIn - len(GroupLeadOut) )
- }
- else
- skipped++
- }
- else
- {
- skipped++
- }
- // Find next entry
- pos = find( work, entrySep )
- }
- if ( 0 != len(work) )
- skipped++
- if ( verbose )
- {
- if ( skipped )
- Result( "\nText To Tag skipped " + skipped + " lines.\n" )
- }
- return tg
- }
- TagGroup CreateTagsFromString_FEI_Default( object self, string input )
- {
- return self.CreateTagsFromString( input, "\n" , "=", "[", "]" )
- }
- TagGroup CreateTagsFromString_ZEISS_Default( object self, string input )
- {
- return self.CreateTagsFromString( input, "\n" , "=", "", "" )
- }
- TagGroup GetTIFFTagsAsTG( object self, string path, number doTextFields, number doSingleValues, number includedSkipped )
- {
- if ( !DoesFileExist( path ) ) Throw( "File not found.\n"+path)
- // Open Stream
- number fileID = OpenFileForReading( path )
- fStream = NewStreamFromFileReference(fileID,1)
- // Find Byte Order
- number val
- byteOrder = 0
- val = self.ReadValueOfType( "uint16" )
- byteOrder = ( kLittleEndianTIFF == val ) ? 2 : ( kBigEndianTIFF == val ? 1 : 0 )
- // Verify TIFF image
- val = self.ReadValueOfType( "uint16" )
- if ( val != kMagicIDNumberTIFF ) Throw( "Not a valid TIFF image" )
- // Find first directory start
- number offset = self.ReadValueOfType( "uint32" )
- // Browse all directories
- number nIFD = 0
- TagGroup AllTiffTagsTGlist = NewTagList()
- TagGroup TiffTGs
- while( 0 != offset )
- {
- // Set to start of directory and read it in
- nIFD++
- TiffTGs = NewTagGroup()
- if ( verbose ) Result( "Reading IFD #" + nIFD + " at \t" + offset )
- fStream.StreamSetPos( 0, offset )
- number nEntries = self.ReadValueOfType( "uint16" )
- for ( number e=0; e<nEntries; e++ )
- {
- number tag = self.ReadValueOfType( "uint16" )
- string tagStr = "ID("+tag+")"
- number typ = self.ReadValueOfType( "uint16" )
- number count = self.ReadValueOfType( "uint32" )
- number dataOffset = self.ReadValueOfType( "uint32" )
- if ( verbose )
- Result( "\n DirEntry # "+Format(e,"%3.0f") + ": TiffIDTag: " + tag + "]ttyp: " + typ + "\tcount: " + count )
- // Read only, if it is either a single value or a string
- if ( ( doTextFields ) && ( 2 == typ ) )// ASCII
- {
- number currentPos = fStream.StreamGetPos()
- fStream.StreamSetPos( 0, dataOffset )
- string textField = fStream.StreamReadAsText( 0, count )
- fStream.StreamSetPos( 0, currentPos )
- if ( verbose ) Result( "\t value: " + left( textField, min(len(textField), kMaxTextShow ) ) )
- TiffTGs.TagGroupSetTagAsString( tagStr, textField )
- }
- else if ( ( doSingleValues ) && ( 1 == count ) ) // Single Value.
- {
- // Note that the 'dataOffset'-4-bytes are already the value for data fitting in 4-bytes!
- // Otherwise, it specifies the staring offset for the value
- if ( 1 == typ ) // uInt8
- {
- TiffTGs.TagGroupSetTagAsShort( tagStr, dataOffset )
- if ( verbose ) Result("\t value:" + dataOffset )
- }
- else if ( 3 == typ ) // uInt16
- {
- TiffTGs.TagGroupSetTagAsUInt16( tagStr, dataOffset )
- if ( verbose ) Result("\t value:" + dataOffset )
- }
- else if ( 4 == typ ) // uInt32
- {
- TiffTGs.TagGroupSetTagAsUInt32( tagStr, dataOffset )
- if ( verbose ) Result("\t value:" + dataOffset )
- }
- else if ( 5 == typ ) // uInt32 / uInt32 (rational)
- {
- number currentPos = fStream.StreamGetPos()
- number val1 = self.ReadValueOfType( "uint32" )
- number val2 = self.ReadValueOfType( "uint32" )
- TiffTGs.TagGroupSetTagAsLongPoint( tagStr, val1, val2 )
- fStream.StreamSetPos( 0, currentPos )
- if ( verbose ) Result("\t value:" + val1 + "/" + val2 )
- }
- else if ( 11 == typ ) // float
- {
- TiffTGs.TagGroupSetTagAsFloat( tagStr, dataOffset )
- if ( verbose ) Result("\t value:" + dataOffset )
- }
- else if ( 12 == typ ) // double
- {
- number currentPos = fStream.StreamGetPos()
- number val = self.ReadValueOfType( "double" )
- TiffTGs.TagGroupSetTagAsDouble( tagStr, val )
- fStream.StreamSetPos( 0, currentPos )
- if ( verbose ) Result("\t value:" + val )
- }
- else if ( includedSkipped )
- {
- if ( verbose ) Result("\t value: SKIPPED DATA TYPE" )
- TiffTGs.TagGroupSetTagAsString( tagStr, "Not imported, TagType (TIFF "+typ+")" )
- }
- }
- else if ( includedSkipped )
- {
- // Multiple value entries
- if ( verbose ) Result("\t value: Multiple values. Arrays are not read." )
- TiffTGs.TagGroupSetTagAsString( tagStr, "Not imported, TagType (TIFF "+typ+") "+count+" values" )
- }
- }
- // Read next directory offset.
- // This is 0000 for the last directory according to spec
- offset = self.ReadValueOfType( "uint32" )
- AllTiffTagsTGlist.TagGroupAddTagGroupAtEnd(TiffTGs)
- }
- // Return list if entries or just one group if there is one directory only
- if ( 1 < nIFD )
- return AllTiffTagsTGlist
- else
- return TiffTGs
- }
- TagGroup GetTIFFTagsAsTG( object self, string path, number includedSkipped )
- {
- return self.GetTIFFTagsAsTG( path, TRUE, TRUE, includedSkipped )
- }
- TagGroup GetTIFFTagsAsTG( object self, string path )
- {
- return self.GetTIFFTagsAsTG( path, TRUE, TRUE, FALSE )
- }
- String GetTIFFAscii( object self, string path, number splitSeparateTags )
- {
- String allText
- TagGroup tgs = self.GetTIFFTagsAsTG(path, TRUE, FALSE, FALSE )
- number nTags = tgs.TagGroupCountTags()
- for ( number n=0; n<nTags; n++ )
- {
- string label = tgs.TagGroupGetTagLabel(n)
- if ( splitSeparateTags )
- {
- if ( 1<nTags )
- allText += (n?"\n":"")+"TIFF Tag " + label + ":\n"
- }
- string text
- if ( tgs.TagGroupGetTagAsString( label, text ) )
- allText += text + "\n"
- }
- return allText
- }
- String GetTIFFAscii( object self, string path)
- {
- return self.GetTIFFAscii( path, true )
- }
- image OpenTIFFWithTags( object self, string path )
- {
- image Imported := OpenImage( path )
- TagGroup TIFFTags = self.GetTIFFTagsAsTG(path, TRUE, TRUE, TRUE)
- Imported.ImageGetTagGroup().TagGroupSetTagAsTagGroup( "TIFF Tags", TIFFTags )
- return Imported
- }
- image OpenFEI_TIFF( object self, string path, number withTiffTags )
- {
- image Imported := OpenImage( path )
- if ( withTiffTags )
- {
- TagGroup TIFFTags = self.GetTIFFTagsAsTG(path, TRUE, TRUE, FALSE )
- Imported.ImageGetTagGroup().TagGroupSetTagAsTagGroup( "TIFF Tags", TIFFTags )
- }
- string ASCIITags = self.GetTIFFAscii(path)
- TagGroup FEITags = self.CreateTagsFromString_FEI_Default( ASCIITags )
- Imported.ImageGetTagGroup().TagGroupSetTagAsTagGroup( "Info", FEITags )
- number sx, sy, ox, oy
- string ux, uy
- if ( self.GetCalibrationFromTags_FEI(FEITags, sx, ox, ux, sy, oy, uy ) )
- {
- Imported.ImageSetDimensionCalibration(0,ox,sx,ux,0)
- Imported.ImageSetDimensionCalibration(1,oy,sy,uy,0)
- }
- else
- {
- if ( verbose )
- Result( "\n FEI calibration not found. Image remains uncalibrated." )
- }
- return Imported
- }
- number GetCalibrationFromTags_FEI( object self, tagGroup FEItags, number &sx, number &ox, string &ux, number &sy, number &oy, string &uy )
- {
- if ( !FEItags.TagGroupIsValid() ) return FALSE
- number foundSomething = FALSE
- ox=0
- oy=0
- sx=1
- sy=1
- ux=""
- uy=""
- number value
- if ( FEITags.TagGroupGetTagAsNumber( "Scan:PixelWidth", value ) )
- {
- foundSomething = TRUE
- // [value] is in [m], scale to nm or um
- if ( value < 1e-6 )
- {
- if ( value < 1e-9 )
- {
- ux = "nm"
- sx = value * 1e9
- }
- else
- {
- ux = "µm"
- sx = value * 1e6
- }
- }
- }
- if ( FEITags.TagGroupGetTagAsNumber( "Scan:PixelHeight", value ) )
- {
- foundSomething = TRUE
- // [value] is in [m], scale to nm or um
- if ( value < 1e-6 )
- {
- if ( value < 1e-9 )
- {
- uy = "nm"
- sy = value * 1e9
- }
- else
- {
- uy = "µm"
- sy = value * 1e6
- }
- }
- }
- return foundSomething
- }
- image OpenFEI_TIFF( object self, string path )
- {
- return self.OpenFEI_TIFF( path, FALSE )
- }
- image OpenZEISS_TIFF( object self, string path, number withTiffTags )
- {
- image Imported := OpenImage( path )
- if ( withTiffTags )
- {
- TagGroup TIFFTags = self.GetTIFFTagsAsTG(path, TRUE, TRUE, FALSE )
- Imported.ImageGetTagGroup().TagGroupSetTagAsTagGroup( "TIFF Tags", TIFFTags )
- }
- string ASCIITags = self.GetTIFFAscii(path)
- TagGroup ZEISSTags = self.CreateTagsFromString_ZEISS_Default( ASCIITags )
- Imported.ImageGetTagGroup().TagGroupSetTagAsTagGroup( "Info", ZEISSTags )
- number sx, sy, ox, oy
- string ux, uy
- if ( self.GetCalibrationFromTags_ZEISS(ZEISSTags, sx, ox, ux, sy, oy, uy ) )
- {
- // "scale" gives full FOV!
- if ( sx!= 1)
- Imported.ImageSetDimensionCalibration(0,ox,sx/Imported.ImageGetDimensionSize(0),ux,0)
- if ( sy!= 1)
- Imported.ImageSetDimensionCalibration(1,oy,sy/Imported.ImageGetDimensionSize(1),uy,0)
- }
- else
- {
- if ( verbose )
- Result( "\n ZEISS calibration not found. Image remains uncalibrated." )
- }
- return Imported
- }
- image OpenZEISS_TIFF( object self, string path )
- {
- return self.OpenZEISS_TIFF( path, FALSE )
- }
- number GetCalibrationFromTags_ZEISS( object self, tagGroup ZEISStags, number &sx, number &ox, string &ux, number &sy, number &oy, string &uy )
- {
- if ( !ZEISStags.TagGroupIsValid() ) return FALSE
- number foundSomething = FALSE
- ox=0
- oy=0
- sx=1
- sy=1
- ux=""
- uy=""
- string value
- if ( ZEISStags.TagGroupGetTagAsString( "Width", value ) )
- {
- number pos = find( value, " " ) // separate unit!
- if ( -1 < pos )
- {
- sx = val( left(value,pos) ) // FOV width not scale!!
- ux = right( value, len(value)-pos-1 )
- foundSomething = TRUE
- }
- }
- if ( ZEISStags.TagGroupGetTagAsString( "Height", value ) )
- {
- number pos = find( value, " " ) // separate unit!
- if ( -1 < pos )
- {
- sy = val( left(value,pos) ) // FOV width not scale!!
- uy = right( value, len(value)-pos-1 )
- foundSomething = TRUE
- }
- }
- return foundSomething
- }
- }
- ///////////////////
- // CALL EXAMPLES //
- ///////////////////
- number option = 1
- string msg
- msg += "IMPORT TIFF - EXAMPLE\n"
- msg += "Select what you want to do:\n"
- msg += "(1)\t Import and calibrate FEI TIFF.\n"
- msg += "(2)\t Import and calibrate ZEISS TIFF.\n"
- msg += "(3)\t Show text content of TIFF.\n"
- msg += "(4)\t Show TIFF tags in browser.\n"
- while ( 4<option || 1>option )
- {
- if ( !GetNumber(msg,option,option)) exit(0)
- }
- string path = GetApplicationDirectory("open_save",0)
- if (!OpenDialog(NULL,"Select TIFF file",path, path)) exit(0)
- if ( 1 == option )
- Alloc(CImportTIFFWithTags).OpenFEI_TIFF(path).ShowImage()
- else if ( 2 == option )
- Alloc(CImportTIFFWithTags).OpenZEISS_TIFF(path).ShowImage()
- else if ( 3 == option )
- Result( "\n\n\n\n_____________________________\n" +Alloc(CImportTIFFWithTags).GetTIFFAscii(path) )
- else if ( 4 == option )
- Alloc(CImportTIFFWithTags).GetTIFFTagsAsTG(path,true,true,true).TagGroupOpenBrowserWindow(path,0)
Advertisement
Add Comment
Please, Sign In to add comment