ITK/Debug Visualizers for Visual Studio

From KitwarePublic
Jump to navigationJump to search

Visual Studio 2008/2010

Visual studio has support for custom visualization of user types in debugger (watch window and mouse hover).

File C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\Packages\Debugger\autoexp.dat controls how different datatypes are displayed. The file itself contains instructions on how to modify it. Anyone can add custom definitions for their own classes. The file below contains definitions for some of the ITK's classes. The contents of itk_debug_visualizers.dat should be merged into autoexp.dat.

With VS2008 SP1 and newer you don't even have to modify autoexp.dat, you can add environment variable _vcee_autoexp which points to your own file which will then be combined with the system one on the fly by Visual Studio each time debugging session is started (F5 pressed).

Watch window displaying itk::Image using enhanced view:

WatchImage.png

itk::Image with underlying buffer expanded (limited to first million elements):

WatchBuffer.png

I have started building this file, but it only contains support for itk::Image, the classes image contains and basic iterator types. With distributed effort, anyone can contribute a visualizer for a class or two for everyone's benefit.

itk_debug_visualizers.dat

<source lang="lisp">

InsightToolkit enhanced debugger visualizers for Visual Studio
I used this
http://www.virtualdub.org/blog/pivot/entry.php?id=120
as the main guide. This too
http://www.filetolink.com/17ad36ef
using Notepad++ with LISP/Scheme syntax highlight is better than plain text
Dženan Zukić

[ExecutionControl]

syntax myfunctionname=NoStepInto
do not step into any of the SmartPointer's methods

itk::SmartPointer::*=NoStepInto

[Visualizer]

-----------------------------------Size-----------------------------------

itk::Size<*>{

 children
  (
     #(
        #array(
           expr :    ($c.m_Size)[$i],
           size :    $T1
          )
     )
  )
  preview
  (
    #(
        "[",
          #array(
           expr :    ($c.m_Size)[$i],
           size :    $T1
          ),
        "]"
     )
  )

}

-----------------------------------Index-----------------------------------

itk::Index<*>{

 children
  (
     #(
        #array(
           expr :    ($c.m_Index)[$i],
           size :    $T1
          )
     )
  )
  preview
  (
    #(
        "[",
          #array(
           expr :    ($c.m_Index)[$i],
           size :    $T1
          ),
        "]"
     )
  )

}

-----------------------------------FixedArray-----------------------------------

itk::FixedArray<double,*>{

 children
  (
     #(
        #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T1
          )
     )
  )
  preview
  (
    #(
        "[",
          #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T1
          ):[$e,g],
        "]"
     )
  )

}

itk::FixedArray<*,*>{

 children
  (
     #(
        #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T2
          )
     )
  )
  preview
  (
    #(
        "[",
          #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T2
          ),
        "]"
     )
  )

}

-----------------------------------CovariantVector-----------------------------------
covariant vector is exactly the same as fixed array, from which it is derived
because CovariantVector does not introduce any new member variables
specialization for double
otherwise there are too many digits displayed in preview

itk::CovariantVector<double,*>{

 children
  (
     #(
        #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T1
          )
     )
  )
  preview
  (
    #(
        "[",
          #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T1
          ):[$e,g],
        "]"
     )
  )

}

itk::CovariantVector<*,*>{

 children
  (
     #(
        #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T2
          )
     )
  )
  preview
  (
    #(
        "[",
          #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T2
          ),
        "]"
     )
  )

}

-----------------------------------Point-----------------------------------
point is exactly the same as fixed array, from which it is derived
because point does not introduce any new member variables
specialization for double
otherwise there are too many digits displayed in preview

itk::Point<double,*>{

 children
  (
     #(
        #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T1
          )
     )
  )
  preview
  (
    #(
        "[",
          #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T1
          ):[$e,g],
        "]"
     )
  )

}

itk::Point<*,*>{

 children
  (
     #(
        #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T2
          )
     )
  )
  preview
  (
    #(
        "[",
          #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T2
          ),
        "]"
     )
  )

}

-----------------------------------Vector-----------------------------------
same as point

itk::Vector<double,*>{

 children
  (
     #(
        #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T1
          )
     )
  )
  preview
  (
    #(
        "[",
          #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T1
          ):[$e,g],
        "]"
     )
  )

}

