X

Help Articles are product support tips and information straight from the NV5 Geospatial Technical Support team developed to help you use our products to their fullest potential.



2920 Rate this article:
No rating

Creating a custom iImage tool which accepts BYTESCALE_RANGE as a keyword.

Topic:
This help article provides an example of a custom iTool that will accept BYTESCALE_RANGE as a keyword. This keyword is used to set the minimum and maximum values used for byte-scaling.Discussion:
Creating this custom iTool involves two steps:

1. Create a launch routine (See MyImage.pro below) that will essentially be a wrapper around the iImage tool. It will accept a DATA argument (which should be an image), all keywords accepted by iImage, and the BYTESCALE_RANGE keyword (which will be used to determine the minimum and maximum values used for byte-scaling the displayed image). When the BYTESCALE_RANGE keyword is set, a new ParameterSet object must be created. The IMAGE_DIMENSIONS, IMAGE_LOCATION and RGB_TABLE keywords are not passed using _EXTRA. These keywords are used to add all of the necessary information to the ParameterSet object passed to the visualization class. See the comments in the code for details.


2. Since we are now accepting a new keyword, we must also define/register a new visualization class (See BSRangeVisImage__Define.pro below), which will be prepared to handle this additional information. Since the majority of the functionality needed is already in the IDLitVisImage object class, the new class will inherit the IDLitVisImage visual class. All methods, with the exception of the OnDataChangeUpdate method, will be used directly from the inherited visual class. Since the OnDataChangeUpdate method handles the appearance of the image, this method must be modified to handle the new keyword (BYTESCALE_RANGE) when necessary. See the comments in the code for details.

Here is an example using this tool:

Create some fake data
  IDL> data = dist(100)

To fully see the affect of the BYTESCALE_RANGE keyword, we will get the data's range

  IDL> print, min(data, max = mx), mx
0.000000 70.7107

Set the minimum byte scale value to be 20 and the maximum byte scale value to be 50.

  IDL> myimage, data, bytescale_range = [20, 50]

The resulting image will have all pixels where the data is less than 20 set to 0, and all pixels where the data is greater than 50 set to 255.Solution:

;*********************** MyImage.pro ************************
pro myimage, data, $
  bytescale_range = bytescale_range, $
  image_location = imagelocation, $
  image_dimensions = imagedimensions, $
  rgb_table = rgbtable, $
  _extra = _extra
 
; Register the BSRangeVisImage visualization.
  itregister, 'my image tool', 'bsrangevisimage', $
    /visualization
 
  case (size(data))[0] of
 
    0: $ ; No data has been passed
      iimage, visualization_type = 'my image tool', $
        _extra = _extra
 
    2: begin ; Single plane image.
 
      if keyword_set(bytescale_range) then begin
 
      ; Initialize an IDLitParameterSet object for
      ; passing information to BSRangeVisImage.
        oparmset = obj_new('idlitparameterset')
 
      ; Add the image data to the IDLitParameterSet object.
        oparmset -> add, obj_new('idlitdataidlimagepixels', $
          data, $
          name = 'Image Plane', $
          identifier='imagepixels', $
          _extra = _extra), $
          parameter_name='imagepixels'
 
        if ((n_elements(imagelocation) eq 2) or $
          (n_elements(imagedimensions) eq 2)) then begin
        ; IMAGE_LOCATION or/and IMAGE_DIMENSIONS is/are set.
 
        ; Get the dimensions of the input data
          imgdims = size(data, /dimensions)
 
          if (n_elements(imagelocation) eq 2) then begin
          ; IMAGE_LOCATION keyword set.
          ; Set XMIN and XMAX according to IMAGELOCATION.
            xmin = imagelocation[0]
            ymin = imagelocation[1]
 
          endif else begin
          ; Otherwise set XMIN and XMAX to 0.
            xmin = 0
            ymin = 0

          endelse

          if (n_elements(imagedimensions) eq 2) then begin
          ; IMAGE_DIMENSIONS keyword set.
          ; Set XMAX, YMAX and DELTA according to
          ; IMAGEDIMENSIONS.
            xmax = xmin + imagedimensions[0]
            ymax = ymin + imagedimensions[1]
            delta = double(imagedimensions) / double(imgdims)

          endif else begin
          ; Otherwise, use the data's dimensions to set
          ; XMAX and YMAX.
            xmax = xmin + imgdims[0]
            ymax = ymin + imgdims[1]
            delta  = [1.0,1.0]

          endelse

        ; Create X and Y vectors/coordinates for the data.
          x = dindgen(imgdims[0])*delta[0] + xmin
          y = dindgen(imgdims[1])*delta[1] + ymin

        ; Add the X vector information to the
        ; IDLitParameterSet object.
          if (obj_valid(oparmset) ne 0) then begin
            oparmset->add, obj_new('idlitdataidlvector', $
              x, name='x'), parameter_name='x'

        ; Add the Y vector information to the
        ; IDLitParameterSet object.
            oparmset->add, obj_new('idlitdataidlvector', $
              y, name='y'), parameter_name='y'

          endif

        endif

      ; Add the BYTESCALE_RANGE information to the
      ; IDLitParameterSet object.
        oparmset -> add, obj_new('idlitdataidlvector', $
          bytescale_range, $
          identifier = 'bytescale_range', _extra = _extra)

        if (n_elements(rgbtable) ne 0) then begin
        ; RGB_TABLE keyword is set.

        ; Copile iImage so the _SetPalette routine can
        ; be used to add the palette information to the
        ; IDLitParameterSet object.
          resolve_routine, 'iimage', /compile_full_file, $
            /no_recompile
          _setpalette, oparmset, rgbtable
        endif

      ; Pass the IDLitParameterSet object to iImage setting
      ; the VISUALIZATION_TYPE to "My IMage".
        iimage, initial_data = oparmset, $
          visualization_type = 'my image tool', $
          _extra = _extra

      endif else $
        iimage, data, visualization_type = 'my image tool', $
          _extra = _extra

    end

    else: $
    ; Pass DATA to iImage.  BYTESCALE_RANGE will be ignored
    ; in all cases other than a single plane image.
      iimage, data, visualization_type = 'my image tool', $
        _extra = _extra

  endcase

