diff --git a/Examples/VolumeRendering/VolumeRenderingExample.cpp b/Examples/VolumeRendering/VolumeRenderingExample.cpp
index efc5dabc4567e2a76bad36f2656d7c6a8ac11e68..f4941787e1c85d58aff8fa43562257164fda97c9 100644
--- a/Examples/VolumeRendering/VolumeRenderingExample.cpp
+++ b/Examples/VolumeRendering/VolumeRenderingExample.cpp
@@ -22,6 +22,7 @@
 #include "imstkCamera.h"
 #include "imstkImageData.h"
 #include "imstkKeyboardSceneControl.h"
+#include "imstkLogger.h"
 #include "imstkMeshIO.h"
 #include "imstkMouseSceneControl.h"
 #include "imstkNew.h"
@@ -44,6 +45,8 @@ using namespace imstk;
 int
 main()
 {
+    Logger::startLogger();
+
     // SDK and Scene
     imstkNew<Scene> scene("VolumeRendering");
 
diff --git a/Source/DynamicalModels/ObjectModels/imstkSPHModel.cpp b/Source/DynamicalModels/ObjectModels/imstkSPHModel.cpp
index 1f7199aa59205e81f3ce26b731e13045ee5a893f..e9b3f59b35bd59bf9061227f2c392eee2411a4ed 100644
--- a/Source/DynamicalModels/ObjectModels/imstkSPHModel.cpp
+++ b/Source/DynamicalModels/ObjectModels/imstkSPHModel.cpp
@@ -886,7 +886,7 @@ SPHModel::writeStateToVtk()
 
         VTKMeshIO   vtkWriter;
         std::string filePath = std::string("sph_output_") + std::to_string(m_totalTime) + std::string(".vtu");
-        vtkWriter.write(m_geomUnstructuredGrid, filePath, VTU);
+        vtkWriter.write(m_geomUnstructuredGrid, filePath, MeshFileType::VTU);
 
         m_vtkTimeModulo  += m_writeToOutputModulo;
         m_vtkPreviousTime = m_totalTime;
diff --git a/Source/MeshIO/imstkMeshIO.cpp b/Source/MeshIO/imstkMeshIO.cpp
index 79663bb56f5d68ef668f49a6fd32b84b1c20e042..adb53e471231d1af1bef5c04b788edb9194ebc2e 100644
--- a/Source/MeshIO/imstkMeshIO.cpp
+++ b/Source/MeshIO/imstkMeshIO.cpp
@@ -29,9 +29,29 @@
 #include "imstkVTKMeshIO.h"
 
 #include <sys/stat.h>
+#include <unordered_map>
 
 namespace imstk
 {
+static std::unordered_map<std::string, MeshFileType> extToType =
+{
+    { "vtk", MeshFileType::VTK },
+    { "vtp", MeshFileType::VTP },
+    { "vtu", MeshFileType::VTU },
+    { "obj", MeshFileType::OBJ },
+    { "stl", MeshFileType::STL },
+    { "ply", MeshFileType::PLY },
+    { "dae", MeshFileType::DAE },
+    { "fbx", MeshFileType::FBX },
+    { "3ds", MeshFileType::_3DS },
+    { "veg", MeshFileType::VEG },
+    { "msh", MeshFileType::MSH },
+    { "dcm", MeshFileType::DCM },
+    { "nrrd", MeshFileType::NRRD },
+    { "nii", MeshFileType::NII },
+    { "mhd", MeshFileType::MHD }
+};
+
 std::shared_ptr<PointSet>
 MeshIO::read(const std::string& filePath)
 {
@@ -54,6 +74,7 @@ MeshIO::read(const std::string& filePath)
     case MeshFileType::NRRD:
     case MeshFileType::NII:
     case MeshFileType::DCM:
+    case MeshFileType::MHD:
         return VTKMeshIO::read(filePath, meshType);
         break;
     case MeshFileType::OBJ:
@@ -68,7 +89,7 @@ MeshIO::read(const std::string& filePath)
     case MeshFileType::MSH:
         return MSHMeshIO::read(filePath, meshType);
         break;
-    case UNKNOWN:
+    case MeshFileType::UNKNOWN:
     default:
         break;
     }
@@ -102,74 +123,20 @@ MeshIO::fileExists(const std::string& file, bool& isDirectory)
 const MeshFileType
 MeshIO::getFileType(const std::string& filePath)
 {
-    MeshFileType meshType = MeshFileType::UNKNOWN;
-
     std::string extString = filePath.substr(filePath.find_last_of(".") + 1);
 
     CHECK(!extString.empty()) << "MeshIO::getFileType error: invalid file name";
 
-    if (extString == "vtk" || extString == "VTK")
-    {
-        meshType = MeshFileType::VTK;
-    }
-    else if (extString == "vtp" || extString == "VTP")
-    {
-        meshType = MeshFileType::VTP;
-    }
-    else if (extString == "vtu" || extString == "VTU")
-    {
-        meshType = MeshFileType::VTU;
-    }
-    else if (extString == "obj" || extString == "OBJ")
-    {
-        meshType = MeshFileType::OBJ;
-    }
-    else if (extString == "stl" || extString == "STL")
-    {
-        meshType = MeshFileType::STL;
-    }
-    else if (extString == "ply" || extString == "PLY")
-    {
-        meshType = MeshFileType::PLY;
-    }
-    else if (extString == "dae" || extString == "DAE")
-    {
-        meshType = MeshFileType::DAE;
-    }
-    else if (extString == "fbx" || extString == "FBX")
-    {
-        meshType = MeshFileType::FBX;
-    }
-    else if (extString == "3ds" || extString == "3DS")
-    {
-        meshType = MeshFileType::_3DS;
-    }
-    else if (extString == "veg" || extString == "VEG")
-    {
-        meshType = MeshFileType::VEG;
-    }
-    else if (extString == "msh" || extString == "MSH")
-    {
-        meshType = MeshFileType::MSH;
-    }
-    else if (extString == "dcm" || extString == "DCM")
-    {
-        meshType = MeshFileType::DCM;
-    }
-    else if (extString == "nrrd" || extString == "NRRD")
-    {
-        meshType = MeshFileType::NRRD;
-    }
-    else if (extString == "nii" || extString == "NII")
-    {
-        meshType = MeshFileType::NII;
-    }
-    else
+    // To lowercase
+    std::transform(extString.begin(), extString.end(), extString.begin(),
+        [](unsigned char c) { return std::tolower(static_cast<int>(c)); });
+
+    if (extToType.count(extString) == 0)
     {
         LOG(FATAL) << "MeshIO::getFileType error: unknown file extension";
     }
 
-    return meshType;
+    return extToType[extString];
 }
 
 bool
@@ -194,6 +161,7 @@ MeshIO::write(const std::shared_ptr<imstk::PointSet> imstkMesh, const std::strin
     case MeshFileType::VTP:
     case MeshFileType::STL:
     case MeshFileType::PLY:
+    case MeshFileType::MHD:
         return VTKMeshIO::write(imstkMesh, filePath, meshType);
         break;
     case MeshFileType::UNKNOWN:
diff --git a/Source/MeshIO/imstkMeshIO.h b/Source/MeshIO/imstkMeshIO.h
index 889ac9de5bf270d9d8b0af2ad44d795cb46640ee..3577b64d38ceaf7ede07db32258a3073ced48834 100644
--- a/Source/MeshIO/imstkMeshIO.h
+++ b/Source/MeshIO/imstkMeshIO.h
@@ -31,7 +31,7 @@ class PointSet;
 ///
 /// \brief Enumeration the mesh file type
 ///
-enum MeshFileType
+enum class MeshFileType
 {
     UNKNOWN,
     VTK,
@@ -47,7 +47,8 @@ enum MeshFileType
     MSH,
     NRRD,
     DCM,
-    NII
+    NII,
+    MHD
 };
 
 ///
diff --git a/Source/MeshIO/imstkVTKMeshIO.cpp b/Source/MeshIO/imstkVTKMeshIO.cpp
index 2356f502bd41d4231a2cf92171910f1d93ba84d4..0997d2f99c04cd21fefb2d78363da9e1a16e7306 100644
--- a/Source/MeshIO/imstkVTKMeshIO.cpp
+++ b/Source/MeshIO/imstkVTKMeshIO.cpp
@@ -32,6 +32,8 @@
 #include <vtkGenericDataObjectReader.h>
 #include <vtkGenericDataObjectWriter.h>
 #include <vtkImageData.h>
+#include <vtkMetaImageReader.h>
+#include <vtkMetaImageWriter.h>
 #include <vtkNIFTIImageReader.h>
 #include <vtkNIFTIImageWriter.h>
 #include <vtkNrrdReader.h>
@@ -91,6 +93,10 @@ VTKMeshIO::read(const std::string& filePath, MeshFileType meshType)
     {
         return VTKMeshIO::readVtkImageDataNIFTI(filePath);
     }
+    case MeshFileType::MHD:
+    {
+        return VTKMeshIO::readVtkImageData<vtkMetaImageReader>(filePath);
+    }
     default:
     {
         LOG(FATAL) << "VTKMeshIO::read error: file type not supported";
@@ -110,6 +116,10 @@ VTKMeshIO::write(const std::shared_ptr<PointSet> imstkMesh, const std::string& f
         {
             return VTKMeshIO::writeVtkImageDataNIFTI(imgMesh, filePath);
         }
+        case MeshFileType::MHD:
+        {
+            return VTKMeshIO::writeMetaImageData(imgMesh, filePath);
+        }
         default:
             LOG(WARNING) << "VTKMeshIO::write error: file type not supported for volumetric mesh.";
             return false;
@@ -250,7 +260,14 @@ VTKMeshIO::writeVtkImageData(const std::shared_ptr<ImageData> imstkMesh, const s
 
     int* dim    = vtkMesh->GetDimensions();
     auto writer = vtkSmartPointer<WriterType>::New();
-    writer->SetFileDimensionality(3);
+    if (vtkMesh->GetDimensions()[2] == 1)
+    {
+        writer->SetFileDimensionality(2);
+    }
+    else
+    {
+        writer->SetFileDimensionality(3);
+    }
     writer->SetInputData(vtkMesh);
     writer->SetFileName(filePath.c_str());
     writer->Write();
@@ -385,9 +402,6 @@ VTKMeshIO::writeVtkUnstructuredGrid(std::shared_ptr<HexahedralMesh> hMesh, const
     return true;
 }
 
-///
-/// \brief Reads vtk image data
-///
 template<typename ReaderType>
 std::shared_ptr<ImageData>
 VTKMeshIO::readVtkImageData(const std::string& filePath)
@@ -400,9 +414,6 @@ VTKMeshIO::readVtkImageData(const std::string& filePath)
     return imageData;
 }
 
-///
-/// \brief Reads nifti/nii format image data
-///
 std::shared_ptr<ImageData>
 VTKMeshIO::readVtkImageDataNIFTI(const std::string& filePath)
 {
@@ -415,9 +426,6 @@ VTKMeshIO::readVtkImageDataNIFTI(const std::string& filePath)
     return imageData;
 }
 
-///
-/// \brief Write nifti/nii format image data
-///
 bool
 VTKMeshIO::writeVtkImageDataNIFTI(std::shared_ptr<ImageData> imageData, const std::string& filePath)
 {
@@ -431,9 +439,40 @@ VTKMeshIO::writeVtkImageDataNIFTI(std::shared_ptr<ImageData> imageData, const st
 
     auto writer = vtkSmartPointer<vtkNIFTIImageWriter>::New();
     writer->SetFileName(filePath.c_str());
-    writer->SetFileDimensionality(3);
+    if (vtkMesh->GetDimensions()[2] == 1)
+    {
+        writer->SetFileDimensionality(2);
+    }
+    else
+    {
+        writer->SetFileDimensionality(3);
+    }
     writer->SetInputData(vtkMesh);
     writer->Update();
     return true;
 }
+
+bool
+VTKMeshIO::writeMetaImageData(std::shared_ptr<ImageData> imageData, const std::string& filePath)
+{
+    vtkSmartPointer<vtkImageData> vtkMesh = GeometryUtils::copyToVtkImageData(imageData);
+    if (!vtkMesh)
+    {
+        return false;
+    }
+
+    auto writer = vtkSmartPointer<vtkMetaImageWriter>::New();
+    if (vtkMesh->GetDimensions()[2] == 1)
+    {
+        writer->SetFileDimensionality(2);
+    }
+    else
+    {
+        writer->SetFileDimensionality(3);
+    }
+    writer->SetInputData(vtkMesh);
+    writer->SetFileName(filePath.c_str());
+    writer->SetRAWFileName((filePath + ".raw").c_str());
+    writer->Write();
+}
 } // imstk
diff --git a/Source/MeshIO/imstkVTKMeshIO.h b/Source/MeshIO/imstkVTKMeshIO.h
index 92dbafda083db45a22578d26af6d9a24ba05707f..24b470ddcc399c7a8b0bcde3a1026e22e061cbe7 100644
--- a/Source/MeshIO/imstkVTKMeshIO.h
+++ b/Source/MeshIO/imstkVTKMeshIO.h
@@ -133,5 +133,10 @@ protected:
     /// \brief Write nifti/nii format image data
     ///
     static bool writeVtkImageDataNIFTI(std::shared_ptr<ImageData> imageData, const std::string& filePath);
+
+    ///
+    /// \brief Write meta/mhd format image data
+    ///
+    static bool writeMetaImageData(std::shared_ptr<ImageData> imageData, const std::string& filePath);
 };
 } // imstk