itk::Vector<*,*>{

 children
  (
     #(
        #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T2
          )
     )
  )
  preview
  (
    #(
        "[",
          #array(
           expr :    ($c.m_InternalArray)[$i],
           size :    $T2
          ),
        "]"
     )
  )

}

-----------------------------------ImportImageContainer-----------------------------------

itk::ImportImageContainer<*,*>{

 children
  (
     #(
        size: $c.m_Size,
        capacity: $c.m_Capacity,
        #(uglyAll: [$c,!]),
        #array(
           expr :    ($c.m_ImportPointer)[$i],
           size :    $c.m_Size
          )
     )
  )
  preview
  (
    #(
        "Alloc ",
        $c.m_Size,
        " of ",
        $c.m_Capacity
     )
  )

}


Note
ImageRegion and/or ImageBase(Image) have a bugged preview
I don't know whether this is a bug in VS or my code is wrong
It does not impair function but it does look ugly
-----------------------------------ImageRegion-----------------------------------

itk::ImageRegion<*>{

 children
  (
     #(
        size: $c.m_Size,
        index: $c.m_Index
     )
  )
  preview
  (
    #(
        "R", $c.m_Size
     )
  )

}

-----------------------------------ImageBase-----------------------------------

itk::ImageBase<*>{

 children
  (
     #(
        size: $c.m_LargestPossibleRegion,
        origin: $c.m_Origin,
        spacing: $c.m_Spacing,
        #(allMembers: [$c,!])
     )
  )
  preview
  (
    #(
        $c.m_LargestPossibleRegion,
        "@",
        $c.m_Origin
     )
  )

}

-----------------------------------Image-----------------------------------
derived from ImageBase + m_Buffer
but it is dependent on one more template parameter

itk::Image<*,*>{

 children
  (
     #(
        size: $c.m_LargestPossibleRegion,
        origin: $c.m_Origin,
        spacing: $c.m_Spacing,
        buffer: $c.m_Buffer,
        #(allMembers: [$c,!])
     )
  )
  preview
  (
    #(
        $c.m_LargestPossibleRegion,
        "@",
        $c.m_Origin
     )
  )

}

for iterators, just define preview (which uses default children)
for this purpose, we can use the same code for all the basic iterators
-----------------------------------ImageConstIterator-----------------------------------

itk::ImageConstIterator<*>{

  preview
  (
    #(
        " [",
        $c.m_Offset,
        "] ",
        *($c.m_Buffer+$c.m_Offset)
     )
  )

}

-----------------------------------ImageIterator-----------------------------------

itk::ImageIterator<*>{

  preview
  (
    #(
        " [",
        $c.m_Offset,
        "] ",
        *($c.m_Buffer+$c.m_Offset)
     )
  )

}

-----------------------------------ImageRegionConstIterator-----------------------------------

itk::ImageRegionConstIterator<*>{

  preview
  (
    #(
        " [",
        $c.m_Offset,
        "] ",
        *($c.m_Buffer+$c.m_Offset)
     )
  )

}

-----------------------------------ImageRegionIterator-----------------------------------

itk::ImageRegionIterator<*>{

  preview
  (
    #(
        " [",
        $c.m_Offset,
        "] ",
        *($c.m_Buffer+$c.m_Offset)
     )
  )

}

the below visualizer for smart pointer is a worthless "improvement" over the deafult
-----------------------------------SmartPointer-----------------------------------
itk
:SmartPointer<*>{
children
(
#(
ptr
*($c.m_Pointer)
)
)
preview
(
#(
(void *)$c.m_Pointer,
" ",
*($c.m_Pointer)
)
)
}

</source>

Visual Studio 2012

Visual Studio 2012 introduces a novel type visualization framework called natvis. A good natvis tutorial is hosted on MSDN. Natvis files are now defined per user and can be put in following folder: %USERPROFILE%/documents/visual studio 2012/visualizers

Image Watch is a Visual Studio add-on which allows developers to display 2D images during debug sessions. In order to integrate support for the display of 2D ITK images, copy this natvis file into the 'visualizers' directory mentioned above.