end
;************************************************************



;**************** BSRangeVisImage__Define.pro ****************

;***** Initialization *****
function bsrangevisimage::init, _ref_extra = _extra

; Initialize the inherited IDLitVisImage superclass.
  if (self -> idlitvisimage::init() ne 1) then $
      return, 0

  if(n_elements(_extra) gt 0)then $
    self->IDLitVisImage::SetProperty, _extra=_extra

    return, 1 ; Success.
end



;***** OnDataChangeUpdate method *****
; This method will override the OnDataChangeUpdate method
; of the inherited object class.  Unless a parameter with
; identifier BYTESCALE_RANGE is encountered, the methods
; from the super class will be called.

pro bsrangevisimage::ondatachangeupdate, osubject, parmname, $
  no_subrect_update=nosubrectupdate

; Input parameters.
  if strlowcase(parmname) eq '' then begin

  ; Get the number of parameters and their names.
    oparams = osubject->get(/all, count = nparam, $
      name = paramnames)

  ; Cycle through the input parameters.
    for i = 0, nparam-1 do begin

    ; Get the identifier for the parameter.
      oparams[i] -> getproperty, identifier = temp

      if strlowcase(temp) eq 'bytescale_range' then begin
      ; BYTESCALE_RANGE parameter encountered.

      ; Get the byte-scale range.
        r = oparams[i] -> getdata(data)

      ; Set the BYTESCALE_MIN and BYTESCALE_MAX
      ; properties.
        self -> setproperty, $
                bytescale_min = data[0], $
                bytescale_max = data[1]

      endif else $
      ; If not the RANGE parameter, call the
      ; OnDataChangeUpdate method of the
      ; IDLitVisImage superclass.
        self -> idlitvisimage::ondatachangeupdate, $
          osubject, parmname, $
          no_subrect_update = nosubrectupdate

    endfor ; i = 0, nparams-1

  endif else $
  ; Pass all other parameters to the OnDataChangeUpdate
  ; method of the IDLitVisImage superclass.
    self -> idlitvisimage::ondatachangeupdate, $
      osubject, parmname, $
      no_subrect_update = nosubrectupdate

end



;***** Class Definition *****
pro bsrangevisimage__define

; Define the BSRangeVisImage class structure which
; inherits the IDLitVisImage class.
  struct = {bsrangevisimage, $
            inherits idlitvisimage}

end
;************************************************************
Please login or register to post comments.
Featured

End-of-Life Policy Enforcement for ENVI 5.3 / IDL 8.5 and Earlier Versions

5/6/2024

April 1, 2024 Dear ENVI/IDL Customer,  We are reaching out to notify you of our supported... more »

How to Upgrade licenses to ENVI 6.x / IDL 9.x

12/5/2023

What is the new Upgrade function? Starting with ENVI 6.0 and IDL 9.0, we have implemented an... more »

What to do if the 'License Administrator - License Server' for the Next-Generation License Server does not start?

6/13/2023

Background: With the release of ENVI 5.7 & IDL 8.9 and the corresponding Next-Generation licensing... more »

Next-Generation Licensing FAQ

4/28/2023

  NV5 Geospatial has adopted a new licensing technology for all future releases of our ENVI, IDL... more »

The IDL Virtual Machine

6/6/2013

What is the IDL Virtual Machine? An IDL Virtual Machine is a runtime version of IDL that can... more »