X

NV5 Geospatial Blog

Each month, NV5 Geospatial posts new blog content across a variety of categories. Browse our latest posts below to learn about important geospatial information or use the search bar to find a specific topic or author. Stay informed of the latest blog posts, events, and technologies by joining our email list!



Comparing Amplitude and Coherence Time Series With ICEYE US GTR Data and ENVI SARscape

Comparing Amplitude and Coherence Time Series With ICEYE US GTR Data and ENVI SARscape

12/3/2025

Large commercial SAR satellite constellations have opened a new era for persistent Earth monitoring, giving analysts the ability to move beyond simple two-image comparisons into robust time series analysis. By acquiring SAR data with near-identical geometry every 24 hours, Ground Track Repeat (GTR) missions minimize geometric decorrelation,... Read More >

Empowering D&I Analysts to Maximize the Value of SAR

Empowering D&I Analysts to Maximize the Value of SAR

12/1/2025

Defense and intelligence (D&I) analysts rely on high-resolution imagery with frequent revisit times to effectively monitor operational areas. While optical imagery is valuable, it faces limitations from cloud cover, smoke, and in some cases, infrequent revisit times. These challenges can hinder timely and accurate data collection and... Read More >

Easily Share Workflows With the Analytics Repository

Easily Share Workflows With the Analytics Repository

10/27/2025

With the recent release of ENVI® 6.2 and the Analytics Repository, it’s now easier than ever to create and share image processing workflows across your organization. With that in mind, we wrote this blog to: Introduce the Analytics Repository Describe how you can use ENVI’s interactive workflows to... Read More >

Deploy, Share, Repeat: AI Meets the Analytics Repository

Deploy, Share, Repeat: AI Meets the Analytics Repository

10/13/2025

The upcoming release of ENVI® Deep Learning 4.0 makes it easier than ever to import, deploy, and share AI models, including industry-standard ONNX models, using the integrated Analytics Repository. Whether you're building deep learning models in PyTorch, TensorFlow, or using ENVI’s native model creation tools, ENVI... Read More >

Blazing a trail: SaraniaSat-led Team Shapes the Future of Space-Based Analytics

Blazing a trail: SaraniaSat-led Team Shapes the Future of Space-Based Analytics

10/13/2025

On July 24, 2025, a unique international partnership of SaraniaSat, NV5 Geospatial Software, BruhnBruhn Innovation (BBI), Netnod, and Hewlett Packard Enterprise (HPE) achieved something unprecedented: a true demonstration of cloud-native computing onboard the International Space Station (ISS) (Fig. 1). Figure 1. Hewlett... Read More >

1345678910Last
12758 Rate this article:
5.0

Serializing IDL Objects and Structures

Jim Pendleton

In my most recent IDL Data Point blog, I showed some example code for extending the IDL_Variable's static methods to include user-defined methods, allowing simplified syntax for serializing data of most variable types.

 

The specific example showed a technique for serializing IDL variables, turning them into compressed ASCII byte streams that can be more easily transmitted under certain protocols, for example via HTTP to ENVI Services Engine instances running on a cloud.

 

 

Object reference and structure data types are excluded from being extended by the IDL_Variable "superclass" definition that's common to other variable representations.

 

 

In this article I'll briefly discuss a mechanism to serialize objects and structures.

 

 

We can't retroactively extend IDL_Variable's static methods to provide the simplified syntax we want for objects and structures.

 

 

An alternate approach to solve the problem is to create a pair of static methods in a new class.  One method would take as input the reference to the variable to be serialized and return the serialization.  The second would invert the operation.

 

 

The static methods for compression and decompression uses the same technique described in the earlier article, calling IDL_BASE64 and ZLIB_COMPRESS or ZLIB_UNCOMPRESS for all variable types other than object reference and structure.

 

 

We need a different solution for them.

 


FUNCTION jp_Serializer::Serialize, v, DIM = Dim, TYPECODE = TypeCode
COMPILE_OPT STATIC
dim = v.Dim
typeCode = v.TypeCode
IF (typeCode EQ 8 || typeCode EQ 11) THEN BEGIN
    ; TODO What about structure (8) and object reference (11)?
ENDIF ELSE BEGIN
    RETURN, IDL_BASE64(ZLIB_COMPRESS(v))
ENDELSE
END

 

 

Notice that namespace partitioning argues for the use of an identifier unlikely to collide.  Here I'm using "jp_" as a prefix. 

 

 

One trick for serialization is to store the variable into an IDL SAVE file, read the file's contents via READ_BINARY into a BYTARR, then serialize the BYTARR using the same technique we apply to the other data.

 

 

    tempFile = FILEPATH('temp.sav', /TMP)
    SAVE, v, /COMPRESS, FILE = tempFile
    b = READ_BINARY(tempfile, DATATYPE = 1)
    FILE_DELETE, tempfile
    RETURN, IDL_BASE64(ZLIB_COMPRESS(b))

 

 

