Welcome to the Harris Geospatial product documentation center. Here you will find reference guides, help documents, and product libraries.


Harris Geospatial / Docs Center / Using IDL / 2D Array Examples

IDL

2D Array Examples

2D Array Examples

Let’s create a 2D array that has 3 rows by 5 columns (3x5). Since the ultimate goal is to give the array to IDL for processing, let’s pretend it is an “image.” We will set the first row to all red, the second row to all green, and the third row to all blue. Here’s the conceptual layout of our array

rrrrr
ggggg
bbbbb

We will see shortly that even though the conceptual 2D layout is the above, the actual layout in linear memory is quite different between SAFEARRAYs and IDL.

Note: In the examples below, the “red” value is really the ASCII character ‘r’, “green” is the ASCII character ‘g’, and so on. We use this scheme so when you look at the actual memory, you’ll see the letters “rgb”, which makes for easy reading. It is much less confusing than using the cardinal numbers 1, 2, 3, when you are also talking about ordinal numbering involving 1, 2, 3.

Note: These examples illustrate how different languages store data. You should not need to include such code in your applications to make them work; the wrapper does the conversion for you.

Visual Basic


Here is how to create the RGB array (matrix) in Visual Basic. This example, by default, creates a valid SAFEARRAY that is compliant with the information above, and stored within a Variant when passed as a parameter in a method call (not shown).

Const RED As Byte = 114
Const GREEN As Byte = 103
Const BLUE As Byte = 98
‘ This creates an array with dimension indices 0..2 & 0..4
‘ inclusive:
‘ i.e., it creates a 3x5 array; with “lower bounds” set to 0.
Dim m(2, 4) As Byte
For I = 0 To 4
m(0, I) = RED
m(1, I) = GREEN
m(2, I) = BLUE
Next I

Resulting linear memory:

rgbrgbrgbrgbrgb

Resulting SAFEARRAY.rgsabounds:

[0,5], [0,3]

Note the reversed order!

C++ Using ATL SAFEARRAY Wrapper Objects


This example uses the ATL Safearray wrapper objects: CComSafeArrayBound and CComSafeArray, which simply wraps the calls to the native Win32 Safearray API calls.

CComSafeArrayBound bound[2];
bound[0].SetCount(3); // 3 rows
bound[1].SetCount(5); // 5 columns
CComSafeArray<byte> matx(bound,2);
long ndx[2];
for ( int i = 0; i < 5; i++ )
{
  ndx[0] = 0;
  ndx[1] = i;
  matx.MultiDimSetAt(ndx,'r');
  ndx[0] = 1;
  ndx[1] = i;
  matx.MultiDimSetAt(ndx,'g');
  ndx[0] = 2; ndx[1] = i;
  matx.MultiDimSetAt(ndx,'b');
}

Resulting linear memory:

rgbrgbrgbrgbrgb

Resulting SAFEARRAY.rgsabounds:

[0,5], [0,3]

Observe that when the CComSafeArrayBound array is created, it is initialized in the conceptually correct order (i.e., specifying the “3 rows” by “5 columns”). But, if you look at the actual SAFEARRAY.rgsabounds[] element in memory, you see that they were reversed when the array was created.

C++ Using SAFEARRAY API Calls and Creating Different Memory Layout


C++ has the flexibility to create SAFEARRAYs in many different ways. By calling the SAFEARRAY API calls directly and judiciously, you can create a SAFEARRAY with data in a different order than what is normally expected. IDL and traditional SAFEARRAY data ordering are different. This example puts the data into the SAFEARRAY in the same order as IDL expects it. In other words, it puts the data in the opposite order that is used for SAFEARRAYs when you use the API calls to set individual data elements.

But first, we must step back and see how the C++ language stores multidimensional arrays. If you have the following declaration:

byte data[3][5] = {
'r','r','r','r','r',
'g','g','g','g','g',
'b','b','b','b','b' };

the resulting linear memory looks like this:

rrrrrgggggbbbbb

This is the same order that IDL expects. However, C++ accesses the memory in the opposite way that IDL would access the same data. For example, if you wanted to set the kth element of the first row (0-indexed), here’s how the two languages compare:

C++:

data[0][k] = value;

IDL:

data[k,0] = value

However, the resulting linear memory layout is the same.

This example creates the 2D RGB array in C++ using the SAFEARRAY API calls and arranging memory in the same layout as IDL.

// First, create the linear memory in the format: rrrrrgggggbbbbb
byte data[3][5];
for ( int i = 0; i < 5; i++ )
{
  data[0][i] = 'r';
  data[1][i] = 'g';
  data[2][i] = 'b';
}
SAFEARRAYBOUND sab[2];
sab[0].lLbound = 0;
sab[0].cElements = 3; // 3 rows
sab[1].lLbound = 0;
sab[1].cElements = 5; // 5 columns
SAFEARRAY* psa = SafeArrayCreateEx(VT_UI1, 2, sab, NULL);
 
// By copying the source data into the safearray data area,
// we can create the data in a different order. Since the
// source data is in the same order as IDL expects, this creates
// a SAFEARRAY with a non-standard ordering.
memcpy(psa->pvData, data, sizeof(data));

Resulting linear memory:

rrrrrgggggbbbbb

Resulting SAFEARRAY.rgsabounds:

[0,5], [0,3]

The consumer of this array needs some indication that the order is different than standard SAFEARRAYs and that it would not need to be converted before passing off to IDL.

Here is how to create the 2D RGB array in IDL pro code:

arr = BYTARR(5, 3)
for i=0,4 do begin
  arr[i,0] = 114B
  arr[i,1] = 103B
  arr[i,2] = 98B
endfor

Resulting linear memory:

rrrrrgggggbbbbb

Calling help, arr gives the following information:

ARR BYTE = Array[5, 3]



© 2017 Exelis Visual Information Solutions, Inc. |  Legal
My Account    |    Buy    |    Contact Us