Note: A more robust implementation would generate a unique, unused file name, perhaps  a topic for another blog post.

 

 

In a similar fashion, the de-serialization converts the uncompressed byte stream, writes it to a file, then reads the data as a SAVE file.

 

 

    tempFile = FILEPATH('temp.sav', /TMP)
    OPENW, lun, tempFile, /GET_LUN
    WRITEU, lun, ZLIB_UNCOMPRESS(IDL_BASE64(var), TYPE = 1)
    FREE_LUN, lun
    RESTORE, tempFile
    FILE_DELETE, tempFile
    RETURN, v

 

 

We know that the variable to be returned is named "v" since that's the way it was saved in the serialization routine, above.  It has "magically" appeared in the context of the routine via RESTORE operation.

 

 

Here is the class with both static methods fully implemented

 

 

 

FUNCTION jp_Serializer::Deserialize, var, DIM = dim, TYPECODE = typeCode
COMPILE_OPT STATIC
IF (typeCode EQ 8 || typeCode eq 11) THEN BEGIN
  tempFile = FILEPATH('temp.sav', /TMP)
  OPENW, lun, tempFile, /GET_LUN
  WRITEU, lun, ZLIB_UNCOMPRESS(IDL_BASE64(var), TYPE = 1)
  FREE_LUN, lun
  RESTORE, tempFile
  FILE_DELETE, tempFile
  RETURN, v
ENDIF ELSE BEGIN
  RETURN, ZLIB_UNCOMPRESS(IDL_BASE64(var), DIM = dim, TYPE = typeCode)
ENDELSE
END

FUNCTION jp_Serializer::Serialize, v, DIM = Dim, TYPECODE = TypeCode
COMPILE_OPT STATIC
dim = v.Dim
typeCode = v.TypeCode
IF (typeCode EQ 8 || typeCode EQ 11) THEN BEGIN
  tempFile = FILEPATH('temp.sav', /TMP)
  SAVE, v, /COMPRESS, FILE = tempFile
  b = READ_BINARY(tempfile, DATATYPE = 1)
  FILE_DELETE, tempfile
  RETURN, IDL_BASE64(ZLIB_COMPRESS(b))
ENDIF ELSE BEGIN
  RETURN, IDL_BASE64(ZLIB_COMPRESS(v))
ENDELSE
END

PRO jp_Serializer__Define
!null = {jp_Serializer, _ : 0B}
END

 

 

 

 

Here's an example of serialization of a "regular" variable

 

IDL> b = bindgen(2,2,2)
IDL> b
   0   1
   2   3

   4   5
   6   7
IDL> s = jp_Serializer.Serialize(b, DIM=dim, TYPECODE=type)
IDL> s,dim,type
eJxiYGRiZmFlYwcAAAD//wMAAFwAHQ==
           2           2           2
           1

 

And the de-serialization follows the same pattern

 

IDL> print, jp_Serializer.Deserialize(s, DIM=dim,TYPECODE=type)
   0   1
   2   3

   4   5
   6   7

 

Now let's see what happens with an object reference

 

IDL> o = orb()
IDL> so = jp_Serializer.Serialize(o)
IDL> so.strlen()
        9384
IDL> dso = jp_Serializer.Deserialize(so, TYPECODE=11)
IDL> dso
<ObjHeapVar28(ORB)>
IDL> xobjview, dso

 

 

Remember that when we SAVE an object reference, it makes a copy of the specified object's data. Additionally it makes a copy of any objects that are referenced within the specified object, so use this capability carefully.

 

 

Obviously, when passing serialized objects between IDL sessions, it's imperative that the required class and structure definitions are synchronized between those sessions and that class definitions are executed before the de-serialized file is restored.  Can you think of a technique for serializing and deserializing executable code to ensure compatibility, assuming the same release version of IDL?  (Hint: One technique would involve SAVE files for routines, very much like we've used above with data files.)

 

 

Why use static methods at all?  Why not simply create functions, in the traditional sense?

 

 

By grouping related functionality in a single class, I can easily extend the functionality without worrying about overwriting other functions.  The code is co-located in a single source file for easy maintenance.  Name space is defined by the class, providing some level of protection against conflicts.

 

 

It would be nice if there were a way to make a method "final" in the sense of other languages where the executive would disallow the re-compilation or sub-classing of methods at run-time.  This could be accomplished, say, via a new COMPILE_OPT.  Although I routinely take advantage of the flexible run-time behaviors that IDL offers relative to other languages, sometimes I'd like to have more control  How about you?

 

Please login or register to post comments.